Version 2.0.0-dev.59.0
Merge commit '1ca17b6d03d0fdf8778d45c486bb5ac617809df0' into dev
diff --git a/BUILD.gn b/BUILD.gn
index f4f9bec..d0cd1b5 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -139,6 +139,12 @@
]
}
+group("observatory_archive") {
+ deps = [
+ "runtime/observatory:observatory_archive"
+ ]
+}
+
# The rules below build a Fuchsia OS image that includes the Dart tree
# under /system/test/dart. To get this into the `user.bootfs` generated
# by the Fuchsia build, add the GN build argument:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d101527..36f7387 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,24 @@
+## 2.0.0-dev.59.0
+
+### Language
+
+The change to make bounds on generic functions invariant has landed in the
+analyzer. The analyzer will now issue an invalid override error on the
+following program ([issue 29014][sdk#29014]).
+
+```dart
+class A {
+ void f<T extends int>() {}
+}
+
+class B extends A {
+ @override
+ void f<T extends num>() {}
+}
+```
+
+[sdk#29014]: https://github.com/dart-lang/sdk/issues/29014
+
## 2.0.0-dev.58.0
## 2.0.0-dev.57.0
@@ -58,6 +79,8 @@
* `dart:io`
* Added `X509Certificate.der`, `X509Certificate.pem`, and
`X509Certificate.sha1`.
+ * Added `FileSystemEntity.fromRawPath` constructor to allow for
+ the creation of `FileSystemEntity` using `Uint8List` buffers.
### Tool Changes
diff --git a/DEPS b/DEPS
index 9f020fb..114668e 100644
--- a/DEPS
+++ b/DEPS
@@ -54,8 +54,8 @@
"async_tag": "2.0.7",
"bazel_worker_tag": "v0.1.9",
"boolean_selector_tag" : "1.0.3",
- "boringssl_gen_rev": "344f455fd13d46f054726638e76026156ea73aa9",
- "boringssl_rev" : "672f6fc2486745d0cabc3aaeb4e0a3cd13b37b12",
+ "boringssl_gen_rev": "fc47eaa1a245d858bae462cd64d4155605b850ea",
+ "boringssl_rev" : "189270cd190267f5bd60cfe8f8ce7a61d07ba6f4",
"charcode_tag": "v1.1.1",
"chrome_rev" : "19997",
"cli_util_tag" : "0.1.2+1",
@@ -79,7 +79,7 @@
# For more details, see https://github.com/dart-lang/sdk/issues/30164
"dart_style_tag": "1.0.14", # Please see the note above before updating.
- "dartdoc_tag" : "v0.19.0",
+ "dartdoc_tag" : "v0.19.1",
"fixnum_tag": "0.10.5",
"func_rev": "25eec48146a58967d75330075ab376b3838b18a8",
"glob_tag": "1.1.5",
@@ -96,11 +96,11 @@
"json_rpc_2_tag": "2.0.6",
"linter_tag": "0.1.51",
"logging_tag": "0.11.3+1",
- "markdown_tag": "1.1.1",
+ "markdown_tag": "2.0.0",
"matcher_tag": "0.12.1+4",
"mime_tag": "0.9.6",
"mockito_tag": "a92db054fba18bc2d605be7670aee74b7cadc00a",
- "mustache4dart_tag" : "v2.1.1",
+ "mustache4dart_tag" : "v2.1.2",
"oauth2_tag": "1.1.0",
"observatory_pub_packages_rev": "d3a3aebefbd35aa30fe7bbc2889b772b398f7d7f",
"package_config_tag": "1.0.3",
@@ -136,7 +136,7 @@
"typed_data_tag": "1.1.3",
"usage_tag": "3.3.0",
"utf_tag": "0.9.0+4",
- "watcher_tag": "0.9.7+7",
+ "watcher_tag": "0.9.7+8",
"web_components_rev": "8f57dac273412a7172c8ade6f361b407e2e4ed02",
"web_socket_channel_tag": "1.0.7",
"WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index b21a7d1..3689187 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -102,7 +102,7 @@
depsformat = "gcc"
description = "CC {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
@@ -112,7 +112,7 @@
depsformat = "gcc"
description = "CXX {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
@@ -123,7 +123,7 @@
depsformat = "gcc"
description = "ASM {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index 4ed409a..ef4b8a5 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -62,7 +62,7 @@
depsformat = "gcc"
description = "CC {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
@@ -72,7 +72,7 @@
depsformat = "gcc"
description = "CXX {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
@@ -83,7 +83,7 @@
depsformat = "gcc"
description = "ASM {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
@@ -93,7 +93,7 @@
depsformat = "gcc"
description = "OBJC {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
@@ -103,7 +103,7 @@
depsformat = "gcc"
description = "OBJCXX {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.o",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
]
}
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index 71c6595..b8d222a 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -76,7 +76,7 @@
depsformat = "msvc"
description = "CC {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.obj",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
}
@@ -93,7 +93,7 @@
depsformat = "msvc"
description = "CXX {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.obj",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
}
@@ -101,7 +101,7 @@
tool("rc") {
command = "$python_path $tool_wrapper_path rc-wrapper $env rc.exe {{defines}} {{include_dirs}} /fo{{output}} {{source}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.res",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.res",
]
description = "RC {{output}}"
}
@@ -117,7 +117,7 @@
command = "$python_path $tool_wrapper_path asm-wrapper $env $ml $x64 {{defines}} {{include_dirs}} {{asmflags}} /c /Fo {{output}} {{source}}"
description = "ASM {{output}}"
outputs = [
- "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.obj",
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
]
}
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 4ad9e1d..5e8b62c 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -1491,7 +1491,8 @@
It is a static warning if a class has a setter named $v=$ with argument type $T$ and a getter named $v$ with return type $S$, and $T$ may not be assigned to $S$.
\LMHash{}
-It is a static warning if a class declares a static setter named $v=$ and also has a non-static member named $v$.
+It is a static warning if a class declares a static setter named $v=$ and has an instance getter named $v$.
+It is a static warning if a class declares a setter named $v=$ and has a method named $v$.
% We need not consider implicit declarations: If $v=$ is declared
% implicitly then there is a static variable $v$, and then it is
@@ -2171,6 +2172,7 @@
\LMHash{}
It is a static warning if a class $C$ declares a static method named $n$ and has a setter named $n=$.
+It is a static warning if a class $C$ declares a static member named $n$ and has an instance member named $n$.
\subsection{Static Variables}
diff --git a/docs/language/informal/extreme-upper-lower-bounds.md b/docs/language/informal/extreme-upper-lower-bounds.md
new file mode 100644
index 0000000..93babb8
--- /dev/null
+++ b/docs/language/informal/extreme-upper-lower-bounds.md
@@ -0,0 +1,254 @@
+# Feature Specification: Upper and Lower Bounds for Extreme Types
+
+**Owner**: eernst@
+
+**Status**: Under discussion.
+
+**Version**: 0.2 (2018-05-22)
+
+
+This document is a Dart 2 feature specification which specifies how to
+compute the standard upper bound and standard lower bound (`SUB` and `SLB`)
+of a pair of types when at least one of the operands is an extreme type:
+`Object`, `dynamic`, `void`, or `bottom`.
+
+
+## Motivation
+
+In order to motivate the rules for upper and lower bounds of a pair of
+types, we will focus on concrete examples that embody upper bounds very
+directly, namely conditional expressions, and extend that to lower bounds
+using functions.
+
+For example, can we use the result from the evaluation of `b ?
+print('Hello!') : 42`? In Dart 2, an expression with static type `void` is
+considered to have a value which is not valid, and it is a compile-time
+error to use it in most situations. When it is one of two possible branches
+in a conditional expression (here: `print('Hello!')`) we would expect to
+consider the whole value to be not valid, because otherwise we could
+receive the value of "the void branch" and thus inadvertently use a value
+which is not valid. Based on this kind of reasoning we have chosen to give
+expressions like `b ? print('Hello!') : 42` the type `void`.
+
+Similarly, can we do `(b ? 42 : f()).isEven` if `f` has return type
+`dynamic`? In this case the result from evaluating the conditional
+expression (`?:`) may have any type whatsoever, so `isEven` cannot be
+assumed to exist in the interface of that object. On the other hand,
+`isEven` could be safely invoked on the result from the branch `42`, and
+the other branch would admit arbitrary member access operations (such as
+`f().isEven`), even though there is no static evidence for the existence of
+any particular members (except for a few members which are declared in
+`Object` and hence inherited or overridden for every object). So you could
+say "it is OK for both branches, so it must be OK for the expression as a
+whole."
+
+Then how about `(b ? 42 : f()).fooBar()` where `f` is again assumed to have
+the return type `dynamic`? In this situation we would accept `f().fooBar()`
+because `dynamic` receivers admit all member accesses, but `42.fooBar()`
+would be rejected. Hence, we might say that "it is not OK for both
+branches, hence it is not OK for the conditional expression".
+
+We could give `b ? 42 : f()` the type `int`, which would allow us to accept
+`(b ? 42 : f()).isEven` and reject `(b ? 42 : f()).fooBar()`. This would
+effectively mean that `dynamic` would be considered to be a subtype of all
+other types during computations of upper and lower bounds.
+
+However, we consider that to be such a serious anomaly relative to the rest
+of the Dart 2 type system that we have not taken that approach.
+
+Instead, we have chosen to accept that a `dynamic` branch in a conditional
+expression will make the whole conditional expression dynamic.
+
+A set of situations with the opposite polarity arise when we consider types
+in a contravariant position, e.g., `b ? (T1 t1) => e1 : (T2 t2) => e2`,
+where we need to consider various combinations of types as the values of
+`T1` and `T2` in order to compute the type of the whole expression.
+
+Ignoring "voidness" and "dynamicness" for a moment and focusing on the pure
+subtyping relationships, we apply the _standard upper bound_ function to
+the types of the two branches in the former situation (like `b ? e1 : e2`),
+and for the latter situation (where an intervening function literal
+reverses the polarity, that is, the types in question occur in
+contravariant locations) we use the _standard lower bound_ function.
+
+These bound functions take exactly two arguments, so we may also call them
+'operators' and the arguments 'operands'. We call these functions
+'standard' rather than 'least' and 'greatest' because the Dart 2 type
+language cannot express a true least upper bound and greatest lower bound
+of all pairs of types, but it is still useful to choose an approximation
+thereof in many cases. We abbreviate the function names to `SUB` and `SLB`.
+
+As long as we are concerned with non-extreme types (everything except the
+top and bottom types), these bound functions deliver an approximation of
+the least upper bound and the greatest lower bound of its operands. For
+instance, `SUB(int, num)` is `num`, and `SLB(int, num)` is `int`, so we get
+the type `Object` for `b ? new Object() : 42`, and the type `num
+Function(int)` for `b ? (num n) => 41 : (int o) => 4.1`.
+
+This specification is concerned with combining the treatment of the pure
+subtyping related properties and the other properties like "dynamicness"
+and "voidness". We achieve that by means of a specification of the values
+of `SUB` and `SLB` when at least one of their operands is an extreme type.
+
+
+## Syntax
+
+The grammar is unaffected by this feature.
+
+
+## Static Analysis
+
+An _extreme type_ is one of the types `Object`, `dynamic`, `void`, and
+`bottom`.
+
+Consider a pair of types such that at least one of them is an extreme
+type. The value of the functions `SUB` and `SLB` on that pair of types is
+then determined by the following rules:
+
+```dart
+SUB(T, T) == T, for all T.
+SUB(S, T) == SUB(T, S), for all S, T.
+SUB(void, T) == void, for all T.
+SUB(dynamic, T) == dynamic, for all T != void.
+SUB(Object, T) == Object, for all T != void, dynamic.
+SUB(bottom, T) == T, for all T.
+
+SLB(T, T) == T, for all T.
+SLB(S, T) == SLB(T, S), for all S, T.
+SLB(void, T) == T, for all T.
+SLB(dynamic, T) == T, for all T != void.
+SLB(Object, T) == T, for all T != void, dynamic.
+SLB(bottom, T) == bottom, for all T.
+```
+
+*Note that this is the same outcome as we would have had if `Object` were a
+proper subtype of `dynamic` and `dynamic` were a proper subtype of
+`void`. Hence, an easy way to recall these rules would be to think `Object
+< dynamic < void`. Here, `<` is a "micro subtype" relationship which is
+able to distinguish between the top types, as opposed to the subtype
+relationship `<:` which considers the top types to be the same type. For
+any relationship involving a non-top type, `<` is the same thing as `<:`.*
+
+
+## Discussion
+
+We considered a different set of rules as well:
+
+```dart
+SUB(T, T) == T, for all T.
+SUB(S, T) == SUB(T, S), for all S, T.
+SUB(void, T) == void, for all T.
+SUB(dynamic, T) == Object, for all T != void, dynamic.
+SUB(Object, T) == Object, for all T != void.
+SUB(bottom, T) == T, for all T != dynamic.
+
+SLB(T, T) == T, for all T.
+SLB(S, T) == SLB(T, S), for all S, T.
+SLB(void, dynamic) == Object.
+SLB(void, T) == T, for all T != dynamic.
+SLB(dynamic, T) == T, for all T != void.
+SLB(Object, T) == T, for all T != void, dynamic.
+SLB(bottom, T) == bottom, for all T.
+```
+
+This set of rules cannot be reduced to any "micro subtype" relationship
+where we simply make a choice of how to order the top types and then get
+all other results as a consequence of that choice. These alternative rules
+are more strict on the propagation of "dynamicness" in a way which may be
+helpful for developers. Here is how it works:
+
+The 'Motivation' section mentioned a number of pragmatic reasons why it may
+be meaningful to let `SUB(dynamic, int)` be some other type than `dynamic`.
+
+If we take the stance that the relaxed type checks on member accesses that
+we apply to `dynamic` receivers are error-prone and hence shouldn't
+propagate very far implicitly, we may chose to eliminate the special
+treatment of `dynamic`, unless that type is present in all branches.
+
+This means that we would make the invocation `(b ? 42 : f()).isEven` a
+compile-time error: We could say that "it is not a dynamic invocation
+because some branches do not deliver a dynamic receiver, and there is no
+static guarantee that the `isEven` method exists, so the expression is a
+compile-time error". This is achieved by means of one of the rules shown
+above: `SUB(dynamic, T) == Object, for all T != void, dynamic`.
+
+In order to show that the alternative set of rules has an internal
+structure (as opposed to being a random mixture of decisions), we can
+describe them in the following manner. First we translate all types into a
+tuple-representation:
+
+```dart
+void (1, 1, 0)
+dynamic (1, 0, 1)
+Object (1, 0, 0)
+T (T, 0, 0), for all non-extreme types T
+bottom (0, 0, 0)
+```
+
+In this tuple, the first component is the core type (where "voidness" and
+"dynamicness" have been erased), where `0` is bottom, `1` is top (that is,
+the types `Object`, `dynamic`, and `void`), and every other (non-extreme)
+type is itself, e.g., `int` is `int`.
+
+The second component is the "voidness": `1` means that the type is a void
+type (there is only `void`), and `0` means non-void.
+
+The third component is the "dynamicness": `1` means that the type is
+dynamic (there is only `dynamic`, at least for now), and `0` means
+non-dynamic.
+
+This means that the tuple contains one "core type" and two "bits" (boolean
+components). With that, we can compute the functions using simple
+operations:
+
+```dart
+SUB((t1, v1, d1), (t2, v2, d2)) = (lub(t1,t2), v1 || v2, d1 && d2)
+SLB((t1, v1, d1), (t2, v2, d2)) = (glb(t1,t2), v1 && v2, d1 && d2)
+
+```
+
+We may also specify the same thing more concisely in a curried form:
+
+```dart
+SUB = (lub, lub, glb)
+SLB = (glb, glb, glb)
+```
+
+where `lub` and `glb` are specialized for the domain of types and booleans,
+respectively, but are basically "least upper bound" and "greatest lower
+bound": For types we rely on an underlying notion of upper and lower bounds
+for all non-extreme types, and for booleans it is simply the indicated
+operators above (`||` and `&&`, respectively).
+
+It may seem tempting, for symmetry, to change the definitions such that we
+get `SLB = (glb, glb, lub)`, but this would introduce types of the form
+`(T, 0, 1)`, that is, types like `dynamic(int)` and
+`dynamic(int Function(String))` that we have considered but not yet decided
+to introduce. Given that the only effect this change would have is to
+change some types in a contravariant location from `Object` to `dynamic`,
+and given that this is generally not detectable for clients (e.g., we don't
+care about, and actually can't even detect, the difference between calling
+a function of type `int Function(Object)` and a function of type `int
+Function(dynamic)`), so this choice is not likely to matter much. Also the
+fact that the use of `min` yields fewer occurrences of the type `dynamic`
+seems to be consistent with the nature of Dart 2 typing.
+
+Note that the operations are reflexive and symmetric by construction, and
+they are also likely to be associative, because both `lub` and `glb` are
+associative for booleans, and for types we will need to consider the actual
+underlying mechanism, but it ought to be associative if at all possible:
+
+```dart
+lub(lub(a,b),c) = lub(a,lub(b,c))
+glb(glb(a,b),c) = glb(a,glb(b,c))
+```
+
+## Updates
+
+* May 22nd 2018, version 0.2: Adjusted to use `Object < dynamic < void`
+ as a "subtyping micro-structure" (which produces a simpler set of
+ rules) and mention the rules from version 0.1 merely as a possible
+ alternative ruleset.
+
+* May 1st 2018, version 0.1: Initial version of this feature
+ specification created, based on discussions in SDK issue 28513.
diff --git a/docs/language/informal/instantiate-to-bound.md b/docs/language/informal/instantiate-to-bound.md
index d182dcb..091c507 100644
--- a/docs/language/informal/instantiate-to-bound.md
+++ b/docs/language/informal/instantiate-to-bound.md
@@ -2,7 +2,7 @@
**Author**: eernst@
-**Version**: 0.5 (2018-01-11)
+**Version**: 0.7 (2018-02-26)
**Status**: Under implementation.
@@ -191,40 +191,41 @@
on, every type variable in its bound, possibly including itself*).
Let _==><sub>m</sub>_ be the transitive closure of _--><sub>m</sub>_.
For each _m_, let _U<sub>i,m+1</sub>_, for _i_ in _1 .. k_, be determined
-as follows:
+by the following iterative process:
-- Let _j_ be the lowest number such that
- _X<sub>j</sub> ==><sub>m</sub> X<sub>j</sub>_ (*that is, such that this
- type variable is a member of a dependency cycle*).
- Let _{Y<sub>1</sub> .. Y<sub>p</sub>}_ be the the maximal subset
- containing _X<sub>j</sub>_ of _{X<sub>1</sub> .. X<sub>k</sub>}_ where
- every pair is related: _Y<sub>q</sub> ==><sub>m</sub> Y<sub>r</sub>_, for
- all _q, r_ in _1 .. p_ (*i.e., this subset is a strongly connected
- component in the dependency graph containing _X<sub>j</sub>_*).
- Then _U<sub>i,m+1</sub>_ is the result of substituting, in
- _U<sub>i,m</sub>_, `Null` for every contravariant occurrence
- of _X<sub>j</sub>_, and `dynamic` for every covariant occurrence of
- _X<sub>j</sub>_, for all _i_ in _1 .. k_ such that _X<sub>i</sub>_ is a
- member of _{Y<sub>1</sub> .. Y<sub>p</sub>}_; and _U<sub>i,m+1</sub>_ is
- _U<sub>i,m</sub>_, for all other _i_ in _1 .. k_.
- *That is, we update the bounds of type variables in the dependency cycle
- such that the type variables in the dependency cycle are replaced by
- `Null` or `dynamic`, depending on the variance of the location.*
+1. If there exists a _j_ in _1 .. k_ such that
+ _X<sub>j</sub> ==><sub>m</sub> X<sub>j</sub>_
+ (*that is, if the dependency graph has a cycle*)
+ let _M<sub>1</sub> .. M<sub>p</sub>_ be the strongly connected components
+ (SCCs) with respect to _--><sub>m</sub>_
+ (*that is, the maximal subsets of _X<sub>1</sub> .. X<sub>k</sub>_
+ where every pair of variables in each subset are related in both directions
+ by _==><sub>m</sub>_; note that the SCCs are pairwise disjoint; also, they
+ are uniquely defined up to reordering, and the order does not matter*).
+ Let _M_ be the union of _M<sub>1</sub> .. M<sub>p</sub>_
+ (*that is, all variables that participate in a dependency cycle*).
+ Let _i_ be in _1 .. k_.
+ If _X<sub>i</sub>_ does not belong to _M_ then
+ _U<sub>i,m+1</sub> = U<sub>i,m</sub>_.
+ Otherwise there exists a _q_ such that _X<sub>i</sub>_ belongs to
+ _M<sub>q</sub>_; _U<sub>i,m+1</sub>_ is then obtained from _U<sub>i,m</sub>_
+ by replacing every covariant occurrence of a variable in _M<sub>q</sub>_ by
+ `dynamic`, and replacing every contravariant occurence of a variable in
+ _M<sub>q</sub>_ by `Null`.
-- Otherwise, (*if no such dependency cycle exists*) let _j_ be the
- lowest number such that _X<sub>j</sub>_ occurs in
- _U<sub>p,m</sub>_ for some _p_ and
- _X<sub>j</sub> -/-><sub>m</sub> X<sub>q</sub>_ for all _q_ in _1..k_
- (*that is, _U<sub>j,m</sub>_ is closed, that is, the current bound of
- _X<sub>j</sub>_ does not depend on any other type variables; but
- _X<sub>j</sub>_ is being depended on by the bounds of some other type
- variables*). Then _U<sub>i,m+1</sub>_ is the result of substituting, in
- _U<sub>i,m</sub>_, `Null` for every contravariant occurrence
- of _X<sub>j</sub>_, and _U<sub>j,m</sub>_ for every covariant occurrence
- of _X<sub>j</sub>_, for all _i_ in _1 .. k_.
+2. Otherwise, (*if no dependency cycle exists*) let _j_ be the lowest number
+ such that _X<sub>j</sub>_ occurs in _U<sub>p,m</sub>_ for some _p_ and
+ _X<sub>j</sub> -/-><sub>m</sub> X<sub>q</sub>_ for all _q_ in _1..k_
+ (*that is, _U<sub>j,m</sub>_ is closed, that is, the current bound of
+ _X<sub>j</sub>_ does not contain any type variables; but _X<sub>j</sub>_ is
+ being depended on by the bound of some other type variable*).
+ Then, for all _i_ in _1 .. k_, _U<sub>i,m+1</sub>_ is obtained from
+ _U<sub>i,m</sub>_ by replacing every covariant occurrence of _X<sub>j</sub>_
+ by _U<sub>j,m</sub>_, and replacing every contravariant occurrence of
+ _X<sub>j</sub>_ by `Null`.
-- Otherwise, (*when no dependencies exist*) terminate with the result
- _<U<sub>1,m</sub> ..., U<sub>k,m</sub>>_.
+3. Otherwise, (*when no dependencies exist*) terminate with the result
+ _<U<sub>1,m</sub> ..., U<sub>k,m</sub>>_.
*This process will always terminate, because the total number of
occurrences of type variables from _{X<sub>1</sub> .. X<sub>k</sub>}_ in
@@ -259,6 +260,13 @@
## Updates
+* Feb 26th 2018, version 0.7: Revised cycle breaking algorithm for
+ F-bounded type variables to avoid specifying orderings that do not matter.
+
+* Feb 22nd 2018, version 0.6: Revised cycle breaking algorithm for
+ F-bounded type variables to replace all members by an extreme type, not
+ just one of them.
+
* Jan 11th 2018, version 0.5: Revised treatment of variance based on
strongly connected components in the dependency graph.
diff --git a/docs/language/informal/super-bounded-types.md b/docs/language/informal/super-bounded-types.md
index db2e46c..b7d19da 100644
--- a/docs/language/informal/super-bounded-types.md
+++ b/docs/language/informal/super-bounded-types.md
@@ -2,7 +2,7 @@
**Author**: eernst@.
-**Version**: 0.5 (2018-01-11).
+**Version**: 0.6 (2018-05-25).
**Status**: Under implementation.
@@ -348,6 +348,51 @@
`void Function(A<Object>)` is well-bounded because `A<Object>` is
super-bounded.*
+*Note that it is necessary to require that the right hand side of a type
+alias declaration is taken into account when determining that a given
+application of a type alias to an actual type argument list is correctly
+super-bounded. That is, we do not think that it is possible for a
+(reasonable) constraint specification mechanism on the formal type
+parameters of a type alias declaration to ensure that all arguments
+satisfying those constraints will also be suitable for the type on the
+right hand side. In particular, we may use simple upper bounds and
+F-bounded constraints (as we have always done), perform and pass the
+'correctly super-bounded' check on a given parameterized type based on a
+type alias, and still have a right hand side which is not well-bounded:*
+```dart
+class B<X extends List<num>> {}
+typedef H<Y extends num> = void Function(B<List<Y>>);
+typedef K<Y extends num> = B<List<Y>> Function(B<List<Y>>);
+
+H<Object> myH = null; // Error!
+```
+*`H<Object>` is a compile-time error because it is not regular-bounded
+(`Object <: num` does not hold), and it is also not correctly
+super-bounded: `Null` does satisfy the constraint in the declaration of
+`Y`, but `H<Object>` gives rise to the right hand side
+`void Function(B<List<Object>>)`, and that is not a well-bounded type:
+It is not regular-bounded (`List<Object> <: List<num>` does not hold),
+and it does not become a regular-bounded type by the type replacements
+(that yield `void Function(B<List<Object>>)` because that occurrence of
+`Object` is contravariant).*
+
+*Semantically, this failure may be motivated by the fact that `H<Object>`,
+were it allowed, would not be a supertype of `H<T>` for all the `T` where
+`H<T>` is regular-bounded. So it would not be capable of playing the role
+as a "default type" that abstracts over all the possible actual types that
+are expressible using `H`. For example, a variable declared like
+`List<H<Object>> x;` would not be allowed to hold a value of type
+`List<H<num>>` because the latter is not a subtype of the former.*
+
+*In the given situation it is possible to express such a default type:
+`H<Null>` is actually a common supertype of `H<T>` for all `T` such that
+`H<T>` is regular-bounded. However, `K` shows that this is not always the
+case: There is no type `S` such that `K<S>` is a common supertype of `K<T>`
+for all those `T` where `K<T>` is regular-bounded. Facing this situation,
+we prefer to bail out rather than implicitly allow some kind of
+super-bounded type (assuming that we amend the rules such that it is not an
+error) which would not abstract over all possible instantiations anyway.*
+
*The subtype relations for super-bounded types follow directly from the
extension of generic covariance to include actual type arguments that
violate the declared bounds. For the example in the Motivation section, `D`
@@ -535,6 +580,9 @@
## Updates
+* Version 0.6 (2018-05-25), added example showing why we must check the
+ right hand side of type aliases.
+
* Version 0.5 (2018-01-11), generalized to allow replacement of top types
covariantly and bottom types contravariantly. Introduced checks on
parameterized type aliases (such that bounds declared for the type
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart
index e0af23c..082517d 100644
--- a/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart
+++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart
@@ -49,6 +49,11 @@
*/
Fix(this.kind, this.change);
+ /**
+ * Returns `true` if this fix is the union of multiple fixes.
+ */
+ bool isFixAllFix() => change.message == kind.appliedTogetherMessage;
+
@override
String toString() {
return 'Fix(kind=$kind, change=$change)';
@@ -72,6 +77,12 @@
AnalysisError get error;
/**
+ * All of the errors in the file. This is used to compute additional fixes
+ * such "Fix all instances in file."
+ */
+ List<AnalysisError> get errors;
+
+ /**
* The [ResourceProvider] to access files and folders.
*/
ResourceProvider get resourceProvider;
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index 96432aa..4979f1e 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -413,7 +413,12 @@
@override
visitMethodInvocation(MethodInvocation node) {
SimpleIdentifier nameNode = node.methodName;
- engine.ExecutableElement executableElement = nameNode.bestElement;
+
+ engine.Element nameElement = nameNode.bestElement;
+ if (nameElement is! engine.ExecutableElement) {
+ return;
+ }
+ engine.ExecutableElement executableElement = nameElement;
String extractString(NodeList<Expression> arguments) {
if (arguments != null && arguments.length > 0) {
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index db27347..05d4310 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -1129,8 +1129,9 @@
pathContext.isWithin(includedPath, excludedPath))
.toList();
processOptionsForDriver(info, options, optionMap);
- ContextRoot contextRoot =
- new ContextRoot(pathContext, folder.path, containedExcludedPaths);
+ ContextRoot contextRoot = new ContextRoot(
+ folder.path, containedExcludedPaths,
+ pathContext: pathContext);
if (optionsFile != null) {
contextRoot.optionsFilePath = optionsFile.path;
}
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 1af301c..86e8dce 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -526,12 +526,18 @@
CompilationUnit unit = result.unit;
LineInfo lineInfo = result.lineInfo;
int requestLine = lineInfo.getLocation(offset).lineNumber;
+ List<engine.AnalysisError> errorsCopy = new List.from(result.errors);
for (engine.AnalysisError error in result.errors) {
int errorLine = lineInfo.getLocation(error.offset).lineNumber;
if (errorLine == requestLine) {
AstProvider astProvider = new AstProviderForDriver(driver);
DartFixContext context = new _DartFixContextImpl(
- server.resourceProvider, result.driver, astProvider, unit, error);
+ server.resourceProvider,
+ result.driver,
+ astProvider,
+ unit,
+ error,
+ errorsCopy);
List<Fix> fixes =
await new DefaultFixContributor().internalComputeFixes(context);
if (fixes.isNotEmpty) {
@@ -679,8 +685,11 @@
@override
final engine.AnalysisError error;
+ @override
+ final List<engine.AnalysisError> errors;
+
_DartFixContextImpl(this.resourceProvider, this.analysisDriver,
- this.astProvider, this.unit, this.error);
+ this.astProvider, this.unit, this.error, this.errors);
@override
GetTopLevelDeclarations get getTopLevelDeclarations =>
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index cdcdc36..9603adb 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -212,8 +212,9 @@
const FixKind('REMOVE_UNUSED_CATCH', 50, "Remove unused 'catch' clause");
static const REMOVE_UNUSED_CATCH_STACK = const FixKind(
'REMOVE_UNUSED_CATCH_STACK', 50, "Remove unused stack trace variable");
- static const REMOVE_UNUSED_IMPORT =
- const FixKind('REMOVE_UNUSED_IMPORT', 50, "Remove unused import");
+ static const REMOVE_UNUSED_IMPORT = const FixKind(
+ 'REMOVE_UNUSED_IMPORT', 50, "Remove unused import",
+ appliedTogetherMessage: "Remove all unused imports in this file");
static const RENAME_TO_CAMEL_CASE =
const FixKind('RENAME_TO_CAMEL_CASE', 50, "Rename to '{0}'");
static const REPLACE_BOOLEAN_WITH_BOOL = const FixKind(
@@ -266,10 +267,15 @@
@override
final AnalysisError error;
- FixContextImpl(this.resourceProvider, this.analysisDriver, this.error);
+ @override
+ final List<AnalysisError> errors;
+
+ FixContextImpl(
+ this.resourceProvider, this.analysisDriver, this.error, this.errors);
FixContextImpl.from(FixContext other)
: resourceProvider = other.resourceProvider,
analysisDriver = other.analysisDriver,
- error = other.error;
+ error = other.error,
+ errors = other.errors;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 3df2168..da9de25 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -84,11 +84,97 @@
try {
FixProcessor processor = new FixProcessor(context);
List<Fix> fixes = await processor.compute();
- return fixes;
+ List<Fix> fixAllFixes = await _computeFixAllFixes(context, fixes);
+ return new List.from(fixes)..addAll(fixAllFixes);
} on CancelCorrectionException {
return Fix.EMPTY_LIST;
}
}
+
+ Future<List<Fix>> _computeFixAllFixes(
+ DartFixContext context, List<Fix> fixes) async {
+ final AnalysisError analysisError = context.error;
+ final List<AnalysisError> allAnalysisErrors = context.errors;
+
+ // Validate inputs:
+ // - return if no fixes
+ // - return if no other analysis errors
+ if (fixes.isEmpty || allAnalysisErrors.length < 2) {
+ return Fix.EMPTY_LIST;
+ }
+
+ // Remove any analysis errors that don't have the expected error code name
+ allAnalysisErrors
+ .removeWhere((e) => analysisError.errorCode.name != e.errorCode.name);
+ if (allAnalysisErrors.length < 2) {
+ return Fix.EMPTY_LIST;
+ }
+
+ // A map between each FixKind and the List of associated fixes
+ final HashMap<FixKind, List<Fix>> map = new HashMap();
+
+ // Populate the HashMap by looping through all AnalysisErrors, creating a
+ // new FixProcessor to compute the other fixes that can be applied with this
+ // one.
+ // For each fix, put the fix into the HashMap.
+ for (int i = 0; i < allAnalysisErrors.length; i++) {
+ final FixContext fixContextI = new FixContextImpl(
+ context.resourceProvider,
+ context.analysisDriver,
+ allAnalysisErrors[i],
+ allAnalysisErrors);
+ final DartFixContextImpl dartFixContextI = new DartFixContextImpl(
+ fixContextI, context.astProvider, context.unit);
+ final FixProcessor processorI = new FixProcessor(dartFixContextI);
+ final List<Fix> fixesListI = await processorI.compute();
+ for (Fix f in fixesListI) {
+ if (!map.containsKey(f.kind)) {
+ map[f.kind] = new List<Fix>()..add(f);
+ } else {
+ map[f.kind].add(f);
+ }
+ }
+ }
+
+ // For each FixKind in the HashMap, union each list together, then return
+ // the set of unioned Fixes.
+ final List<Fix> result = new List<Fix>();
+ map.forEach((FixKind kind, List<Fix> fixesListJ) {
+ if (fixesListJ.first.kind.canBeAppliedTogether()) {
+ Fix unionFix = _unionFixList(fixesListJ);
+ if (unionFix != null) {
+ result.add(unionFix);
+ }
+ }
+ });
+ return result;
+ }
+
+ Fix _unionFixList(List<Fix> fixList) {
+ if (fixList == null || fixList.isEmpty) {
+ return null;
+ } else if (fixList.length == 1) {
+ return fixList[0];
+ }
+ final SourceChange sourceChange =
+ new SourceChange(fixList[0].kind.appliedTogetherMessage);
+ sourceChange.edits = new List.from(fixList[0].change.edits);
+ final List<SourceEdit> edits = new List<SourceEdit>();
+ edits.addAll(fixList[0].change.edits[0].edits);
+ sourceChange.linkedEditGroups =
+ new List.from(fixList[0].change.linkedEditGroups);
+ for (int i = 1; i < fixList.length; i++) {
+ edits.addAll(fixList[i].change.edits[0].edits);
+ sourceChange.linkedEditGroups..addAll(fixList[i].change.linkedEditGroups);
+ }
+ // Sort the list of SourceEdits so that when the edits are applied, they
+ // are applied from the end of the file to the top of the file.
+ edits.sort((s1, s2) => s2.offset - s1.offset);
+
+ sourceChange.edits[0].edits = edits;
+
+ return new Fix(fixList[0].kind, sourceChange);
+ }
}
/**
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 8060d58..f4b1cc7 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -137,8 +137,8 @@
resourceProvider,
new MemoryByteStore(),
fileContentOverlay,
- new ContextRoot(resourceProvider.pathContext,
- resourceProvider.convertPath('/project'), []),
+ new ContextRoot(resourceProvider.convertPath('/project'), [],
+ pathContext: resourceProvider.pathContext),
sourceFactory,
new AnalysisOptionsImpl()..strongMode = true);
scheduler.start();
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 62b0d84..dbd1ee2 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -100,6 +100,27 @@
await _assertNoFix(kind, error);
}
+ assertHasFixAllFix(ErrorCode errorCode, FixKind kind, String expected,
+ {String target}) async {
+ AnalysisError error = await _findErrorToFixOfType(errorCode);
+ fix = await _assertHasFix(kind, error, hasFixAllFix: true);
+ change = fix.change;
+
+ // apply to "file"
+ List<SourceFileEdit> fileEdits = change.edits;
+ expect(fileEdits, hasLength(1));
+
+ String fileContent = testCode;
+ if (target != null) {
+ expect(fileEdits.first.file, convertPath(target));
+ fileContent = getFile(target).readAsStringSync();
+ }
+
+ resultCode = SourceEdit.applySequence(fileContent, change.edits[0].edits);
+ // verify
+ expect(resultCode, expected);
+ }
+
List<LinkedEditSuggestion> expectedSuggestions(
LinkedEditSuggestionKind kind, List<String> values) {
return values.map((value) {
@@ -115,14 +136,53 @@
/**
* Computes fixes and verifies that there is a fix of the given kind.
*/
- Future<Fix> _assertHasFix(FixKind kind, AnalysisError error) async {
- List<Fix> fixes = await _computeFixes(error);
- for (Fix fix in fixes) {
- if (fix.kind == kind) {
- return fix;
+ Future<Fix> _assertHasFix(FixKind kind, AnalysisError error,
+ {bool hasFixAllFix: false}) async {
+ if (hasFixAllFix && !kind.canBeAppliedTogether()) {
+ fail(
+ 'Expected to find and return fix-all FixKind for $kind, but kind.canBeAppliedTogether is ${kind.canBeAppliedTogether}');
+ }
+
+ // Compute the fixes for this AnalysisError
+ final List<Fix> fixes = await _computeFixes(error);
+
+ // If hasFixAllFix is false, assert that none of the fixes are a fix-all fix
+ if (!hasFixAllFix) {
+ for (Fix f in fixes) {
+ if (f.isFixAllFix()) {
+ fail("The boolean hasFixAllFix is false, but such a fix was found in "
+ "the computed set of fixes: $fixes, error: $error.");
+ }
}
}
- fail('Expected to find fix $kind in\n${fixes.join('\n')}');
+ // If hasFixAllFix is true, assert that there exists such a fix in the list
+ else {
+ bool foundFixAllFix = false;
+ for (Fix f in fixes) {
+ if (f.isFixAllFix()) {
+ foundFixAllFix = true;
+ break;
+ }
+ }
+ if (!foundFixAllFix) {
+ fail("The boolean hasFixAllFix is true, but no fix-all fix was found "
+ "in the computed set of fixes: $fixes, error: $error.");
+ }
+ }
+
+ Fix foundFix = null;
+ if (!hasFixAllFix) {
+ foundFix =
+ fixes.firstWhere((fix) => fix.kind == kind && !fix.isFixAllFix());
+ } else {
+ foundFix =
+ fixes.lastWhere((fix) => fix.kind == kind && fix.isFixAllFix());
+ }
+ if (foundFix == null) {
+ fail('Expected to find fix $kind in\n${fixes.join('\n')}, hasFixAllFix = '
+ '$hasFixAllFix');
+ }
+ return foundFix;
}
void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings,
@@ -151,8 +211,13 @@
* Computes fixes for the given [error] in [testUnit].
*/
Future<List<Fix>> _computeFixes(AnalysisError error) async {
- DartFixContext fixContext = new _DartFixContextImpl(resourceProvider,
- driver, new AstProviderForDriver(driver), testUnit, error);
+ DartFixContext fixContext = new _DartFixContextImpl(
+ resourceProvider,
+ driver,
+ new AstProviderForDriver(driver),
+ testUnit,
+ error,
+ await _computeErrors());
return await new DefaultFixContributor().internalComputeFixes(fixContext);
}
@@ -189,6 +254,14 @@
return errors[0];
}
+ Future<AnalysisError> _findErrorToFixOfType(ErrorCode errorCode) async {
+ List<AnalysisError> errors = await _computeErrors();
+ if (errorFilter != null) {
+ errors = errors.where(errorFilter).toList();
+ }
+ return errors.firstWhere((error) => errorCode == error.errorCode);
+ }
+
List<Position> _findResultPositions(List<String> searchStrings) {
List<Position> positions = <Position>[];
for (String search in searchStrings) {
@@ -5119,6 +5192,71 @@
''');
}
+ test_removeUnusedImport_all() async {
+ await resolveTestUnit('''
+import 'dart:math';
+import 'dart:math';
+import 'dart:math';
+main() {
+}
+''');
+ await assertHasFixAllFix(
+ HintCode.UNUSED_IMPORT, DartFixKind.REMOVE_UNUSED_IMPORT, '''
+main() {
+}
+''');
+ }
+
+ test_removeUnusedImport_all_diverseImports() async {
+ await resolveTestUnit('''
+import 'dart:math';
+import 'dart:math';
+import 'dart:async';
+main() {
+}
+''');
+ await assertHasFixAllFix(
+ HintCode.UNUSED_IMPORT, DartFixKind.REMOVE_UNUSED_IMPORT, '''
+main() {
+}
+''');
+ }
+
+ test_removeUnusedImport_all_diverseImports2() async {
+ await resolveTestUnit('''
+import 'dart:async';
+import 'dart:math' as math;
+import 'dart:async';
+
+var tau = math.pi * 2;
+
+main() {
+}
+''');
+ await assertHasFixAllFix(
+ HintCode.UNUSED_IMPORT, DartFixKind.REMOVE_UNUSED_IMPORT, '''
+import 'dart:math' as math;
+
+var tau = math.pi * 2;
+
+main() {
+}
+''');
+ }
+
+ test_removeUnusedImport_all_singleLine() async {
+ await resolveTestUnit('''
+import 'dart:math'; import 'dart:math'; import 'dart:math';
+main() {
+}
+''');
+ await assertHasFixAllFix(
+ HintCode.UNUSED_IMPORT, DartFixKind.REMOVE_UNUSED_IMPORT, '''
+main() {
+}
+''');
+ }
+
test_replaceVarWithDynamic() async {
errorFilter = (AnalysisError error) {
return error.errorCode == ParserErrorCode.VAR_AS_TYPE_NAME;
@@ -7923,8 +8061,11 @@
@override
final AnalysisError error;
+ @override
+ final List<AnalysisError> errors;
+
_DartFixContextImpl(this.resourceProvider, this.analysisDriver,
- this.astProvider, this.unit, this.error);
+ this.astProvider, this.unit, this.error, this.errors);
@override
GetTopLevelDeclarations get getTopLevelDeclarations =>
diff --git a/pkg/analysis_server/test/src/computer/outline_computer_test.dart b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
index 67e9b9b..23079a7 100644
--- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -546,6 +546,20 @@
expect(outline, isNotNull);
}
+ /**
+ * Code like this caused Dart2 failure in the past.
+ *
+ * https://github.com/dart-lang/sdk/issues/33228
+ */
+ test_invocation_ofParameter() async {
+ Outline outline = await _computeOutline('''
+main(p()) {
+ p();
+}
+''');
+ expect(outline, isNotNull);
+ }
+
test_isTest_isTestGroup() async {
addMetaPackageSource();
Outline outline = await _computeOutline('''
diff --git a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
index 5fd654d..f5cb609 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
@@ -34,7 +34,7 @@
}
ContextRoot _newContextRoot(String root, {List<String> exclude: const []}) {
- return new ContextRoot(path.context, root, exclude);
+ return new ContextRoot(root, exclude, pathContext: path.context);
}
@reflectiveTest
diff --git a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
index 0951011..694d46e 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
@@ -50,8 +50,8 @@
newFile(
'/pkg2/${PluginLocator.toolsFolderName}/${PluginLocator.defaultPluginFolderName}/bin/plugin.dart');
- ContextRoot contextRoot =
- new ContextRoot(resourceProvider.pathContext, pkg1Path, []);
+ ContextRoot contextRoot = new ContextRoot(pkg1Path, [],
+ pathContext: resourceProvider.pathContext);
TestDriver driver = new TestDriver(resourceProvider, contextRoot);
driver.analysisOptions.enabledPluginNames = ['pkg2'];
watcher.addedDriver(driver, contextRoot);
@@ -80,8 +80,8 @@
String pkg1Path = newFolder('/pkg1').path;
newFile('/pkg1/lib/test1.dart');
- ContextRoot contextRoot =
- new ContextRoot(resourceProvider.pathContext, pkg1Path, []);
+ ContextRoot contextRoot = new ContextRoot(pkg1Path, [],
+ pathContext: resourceProvider.pathContext);
TestDriver driver = new TestDriver(resourceProvider, contextRoot);
driver.analysisOptions.enabledPluginNames = ['pkg3'];
watcher.addedDriver(driver, contextRoot);
@@ -102,8 +102,8 @@
test_removedDriver() {
String pkg1Path = newFolder('/pkg1').path;
- ContextRoot contextRoot =
- new ContextRoot(resourceProvider.pathContext, pkg1Path, []);
+ ContextRoot contextRoot = new ContextRoot(pkg1Path, [],
+ pathContext: resourceProvider.pathContext);
TestDriver driver = new TestDriver(resourceProvider, contextRoot);
watcher.addedDriver(driver, contextRoot);
watcher.removedDriver(driver);
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 8d9ed60..92c46dc 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,14 @@
+## 0.32.1-alpha.0
+
+* Add the ability to specify a pathContext when creating a ContextRoot (not part
+ of the officially supported API, but needed by some clients).
+* AnalysisSession now exports resourceProvider.
+* Function type parameters are now invariant. (#29014)
+* New logic to find source files generated by package:build when that build
+ system is detected.
+* Data stored by FileDataStore is now checked using CRC32.
+* Add ability for the angular plugin to set ErrorVerifier.enclosingClass.
+
## 0.32.0
* Allow annotations on enum constants.
diff --git a/pkg/analyzer/lib/src/context/context_root.dart b/pkg/analyzer/lib/src/context/context_root.dart
index 1c32428..ebb208b7 100644
--- a/pkg/analyzer/lib/src/context/context_root.dart
+++ b/pkg/analyzer/lib/src/context/context_root.dart
@@ -38,7 +38,8 @@
/**
* Initialize a newly created context root.
*/
- ContextRoot(this.pathContext, this.root, this.exclude);
+ ContextRoot(this.root, this.exclude, {path.Context pathContext})
+ : pathContext = pathContext ?? path.context;
@override
int get hashCode {
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index 2d54d53..bf4d9ba 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -80,9 +80,8 @@
builder.performanceLog = performanceLog;
old.ContextRoot oldContextRoot = new old.ContextRoot(
- resourceProvider.pathContext,
- contextRoot.root.path,
- contextRoot.excludedPaths.toList());
+ contextRoot.root.path, contextRoot.excludedPaths.toList(),
+ pathContext: resourceProvider.pathContext);
AnalysisDriver driver = builder.buildDriver(oldContextRoot);
DriverBasedAnalysisContext context =
new DriverBasedAnalysisContext(resourceProvider, contextRoot, driver);
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index 5d290be..5f36fcb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -101,9 +101,8 @@
List<AnalysisContext> contextList = <AnalysisContext>[];
for (ContextRoot root in roots) {
old.ContextRoot contextRoot = new old.ContextRoot(
- resourceProvider.pathContext,
- root.root.path,
- root.excludedPaths.toList());
+ root.root.path, root.excludedPaths.toList(),
+ pathContext: resourceProvider.pathContext);
AnalysisDriver driver = builder.buildDriver(contextRoot);
DriverBasedAnalysisContext context =
new DriverBasedAnalysisContext(resourceProvider, root, driver);
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 0d4084c..0563ff8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -95,7 +95,7 @@
/**
* The version of data format, should be incremented on every format change.
*/
- static const int DATA_VERSION = 59;
+ static const int DATA_VERSION = 60;
/**
* The number of exception contexts allowed to write. Once this field is
@@ -201,6 +201,13 @@
final _requestedFiles = <String, List<Completer<AnalysisResult>>>{};
/**
+ * The task that discovers available files. If this field is not `null`,
+ * and the task is not completed, it should be performed and completed
+ * before any name searching task.
+ */
+ _DiscoverAvailableFilesTask _discoverAvailableFilesTask;
+
+ /**
* The list of tasks to compute files defining a class member name.
*/
final _definingClassMemberNameTasks = <_FilesDefiningClassMemberNameTask>[];
@@ -478,6 +485,10 @@
if (_requestedFiles.isNotEmpty) {
return AnalysisDriverPriority.interactive;
}
+ if (_discoverAvailableFilesTask != null &&
+ !_discoverAvailableFilesTask.isCompleted) {
+ return AnalysisDriverPriority.interactive;
+ }
if (_definingClassMemberNameTasks.isNotEmpty ||
_referencingNameTasks.isNotEmpty) {
return AnalysisDriverPriority.interactive;
@@ -650,6 +661,7 @@
* define a class member with the given [name].
*/
Future<List<String>> getFilesDefiningClassMemberName(String name) {
+ _discoverAvailableFiles();
var task = new _FilesDefiningClassMemberNameTask(this, name);
_definingClassMemberNameTasks.add(task);
_scheduler.notify(this);
@@ -661,6 +673,7 @@
* reference the given external [name].
*/
Future<List<String>> getFilesReferencingName(String name) {
+ _discoverAvailableFiles();
var task = new _FilesReferencingNameTask(this, name);
_referencingNameTasks.add(task);
_scheduler.notify(this);
@@ -793,6 +806,7 @@
*/
Future<List<TopLevelDeclarationInSource>> getTopLevelNameDeclarations(
String name) {
+ _discoverAvailableFiles();
var task = new _TopLevelNameDeclarationsTask(this, name);
_topLevelNameDeclarationsTasks.add(task);
_scheduler.notify(this);
@@ -967,6 +981,13 @@
return;
}
+ // Discover available files.
+ if (_discoverAvailableFilesTask != null &&
+ !_discoverAvailableFilesTask.isCompleted) {
+ _discoverAvailableFilesTask.perform();
+ return;
+ }
+
// Compute files defining a name.
if (_definingClassMemberNameTasks.isNotEmpty) {
_FilesDefiningClassMemberNameTask task =
@@ -1417,6 +1438,14 @@
}
/**
+ * If this has not been done yet, schedule discovery of all files that are
+ * potentially available, so that they are included in [knownFiles].
+ */
+ void _discoverAvailableFiles() {
+ _discoverAvailableFilesTask ??= new _DiscoverAvailableFilesTask(this);
+ }
+
+ /**
* Fill [_salt] with data.
*/
void _fillSalt() {
@@ -2223,6 +2252,79 @@
}
/**
+ * Task that discovers all files that are available to the driver, and makes
+ * them known.
+ */
+class _DiscoverAvailableFilesTask {
+ static const int _MS_WORK_INTERVAL = 5;
+
+ final AnalysisDriver driver;
+
+ bool isCompleted = false;
+
+ Iterator<Folder> folderIterator;
+ List<String> files;
+ int fileIndex = 0;
+
+ _DiscoverAvailableFilesTask(this.driver);
+
+ /**
+ * Perform the next piece of work, and set [isCompleted] to `true` to
+ * indicate that the task is done, or keeps it `false` to indicate that the
+ * task should continue to be run.
+ */
+ void perform() {
+ // Prepare the iterator of package/lib folders.
+ if (folderIterator == null) {
+ var packageMap = driver._sourceFactory.packageMap;
+ if (packageMap != null) {
+ folderIterator = packageMap.values.expand((f) => f).iterator;
+ files = <String>[];
+ } else {
+ isCompleted = true;
+ return;
+ }
+ }
+
+ // List each package/lib folder recursively.
+ Stopwatch timer = new Stopwatch()..start();
+ while (folderIterator.moveNext()) {
+ if (timer.elapsedMilliseconds > _MS_WORK_INTERVAL) {
+ return;
+ }
+ var folder = folderIterator.current;
+ _appendFilesRecursively(folder);
+ }
+
+ // Get know files one by one.
+ while (fileIndex < files.length) {
+ if (timer.elapsedMilliseconds > _MS_WORK_INTERVAL) {
+ return;
+ }
+ var file = files[fileIndex++];
+ driver._fsState.getFileForPath(file);
+ }
+
+ // The task is done, clean up.
+ isCompleted = true;
+ folderIterator = null;
+ files = null;
+ }
+
+ void _appendFilesRecursively(Folder folder) {
+ try {
+ for (var child in folder.getChildren()) {
+ if (child is File) {
+ files.add(child.path);
+ } else if (child is Folder) {
+ _appendFilesRecursively(child);
+ }
+ }
+ } catch (_) {}
+ }
+}
+
+/**
* Information about an exception and its context.
*/
class _ExceptionState {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index ac82f5f..822d245 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1281,7 +1281,7 @@
if (_kernel.mixedInType != null) {
_kernelMixins.add(_kernel.mixedInType);
}
- while (supertype.classNode.isSyntheticMixinImplementation) {
+ while (supertype.classNode.isAnonymousMixin) {
var superNode = supertype.classNode;
var substitute = kernel.Substitution.fromSupertype(supertype);
@@ -1855,7 +1855,7 @@
List<ClassElement> get types {
if (_kernelContext != null) {
_types ??= _kernelContext.kernelUnit.classes
- .where((k) => !k.isEnum && !k.isSyntheticMixinImplementation)
+ .where((k) => !k.isEnum && !k.isAnonymousMixin)
.map((k) => new ClassElementImpl.forKernel(this, k))
.toList(growable: false);
}
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 5d91528..3ccdac9 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -1175,8 +1175,8 @@
/**
* Compares two function types [t] and [s] to see if their corresponding
- * parameter types match [parameterRelation] and their return types match
- * [returnRelation].
+ * parameter types match [parameterRelation], return types match
+ * [returnRelation], and type parameter bounds match [boundsRelation].
*
* Used for the various relations on function types which have the same
* structural rules for handling optional parameters and arity, but use their
@@ -1184,14 +1184,20 @@
*
* If [parameterRelation] is omitted, uses [returnRelation] for both. This
* is convenient for Dart 1 type system methods.
+ *
+ * If [boundsRelation] is omitted, uses [returnRelation]. This is for
+ * backwards compatibility, and convenience for Dart 1 type system methods.
*/
static bool relate(
FunctionType t,
DartType other,
bool returnRelation(DartType t, DartType s),
DartType instantiateToBounds(DartType t),
- {bool parameterRelation(ParameterElement t, ParameterElement s)}) {
+ {bool parameterRelation(ParameterElement t, ParameterElement s),
+ bool boundsRelation(DartType bound2, DartType bound1,
+ TypeParameterElement formal2, TypeParameterElement formal1)}) {
parameterRelation ??= (t, s) => returnRelation(t.type, s.type);
+ boundsRelation ??= (t, s, _, __) => returnRelation(t, s);
// Trivial base cases.
if (other == null) {
@@ -1208,8 +1214,7 @@
// This type cast is safe, because we checked it above.
FunctionType s = other as FunctionType;
if (t.typeFormals.isNotEmpty) {
- List<DartType> freshVariables =
- relateTypeFormals(t, s, (s, t, _, __) => returnRelation(s, t));
+ List<DartType> freshVariables = relateTypeFormals(t, s, boundsRelation);
if (freshVariables == null) {
return false;
}
diff --git a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
index 28b8ae0..94cbe97 100644
--- a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:front_end/src/fasta/kernel/body_builder.dart' show LabelTarget;
import 'package:front_end/src/fasta/kernel/forest.dart';
import 'package:kernel/ast.dart' as kernel;
@@ -103,6 +104,48 @@
}
@override
+ CatchClause catchClause(
+ Token onKeyword,
+ TypeAnnotation exceptionType,
+ Token catchKeyword,
+ SimpleIdentifier exceptionParameter,
+ SimpleIdentifier stackTraceParameter,
+ TypeAnnotation stackTraceType,
+ Statement body) {
+ // TODO(brianwilkerson) The following is not reliable in the presence of
+ // recovery. Consider passing the required tokens from the Parser to the
+ // BodyBuilder to here.
+ Token leftParenthesis;
+ if (catchKeyword != null) {
+ leftParenthesis = catchKeyword.next;
+ }
+ Token comma;
+ if (stackTraceParameter != null) {
+ comma = exceptionParameter.endToken.next;
+ }
+ Token rightParenthesis;
+ if (catchKeyword != null) {
+ if (stackTraceParameter != null) {
+ rightParenthesis = stackTraceParameter.endToken.next;
+ } else if (comma != null) {
+ rightParenthesis = comma.next;
+ } else {
+ rightParenthesis = exceptionParameter.endToken.next;
+ }
+ }
+ return astFactory.catchClause(
+ onKeyword,
+ exceptionType,
+ catchKeyword,
+ leftParenthesis,
+ exceptionParameter,
+ comma,
+ stackTraceParameter,
+ rightParenthesis,
+ body);
+ }
+
+ @override
Expression checkLibraryIsLoaded(dependency) {
// TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
@@ -121,6 +164,16 @@
continueKeyword, astFactory.simpleIdentifier(label.token), semicolon);
@override
+ Generator<Expression, Statement, _Arguments> deferredAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ PrefixBuilder builder,
+ Generator<Expression, Statement, _Arguments> generator) {
+ // TODO(brianwilkerson) Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
Statement doStatement(Token doKeyword, Statement body, Token whileKeyword,
ParenthesizedExpression condition, Token semicolon) =>
astFactory.doStatement(
@@ -148,7 +201,7 @@
covariant initialization,
Token leftSeparator,
Expression condition,
- Token rightSeparator,
+ Statement conditionStatement,
List<Expression> updaters,
Token rightParenthesis,
Statement body) =>
@@ -159,7 +212,7 @@
initialization,
leftSeparator,
condition,
- rightSeparator,
+ getSemicolon(conditionStatement),
updaters,
rightParenthesis,
body);
@@ -168,7 +221,13 @@
Expression getExpressionFromExpressionStatement(Statement statement) =>
(statement as ExpressionStatement).expression;
+ String getLabelName(Label label) => label.label.name;
+
@override
+ int getLabelOffset(Label label) => label.offset;
+
+ /// Return the semicolon at the end of the given [statement], or `null` if the
+ /// statement is not terminated by a semicolon.
Token getSemicolon(Statement statement) {
if (statement is ExpressionStatement) {
return statement.semicolon;
@@ -212,7 +271,7 @@
Expression index,
kernel.Procedure getter,
kernel.Procedure setter) {
- // TODO(brianwilkerson): Implement this.
+ // TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
}
@@ -235,6 +294,9 @@
statement is ExpressionStatement;
@override
+ bool isLabel(covariant node) => node is Label;
+
+ @override
bool isThisExpression(Object node) => node is ThisExpression;
@override
@@ -242,6 +304,23 @@
node is VariableDeclarationStatement && node.variables != 1;
@override
+ Label label(Token identifier, Token colon) =>
+ astFactory.label(astFactory.simpleIdentifier(identifier), colon);
+
+ @override
+ Statement labeledStatement(
+ LabelTarget<Statement> target, Statement statement) =>
+ astFactory.labeledStatement(target.labels.cast<Label>(), statement);
+
+ @override
+ Generator<Expression, Statement, _Arguments> largeIntAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token) {
+ // TODO(brianwilkerson) Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
Expression literalBool(bool value, Token location) =>
astFactory.booleanLiteral(location, value)
..staticType = _typeProvider?.boolType;
@@ -326,6 +405,15 @@
}
@override
+ Generator<Expression, Statement, _Arguments> loadLibraryGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ LoadLibraryBuilder builder) {
+ // TODO(brianwilkerson) Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
Object mapEntry(Expression key, Token colon, Expression value) =>
astFactory.mapLiteralEntry(key, colon, value);
@@ -346,7 +434,7 @@
kernel.Member getter,
kernel.Member setter,
kernel.DartType type) {
- // TODO(brianwilkerson): Implement this.
+ // TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
}
@@ -364,7 +452,7 @@
kernel.Name name,
kernel.Member getter,
kernel.Member setter) {
- // TODO(brianwilkerson): Implement this.
+ // TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
}
@@ -372,6 +460,16 @@
int readOffset(AstNode node) => node.offset;
@override
+ Generator<Expression, Statement, _Arguments> readOnlyAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ Expression expression,
+ String plainNameForRead) {
+ // TODO(brianwilkerson) Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
void resolveBreak(Statement target, BreakStatement user) {
user.target = target;
}
@@ -397,18 +495,44 @@
astFactory.returnStatement(returnKeyword, expression, semicolon);
@override
+ void setParameterType(FormalParameter parameter, TypeAnnotation type) {
+ parameter.identifier.staticType = type.type;
+ }
+
+ @override
+ Generator<Expression, Statement, _Arguments> staticAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ kernel.Member getter,
+ kernel.Member setter) {
+ // TODO(brianwilkerson) Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
Expression stringConcatenationExpression(
List<Expression> strings, Token location) =>
astFactory.adjacentStrings(strings.cast<StringLiteral>());
@override
+ Generator<Expression, Statement, _Arguments> superIndexedAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ Expression index,
+ kernel.Member getter,
+ kernel.Member setter) {
+ // TODO(brianwilkerson) Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
Generator<Expression, Statement, _Arguments> superPropertyAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
Token token,
kernel.Name name,
kernel.Member getter,
kernel.Member setter) {
- // TODO(brianwilkerson): Implement this.
+ // TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
}
@@ -426,7 +550,7 @@
Expression index,
kernel.Procedure getter,
kernel.Procedure setter) {
- // TODO(brianwilkerson): Implement this.
+ // TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
}
@@ -437,7 +561,7 @@
kernel.Name name,
kernel.Member getter,
kernel.Member setter) {
- // TODO(brianwilkerson): Implement this.
+ // TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
}
@@ -456,6 +580,18 @@
tryKeyword, body, catchClauses, finallyKeyword, finallyBlock);
@override
+ Generator<Expression, Statement, _Arguments> typeUseGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ PrefixBuilder prefix,
+ int declarationReferenceOffset,
+ TypeDeclarationBuilder declaration,
+ String plainNameForRead) {
+ // TODO(brianwilkerson) Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
VariableDeclarationStatement variablesDeclaration(
List<VariableDeclaration> declarations, Uri uri) {
// TODO(brianwilkerson) Implement this.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 185d6d3..6fdac95 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -76,17 +76,21 @@
}
Element element = nameScope.lookup(methodName, definingLibrary);
if (element is ClassElement) {
+ ConstructorElement constructorElement = element.unnamedConstructor;
AstFactory astFactory = new AstFactoryImpl();
TypeName typeName = astFactory.typeName(methodName, node.typeArguments);
+ ConstructorName constructorName =
+ astFactory.constructorName(typeName, null, null);
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
- _getKeyword(node),
- astFactory.constructorName(typeName, null, null),
- node.argumentList);
+ _getKeyword(node), constructorName, node.argumentList);
DartType type = _getType(element, node.typeArguments);
methodName.staticElement = element;
methodName.staticType = type;
typeName.type = type;
+ constructorName.staticElement = constructorElement;
+ instanceCreationExpression.staticType = type;
+ instanceCreationExpression.staticElement = constructorElement;
NodeReplacer.replace(node, instanceCreationExpression);
}
} else if (target is SimpleIdentifier) {
@@ -98,19 +102,22 @@
Element element = nameScope.lookup(target, definingLibrary);
if (element is ClassElement) {
// Possible case: C.n()
- if (element.getNamedConstructor(methodName.name) != null) {
+ var constructorElement = element.getNamedConstructor(methodName.name);
+ if (constructorElement != null) {
AstFactory astFactory = new AstFactoryImpl();
TypeName typeName = astFactory.typeName(target, node.typeArguments);
+ ConstructorName constructorName =
+ astFactory.constructorName(typeName, node.operator, methodName);
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
- _getKeyword(node),
- astFactory.constructorName(
- typeName, node.operator, methodName),
- node.argumentList);
+ _getKeyword(node), constructorName, node.argumentList);
DartType type = _getType(element, node.typeArguments);
methodName.staticElement = element;
methodName.staticType = type;
typeName.type = type;
+ constructorName.staticElement = constructorElement;
+ instanceCreationExpression.staticType = type;
+ instanceCreationExpression.staticElement = constructorElement;
NodeReplacer.replace(node, instanceCreationExpression);
}
} else if (element is PrefixElement) {
@@ -122,18 +129,23 @@
astFactory.simpleIdentifier(methodName.token));
Element prefixedElement = nameScope.lookup(identifier, definingLibrary);
if (prefixedElement is ClassElement) {
+ ConstructorElement constructorElement =
+ prefixedElement.unnamedConstructor;
TypeName typeName = astFactory.typeName(
astFactory.prefixedIdentifier(target, node.operator, methodName),
node.typeArguments);
+ ConstructorName constructorName =
+ astFactory.constructorName(typeName, null, null);
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
- _getKeyword(node),
- astFactory.constructorName(typeName, null, null),
- node.argumentList);
+ _getKeyword(node), constructorName, node.argumentList);
DartType type = _getType(prefixedElement, node.typeArguments);
methodName.staticElement = element;
methodName.staticType = type;
typeName.type = type;
+ constructorName.staticElement = constructorElement;
+ instanceCreationExpression.staticType = type;
+ instanceCreationExpression.staticElement = constructorElement;
NodeReplacer.replace(node, instanceCreationExpression);
}
}
@@ -143,19 +155,22 @@
if (prefixElement is PrefixElement) {
Element element = nameScope.lookup(target, definingLibrary);
if (element is ClassElement) {
- if (element.getNamedConstructor(methodName.name) != null) {
+ var constructorElement = element.getNamedConstructor(methodName.name);
+ if (constructorElement != null) {
AstFactory astFactory = new AstFactoryImpl();
TypeName typeName = astFactory.typeName(target, node.typeArguments);
+ ConstructorName constructorName =
+ astFactory.constructorName(typeName, node.operator, methodName);
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
- _getKeyword(node),
- astFactory.constructorName(
- typeName, node.operator, methodName),
- node.argumentList);
+ _getKeyword(node), constructorName, node.argumentList);
DartType type = _getType(element, node.typeArguments);
methodName.staticElement = element;
methodName.staticType = type;
typeName.type = type;
+ constructorName.staticElement = constructorElement;
+ instanceCreationExpression.staticType = type;
+ instanceCreationExpression.staticElement = constructorElement;
NodeReplacer.replace(node, instanceCreationExpression);
}
}
@@ -6748,6 +6763,9 @@
*/
void _inferFunctionExpressionParametersTypes(
Expression mayBeClosure, DartType mayByFunctionType) {
+ // TODO(mfairhurst): remove this code and callers. It's doing
+ // "propagated type" inference for the Dart 1 type system.
+ assert(!strongMode);
// prepare closure
if (mayBeClosure is! FunctionExpression) {
return;
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index d693693..c7e14c8 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -272,6 +272,9 @@
* An implementation of an non-existing [Source].
*/
class NonExistingSource extends Source {
+ static final unknown = new NonExistingSource(
+ '/unknown.dart', pathos.toUri('/unknown.dart'), UriKind.FILE_URI);
+
@override
final String fullName;
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index d178f25..ab376a1 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -646,18 +646,14 @@
if (t1 is FunctionType && t2 is FunctionType) {
return FunctionTypeImpl.relate(
- t1,
- t2,
- (t1, t2) {
- // TODO(jmesserly): should we flip covariance when we're relating
- // type formal bounds? They're more like parameters.
- return matchSubtype(t1, t2);
- },
- _typeSystem.instantiateToBounds,
+ t1, t2, matchSubtype, _typeSystem.instantiateToBounds,
parameterRelation: (p1, p2) {
return _matchSubtypeOf(p2.type, p1.type, null, origin,
covariant: !covariant);
- });
+ },
+ // Type parameter bounds are invariant.
+ boundsRelation: (t1, t2, p1, p2) =>
+ matchSubtype(t1, t2) && matchSubtype(t2, t1));
}
if (t1 is FunctionType && t2 == typeProvider.functionType) {
@@ -1181,7 +1177,10 @@
/// - it allows opt-in covariant parameters.
bool isOverrideSubtypeOf(FunctionType f1, FunctionType f2) {
return FunctionTypeImpl.relate(f1, f2, isSubtypeOf, instantiateToBounds,
- parameterRelation: isOverrideSubtypeOfParameter);
+ parameterRelation: isOverrideSubtypeOfParameter,
+ // Type parameter bounds are invariant.
+ boundsRelation: (t1, t2, p1, p2) =>
+ isSubtypeOf(t1, t2) && isSubtypeOf(t2, t1));
}
/// Check that parameter [p2] is a subtype of [p1], given that we are
@@ -1522,7 +1521,10 @@
/// Check that [f1] is a subtype of [f2].
bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2) {
return FunctionTypeImpl.relate(f1, f2, isSubtypeOf, instantiateToBounds,
- parameterRelation: (p1, p2) => isSubtypeOf(p2.type, p1.type));
+ parameterRelation: (p1, p2) => isSubtypeOf(p2.type, p1.type),
+ // Type parameter bounds are invariant.
+ boundsRelation: (t1, t2, p1, p2) =>
+ isSubtypeOf(t1, t2) && isSubtypeOf(t2, t1));
}
bool _isInterfaceSubtypeOf(
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 03cdb82..2a7256e 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.32.0
+version: 0.32.1-alpha.0
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -11,10 +11,10 @@
collection: ^1.10.1
convert: ^2.0.0
crypto: '>=1.1.1 <3.0.0'
- front_end: 0.1.0
+ front_end: 0.1.1-alpha.0
glob: ^1.0.3
html: '>=0.12.0 <1.14.0'
- kernel: 0.3.0
+ kernel: 0.3.1-alpha.0
meta: ^1.0.2
package_config: '>=0.1.5 <2.0.0'
path: '>=0.9.0 <2.0.0'
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 6ef150d..73c2001 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -4786,6 +4786,49 @@
assertNoErrors(source);
}
+ test_optionalNew_rewrite() async {
+ resetWith(
+ options: new AnalysisOptionsImpl()
+ ..previewDart2 = true
+ ..strongMode = true);
+ Source source = addSource(r'''
+import 'b.dart';
+main() {
+ const B.named1();
+ const B.named2();
+ const B.named3();
+ const B.named4();
+}
+''');
+ addNamedSource("/a.dart", r'''
+class A {
+ const A();
+ const A.named();
+}
+''');
+ addNamedSource("/b.dart", r'''
+import 'a.dart';
+import 'a.dart' as p;
+
+const _a1 = A();
+const _a2 = A.named();
+const _a3 = p.A();
+const _a4 = p.A.named();
+
+class B {
+ const B.named1({this.a: _a1}) : assert(a != null);
+ const B.named2({this.a: _a2}) : assert(a != null);
+ const B.named3({this.a: _a3}) : assert(a != null);
+ const B.named4({this.a: _a4}) : assert(a != null);
+
+ final A a;
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_optionalParameterInOperator_required() async {
Source source = addSource(r'''
class A {
diff --git a/pkg/analyzer/test/generated/package_build_test.dart b/pkg/analyzer/test/generated/package_build_test.dart
index 1b2dedd..a731844 100644
--- a/pkg/analyzer/test/generated/package_build_test.dart
+++ b/pkg/analyzer/test/generated/package_build_test.dart
@@ -116,8 +116,9 @@
Uri addPackageSource(String path, String uriStr, {bool create: true}) {
Uri uri = Uri.parse(uriStr);
- final File file =
- create ? provider.newFile(_p(path), '') : provider.getResource(path);
+ final File file = create
+ ? provider.newFile(_p(path), '')
+ : provider.getResource(_p(path));
final Source source = file.createSource(uri);
when(packageUriResolver.resolveAbsolute(uri)).thenReturn(source);
return uri;
@@ -226,7 +227,7 @@
final libFile = provider.newFile(
_p('/workspace/.dart_tool/build/generated/project/lib/file.dart'), '');
- expect(workspace.builtFile('lib/file.dart', 'project'), libFile);
+ expect(workspace.builtFile(_p('lib/file.dart'), 'project'), libFile);
}
void test_builtFile_importedPackage() {
@@ -238,7 +239,7 @@
final libFile = provider.newFile(
_p('/workspace/.dart_tool/build/generated/foo/lib/file.dart'), '');
- expect(workspace.builtFile('lib/file.dart', 'foo'), libFile);
+ expect(workspace.builtFile(_p('lib/file.dart'), 'foo'), libFile);
}
void test_builtFile_notInPackagesGetsHidden() {
@@ -382,7 +383,7 @@
_createWorkspace('/workspace', ['project']);
final binFile = provider.newFile(_p('/workspace/bin/file.dart'), '');
- expect(workspace.findFile('/workspace/bin/file.dart'), binFile);
+ expect(workspace.findFile(_p('/workspace/bin/file.dart')), binFile);
}
void test_findFile_binGenerated() {
@@ -394,7 +395,7 @@
final binFile = provider.newFile(
_p('/workspace/.dart_tool/build/generated/project/bin/file.dart'), '');
- expect(workspace.findFile('/workspace/bin/file.dart'), binFile);
+ expect(workspace.findFile(_p('/workspace/bin/file.dart')), binFile);
}
void test_findFile_libGenerated() {
@@ -406,7 +407,7 @@
final libFile = provider.newFile(
_p('/workspace/.dart_tool/build/generated/project/lib/file.dart'), '');
- expect(workspace.findFile('/workspace/lib/file.dart'), libFile);
+ expect(workspace.findFile(_p('/workspace/lib/file.dart')), libFile);
}
void test_findFile_test() {
@@ -418,7 +419,7 @@
_createWorkspace('/workspace', ['project']);
final testFile = provider.newFile(_p('/workspace/test/file.dart'), '');
- expect(workspace.findFile('/workspace/test/file.dart'), testFile);
+ expect(workspace.findFile(_p('/workspace/test/file.dart')), testFile);
}
void test_findFile_testGenerated() {
@@ -431,7 +432,7 @@
final testFile = provider.newFile(
_p('/workspace/.dart_tool/build/generated/project/test/file.dart'), '');
- expect(workspace.findFile('/workspace/test/file.dart'), testFile);
+ expect(workspace.findFile(_p('/workspace/test/file.dart')), testFile);
}
void test_findFile_web() {
@@ -442,7 +443,7 @@
_createWorkspace('/workspace', ['project']);
final webFile = provider.newFile(_p('/workspace/web/file.dart'), '');
- expect(workspace.findFile('/workspace/web/file.dart'), webFile);
+ expect(workspace.findFile(_p('/workspace/web/file.dart')), webFile);
}
void test_findFile_webGenerated() {
@@ -454,7 +455,7 @@
final webFile = provider.newFile(
_p('/workspace/.dart_tool/build/generated/project/web/file.dart'), '');
- expect(workspace.findFile('/workspace/web/file.dart'), webFile);
+ expect(workspace.findFile(_p('/workspace/web/file.dart')), webFile);
}
PackageBuildWorkspace _createWorkspace(
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index e634c00..2ff080d 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -53,12 +53,6 @@
@reflectiveTest
class ClassMemberParserTest_Fasta extends FastaParserTestCase
with ClassMemberParserTestMixin {
- @failingTest
- @override
- void test_parseAwaitExpression_inSync() {
- super.test_parseAwaitExpression_inSync();
- }
-
@override
void test_parseClassMember_method_generic_comment_noReturnType() {
// Ignored: Fasta does not support the generic comment syntax.
@@ -1318,13 +1312,6 @@
@override
@failingTest
- void test_incompleteTypeArguments_field() {
- // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
- super.test_incompleteTypeArguments_field();
- }
-
- @override
- @failingTest
void test_missingIdentifier_afterAnnotation() {
// TODO(brianwilkerson) reportUnrecoverableErrorWithToken
super.test_missingIdentifier_afterAnnotation();
diff --git a/pkg/analyzer/test/generated/parser_forest_test.dart b/pkg/analyzer/test/generated/parser_forest_test.dart
index 1ec29cc..5908df2 100644
--- a/pkg/analyzer/test/generated/parser_forest_test.dart
+++ b/pkg/analyzer/test/generated/parser_forest_test.dart
@@ -891,6 +891,16 @@
}
@failingTest
+ void test_constructorPartial2() {
+ super.test_constructorPartial();
+ }
+
+ @failingTest
+ void test_constructorPartial3() {
+ super.test_constructorPartial();
+ }
+
+ @failingTest
void test_constructorWithReturnType() {
super.test_constructorWithReturnType();
}
@@ -4279,6 +4289,11 @@
}
@failingTest
+ void test_incompleteTypeParameters3() {
+ super.test_incompleteTypeParameters3();
+ }
+
+ @failingTest
void test_invalidFunctionBodyModifier() {
super.test_invalidFunctionBodyModifier();
}
@@ -5045,21 +5060,11 @@
}
@failingTest
- void test_parseBreakStatement_label() {
- super.test_parseBreakStatement_label();
- }
-
- @failingTest
void test_parseBreakStatement_noLabel() {
super.test_parseBreakStatement_noLabel();
}
@failingTest
- void test_parseContinueStatement_label() {
- super.test_parseContinueStatement_label();
- }
-
- @failingTest
void test_parseContinueStatement_noLabel() {
super.test_parseContinueStatement_noLabel();
}
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 7b529d3..35b6075 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -372,13 +372,22 @@
}
void test_parseAwaitExpression_inSync() {
- // This test requires better error recovery than we currently have. In
- // particular, we need to be able to distinguish between an await expression
- // in the wrong context, and the use of 'await' as an identifier.
createParser('m() { return await x + await y; }');
MethodDeclaration method = parser.parseClassMember('C');
expect(method, isNotNull);
- assertNoErrors();
+ listener.assertErrors(usingFastaParser
+ ? [
+ expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 13, 5),
+ expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 5)
+ ]
+ : [
+ // This test requires better error recovery than we currently have.
+ // In particular, we need to be able to distinguish
+ // between an await expression in the wrong context,
+ // and the use of 'await' as an identifier.
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 5),
+ expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 1)
+ ]);
FunctionBody body = method.body;
EngineTestCase.assertInstanceOf(
(obj) => obj is BlockFunctionBody, BlockFunctionBody, body);
@@ -388,10 +397,13 @@
Expression expression = (statement as ReturnStatement).expression;
EngineTestCase.assertInstanceOf(
(obj) => obj is BinaryExpression, BinaryExpression, expression);
- EngineTestCase.assertInstanceOf((obj) => obj is AwaitExpression,
- AwaitExpression, (expression as BinaryExpression).leftOperand);
- EngineTestCase.assertInstanceOf((obj) => obj is AwaitExpression,
- AwaitExpression, (expression as BinaryExpression).rightOperand);
+ if (!usingFastaParser) {
+ // TODO(danrubel): capture `await` keywords in fasta generated AST
+ EngineTestCase.assertInstanceOf((obj) => obj is AwaitExpression,
+ AwaitExpression, (expression as BinaryExpression).leftOperand);
+ EngineTestCase.assertInstanceOf((obj) => obj is AwaitExpression,
+ AwaitExpression, (expression as BinaryExpression).rightOperand);
+ }
}
void test_parseClassMember_constructor_withDocComment() {
@@ -2703,6 +2715,42 @@
]);
}
+ void test_constructorPartial2() {
+ createParser('class C { C<@Foo }');
+ parser.parseCompilationUnit2();
+ listener.assertErrors(usingFastaParser
+ ? [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 17, 1),
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1),
+ expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
+ expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1)
+ ]
+ : [
+ expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
+ expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 12, 1),
+ expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 17, 1)
+ ]);
+ }
+
+ void test_constructorPartial3() {
+ createParser('class C { C<@Foo @Bar() }');
+ parser.parseCompilationUnit2();
+ listener.assertErrors(usingFastaParser
+ ? [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 1),
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
+ expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
+ expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 24, 1)
+ ]
+ : [
+ expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
+ expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 12, 1),
+ expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 24, 1)
+ ]);
+ }
+
void test_constructorWithReturnType() {
createParser('C C() {}');
ClassMember member = parser.parseClassMember('C');
@@ -4420,12 +4468,15 @@
// It doesn't try to advance past the invalid token `!` to find the
// valid `>`. If it did we'd get less cascading errors, at least for this
// particular example.
- createParser('void m<E, hello!>() {}');
+ createParser('void m<E, hello!>() {}', expectedEndOffset: 6);
ClassMember member = parser.parseClassMember('C');
expectNotNullIfNoErrors(member);
listener.assertErrors(usingFastaParser
? [
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1) /*>*/
+ // TODO(danrubel): Improve recovery
+ expectedError(
+ ParserErrorCode.MISSING_METHOD_PARAMETERS, 5, 1) /*<*/,
+ expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 6, 1) /*E*/
]
: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0) /*>*/,
@@ -4436,8 +4487,10 @@
]);
expect(member, new isInstanceOf<MethodDeclaration>());
MethodDeclaration method = member;
- expect(method.typeParameters.toString(), '<E, hello>',
- reason: 'parser recovers what it can');
+ if (!usingFastaParser) {
+ expect(method.typeParameters.toString(), '<E, hello>',
+ reason: 'parser recovers what it can');
+ }
}
void test_missingAssignableSelector_identifiersAssigned() {
@@ -10000,7 +10053,7 @@
listener ??= AnalysisErrorListener.NULL_LISTENER;
Scanner scanner = new Scanner(null, new CharSequenceReader(code), listener);
Token token = scanner.tokenize();
- Parser parser = new Parser(null, listener);
+ Parser parser = new Parser(NonExistingSource.unknown, listener);
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
CompilationUnit unit = parser.parseCompilationUnit(token);
unit.lineInfo = new LineInfo(scanner.lineStarts);
@@ -11474,7 +11527,7 @@
CompilationUnit unit = parseCompilationUnit(r'''
class C {
final List<int f;
-}''', codes: [ParserErrorCode.EXPECTED_TOKEN]);
+}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 1)]);
// one class
List<CompilationUnitMember> declarations = unit.declarations;
expect(declarations, hasLength(1));
@@ -11532,6 +11585,26 @@
expect(token.isSynthetic, isTrue);
}
+ void test_incompleteTypeParameters3() {
+ CompilationUnit unit = parseCompilationUnit(r'''
+class C<K extends L<T {
+}''', errors: [
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1)
+ ]);
+ // one class
+ List<CompilationUnitMember> declarations = unit.declarations;
+ expect(declarations, hasLength(1));
+ ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+ // validate the type parameters
+ TypeParameterList typeParameters = classDecl.typeParameters;
+ expect(typeParameters.typeParameters, hasLength(1));
+ // synthetic '>'
+ Token token = typeParameters.endToken;
+ expect(token.type, TokenType.GT);
+ expect(token.isSynthetic, isTrue);
+ }
+
void test_invalidFunctionBodyModifier() {
parseCompilationUnit("f() sync {}",
codes: [ParserErrorCode.MISSING_STAR_AFTER_SYNC]);
@@ -11543,14 +11616,7 @@
G<int double> g;
}''',
errors: usingFastaParser
- ? [
- // TODO(danrubel): Improve missing comma recovery.
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6),
- expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 12, 1),
- expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 26, 1),
- expectedError(
- ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 26, 1),
- ]
+ ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6)]
: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6),
@@ -11564,12 +11630,12 @@
expect(declarations, hasLength(1));
// validate members
if (usingFastaParser) {
-// ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
-// expect(classDecl.members, hasLength(1));
-// FieldDeclaration fields = classDecl.members.first;
-// expect(fields.fields.variables, hasLength(1));
-// VariableDeclaration field = fields.fields.variables.first;
-// expect(field.name.name, 'g');
+ ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+ expect(classDecl.members, hasLength(1));
+ FieldDeclaration fields = classDecl.members.first;
+ expect(fields.fields.variables, hasLength(1));
+ VariableDeclaration field = fields.fields.variables.first;
+ expect(field.name.name, 'g');
}
}
@@ -13107,7 +13173,7 @@
}
void test_Parser() {
- expect(new Parser(null, null), isNotNull);
+ expect(new Parser(NonExistingSource.unknown, null), isNotNull);
}
void test_parseTypeName_parameterized_nullable() {
diff --git a/pkg/analyzer/test/generated/strong_mode_kernel_test.dart b/pkg/analyzer/test/generated/strong_mode_kernel_test.dart
index fdd3388..763d120 100644
--- a/pkg/analyzer/test/generated/strong_mode_kernel_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_kernel_test.dart
@@ -357,9 +357,18 @@
@override
@failingTest
- test_genericMethod_override_invalidTypeParamBounds() async {
+ test_genericMethod_override_invalidCovariantTypeParamBounds() async {
// Expected 1 errors of type StrongModeCode.STRONG_MODE_INVALID_METHOD_OVERRIDE, found 0
- await super.test_genericMethod_override_invalidTypeParamBounds();
+ await super
+ .test_genericMethod_override_invalidContravariantTypeParamBounds();
+ }
+
+ @override
+ @failingTest
+ test_genericMethod_override_invalidContravariantTypeParamBounds() async {
+ // Expected 1 errors of type StrongModeCode.STRONG_MODE_INVALID_METHOD_OVERRIDE, found 0
+ await super
+ .test_genericMethod_override_invalidContravariantTypeParamBounds();
}
@override
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 6a0a0b3..ab24845 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -3407,13 +3407,17 @@
test_genericMethod_override_bounds() async {
await resolveTestUnit(r'''
class A {}
-class B extends A {}
-class C {
- T f<T extends B>(T x) => null;
-}
-class D extends C {
+class B {
T f<T extends A>(T x) => null;
}
+// override with the same bound is OK
+class C extends B {
+ T f<T extends A>(T x) => null;
+}
+// override with new name and the same bound is OK
+class D extends B {
+ Q f<Q extends A>(Q x) => null;
+}
''');
}
@@ -3433,20 +3437,27 @@
verify([source]);
}
- test_genericMethod_override_invalidReturnType() async {
+ test_genericMethod_override_differentContextsSameBounds() async {
Source source = addSource(r'''
-class C {
- Iterable<T> f<T>(T x) => null;
+ class GenericMethodBounds<T> {
+ Type get t => T;
+ GenericMethodBounds<E> foo<E extends T>() => new GenericMethodBounds<E>();
+ GenericMethodBounds<E> bar<E extends void Function(T)>() =>
+ new GenericMethodBounds<E>();
}
-class D extends C {
- String f<S>(S x) => null;
-}''');
+
+class GenericMethodBoundsDerived extends GenericMethodBounds<num> {
+ GenericMethodBounds<E> foo<E extends num>() => new GenericMethodBounds<E>();
+ GenericMethodBounds<E> bar<E extends void Function(num)>() =>
+ new GenericMethodBounds<E>();
+}
+''');
await computeAnalysisResult(source);
- assertErrors(source, [StrongModeCode.INVALID_METHOD_OVERRIDE]);
+ assertNoErrors(source);
verify([source]);
}
- test_genericMethod_override_invalidTypeParamBounds() async {
+ test_genericMethod_override_invalidContravariantTypeParamBounds() async {
Source source = addSource(r'''
class A {}
class B extends A {}
@@ -3461,6 +3472,34 @@
verify([source]);
}
+ test_genericMethod_override_invalidCovariantTypeParamBounds() async {
+ Source source = addSource(r'''
+class A {}
+class B extends A {}
+class C {
+ T f<T extends B>(T x) => null;
+}
+class D extends C {
+ T f<T extends A>(T x) => null;
+}''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [StrongModeCode.INVALID_METHOD_OVERRIDE]);
+ verify([source]);
+ }
+
+ test_genericMethod_override_invalidReturnType() async {
+ Source source = addSource(r'''
+class C {
+ Iterable<T> f<T>(T x) => null;
+}
+class D extends C {
+ String f<S>(S x) => null;
+}''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [StrongModeCode.INVALID_METHOD_OVERRIDE]);
+ verify([source]);
+ }
+
test_genericMethod_override_invalidTypeParamCount() async {
Source source = addSource(r'''
class C {
@@ -3910,6 +3949,48 @@
''');
}
+ @failingTest
+ test_notInstantiatedBound_class_error_recursion() async {
+ String code = r'''
+class A<T extends B> {} // points to a
+class B<T extends A> {} // points to b
+class C<T extends A> {} // points to a cyclical type
+''';
+ await resolveTestUnit(code, noErrors: false);
+ assertErrors(testSource, [
+ StrongModeCode.NOT_INSTANTIATED_BOUND,
+ StrongModeCode.NOT_INSTANTIATED_BOUND,
+ StrongModeCode.NOT_INSTANTIATED_BOUND,
+ ]);
+ }
+
+ @failingTest
+ test_notInstantiatedBound_class_error_recursion_less_direct() async {
+ String code = r'''
+class A<T extends B<A>> {}
+class B<T extends A<B>> {}
+''';
+ await resolveTestUnit(code, noErrors: false);
+ assertErrors(testSource, [
+ StrongModeCode.NOT_INSTANTIATED_BOUND,
+ StrongModeCode.NOT_INSTANTIATED_BOUND,
+ ]);
+ }
+
+ test_notInstantiatedBound_class_error_recursion_typedef() async {
+ String code = r'''
+typedef F(C value);
+class C<T extends F> {}
+class D<T extends C> {}
+''';
+ await resolveTestUnit(code, noErrors: false);
+ assertErrors(testSource, [
+ StrongModeCode.NOT_INSTANTIATED_BOUND,
+ StrongModeCode.NOT_INSTANTIATED_BOUND,
+ CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
+ ]);
+ }
+
test_notInstantiatedBound_error_class_argument() async {
String code = r'''
class A<K, V extends List<K>> {}
@@ -3959,34 +4040,6 @@
]);
}
- @failingTest
- test_notInstantiatedBound_class_error_recursion() async {
- String code = r'''
-class A<T extends B> {} // points to a
-class B<T extends A> {} // points to b
-class C<T extends A> {} // points to a cyclical type
-''';
- await resolveTestUnit(code, noErrors: false);
- assertErrors(testSource, [
- StrongModeCode.NOT_INSTANTIATED_BOUND,
- StrongModeCode.NOT_INSTANTIATED_BOUND,
- StrongModeCode.NOT_INSTANTIATED_BOUND,
- ]);
- }
-
- @failingTest
- test_notInstantiatedBound_class_error_recursion_less_direct() async {
- String code = r'''
-class A<T extends B<A>> {}
-class B<T extends A<B>> {}
-''';
- await resolveTestUnit(code, noErrors: false);
- assertErrors(testSource, [
- StrongModeCode.NOT_INSTANTIATED_BOUND,
- StrongModeCode.NOT_INSTANTIATED_BOUND,
- ]);
- }
-
test_notInstantiatedBound_error_typedef_argument() async {
String code = r'''
class A<K, V extends List<K>> {}
@@ -4014,20 +4067,6 @@
assertErrors(testSource, [StrongModeCode.NOT_INSTANTIATED_BOUND]);
}
- test_notInstantiatedBound_class_error_recursion_typedef() async {
- String code = r'''
-typedef F(C value);
-class C<T extends F> {}
-class D<T extends C> {}
-''';
- await resolveTestUnit(code, noErrors: false);
- assertErrors(testSource, [
- StrongModeCode.NOT_INSTANTIATED_BOUND,
- StrongModeCode.NOT_INSTANTIATED_BOUND,
- CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
- ]);
- }
-
test_notInstantiatedBound_ok_class() async {
String code = r'''
class A<T extends int> {}
@@ -4068,6 +4107,15 @@
assertNoErrors(testSource);
}
+ test_notInstantiatedBound_ok_class_function() async {
+ String code = r'''
+class A<T extends void Function<Z>()> {}
+class B<T extends A> {}
+''';
+ await resolveTestUnit(code);
+ assertNoErrors(testSource);
+ }
+
test_notInstantiatedBound_ok_class_typedef() async {
String code = r'''
typedef void F<T extends int>();
@@ -4086,15 +4134,6 @@
assertNoErrors(testSource);
}
- test_notInstantiatedBound_ok_class_function() async {
- String code = r'''
-class A<T extends void Function<Z>()> {}
-class B<T extends A> {}
-''';
- await resolveTestUnit(code);
- assertNoErrors(testSource);
- }
-
test_objectMethodOnFunctions_Anonymous() async {
String code = r'''
void main() {
@@ -4403,7 +4442,7 @@
}
abstract class Override implements Base, BaseCopy {
- f<E>(x) => null;
+ f<E extends int>(x) => null;
}
class C extends Override implements Base {}
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index c371ec8..a7ec816 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -2145,28 +2145,6 @@
}
}
- void test_genericFunction_simple_fBounded() {
- ClassElementImpl AClass = ElementFactory.classElement2('A', ["Q"]);
- InterfaceType AType = AClass.type;
- ClassElementImpl BClass = ElementFactory.classElement2('B', ["R"]);
- BClass.supertype = AType.instantiate([BClass.typeParameters[0].type]);
- InterfaceType BType = BClass.type;
-
- DartType s = TypeBuilder.variable("S");
- (s.element as TypeParameterElementImpl).bound = AType.instantiate([s]);
- DartType t = TypeBuilder.variable("T", bound: s);
- DartType u = TypeBuilder.variable("U");
- (u.element as TypeParameterElementImpl).bound = BType.instantiate([u]);
- DartType v = TypeBuilder.variable("V", bound: u);
-
- _checkIsStrictSubtypeOf(
- TypeBuilder.function(types: [s]), TypeBuilder.function(types: [u]));
-
- _checkIsStrictSubtypeOf(
- TypeBuilder.function(types: [s, t], required: [s], result: t),
- TypeBuilder.function(types: [u, v], required: [u], result: v));
- }
-
void test_generics() {
ClassElementImpl LClass = ElementFactory.classElement2('L', ["T"]);
InterfaceType LType = LClass.type;
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index f960be0..010ae47 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -1184,7 +1184,7 @@
CharSequenceReader reader = new CharSequenceReader(code);
Scanner scanner = new Scanner(null, reader, listener);
Token token = scanner.tokenize();
- Parser parser = new Parser(null, listener);
+ Parser parser = new Parser(NonExistingSource.unknown, listener);
CompilationUnit unit = parser.parseCompilationUnit(token);
expect(unit, isNotNull);
listener.assertNoErrors();
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index dc970a1..558578c 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -891,7 +891,7 @@
- empty_constructor_bodies
''');
- ContextRoot root = new ContextRoot(pathContext, path, []);
+ ContextRoot root = new ContextRoot(path, [], pathContext: pathContext);
builder.getAnalysisOptions(path, contextRoot: root);
expect(root.optionsFilePath, equals(filePath));
}
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index dacd732..373fd4b 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -94,7 +94,9 @@
new DartUriResolver(sdk),
generatedUriResolver,
new PackageMapUriResolver(provider, <String, List<Folder>>{
- 'test': [provider.getFolder(testProject)]
+ 'test': [provider.getFolder(testProject)],
+ 'aaa': [provider.getFolder(_p('/aaa/lib'))],
+ 'bbb': [provider.getFolder(_p('/bbb/lib'))],
}),
new ResourceUriResolver(provider)
], null, provider),
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 99871a4..cb583d2 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -1987,6 +1987,39 @@
await driver.getTopLevelNameDeclarations('X'), [], []);
}
+ test_getTopLevelNameDeclarations_discoverAvailable() async {
+ var t = _p('/test/lib/test.dart');
+ var a1 = _p('/aaa/lib/a1.dart');
+ var a2 = _p('/aaa/lib/src/a2.dart');
+ var b = _p('/bbb/lib/b.dart');
+ var c = _p('/ccc/lib/c.dart');
+
+ provider.newFile(t, 'class T {}');
+ provider.newFile(a1, 'class A1 {}');
+ provider.newFile(a2, 'class A2 {}');
+ provider.newFile(b, 'class B {}');
+ provider.newFile(c, 'class C {}');
+
+ driver.addFile(t);
+ // Don't add a1.dart, a2.dart, or b.dart - they should be discovered.
+ // And c.dart is not in .packages, so should not be discovered.
+
+ _assertTopLevelDeclarations(
+ await driver.getTopLevelNameDeclarations('T'), [t], [false]);
+
+ _assertTopLevelDeclarations(
+ await driver.getTopLevelNameDeclarations('A1'), [a1], [false]);
+
+ _assertTopLevelDeclarations(
+ await driver.getTopLevelNameDeclarations('A2'), [a2], [false]);
+
+ _assertTopLevelDeclarations(
+ await driver.getTopLevelNameDeclarations('B'), [b], [false]);
+
+ _assertTopLevelDeclarations(
+ await driver.getTopLevelNameDeclarations('C'), [], []);
+ }
+
test_getTopLevelNameDeclarations_parts() async {
var a = _p('/test/lib/a.dart');
var b = _p('/test/lib/b.dart');
diff --git a/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart b/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
index 99320a1..74c0314 100644
--- a/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
+++ b/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
@@ -412,7 +412,7 @@
// print(problem.formatted);
};
- options = new ProcessedOptions(optionBuilder, false, [entryPoint]);
+ options = new ProcessedOptions(optionBuilder, [entryPoint]);
UriTranslatorImpl uriTranslator = await options.getUriTranslator();
diff --git a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
index 9d6e061..d312b78 100644
--- a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
@@ -119,6 +119,24 @@
''');
}
+ @failingTest
+ void test_initializerList_missingComma() {
+ // https://github.com/dart-lang/sdk/issues/33241
+ testRecovery('''
+class Test {
+ Test()
+ : assert(true)
+ assert(true);
+}
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+class Test {
+ Test()
+ : assert(true),
+ assert(true);
+}
+''');
+ }
+
void test_asExpression_missingRight() {
testRecovery('''
convert(x) => x as ;
diff --git a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
index 1e2348b..b8145d1 100644
--- a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
@@ -84,7 +84,6 @@
@failingTest
void test_typeArguments_inner_last() {
- // Parser crashes
testRecovery('''
List<List<int>
''', [ScannerErrorCode.EXPECTED_TOKEN], '''
@@ -92,9 +91,16 @@
''');
}
+ void test_typeArguments_inner_last2() {
+ testRecovery('''
+List<List<int> f;
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+List<List<int>> f;
+''');
+ }
+
@failingTest
void test_typeArguments_inner_notLast() {
- // Parser crashes
testRecovery('''
Map<List<int, List<String>>
''', [ScannerErrorCode.EXPECTED_TOKEN], '''
@@ -102,9 +108,17 @@
''');
}
+ void test_typeArguments_inner_notLast2() {
+ // TODO(danrubel): Investigate better recovery.
+ testRecovery('''
+Map<List<int, List<String>> f;
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+Map<List<int, List<String>>> f;
+''');
+ }
+
@failingTest
void test_typeArguments_outer_last() {
- // Parser crashes
testRecovery('''
List<int
''', [ScannerErrorCode.EXPECTED_TOKEN], '''
@@ -112,6 +126,22 @@
''');
}
+ void test_typeArguments_outer_last2() {
+ testRecovery('''
+List<int f;
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+List<int> f;
+''');
+ }
+
+ void test_typeArguments_missing_comma() {
+ testRecovery('''
+List<int double> f;
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+List<int, double> f;
+''');
+ }
+
void test_typeParameters_last() {
testRecovery('''
f<T() => null;
@@ -284,13 +314,13 @@
''');
}
- @failingTest
void test_parameterList_class() {
// Parser crashes
testRecovery('''
f(x
class C {}
-''', [ScannerErrorCode.EXPECTED_TOKEN], '''
+''', [ScannerErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_FUNCTION_BODY],
+ '''
f(x) {}
class C {}
''');
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/instance_creation_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/instance_creation_test.dart
index 48660aa..826aa32 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/instance_creation_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/instance_creation_test.dart
@@ -29,7 +29,6 @@
'$keyword',
[
ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
],
"$keyword _s_()"),
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/part_of_directive_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/part_of_directive_test.dart
index 24b5890..17da7bc 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/part_of_directive_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/part_of_directive_test.dart
@@ -34,8 +34,7 @@
ParserErrorCode.EXPECTED_STRING_LITERAL,
ParserErrorCode.EXPECTED_TOKEN
],
- 'part of "";',
- failing: []),
+ 'part of "";'),
],
nonIdentifierSuffixes);
buildTests(
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
index d9da37e..589b4c2 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
@@ -12,8 +12,6 @@
class TryStatementTest extends PartialCodeTest {
buildAll() {
- final allExceptEof =
- PartialCodeTest.statementSuffixes.map((ts) => ts.name).toList();
buildTests(
'try_statement',
[
@@ -67,32 +65,57 @@
[
ScannerErrorCode.EXPECTED_TOKEN,
ParserErrorCode.CATCH_SYNTAX,
+ ParserErrorCode.CATCH_SYNTAX,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
],
"try {} catch (e) {}",
- failing: allExceptEof),
+ failing: [
+ 'eof',
+ 'block',
+ 'labeled',
+ 'localFunctionNonVoid',
+ 'localFunctionVoid',
+ 'localVariable'
+ ]),
new TestDescriptor(
'catch_identifier',
'try {} catch (e',
- [ParserErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN],
- "try {} catch (e) {}",
- failing: allExceptEof),
- new TestDescriptor(
- 'catch_identifierComma',
- 'try {} catch (e, ',
[
ParserErrorCode.CATCH_SYNTAX,
ParserErrorCode.EXPECTED_TOKEN,
ScannerErrorCode.EXPECTED_TOKEN
],
+ "try {} catch (e) {}",
+ failing: ['eof', 'block', 'labeled', 'localFunctionNonVoid']),
+ new TestDescriptor(
+ 'catch_identifierComma',
+ 'try {} catch (e, ',
+ [
+ ParserErrorCode.CATCH_SYNTAX,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN,
+ ScannerErrorCode.EXPECTED_TOKEN
+ ],
"try {} catch (e, _s_) {}",
- failing: allExceptEof),
+ failing: [
+ 'eof',
+ 'block',
+ 'labeled',
+ 'localFunctionNonVoid',
+ 'localFunctionVoid',
+ 'localVariable'
+ ]),
new TestDescriptor(
'catch_identifierCommaIdentifier',
'try {} catch (e, s',
- [ParserErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN],
+ [
+ ParserErrorCode.CATCH_SYNTAX,
+ ParserErrorCode.EXPECTED_TOKEN,
+ ScannerErrorCode.EXPECTED_TOKEN
+ ],
"try {} catch (e, s) {}",
- failing: allExceptEof),
+ failing: ['eof', 'block', 'labeled', 'localFunctionNonVoid']),
new TestDescriptor('catch_rightParen', 'try {} catch (e, s)',
[ParserErrorCode.EXPECTED_TOKEN], "try {} catch (e, s) {}",
failing: ['block']),
@@ -110,33 +133,58 @@
'try {} on A catch (',
[
ParserErrorCode.CATCH_SYNTAX,
+ ParserErrorCode.CATCH_SYNTAX,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
ScannerErrorCode.EXPECTED_TOKEN
],
"try {} on A catch (e) {}",
- failing: allExceptEof),
+ failing: [
+ 'eof',
+ 'block',
+ 'labeled',
+ 'localFunctionNonVoid',
+ 'localFunctionVoid',
+ 'localVariable'
+ ]),
new TestDescriptor(
'on_catch_identifier',
'try {} on A catch (e',
- [ParserErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN],
- "try {} on A catch (e) {}",
- failing: allExceptEof),
- new TestDescriptor(
- 'on_catch_identifierComma',
- 'try {} on A catch (e, ',
[
ParserErrorCode.CATCH_SYNTAX,
ParserErrorCode.EXPECTED_TOKEN,
ScannerErrorCode.EXPECTED_TOKEN
],
+ "try {} on A catch (e) {}",
+ failing: ['eof', 'block', 'labeled', 'localFunctionNonVoid']),
+ new TestDescriptor(
+ 'on_catch_identifierComma',
+ 'try {} on A catch (e, ',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.CATCH_SYNTAX,
+ ParserErrorCode.EXPECTED_TOKEN,
+ ScannerErrorCode.EXPECTED_TOKEN
+ ],
"try {} on A catch (e, _s_) {}",
- failing: allExceptEof),
+ failing: [
+ 'eof',
+ 'block',
+ 'labeled',
+ 'localFunctionVoid',
+ 'localFunctionNonVoid',
+ 'localVariable'
+ ]),
new TestDescriptor(
'on_catch_identifierCommaIdentifier',
'try {} on A catch (e, s',
- [ParserErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN],
+ [
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.CATCH_SYNTAX,
+ ScannerErrorCode.EXPECTED_TOKEN
+ ],
"try {} on A catch (e, s) {}",
- failing: allExceptEof),
+ failing: ['eof', 'block', 'labeled', 'localFunctionNonVoid']),
new TestDescriptor('on_catch_rightParen', 'try {} on A catch (e, s)',
[ParserErrorCode.EXPECTED_TOKEN], "try {} on A catch (e, s) {}",
failing: ['block']),
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/while_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/while_statement_test.dart
index 29040d2..c13652f 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/while_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/while_statement_test.dart
@@ -20,11 +20,12 @@
'while',
[
ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
],
"while (_s_)",
- allFailing: true,
expectedErrorsInValidCode: [
ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
@@ -33,9 +34,13 @@
new TestDescriptor(
'leftParen',
'while (',
- [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ [
+ ScannerErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
"while (_s_)",
- allFailing: true,
expectedErrorsInValidCode: [
ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
@@ -44,9 +49,12 @@
new TestDescriptor(
'condition',
'while (a',
- [ParserErrorCode.EXPECTED_TOKEN],
+ [
+ ScannerErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
"while (a)",
- allFailing: true,
expectedErrorsInValidCode: [
ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
index f95085b..d78d8a7 100644
--- a/pkg/analyzer/test/src/summary/summarize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
@@ -314,7 +314,8 @@
Scanner scanner =
new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER);
Token token = scanner.tokenize();
- Parser parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER);
+ Parser parser = new Parser(
+ NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER);
CompilationUnit unit = parser.parseCompilationUnit(token);
unit.lineInfo = new LineInfo(scanner.lineStarts);
return unit;
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index 6866377..6dc47f7 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -178,13 +178,14 @@
@override
void endArguments(int count, Token beginToken, Token endToken) {
debugEvent("Arguments");
- push(popList(count));
+ push(popList(count, new List<dynamic>.filled(count, null, growable: true)));
}
@override
void endClassBody(int memberCount, Token beginToken, Token endToken) {
debugEvent("ClassBody");
- push(popList(memberCount));
+ push(popList(memberCount,
+ new List<dynamic>.filled(memberCount, null, growable: true)));
}
@override
@@ -229,7 +230,9 @@
void endEnum(Token enumKeyword, Token leftBrace, int count) {
debugEvent("Enum");
- List<EnumConstantDeclaration> constants = popList(count);
+ List<EnumConstantDeclaration> constants =
+ new List.filled(count, null, growable: true);
+ popList(count, constants);
String name = pop();
List<Annotation> metadata = pop();
Comment comment = pop();
@@ -273,7 +276,7 @@
@override
void handleIdentifierList(int count) {
debugEvent("IdentifierList");
- push(popList(count));
+ push(popList(count, new List<dynamic>.filled(count, null, growable: true)));
}
@override
@@ -345,7 +348,9 @@
@override
void endMetadataStar(int count) {
debugEvent("MetadataStar");
- push(popList(count) ?? NullValue.Metadata);
+ push(
+ popList(count, new List<dynamic>.filled(count, null, growable: true)) ??
+ NullValue.Metadata);
}
void endMethod(
@@ -384,7 +389,8 @@
// We ignore top level variable declarations; they are present just to make
// the IDL analyze without warnings.
debugEvent("TopLevelFields");
- popList(count); // Fields
+ popList(
+ count, new List<dynamic>.filled(count, null, growable: true)); // Fields
pop(); // Type
pop(); // Metadata
pop(); // Comment
@@ -393,7 +399,7 @@
@override
void endTypeArguments(int count, Token beginToken, Token endToken) {
debugEvent("TypeArguments");
- push(popList(count));
+ push(popList(count, new List<dynamic>.filled(count, null, growable: true)));
}
@override
diff --git a/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart b/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart
index 865d169..3fc7fde7 100644
--- a/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart
+++ b/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart
@@ -139,11 +139,30 @@
final String message;
/**
- * Initialize a newly created kind of fix to have the given [name],
- * [priority] and [message].
+ * A human-readable description of the changes that will be applied by this
+ * kind of 'applied together' fix.
*/
- const FixKind(this.name, this.priority, this.message);
+ final String appliedTogetherMessage;
+
+ /**
+ * The change can be made with other fixes of this [FixKind].
+ */
+ bool canBeAppliedTogether() => appliedTogetherMessage != null;
+
+ /**
+ * Initialize a newly created kind of fix to have the given [name],
+ * [priority], [message], and optionally [canBeAppliedTogether] and
+ * [appliedTogetherMessage].
+ */
+ const FixKind(this.name, this.priority, this.message,
+ {this.appliedTogetherMessage: null});
@override
String toString() => name;
+
+ @override
+ bool operator ==(o) => o is FixKind && o.name == name;
+
+ @override
+ int get hashCode => name.hashCode;
}
diff --git a/pkg/build_integration/lib/file_system/multi_root.dart b/pkg/build_integration/lib/file_system/multi_root.dart
index 1163d39..ed1bb8c 100644
--- a/pkg/build_integration/lib/file_system/multi_root.dart
+++ b/pkg/build_integration/lib/file_system/multi_root.dart
@@ -4,7 +4,7 @@
import 'dart:async';
-import 'package:front_end/src/api_prototype/file_system.dart';
+import 'package:front_end/src/api_unstable/build_integration.dart';
/// Wraps a file system to create an overlay of files from multiple roots.
///
@@ -76,7 +76,7 @@
Future<String> readAsString() async => (await delegate).readAsString();
}
-_normalize(root) {
+Uri _normalize(root) {
Uri uri = root;
return uri.path.endsWith('/') ? uri : uri.replace(path: '${uri.path}/');
}
diff --git a/pkg/build_integration/lib/file_system/single_root.dart b/pkg/build_integration/lib/file_system/single_root.dart
new file mode 100644
index 0000000..175379d
--- /dev/null
+++ b/pkg/build_integration/lib/file_system/single_root.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:front_end/src/api_unstable/build_integration.dart';
+
+/// A [FileSystem] that resolves custom URIs to entities under a specified root
+/// folder on an underlying [FileSystem].
+///
+/// This abstraction lets packages like `package:front_end` use absolute URIs
+/// freely, while hiding machine-specific or user-specific details. In
+/// particular, this file-system is used to create a machine-independent .dill
+/// files in distributed build systems.
+///
+/// The resolution rules are as follows: if a given URI uses a special
+/// [markerScheme] it gets resolved under the given [root], while a given URI
+/// with any other scheme will produce an error.
+///
+/// For example, if [markerScheme] is `single-root`, and [root] is
+/// `file:///a/b/c/`, then, calling [entityForUri] will:
+///
+/// * resolve `single-root:///f1.dart` to `file:///a/b/c/f1.dart`.
+/// * resolve `single-root:///d/f2.dart` to `file:///a/b/c/d/f2.dart`.
+/// * throw on `other-custom-scheme:///d/f2.dart`.
+/// * throw on `file:///d/f2.dart`.
+class SingleRootFileSystem implements FileSystem {
+ final String markerScheme;
+ final Uri root;
+ final FileSystem original;
+
+ SingleRootFileSystem(this.markerScheme, Uri root, this.original)
+ : root = _normalize(root);
+
+ @override
+ FileSystemEntity entityForUri(Uri uri) {
+ if (uri.scheme != markerScheme) {
+ throw new FileSystemException(
+ uri,
+ "This SingleRootFileSystem only handles URIs with the '$markerScheme'"
+ " scheme and cannot handle URIs with scheme '${uri.scheme}': $uri");
+ }
+ if (!uri.path.startsWith('/')) {
+ throw new FileSystemException(
+ uri, "This SingleRootFileSystem only handles absolutes URIs: $uri");
+ }
+ var path = uri.path.substring(1);
+ return new SingleRootFileSystemEntity(
+ uri, original.entityForUri(root.resolve(path)));
+ }
+}
+
+/// [FileSystemEntity] with a URI of the `SingleRootFileSystem.markerScheme`,
+/// that delegates all operations to an underlying entity in the original
+/// `SingleRootFileSystem.filesystem`.
+class SingleRootFileSystemEntity implements FileSystemEntity {
+ final Uri uri;
+ final FileSystemEntity delegate;
+
+ SingleRootFileSystemEntity(this.uri, this.delegate);
+
+ @override
+ Future<bool> exists() async => delegate.exists();
+
+ @override
+ Future<List<int>> readAsBytes() async => delegate.readAsBytes();
+
+ @override
+ Future<String> readAsString() async => delegate.readAsString();
+}
+
+_normalize(root) {
+ Uri uri = root;
+ return uri.path.endsWith('/') ? uri : uri.replace(path: '${uri.path}/');
+}
diff --git a/pkg/build_integration/test/file_system/single_root_test.dart b/pkg/build_integration/test/file_system/single_root_test.dart
new file mode 100644
index 0000000..38ed4f8
--- /dev/null
+++ b/pkg/build_integration/test/file_system/single_root_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:build_integration/file_system/single_root.dart';
+import 'package:front_end/src/api_unstable/build_integration.dart';
+import 'package:front_end/src/api_prototype/memory_file_system.dart';
+import 'package:test/test.dart';
+
+main() {
+ var root = Uri.parse('org-dartlang-test:///');
+ var fileSystem = new SingleRootFileSystem(
+ 'single-root', root.resolve('A/B'), new MemoryFileSystem(root));
+
+ SingleRootFileSystemEntity entityOf(String uri) =>
+ fileSystem.entityForUri(Uri.parse(uri));
+
+ String effectiveUriOf(String uri) => '${entityOf(uri).delegate.uri}';
+
+ test('root is normalized', () {
+ expect(fileSystem.root.path, '/A/B/');
+ });
+
+ test('URIs with the marker scheme are converted', () {
+ expect(effectiveUriOf('single-root:///a/b/1.dart'),
+ 'org-dartlang-test:///A/B/a/b/1.dart');
+ });
+
+ test('single-root expects absolute paths', () {
+ expect(effectiveUriOf('single-root:///a/8.dart'),
+ 'org-dartlang-test:///A/B/a/8.dart');
+ expect(effectiveUriOf('single-root:///../B/a/8.dart'),
+ 'org-dartlang-test:///A/B/B/a/8.dart');
+ });
+
+ test('URIs with other schemes are not supported', () {
+ expect(() => entityOf('foo-root:///a/b/1.dart'),
+ throwsA((e) => e is FileSystemException));
+
+ // The scheme of the underlying file system is also not supported
+ expect(() => entityOf('org-dartlang-test:///a/b/1.dart'),
+ throwsA((e) => e is FileSystemException));
+ });
+}
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index cd2101a..6eb3847 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -119,8 +119,8 @@
return new Future.value();
}
- Future<Null> setupSdk() {
- Future future = new Future.value(null);
+ Future setupSdk() {
+ var future = new Future.value(null);
if (resolvedUriTranslator.isNotSet) {
future = future.then((_) {
return platform_configuration
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 0e83adc..884aadb 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -1118,6 +1118,9 @@
FunctionEntity get instantiatedGenericFunctionType =>
_findHelperFunction('instantiatedGenericFunctionType');
+ FunctionEntity get extractFunctionTypeObjectFromInternal =>
+ _findHelperFunction('extractFunctionTypeObjectFromInternal');
+
// From dart:_internal
ClassEntity _symbolImplementationClass;
@@ -1497,19 +1500,10 @@
/// Returns the metadata constants declared on [cls].
Iterable<ConstantValue> getClassMetadata(ClassEntity cls);
- /// Returns the metadata constants declared on [typedef].
- Iterable<ConstantValue> getTypedefMetadata(TypedefEntity typedef);
-
/// Returns the metadata constants declared on [member].
Iterable<ConstantValue> getMemberMetadata(MemberEntity member,
{bool includeParameterMetadata: false});
- /// Returns the function type that is an alias of a [typedef].
- FunctionType getFunctionTypeOfTypedef(TypedefEntity typedef);
-
- /// Returns the typedef type that is declared by a [typedef].
- TypedefType getTypedefTypeOfTypedef(TypedefEntity typedef);
-
/// Returns `true` if [cls] is a Dart enum class.
bool isEnumClass(ClassEntity cls);
}
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index a62b1a9..ca5e4ab 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -303,7 +303,6 @@
resolutionEnqueuer = enqueuer.createResolutionEnqueuer();
backend.onResolutionStart();
}
- resolutionEnqueuer.addDeferredActions(libraryLoader.pullDeferredActions());
return resolutionEnqueuer;
}
@@ -418,13 +417,13 @@
phase = PHASE_DONE_RESOLVING;
ClosedWorld closedWorld = resolutionWorldBuilder.closeWorld();
+ OutputUnitData result = deferredLoadTask.run(mainFunction, closedWorld);
ClosedWorldRefiner closedWorldRefiner =
backendStrategy.createClosedWorldRefiner(closedWorld);
// Compute whole-program-knowledge that the backend needs. (This might
// require the information computed in [world.closeWorld].)
backend.onResolutionClosedWorld(closedWorld, closedWorldRefiner);
- OutputUnitData result = deferredLoadTask.run(mainFunction, closedWorld);
backend.onDeferredLoadComplete(result);
// TODO(johnniwinther): Move this after rti computation but before
diff --git a/pkg/compiler/lib/src/constants/evaluation.dart b/pkg/compiler/lib/src/constants/evaluation.dart
index b647d48..fbeddd0 100644
--- a/pkg/compiler/lib/src/constants/evaluation.dart
+++ b/pkg/compiler/lib/src/constants/evaluation.dart
@@ -4,12 +4,13 @@
library dart2js.constants.evaluation;
+import 'package:front_end/src/fasta/util/link.dart' show Link;
+
import '../common.dart';
import '../common_elements.dart' show CommonElements;
import '../elements/entities.dart';
import '../elements/types.dart';
import '../universe/call_structure.dart' show CallStructure;
-import '../util/util.dart' show Link;
import 'constructors.dart';
import 'expressions.dart';
import 'values.dart';
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 0c6117c..e1a8e61 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -133,7 +133,7 @@
bool showHints;
bool enableColors;
Uri platformBinaries = computePlatformBinariesLocation();
- Map<String, dynamic> environment = new Map<String, dynamic>();
+ Map<String, String> environment = new Map<String, String>();
void passThrough(String argument) => options.add(argument);
void ignoreOption(String argument) {}
@@ -787,7 +787,7 @@
Future<api.CompilationResult> internalMain(List<String> arguments,
{fe.InitializedCompilerState kernelInitializedCompilerState}) {
- Future onError(exception, trace) {
+ Future<api.CompilationResult> onError(exception, trace) {
// If we are already trying to exit, just continue exiting.
if (exception == _EXIT_SIGNAL) throw exception;
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 2064ae8..7418a1a 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -16,11 +16,9 @@
ConstructedConstantValue,
DeferredConstantValue,
DeferredGlobalConstantValue,
- InstantiationConstantValue,
- TypeConstantValue;
+ InstantiationConstantValue;
import 'elements/types.dart';
import 'elements/entities.dart';
-import 'kernel/kelements.dart' show KLocalFunction;
import 'universe/use.dart';
import 'universe/world_impact.dart'
show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
@@ -111,8 +109,15 @@
/// this map.
final Map<ImportEntity, String> _importDeferName = <ImportEntity, String>{};
- /// A mapping from elements and constants to their import set.
- Map<Entity, ImportSet> _elementToSet = new Map<Entity, ImportSet>();
+ /// A mapping from classes to their import set.
+ Map<ClassEntity, ImportSet> _classToSet = new Map<ClassEntity, ImportSet>();
+
+ /// A mapping from members to their import set.
+ Map<MemberEntity, ImportSet> _memberToSet =
+ new Map<MemberEntity, ImportSet>();
+
+ /// A mapping from local functions to their import set.
+ Map<Local, ImportSet> _localFunctionToSet = new Map<Local, ImportSet>();
/// A mapping from constants to their import set.
Map<ConstantValue, ImportSet> _constantToSet =
@@ -180,69 +185,72 @@
}
/// Returns every [ImportEntity] that imports [element] into [library].
- Iterable<ImportEntity> importsTo(Entity element, LibraryEntity library);
+ Iterable<ImportEntity> classImportsTo(
+ ClassEntity element, LibraryEntity library);
+
+ /// Returns every [ImportEntity] that imports [element] into [library].
+ Iterable<ImportEntity> memberImportsTo(
+ MemberEntity element, LibraryEntity library);
+
+ /// Collects all direct dependencies of [element].
+ ///
+ /// The collected dependent elements and constants are are added to
+ /// [elements] and [constants] respectively.
+ void _collectDirectMemberDependencies(
+ MemberEntity element, Dependencies dependencies) {
+ // TODO(sigurdm): We want to be more specific about this - need a better
+ // way to query "liveness".
+ if (!compiler.resolutionWorldBuilder.isMemberUsed(element)) {
+ return;
+ }
+ _collectDependenciesFromImpact(element, dependencies);
+ collectConstantsInBody(element, dependencies);
+ }
/// Finds all elements and constants that [element] depends directly on.
/// (not the transitive closure.)
///
/// Adds the results to [elements] and [constants].
- void _collectAllElementsAndConstantsResolvedFrom(Entity element,
- Set<Entity> elements, Set<ConstantValue> constants, isMirrorUsage) {
- /// Collects all direct dependencies of [element].
- ///
- /// The collected dependent elements and constants are are added to
- /// [elements] and [constants] respectively.
- void collectDependencies(Entity element) {
- if (element is TypedefEntity) {
- _collectTypeDependencies(
- elementEnvironment.getTypedefTypeOfTypedef(element), elements);
- return;
- }
-
- // TODO(sigurdm): We want to be more specific about this - need a better
- // way to query "liveness".
- if (!compiler.resolutionWorldBuilder.isMemberUsed(element)) {
- return;
- }
- _collectDependenciesFromImpact(element, elements);
- collectConstantsInBody(element, constants);
+ void _collectAllElementsAndConstantsResolvedFromClass(
+ ClassEntity element, Dependencies dependencies) {
+ // If we see a class, add everything its live instance members refer
+ // to. Static members are not relevant, unless we are processing
+ // extra dependencies due to mirrors.
+ void addLiveInstanceMember(MemberEntity member) {
+ if (!compiler.resolutionWorldBuilder.isMemberUsed(member)) return;
+ if (!member.isInstanceMember) return;
+ dependencies.members.add(member);
+ _collectDirectMemberDependencies(member, dependencies);
}
+ ClassEntity cls = element;
+ elementEnvironment.forEachLocalClassMember(cls, addLiveInstanceMember);
+ elementEnvironment.forEachSupertype(cls, (InterfaceType type) {
+ _collectTypeDependencies(type, dependencies);
+ });
+ dependencies.classes.add(cls);
+ }
+
+ /// Finds all elements and constants that [element] depends directly on.
+ /// (not the transitive closure.)
+ ///
+ /// Adds the results to [elements] and [constants].
+ void _collectAllElementsAndConstantsResolvedFromMember(
+ MemberEntity element, Dependencies dependencies) {
if (element is FunctionEntity) {
_collectTypeDependencies(
- elementEnvironment.getFunctionType(element), elements);
+ elementEnvironment.getFunctionType(element), dependencies);
}
-
- if (element is ClassEntity) {
- // If we see a class, add everything its live instance members refer
- // to. Static members are not relevant, unless we are processing
- // extra dependencies due to mirrors.
- void addLiveInstanceMember(_element) {
- MemberEntity element = _element;
- if (!compiler.resolutionWorldBuilder.isMemberUsed(element)) return;
- if (!isMirrorUsage && !element.isInstanceMember) return;
- elements.add(element);
- collectDependencies(element);
- }
-
- ClassEntity cls = element;
- elementEnvironment.forEachLocalClassMember(cls, addLiveInstanceMember);
- elementEnvironment.forEachSupertype(cls, (InterfaceType type) {
- _collectTypeDependencies(type, elements);
- });
- elements.add(cls);
- } else if (element is MemberEntity &&
- (element.isStatic || element.isTopLevel || element.isConstructor)) {
- elements.add(element);
- collectDependencies(element);
+ if (element.isStatic || element.isTopLevel || element.isConstructor) {
+ dependencies.members.add(element);
+ _collectDirectMemberDependencies(element, dependencies);
}
if (element is ConstructorEntity && element.isGenerativeConstructor) {
// When instantiating a class, we record a reference to the
// constructor, not the class itself. We must add all the
// instance members of the constructor's class.
ClassEntity cls = element.enclosingClass;
- _collectAllElementsAndConstantsResolvedFrom(
- cls, elements, constants, isMirrorUsage);
+ _collectAllElementsAndConstantsResolvedFromClass(cls, dependencies);
}
// Other elements, in particular instance members, are ignored as
@@ -257,45 +265,55 @@
Entity element, Set<ConstantValue> constants);
/// Extract the set of constants that are used in the body of [element].
- void collectConstantsInBody(Entity element, Set<ConstantValue> constants);
+ void collectConstantsInBody(MemberEntity element, Dependencies dependencies);
/// Recursively collects all the dependencies of [type].
- void _collectTypeDependencies(DartType type, Set<Entity> elements) {
+ void _collectTypeDependencies(DartType type, Dependencies dependencies) {
// TODO(het): we would like to separate out types that are only needed for
// rti from types that are needed for their members.
if (type is FunctionType) {
for (DartType argumentType in type.parameterTypes) {
- _collectTypeDependencies(argumentType, elements);
+ _collectTypeDependencies(argumentType, dependencies);
}
for (DartType argumentType in type.optionalParameterTypes) {
- _collectTypeDependencies(argumentType, elements);
+ _collectTypeDependencies(argumentType, dependencies);
}
for (DartType argumentType in type.namedParameterTypes) {
- _collectTypeDependencies(argumentType, elements);
+ _collectTypeDependencies(argumentType, dependencies);
}
- _collectTypeDependencies(type.returnType, elements);
+ _collectTypeDependencies(type.returnType, dependencies);
} else if (type is TypedefType) {
- type.typeArguments.forEach((t) => _collectTypeDependencies(t, elements));
- elements.add(type.element);
- _collectTypeDependencies(type.unaliased, elements);
+ type.typeArguments
+ .forEach((t) => _collectTypeDependencies(t, dependencies));
+ _collectTypeDependencies(type.unaliased, dependencies);
} else if (type is InterfaceType) {
- type.typeArguments.forEach((t) => _collectTypeDependencies(t, elements));
- elements.add(type.element);
+ type.typeArguments
+ .forEach((t) => _collectTypeDependencies(t, dependencies));
+ dependencies.classes.add(type.element);
}
}
/// Extract any dependencies that are known from the impact of [element].
- void _collectDependenciesFromImpact(Entity element, Set<Entity> elements) {
+ void _collectDependenciesFromImpact(
+ MemberEntity element, Dependencies dependencies) {
WorldImpact worldImpact = compiler.impactCache[element];
compiler.impactStrategy.visitImpact(
element,
worldImpact,
new WorldImpactVisitorImpl(visitStaticUse: (StaticUse staticUse) {
- elements.add(staticUse.element);
+ if (staticUse.element is MemberEntity) {
+ dependencies.members.add(staticUse.element);
+ } else {
+ assert(
+ staticUse.element is Local,
+ failedAt(
+ staticUse.element, "Unexpected static use $staticUse."));
+ dependencies.localFunctions.add(staticUse.element);
+ }
switch (staticUse.kind) {
case StaticUseKind.CONSTRUCTOR_INVOKE:
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
- _collectTypeDependencies(staticUse.type, elements);
+ _collectTypeDependencies(staticUse.type, dependencies);
break;
case StaticUseKind.INVOKE:
case StaticUseKind.CLOSURE_CALL:
@@ -305,7 +323,7 @@
List<DartType> typeArguments = staticUse.typeArguments;
if (typeArguments != null) {
for (DartType typeArgument in typeArguments) {
- _collectTypeDependencies(typeArgument, elements);
+ _collectTypeDependencies(typeArgument, dependencies);
}
}
break;
@@ -315,12 +333,9 @@
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.TYPE_LITERAL:
- if (type.isTypedef) {
- TypedefType typedef = type;
- elements.add(typedef.element);
- } else if (type.isInterfaceType) {
+ if (type.isInterfaceType) {
InterfaceType interface = type;
- elements.add(interface.element);
+ dependencies.classes.add(interface.element);
}
break;
case TypeUseKind.INSTANTIATION:
@@ -329,21 +344,21 @@
case TypeUseKind.IS_CHECK:
case TypeUseKind.AS_CAST:
case TypeUseKind.CATCH_TYPE:
- _collectTypeDependencies(type, elements);
+ _collectTypeDependencies(type, dependencies);
break;
case TypeUseKind.IMPLICIT_CAST:
if (compiler.options.implicitDowncastCheckPolicy.isEmitted) {
- _collectTypeDependencies(type, elements);
+ _collectTypeDependencies(type, dependencies);
}
break;
case TypeUseKind.PARAMETER_CHECK:
if (compiler.options.parameterCheckPolicy.isEmitted) {
- _collectTypeDependencies(type, elements);
+ _collectTypeDependencies(type, dependencies);
}
break;
case TypeUseKind.CHECKED_MODE_CHECK:
if (compiler.options.assignmentCheckPolicy.isEmitted) {
- _collectTypeDependencies(type, elements);
+ _collectTypeDependencies(type, dependencies);
}
break;
}
@@ -353,7 +368,7 @@
List<DartType> typeArguments = dynamicUse.typeArguments;
if (typeArguments != null) {
for (DartType typeArgument in typeArguments) {
- _collectTypeDependencies(typeArgument, elements);
+ _collectTypeDependencies(typeArgument, dependencies);
}
}
}),
@@ -380,18 +395,12 @@
_constantToSet[constant] = newSet;
if (constant is ConstructedConstantValue) {
ClassEntity cls = constant.type.element;
- _updateElementRecursive(cls, oldSet, newSet, queue);
- }
- if (constant is TypeConstantValue) {
- var type = constant.representedType;
- if (type is TypedefType) {
- _updateElementRecursive(type.element, oldSet, newSet, queue);
- }
+ _updateClassRecursive(cls, oldSet, newSet, queue);
}
if (constant is InstantiationConstantValue) {
for (DartType type in constant.typeArguments) {
if (type is InterfaceType) {
- _updateElementRecursive(type.element, oldSet, newSet, queue);
+ _updateClassRecursive(type.element, oldSet, newSet, queue);
}
}
}
@@ -421,77 +430,111 @@
}
}
- /// Update the import set of all elements reachable from [element], as long as
- /// they had the [oldSet]. As soon as we see an element with a different
- /// import set, we stop and enqueue a new recursive update in [queue].
- void _updateElementRecursive(
- Entity element, ImportSet oldSet, ImportSet newSet, WorkQueue queue,
- {bool isMirrorUsage: false}) {
+ void _updateClassRecursive(ClassEntity element, ImportSet oldSet,
+ ImportSet newSet, WorkQueue queue) {
if (element == null) return;
- var currentSet = _elementToSet[element];
+
+ ImportSet currentSet = _classToSet[element];
// Already visited. We may visit some root nodes a second time with
// [isMirrorUsage] in order to mark static members used reflectively.
- if (currentSet == newSet && !isMirrorUsage) return;
+ if (currentSet == newSet) return;
// Elements in the main output unit always remain there.
if (currentSet == importSets.mainSet) return;
if (currentSet == oldSet) {
// Continue recursively updating from [oldSet] to [newSet].
- _elementToSet[element] = newSet;
+ _classToSet[element] = newSet;
- Set<Entity> dependentElements = new Set<Entity>();
- Set<ConstantValue> dependentConstants = new Set<ConstantValue>();
- _collectAllElementsAndConstantsResolvedFrom(
- element, dependentElements, dependentConstants, isMirrorUsage);
-
- // TODO(sigmund): split API to collect data about each kind of entity
- // separately so we can avoid this ugly pattern.
- LibraryEntity library;
- if (element is ClassEntity) {
- library = element.library;
- } else if (element is MemberEntity) {
- library = element.library;
- } else if (element is TypedefEntity) {
- library = element.library;
- } else if (element is KLocalFunction) {
- // TODO(sigmund): consider adding `Local.library`
- library = element.memberContext.library;
- } else {
- assert(false, "Unexpected entity: ${element.runtimeType}");
- }
-
- for (Entity dependency in dependentElements) {
- Iterable<ImportEntity> imports = importsTo(dependency, library);
- if (_isExplicitlyDeferred(imports)) {
- /// New deferred-imports are only discovered when we are visiting the
- /// main output unit (size == 0) or code reachable from a deferred
- /// import (size == 1). After that, we are rediscovering the
- /// same nodes we have already seen.
- if (newSet.length <= 1) {
- for (ImportEntity deferredImport in imports) {
- queue.addElement(
- dependency, importSets.singleton(deferredImport));
- }
- }
- } else {
- _updateElementRecursive(dependency, oldSet, newSet, queue);
- }
- }
-
- for (ConstantValue dependency in dependentConstants) {
- if (dependency is DeferredConstantValue) {
- if (newSet.length <= 1) {
- queue.addConstant(
- dependency, importSets.singleton(dependency.import));
- }
- } else {
- _updateConstantRecursive(dependency, oldSet, newSet, queue);
- }
- }
+ Dependencies dependencies = new Dependencies();
+ _collectAllElementsAndConstantsResolvedFromClass(element, dependencies);
+ LibraryEntity library = element.library;
+ _processDependencies(library, dependencies, oldSet, newSet, queue);
} else {
- queue.addElement(element, newSet);
+ queue.addClass(element, newSet);
+ }
+ }
+
+ void _updateMemberRecursive(MemberEntity element, ImportSet oldSet,
+ ImportSet newSet, WorkQueue queue) {
+ if (element == null) return;
+
+ ImportSet currentSet = _memberToSet[element];
+
+ // Already visited. We may visit some root nodes a second time with
+ // [isMirrorUsage] in order to mark static members used reflectively.
+ if (currentSet == newSet) return;
+
+ // Elements in the main output unit always remain there.
+ if (currentSet == importSets.mainSet) return;
+
+ if (currentSet == oldSet) {
+ // Continue recursively updating from [oldSet] to [newSet].
+ _memberToSet[element] = newSet;
+
+ Dependencies dependencies = new Dependencies();
+ _collectAllElementsAndConstantsResolvedFromMember(element, dependencies);
+
+ LibraryEntity library = element.library;
+ _processDependencies(library, dependencies, oldSet, newSet, queue);
+ } else {
+ queue.addMember(element, newSet);
+ }
+ }
+
+ void _processDependencies(LibraryEntity library, Dependencies dependencies,
+ ImportSet oldSet, ImportSet newSet, WorkQueue queue) {
+ for (ClassEntity cls in dependencies.classes) {
+ Iterable<ImportEntity> imports = classImportsTo(cls, library);
+ if (_isExplicitlyDeferred(imports)) {
+ /// New deferred-imports are only discovered when we are visiting the
+ /// main output unit (size == 0) or code reachable from a deferred
+ /// import (size == 1). After that, we are rediscovering the
+ /// same nodes we have already seen.
+ if (newSet.length <= 1) {
+ for (ImportEntity deferredImport in imports) {
+ queue.addClass(cls, importSets.singleton(deferredImport));
+ }
+ }
+ } else {
+ _updateClassRecursive(cls, oldSet, newSet, queue);
+ }
+ }
+
+ for (MemberEntity member in dependencies.members) {
+ Iterable<ImportEntity> imports = memberImportsTo(member, library);
+ if (_isExplicitlyDeferred(imports)) {
+ /// New deferred-imports are only discovered when we are visiting the
+ /// main output unit (size == 0) or code reachable from a deferred
+ /// import (size == 1). After that, we are rediscovering the
+ /// same nodes we have already seen.
+ if (newSet.length <= 1) {
+ for (ImportEntity deferredImport in imports) {
+ queue.addMember(member, importSets.singleton(deferredImport));
+ }
+ }
+ } else {
+ _updateMemberRecursive(member, oldSet, newSet, queue);
+ }
+ }
+
+ for (Local localFunction in dependencies.localFunctions) {
+ // Local function are not updated recursively because the dependencies are
+ // already visited as dependencies of the enclosing member, so we just
+ // assign the [newSet] to each local function.
+ _localFunctionToSet[localFunction] = newSet;
+ }
+
+ for (ConstantValue dependency in dependencies.constants) {
+ if (dependency is DeferredConstantValue) {
+ if (newSet.length <= 1) {
+ queue.addConstant(
+ dependency, importSets.singleton(dependency.import));
+ }
+ } else {
+ _updateConstantRecursive(dependency, oldSet, newSet, queue);
+ }
}
}
@@ -517,7 +560,9 @@
// Generate an output unit for all import sets that are associated with an
// element or constant.
- _elementToSet.values.forEach(addUnit);
+ _classToSet.values.forEach(addUnit);
+ _memberToSet.values.forEach(addUnit);
+ _localFunctionToSet.values.forEach(addUnit);
_constantToSet.values.forEach(addUnit);
// Sort output units to make the output of the compiler more stable.
@@ -665,7 +710,7 @@
// Add `main` and their recursive dependencies to the main output unit.
// We do this upfront to avoid wasting time visiting these elements when
// analyzing deferred imports.
- queue.addElement(main, importSets.mainSet);
+ queue.addMember(main, importSets.mainSet);
// Also add "global" dependencies to the main output unit. These are
// things that the backend needs but cannot associate with a particular
@@ -673,26 +718,17 @@
// information.
for (MemberEntity element
in closedWorld.backendUsage.globalFunctionDependencies) {
- queue.addElement(element, importSets.mainSet);
+ queue.addMember(element, importSets.mainSet);
}
for (ClassEntity element
in closedWorld.backendUsage.globalClassDependencies) {
- queue.addElement(element, importSets.mainSet);
+ queue.addClass(element, importSets.mainSet);
}
void emptyQueue() {
while (queue.isNotEmpty) {
- var item = queue.nextItem();
- if (item.element != null) {
- var oldSet = _elementToSet[item.element];
- var newSet = importSets.union(oldSet, item.newSet);
- _updateElementRecursive(item.element, oldSet, newSet, queue,
- isMirrorUsage: item.isMirrorUsage);
- } else if (item.value != null) {
- var oldSet = _constantToSet[item.value];
- var newSet = importSets.union(oldSet, item.newSet);
- _updateConstantRecursive(item.value, oldSet, newSet, queue);
- }
+ WorkItem item = queue.nextItem();
+ item.update(this, queue);
}
}
@@ -710,16 +746,29 @@
OutputUnitData _buildResult() {
_createOutputUnits();
_setupHunksToLoad();
- Map<Entity, OutputUnit> entityMap = <Entity, OutputUnit>{};
+ Map<ClassEntity, OutputUnit> classMap = <ClassEntity, OutputUnit>{};
+ Map<MemberEntity, OutputUnit> memberMap = <MemberEntity, OutputUnit>{};
+ Map<Local, OutputUnit> localFunctionMap = <Local, OutputUnit>{};
Map<ConstantValue, OutputUnit> constantMap = <ConstantValue, OutputUnit>{};
- _elementToSet.forEach((entity, s) => entityMap[entity] = s.unit);
+ _classToSet.forEach((cls, s) => classMap[cls] = s.unit);
+ _memberToSet.forEach((member, s) => memberMap[member] = s.unit);
+ _localFunctionToSet.forEach(
+ (localFunction, s) => localFunctionMap[localFunction] = s.unit);
_constantToSet.forEach((constant, s) => constantMap[constant] = s.unit);
- _elementToSet = null;
+ _classToSet = null;
+ _memberToSet = null;
+ _localFunctionToSet = null;
_constantToSet = null;
cleanup();
- return new OutputUnitData(this.isProgramSplit && !disableProgramSplit,
- this.mainOutputUnit, entityMap, constantMap, importSets);
+ return new OutputUnitData(
+ this.isProgramSplit && !disableProgramSplit,
+ this.mainOutputUnit,
+ classMap,
+ memberMap,
+ localFunctionMap,
+ constantMap,
+ importSets);
}
/// Frees up strategy-specific temporary data.
@@ -808,25 +857,31 @@
String dump() {
Map<OutputUnit, List<String>> elementMap = <OutputUnit, List<String>>{};
Map<OutputUnit, List<String>> constantMap = <OutputUnit, List<String>>{};
- _elementToSet.forEach((Entity element, ImportSet importSet) {
+ _classToSet.forEach((ClassEntity element, ImportSet importSet) {
if (ignoreEntityInDump(element)) return;
var elements = elementMap.putIfAbsent(importSet.unit, () => <String>[]);
var id = element.name ?? '$element';
- if (element is MemberEntity) {
- var cls = element.enclosingClass?.name;
- if (cls != null) id = '$cls.$id';
- if (element.isSetter) id = '$id=';
- id = '$id member';
- } else if (element is ClassEntity) {
- id = '$id cls';
- } else if (element is TypedefEntity) {
- id = '$id typedef';
- } else if (element is Local) {
- var context = (element as dynamic).memberContext.name;
- id = element.name == null || element.name == '' ? '<anonymous>' : id;
- id = '$context.$id';
- id = '$id local';
- }
+ id = '$id cls';
+ elements.add(id);
+ });
+ _memberToSet.forEach((MemberEntity element, ImportSet importSet) {
+ if (ignoreEntityInDump(element)) return;
+ var elements = elementMap.putIfAbsent(importSet.unit, () => <String>[]);
+ var id = element.name ?? '$element';
+ var cls = element.enclosingClass?.name;
+ if (cls != null) id = '$cls.$id';
+ if (element.isSetter) id = '$id=';
+ id = '$id member';
+ elements.add(id);
+ });
+ _localFunctionToSet.forEach((Local element, ImportSet importSet) {
+ if (ignoreEntityInDump(element)) return;
+ var elements = elementMap.putIfAbsent(importSet.unit, () => <String>[]);
+ var id = element.name ?? '$element';
+ var context = (element as dynamic).memberContext.name;
+ id = element.name == null || element.name == '' ? '<anonymous>' : id;
+ id = '$context.$id';
+ id = '$id local';
elements.add(id);
});
_constantToSet.forEach((ConstantValue value, ImportSet importSet) {
@@ -1027,8 +1082,11 @@
/// The actual queue of work that needs to be done.
final Queue<WorkItem> queue = new Queue<WorkItem>();
- /// An index to find work items in the queue corresponding to an entity.
- final Map<Entity, WorkItem> pendingElements = <Entity, WorkItem>{};
+ /// An index to find work items in the queue corresponding to a class.
+ final Map<ClassEntity, WorkItem> pendingClasses = <ClassEntity, WorkItem>{};
+
+ /// An index to find work items in the queue corresponding to a member.
+ final Map<MemberEntity, WorkItem> pendingMembers = <MemberEntity, WorkItem>{};
/// An index to find work items in the queue corresponding to a constant.
final Map<ConstantValue, WorkItem> pendingConstants =
@@ -1045,26 +1103,37 @@
/// Pop the next element in the queue.
WorkItem nextItem() {
assert(isNotEmpty);
- var item = queue.removeFirst();
- if (item.element != null) pendingElements.remove(item.element);
- if (item.value != null) pendingConstants.remove(item.value);
- return item;
+ return queue.removeFirst();
}
/// Add to the queue that [element] should be updated to include all imports
/// in [importSet]. If there is already a work item in the queue for
/// [element], this makes sure that the work item now includes the union of
/// [importSet] and the existing work item's import set.
- void addElement(Entity element, ImportSet importSet, {isMirrorUsage: false}) {
- var item = pendingElements[element];
+ void addClass(ClassEntity element, ImportSet importSet) {
+ var item = pendingClasses[element];
if (item == null) {
- item = new WorkItem(element, importSet);
- pendingElements[element] = item;
+ item = new ClassWorkItem(element, importSet);
+ pendingClasses[element] = item;
queue.add(item);
} else {
- item.newSet = _importSets.union(item.newSet, importSet);
+ item.importsToAdd = _importSets.union(item.importsToAdd, importSet);
}
- if (isMirrorUsage) item.isMirrorUsage = true;
+ }
+
+ /// Add to the queue that [element] should be updated to include all imports
+ /// in [importSet]. If there is already a work item in the queue for
+ /// [element], this makes sure that the work item now includes the union of
+ /// [importSet] and the existing work item's import set.
+ void addMember(MemberEntity element, ImportSet importSet) {
+ var item = pendingMembers[element];
+ if (item == null) {
+ item = new MemberWorkItem(element, importSet);
+ pendingMembers[element] = item;
+ queue.add(item);
+ } else {
+ item.importsToAdd = _importSets.union(item.importsToAdd, importSet);
+ }
}
/// Add to the queue that [constant] should be updated to include all imports
@@ -1074,39 +1143,73 @@
void addConstant(ConstantValue constant, ImportSet importSet) {
var item = pendingConstants[constant];
if (item == null) {
- item = new WorkItem.constant(constant, importSet);
+ item = new ConstantWorkItem(constant, importSet);
pendingConstants[constant] = item;
queue.add(item);
} else {
- item.newSet = _importSets.union(item.newSet, importSet);
+ item.importsToAdd = _importSets.union(item.importsToAdd, importSet);
}
}
}
-/// Summary of the work that needs to be done on an entity or constant.
-class WorkItem {
- /// Entity to be recursively updated.
- final Entity element;
-
- /// Constant to be recursively updated.
- final ConstantValue value;
-
+/// Summary of the work that needs to be done on a class, member, or constant.
+abstract class WorkItem {
/// Additional imports that use [element] or [value] and need to be added by
/// the algorithm.
///
/// This is non-final in case we add more deferred imports to the set before
/// the work item is applied (see [WorkQueue.addElement] and
/// [WorkQueue.addConstant]).
- ImportSet newSet;
+ ImportSet importsToAdd;
- /// Whether [element] is used via mirrors.
- ///
- /// This is non-final in case we later discover that the same [element] is
- /// used via mirrors (but before the work item is applied).
- bool isMirrorUsage = false;
+ WorkItem(this.importsToAdd);
- WorkItem(this.element, this.newSet) : value = null;
- WorkItem.constant(this.value, this.newSet) : element = null;
+ void update(DeferredLoadTask task, WorkQueue queue);
+}
+
+/// Summary of the work that needs to be done on a class.
+class ClassWorkItem extends WorkItem {
+ /// Class to be recursively updated.
+ final ClassEntity cls;
+
+ ClassWorkItem(this.cls, ImportSet newSet) : super(newSet);
+
+ void update(DeferredLoadTask task, WorkQueue queue) {
+ queue.pendingClasses.remove(cls);
+ ImportSet oldSet = task._classToSet[cls];
+ ImportSet newSet = task.importSets.union(oldSet, importsToAdd);
+ task._updateClassRecursive(cls, oldSet, newSet, queue);
+ }
+}
+
+/// Summary of the work that needs to be done on a member.
+class MemberWorkItem extends WorkItem {
+ /// Member to be recursively updated.
+ final MemberEntity member;
+
+ MemberWorkItem(this.member, ImportSet newSet) : super(newSet);
+
+ void update(DeferredLoadTask task, WorkQueue queue) {
+ queue.pendingMembers.remove(member);
+ ImportSet oldSet = task._memberToSet[member];
+ ImportSet newSet = task.importSets.union(oldSet, importsToAdd);
+ task._updateMemberRecursive(member, oldSet, newSet, queue);
+ }
+}
+
+/// Summary of the work that needs to be done on a constant.
+class ConstantWorkItem extends WorkItem {
+ /// Constant to be recursively updated.
+ final ConstantValue constant;
+
+ ConstantWorkItem(this.constant, ImportSet newSet) : super(newSet);
+
+ void update(DeferredLoadTask task, WorkQueue queue) {
+ queue.pendingConstants.remove(constant);
+ ImportSet oldSet = task._constantToSet[constant];
+ ImportSet newSet = task.importSets.union(oldSet, importsToAdd);
+ task._updateConstantRecursive(constant, oldSet, newSet, queue);
+ }
}
/// Results of the deferred loading algorithm.
@@ -1118,57 +1221,63 @@
class OutputUnitData {
final bool isProgramSplit;
final OutputUnit mainOutputUnit;
- final Map<Entity, OutputUnit> _entityToUnit;
+ final Map<ClassEntity, OutputUnit> _classToUnit;
+ final Map<MemberEntity, OutputUnit> _memberToUnit;
+ final Map<Local, OutputUnit> _localFunctionToUnit;
final Map<ConstantValue, OutputUnit> _constantToUnit;
final ImportSetLattice _importSets;
- OutputUnitData(this.isProgramSplit, this.mainOutputUnit, this._entityToUnit,
- this._constantToUnit, this._importSets);
+ OutputUnitData(
+ this.isProgramSplit,
+ this.mainOutputUnit,
+ this._classToUnit,
+ this._memberToUnit,
+ this._localFunctionToUnit,
+ this._constantToUnit,
+ this._importSets);
OutputUnitData.from(
OutputUnitData other,
- Map<Entity, OutputUnit> Function(Map<Entity, OutputUnit>)
- convertEntityMap,
+ Map<ClassEntity, OutputUnit> Function(
+ Map<ClassEntity, OutputUnit>, Map<Local, OutputUnit>)
+ convertClassMap,
+ Map<MemberEntity, OutputUnit> Function(
+ Map<MemberEntity, OutputUnit>, Map<Local, OutputUnit>)
+ convertMemberMap,
Map<ConstantValue, OutputUnit> Function(Map<ConstantValue, OutputUnit>)
convertConstantMap)
: isProgramSplit = other.isProgramSplit,
mainOutputUnit = other.mainOutputUnit,
- _entityToUnit = convertEntityMap(other._entityToUnit),
+ _memberToUnit =
+ convertMemberMap(other._memberToUnit, other._localFunctionToUnit),
+ _classToUnit =
+ convertClassMap(other._classToUnit, other._localFunctionToUnit),
+ _localFunctionToUnit = const <Local, OutputUnit>{},
_constantToUnit = convertConstantMap(other._constantToUnit),
_importSets = other._importSets;
- /// Returns the [OutputUnit] where [element] belongs.
- OutputUnit outputUnitForEntity(Entity entity) {
- // TODO(johnniwinther): Support use of entities by splitting maps by
- // entity kind.
+ /// Returns the [OutputUnit] where [cls] belongs.
+ OutputUnit outputUnitForClass(ClassEntity cls) {
if (!isProgramSplit) return mainOutputUnit;
- OutputUnit unit = _entityToUnit[entity];
+ OutputUnit unit = _classToUnit[cls];
+ return unit ?? mainOutputUnit;
+ }
+
+ /// Returns the [OutputUnit] where [member] belongs.
+ OutputUnit outputUnitForMember(MemberEntity member) {
+ if (!isProgramSplit) return mainOutputUnit;
+ OutputUnit unit = _memberToUnit[member];
if (unit != null) return unit;
- if (entity is MemberEntity && entity.isInstanceMember) {
- return outputUnitForEntity(entity.enclosingClass);
+ if (member.isInstanceMember) {
+ return outputUnitForClass(member.enclosingClass);
}
return mainOutputUnit;
}
- /// Direct access to the output-unit to element relation used for testing.
- OutputUnit outputUnitForEntityForTesting(Entity entity) {
- return _entityToUnit[entity];
- }
-
/// Direct access to the output-unit to constants map used for testing.
Iterable<ConstantValue> get constantsForTesting => _constantToUnit.keys;
- /// Returns the [OutputUnit] where [element] belongs.
- OutputUnit outputUnitForClass(ClassEntity element) {
- return outputUnitForEntity(element);
- }
-
- /// Returns the [OutputUnit] where [element] belongs.
- OutputUnit outputUnitForMember(MemberEntity element) {
- return outputUnitForEntity(element);
- }
-
/// Returns the [OutputUnit] where [constant] belongs.
OutputUnit outputUnitForConstant(ConstantValue constant) {
if (!isProgramSplit) return mainOutputUnit;
@@ -1176,13 +1285,8 @@
}
/// Indicates whether [element] is deferred.
- bool isDeferred(Entity element) {
- return outputUnitForEntity(element) != mainOutputUnit;
- }
-
- /// Indicates whether [element] is deferred.
bool isDeferredClass(ClassEntity element) {
- return outputUnitForEntity(element) != mainOutputUnit;
+ return outputUnitForClass(element) != mainOutputUnit;
}
/// Returns `true` if element [to] is reachable from element [from] without
@@ -1191,9 +1295,9 @@
/// For example, if we have two deferred libraries `A` and `B` that both
/// import a library `C`, then even though elements from `A` and `C` end up in
/// different output units, there is a non-deferred path between `A` and `C`.
- bool hasOnlyNonDeferredImportPaths(Entity from, Entity to) {
- OutputUnit outputUnitFrom = outputUnitForEntity(from);
- OutputUnit outputUnitTo = outputUnitForEntity(to);
+ bool hasOnlyNonDeferredImportPaths(MemberEntity from, MemberEntity to) {
+ OutputUnit outputUnitFrom = outputUnitForMember(from);
+ OutputUnit outputUnitTo = outputUnitForMember(to);
if (outputUnitTo == mainOutputUnit) return true;
if (outputUnitFrom == mainOutputUnit) return false;
return outputUnitTo._imports.containsAll(outputUnitFrom._imports);
@@ -1213,7 +1317,14 @@
/// [existingEntity];
void registerColocatedMembers(
MemberEntity existingEntity, MemberEntity newEntity) {
- assert(_entityToUnit[newEntity] == null);
- _entityToUnit[newEntity] = outputUnitForMember(existingEntity);
+ assert(_memberToUnit[newEntity] == null);
+ _memberToUnit[newEntity] = outputUnitForMember(existingEntity);
}
}
+
+class Dependencies {
+ final Set<ClassEntity> classes = new Set<ClassEntity>();
+ final Set<MemberEntity> members = new Set<MemberEntity>();
+ final Set<Local> localFunctions = new Set<Local>();
+ final Set<ConstantValue> constants = new Set<ConstantValue>();
+}
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 75010fd..a723729 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -55,7 +55,6 @@
result.constants.add(info);
});
environment.libraries.forEach(visitLibrary);
- closedWorld.allTypedefs.forEach(visitTypedef);
}
/// Whether to emit information about [entity].
@@ -106,18 +105,6 @@
return info;
}
- TypedefInfo visitTypedef(TypedefEntity typdef) {
- var type = environment.getFunctionTypeOfTypedef(typdef);
- TypedefInfo info =
- new TypedefInfo(typdef.name, '$type', _unitInfoForEntity(typdef));
- _entityToInfo[typdef] = info;
- LibraryInfo lib = _entityToInfo[typdef.library];
- lib.typedefs.add(info);
- info.parent = lib;
- result.typedefs.add(info);
- return info;
- }
-
GlobalTypeInferenceMemberResult _resultOfMember(MemberEntity e) =>
compiler.globalInference.results.resultOfMember(e);
@@ -147,7 +134,7 @@
type: '${environment.getFieldType(field)}',
inferredType: '$inferredType',
code: code,
- outputUnit: _unitInfoForEntity(field),
+ outputUnit: _unitInfoForMember(field),
isConst: field.isConst);
_entityToInfo[field] = info;
if (codegenWorldBuilder.hasConstantFieldInitializer(field)) {
@@ -179,7 +166,7 @@
ClassInfo classInfo = new ClassInfo(
name: clazz.name,
isAbstract: clazz.isAbstract,
- outputUnit: _unitInfoForEntity(clazz));
+ outputUnit: _unitInfoForClass(clazz));
_entityToInfo[clazz] = classInfo;
int size = compiler.dumpInfoTask.sizeOf(clazz);
@@ -232,7 +219,7 @@
ClosureInfo visitClosureClass(ClassEntity element) {
ClosureInfo closureInfo = new ClosureInfo(
name: element.name,
- outputUnit: _unitInfoForEntity(element),
+ outputUnit: _unitInfoForClass(element),
size: compiler.dumpInfoTask.sizeOf(element));
_entityToInfo[element] = closureInfo;
@@ -313,7 +300,7 @@
inlinedCount: inlinedCount,
code: code,
type: functionType.toString(),
- outputUnit: _unitInfoForEntity(function));
+ outputUnit: _unitInfoForMember(function));
_entityToInfo[function] = info;
int closureSize = _addClosureInfo(info, function);
@@ -366,9 +353,14 @@
});
}
- OutputUnitInfo _unitInfoForEntity(Entity entity) {
+ OutputUnitInfo _unitInfoForMember(MemberEntity entity) {
return _infoFromOutputUnit(
- compiler.backend.outputUnitData.outputUnitForEntity(entity));
+ compiler.backend.outputUnitData.outputUnitForMember(entity));
+ }
+
+ OutputUnitInfo _unitInfoForClass(ClassEntity entity) {
+ return _infoFromOutputUnit(
+ compiler.backend.outputUnitData.outputUnitForClass(entity));
}
OutputUnitInfo _unitInfoForConstant(ConstantValue constant) {
@@ -470,10 +462,11 @@
entity,
impact,
new WorldImpactVisitorImpl(visitDynamicUse: (dynamicUse) {
+ TypeMask mask = dynamicUse.mask;
selections.addAll(closedWorld
// TODO(het): Handle `call` on `Closure` through
// `world.includesClosureCall`.
- .locateMembers(dynamicUse.selector, dynamicUse.mask)
+ .locateMembers(dynamicUse.selector, mask)
.map((MemberEntity e) => new Selection(e, dynamicUse.mask)));
}, visitStaticUse: (staticUse) {
selections.add(new Selection(staticUse.element, null));
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 20264b1..dc244d9 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -562,17 +562,13 @@
final List<FunctionTypeVariable> typeVariables;
- /// The originating [TypedefType], if any.
- final TypedefType typedefType;
-
FunctionType(
this.returnType,
this.parameterTypes,
this.optionalParameterTypes,
this.namedParameters,
this.namedParameterTypes,
- this.typeVariables,
- this.typedefType);
+ this.typeVariables);
bool get containsTypeVariables {
return typeVariables.any((type) => type.bound.containsTypeVariables) ||
@@ -665,8 +661,7 @@
newOptionalParameterTypes,
namedParameters,
newNamedParameterTypes,
- newTypeVariables,
- typedefType);
+ newTypeVariables);
}
return this;
}
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 0abf135..decc885 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -211,10 +211,6 @@
final Queue<WorkItem> _queue = new Queue<WorkItem>();
- /// Queue of deferred resolution actions to execute when the resolution queue
- /// has been emptied.
- final Queue<DeferredAction> _deferredQueue = new Queue<DeferredAction>();
-
// If not `null` this is called when the queue has been emptied. It allows for
// applying additional impacts before re-emptying the queue.
void Function() onEmptyForTesting;
@@ -378,15 +374,9 @@
}
break;
case TypeUseKind.TYPE_LITERAL:
- TypedefType typedef;
- if (type.isTypedef) {
- typedef = type;
- } else if (type is FunctionType) {
- typedef = type.typedefType;
- } else if (type is TypeVariableType) {
+ if (type is TypeVariableType) {
_worldBuilder.registerTypeVariableTypeLiteral(type);
}
- if (typedef != null) worldBuilder.registerTypedef(typedef.element);
break;
}
}
@@ -418,10 +408,8 @@
if (!_onQueueEmpty(recents)) {
_recentClasses.addAll(recents);
}
- } while (_queue.isNotEmpty ||
- _recentClasses.isNotEmpty ||
- _deferredQueue.isNotEmpty ||
- _recentConstants);
+ } while (
+ _queue.isNotEmpty || _recentClasses.isNotEmpty || _recentConstants);
}
void forEach(void f(WorkItem work)) {
@@ -470,25 +458,6 @@
_queue.add(workItem);
}
- /// Adds an action to the deferred task queue.
- /// The action is performed the next time the resolution queue has been
- /// emptied.
- ///
- /// The queue is processed in FIFO order.
- void addDeferredAction(DeferredAction deferredAction) {
- if (queueIsClosed) {
- failedAt(
- deferredAction.element,
- "Resolution work list is closed. "
- "Trying to add deferred action for ${deferredAction.element}");
- }
- _deferredQueue.add(deferredAction);
- }
-
- void addDeferredActions(Iterable<DeferredAction> deferredActions) {
- deferredActions.forEach(addDeferredAction);
- }
-
/// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses]
/// contains the set of all classes seen for the first time since
/// [_onQueueEmpty] was called last. A return value of [true] indicates that
@@ -496,19 +465,8 @@
/// returned, [_onQueueEmpty] will be called once the queue is empty again (or
/// still empty) and [recentClasses] will be a superset of the current value.
bool _onQueueEmpty(Iterable<ClassEntity> recentClasses) {
- _emptyDeferredQueue();
-
return listener.onQueueEmpty(this, recentClasses);
}
-
- void emptyDeferredQueueForTesting() => _emptyDeferredQueue();
-
- void _emptyDeferredQueue() {
- while (!_deferredQueue.isEmpty) {
- DeferredAction task = _deferredQueue.removeFirst();
- _reporter.withCurrentElement(task.element, task.action);
- }
- }
}
/// Strategy used by the enqueuer to populate the world.
@@ -616,15 +574,6 @@
}
}
-typedef void DeferredActionFunction();
-
-class DeferredAction {
- final Entity element;
- final DeferredActionFunction action;
-
- DeferredAction(this.element, this.action);
-}
-
/// Interface for creating work items for enqueued member entities.
abstract class WorkItemBuilder {
WorkItem createWorkItem(covariant MemberEntity entity);
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index c995cfb..bb5ebdb 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -48,12 +48,12 @@
final GlobalTypeInferenceElementData<ir.Node> _memberData;
final bool _inGenerativeConstructor;
- LocalsHandler _locals;
+ LocalsHandler<ir.Node> _locals;
final SideEffectsBuilder _sideEffectsBuilder;
- final Map<JumpTarget, List<LocalsHandler>> _breaksFor =
- <JumpTarget, List<LocalsHandler>>{};
- final Map<JumpTarget, List<LocalsHandler>> _continuesFor =
- <JumpTarget, List<LocalsHandler>>{};
+ final Map<JumpTarget, List<LocalsHandler<ir.Node>>> _breaksFor =
+ <JumpTarget, List<LocalsHandler<ir.Node>>>{};
+ final Map<JumpTarget, List<LocalsHandler<ir.Node>>> _continuesFor =
+ <JumpTarget, List<LocalsHandler<ir.Node>>>{};
TypeInformation _returnType;
final Set<Local> _capturedVariables = new Set<Local>();
@@ -90,7 +90,7 @@
FieldInitializationScope<ir.Node> fieldScope =
_inGenerativeConstructor ? new FieldInitializationScope(_types) : null;
- _locals = new LocalsHandler(
+ _locals = new LocalsHandler<ir.Node>(
_inferrer, _types, _options, _analyzedNode, fieldScope);
}
@@ -522,7 +522,7 @@
continueTargets.forEach(_clearBreaksAndContinues);
} else {
LocalsHandler saved = _locals;
- List<LocalsHandler> localsToMerge = <LocalsHandler>[];
+ List<LocalsHandler<ir.Node>> localsToMerge = <LocalsHandler<ir.Node>>[];
bool hasDefaultCase = false;
for (ir.SwitchCase switchCase in node.cases) {
@@ -580,8 +580,8 @@
@override
TypeInformation visitMapLiteral(ir.MapLiteral node) {
return _inferrer.concreteTypes.putIfAbsent(node, () {
- List keyTypes = [];
- List valueTypes = [];
+ List keyTypes = <TypeInformation>[];
+ List valueTypes = <TypeInformation>[];
for (ir.MapEntry entry in node.entries) {
keyTypes.add(visit(entry.key));
@@ -944,8 +944,12 @@
void _setupBreaksAndContinues(JumpTarget target) {
if (target == null) return;
- if (target.isContinueTarget) _continuesFor[target] = <LocalsHandler>[];
- if (target.isBreakTarget) _breaksFor[target] = <LocalsHandler>[];
+ if (target.isContinueTarget) {
+ _continuesFor[target] = <LocalsHandler<ir.Node>>[];
+ }
+ if (target.isBreakTarget) {
+ _breaksFor[target] = <LocalsHandler<ir.Node>>[];
+ }
}
void _clearBreaksAndContinues(JumpTarget element) {
@@ -953,15 +957,15 @@
_breaksFor.remove(element);
}
- List<LocalsHandler> _getBreaks(JumpTarget target) {
- List<LocalsHandler> list = <LocalsHandler>[_locals];
+ List<LocalsHandler<ir.Node>> _getBreaks(JumpTarget target) {
+ List<LocalsHandler<ir.Node>> list = <LocalsHandler<ir.Node>>[_locals];
if (target == null) return list;
if (!target.isBreakTarget) return list;
return list..addAll(_breaksFor[target]);
}
- List<LocalsHandler> _getLoopBackEdges(JumpTarget target) {
- List<LocalsHandler> list = <LocalsHandler>[_locals];
+ List<LocalsHandler<ir.Node>> _getLoopBackEdges(JumpTarget target) {
+ List<LocalsHandler<ir.Node>> list = <LocalsHandler<ir.Node>>[_locals];
if (target == null) return list;
if (!target.isContinueTarget) return list;
return list..addAll(_continuesFor[target]);
@@ -1463,7 +1467,7 @@
// We don't put the closure in the work queue of the
// inferrer, because it will share information with its enclosing
// method, like for example the types of local variables.
- LocalsHandler closureLocals =
+ LocalsHandler<ir.Node> closureLocals =
new LocalsHandler.from(_locals, node, useOtherTryBlock: false);
KernelTypeGraphBuilder visitor = new KernelTypeGraphBuilder(
_options,
diff --git a/pkg/compiler/lib/src/io/source_file.dart b/pkg/compiler/lib/src/io/source_file.dart
index 8cfa41e..ff227ae 100644
--- a/pkg/compiler/lib/src/io/source_file.dart
+++ b/pkg/compiler/lib/src/io/source_file.dart
@@ -227,7 +227,7 @@
}
}
-class StringSourceFile extends SourceFile<String> {
+class StringSourceFile extends SourceFile<List<int>> {
final Uri uri;
final String filename;
final String text;
@@ -240,7 +240,7 @@
StringSourceFile.fromName(String filename, String text)
: this(new Uri(path: filename), filename, text);
- String get data => text;
+ List<int> get data => utf8.encode(text);
int get length => text.length;
set length(int v) {}
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 71bec0c..90bc21f 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -774,6 +774,7 @@
_commonElements.instantiate2,
_commonElements.instantiate3,
_commonElements.instantiatedGenericFunctionType,
+ _commonElements.extractFunctionTypeObjectFromInternal,
], instantiatedClasses: [
_commonElements.instantiation1Class,
_commonElements.instantiation2Class,
diff --git a/pkg/compiler/lib/src/js_backend/codegen_listener.dart b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
index 461bd279..bb430e2 100644
--- a/pkg/compiler/lib/src/js_backend/codegen_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
@@ -155,6 +155,7 @@
_customElementsAnalysis.registerTypeConstant(representedType.element);
}
} else if (constant is InstantiationConstantValue) {
+ // TODO(johnniwinther): Register these using `BackendImpact`.
impactBuilder.registerTypeUse(new TypeUse.instantiation(
_elementEnvironment
.getThisType(_commonElements.instantiation1Class)));
@@ -167,6 +168,9 @@
impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
_commonElements.instantiatedGenericFunctionType,
CallStructure.TWO_ARGS));
+ impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
+ _commonElements.extractFunctionTypeObjectFromInternal,
+ CallStructure.ONE_ARG));
}
}
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
index 1869f4d..5e9c4cb 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -53,7 +53,6 @@
new List<DartType>.filled(16, const DynamicType()),
const <String>[],
const <DartType>[],
- const <FunctionTypeVariable>[],
- null);
+ const <FunctionTypeVariable>[]);
}
}
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 4ce047a..1f202ed 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -1102,7 +1102,7 @@
}
jsAst.Name _disambiguateGlobalMember(MemberEntity element) {
- return _disambiguateGlobal(element, _proposeNameForMember);
+ return _disambiguateGlobal<MemberEntity>(element, _proposeNameForMember);
}
jsAst.Name _disambiguateGlobalType(Entity element) {
@@ -1112,8 +1112,8 @@
/// Returns the disambiguated name for a top-level or static element.
///
/// The resulting name is unique within the global-member namespace.
- jsAst.Name _disambiguateGlobal(
- Entity element, String proposeName(Entity element)) {
+ jsAst.Name _disambiguateGlobal<T extends Entity>(
+ T element, String proposeName(T element)) {
// TODO(asgerf): We can reuse more short names if we disambiguate with
// a separate namespace for each of the global holder objects.
jsAst.Name newName = userGlobals[element];
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 2364c42..1281eb9 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -1571,6 +1571,26 @@
typeVariableTestsForTesting = typeVariableTests;
}
+ /*print(typeVariableTests.dump());
+ print('------------------------------------------------------------------');
+ print('classesNeedingTypeArguments:');
+ classesNeedingTypeArguments.forEach((e) => print(' $e'));
+ print('------------------------------------------------------------------');
+ print('methodsNeedingSignature:');
+ methodsNeedingSignature.forEach((e) => print(' $e'));
+ print('------------------------------------------------------------------');
+ print('methodsNeedingTypeArguments:');
+ methodsNeedingTypeArguments.forEach((e) => print(' $e'));
+ print('------------------------------------------------------------------');
+ print('localFunctionsNeedingSignature:');
+ localFunctionsNeedingSignature.forEach((e) => print(' $e'));
+ print('------------------------------------------------------------------');
+ print('localFunctionsNeedingTypeArguments:');
+ localFunctionsNeedingTypeArguments.forEach((e) => print(' $e'));
+ print('------------------------------------------------------------------');
+ print('selectorsNeedingTypeArguments:');
+ selectorsNeedingTypeArguments.forEach((e) => print(' $e'));*/
+
return _createRuntimeTypesNeed(
_elementEnvironment,
closedWorld.backendUsage,
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index ee51d11..3a54cf6 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -93,7 +93,7 @@
jsAst.Name constructorName = namer.className(classElement);
OutputUnit outputUnit =
- compiler.backend.outputUnitData.outputUnitForEntity(classElement);
+ compiler.backend.outputUnitData.outputUnitForClass(classElement);
emitter.assemblePrecompiledConstructor(
outputUnit, constructorName, constructorAst, fieldNames);
}
@@ -317,7 +317,7 @@
ClassEntity cls = member.enclosingClass;
jsAst.Name className = namer.className(cls);
OutputUnit outputUnit =
- compiler.backend.outputUnitData.outputUnitForEntity(member);
+ compiler.backend.outputUnitData.outputUnitForMember(member);
emitter
.cspPrecompiledFunctionFor(outputUnit)
.add(js('#.prototype.# = #', [className, getterName, function]));
@@ -332,7 +332,7 @@
ClassEntity cls = member.enclosingClass;
jsAst.Name className = namer.className(cls);
OutputUnit outputUnit =
- compiler.backend.outputUnitData.outputUnitForEntity(member);
+ compiler.backend.outputUnitData.outputUnitForMember(member);
emitter
.cspPrecompiledFunctionFor(outputUnit)
.add(js('#.prototype.# = #', [className, setterName, function]));
diff --git a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
index 865fc15..477ced0 100644
--- a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
@@ -104,18 +104,19 @@
/// ```
/// $signature:: function() {
/// return H.instantiatedGenericFunctionType(
- /// this._genericClosure.$signature(),
+ /// H.extractFunctionTypeObjectFromInternal(this._genericClosure),
/// this.$ti);
/// }
/// ```
ParameterStubMethod _generateSignatureStub(FieldEntity functionField) {
jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
- jsAst.Fun function = js('function() { return #(this.#.#(), this.#); }', [
+ jsAst.Fun function = js('function() { return #(#(this.#), this.#); }', [
_emitter.staticFunctionAccess(
_commonElements.instantiatedGenericFunctionType),
+ _emitter.staticFunctionAccess(
+ _commonElements.extractFunctionTypeObjectFromInternal),
_namer.fieldPropertyName(functionField),
- operatorSignature,
_namer.rtiFieldJsName,
]);
// TODO(sra): Generate source information for stub that has no member.
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 88f2c2d..905c3bd 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -616,7 +616,7 @@
List<StaticMethod> statics = memberElements
.where((e) => !e.isField)
.cast<FunctionEntity>()
- .map(_buildStaticMethod)
+ .map<StaticMethod>(_buildStaticMethod)
.toList();
if (library == _commonElements.interceptorsLibrary) {
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index 3615c8c..e76a39d 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -101,6 +101,7 @@
final RuntimeTypesEncoder _rtiEncoder;
final JsInteropAnalysis _jsInteropAnalysis;
final bool _strongMode;
+ final _TypeContainedInOutputUnitVisitor _outputUnitVisitor;
RuntimeTypeGenerator(
this._commonElements,
@@ -111,7 +112,9 @@
this._rtiChecks,
this._rtiEncoder,
this._jsInteropAnalysis,
- this._strongMode);
+ this._strongMode)
+ : _outputUnitVisitor = new _TypeContainedInOutputUnitVisitor(
+ _commonElements, _outputUnitData);
/**
* Generate "is tests" for [cls] itself, and the "is tests" for the
@@ -145,19 +148,28 @@
// signatures. We either need them for mirrors or because [type] is
// potentially a subtype of a checked function. Currently we eagerly
// generate a function type index or signature for all callable classes.
- if (storeFunctionTypeInMetadata && !type.containsTypeVariables) {
- // TODO(johnniwinther,efortuna): Should we use the scheme for Dart 2?
- // TODO(sigmund): use output unit of `method` (Issue #31032)
- OutputUnit outputUnit = _outputUnitData.mainOutputUnit;
- result.functionTypeIndex =
- emitterTask.metadataCollector.reifyType(type, outputUnit);
+ jsAst.Expression functionTypeIndex;
+ if (!type.containsTypeVariables) {
+ // TODO(sigmund): use output unit of [method] when the classes mentioned
+ // in [type] aren't in the main output unit. (Issue #31032)
+ OutputUnit mainOutputUnit = _outputUnitData.mainOutputUnit;
+ if (_outputUnitVisitor.isTypeContainedIn(type, mainOutputUnit)) {
+ functionTypeIndex =
+ emitterTask.metadataCollector.reifyType(type, mainOutputUnit);
+ }
+ }
+ if (storeFunctionTypeInMetadata && functionTypeIndex != null) {
+ result.functionTypeIndex = functionTypeIndex;
} else {
jsAst.Expression encoding =
generatedCode[classFunctionType.signatureFunction];
- if (classFunctionType.signatureFunction != null) {
- // Use precomputed signature function if live.
- } else {
- assert(!_strongMode);
+ if (_strongMode) {
+ if (classFunctionType.signatureFunction == null) {
+ // The signature function isn't live.
+ return;
+ }
+ encoding = functionTypeIndex ?? encoding;
+ } else if (encoding == null) {
// Generate the signature on the fly. This is only supported for
// Dart 1.
@@ -240,3 +252,84 @@
}
}
}
+
+/// Visitor that checks whether a type is contained within one output unit.
+class _TypeContainedInOutputUnitVisitor
+ implements DartTypeVisitor<bool, OutputUnit> {
+ final CommonElements _commonElements;
+ final OutputUnitData _outputUnitData;
+
+ _TypeContainedInOutputUnitVisitor(this._commonElements, this._outputUnitData);
+
+ /// Returns `true` if all classes mentioned in [type] are in [outputUnit].
+ bool isTypeContainedIn(DartType type, OutputUnit outputUnit) =>
+ visit(type, outputUnit);
+
+ @override
+ bool visit(DartType type, OutputUnit argument) => type.accept(this, argument);
+
+ bool visitList(List<DartType> types, OutputUnit argument) {
+ for (DartType type in types) {
+ if (!visit(type, argument)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @override
+ bool visitFutureOrType(FutureOrType type, OutputUnit argument) {
+ if (_outputUnitData.outputUnitForClass(_commonElements.functionClass) !=
+ argument) {
+ return false;
+ }
+ return visit(type.typeArgument, argument);
+ }
+
+ @override
+ bool visitDynamicType(DynamicType type, OutputUnit argument) => true;
+
+ @override
+ bool visitTypedefType(TypedefType type, OutputUnit argument) {
+ return visit(type.unaliased, argument);
+ }
+
+ @override
+ bool visitInterfaceType(InterfaceType type, OutputUnit argument) {
+ if (_outputUnitData.outputUnitForClass(type.element) != argument) {
+ return false;
+ }
+ return visitList(type.typeArguments, argument);
+ }
+
+ @override
+ bool visitFunctionType(FunctionType type, OutputUnit argument) {
+ bool result = visit(type.returnType, argument) &&
+ visitList(type.parameterTypes, argument) &&
+ visitList(type.optionalParameterTypes, argument) &&
+ visitList(type.namedParameterTypes, argument);
+ if (!result) return false;
+ for (FunctionTypeVariable typeVariable in type.typeVariables) {
+ if (!visit(typeVariable.bound, argument)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @override
+ bool visitFunctionTypeVariable(
+ FunctionTypeVariable type, OutputUnit argument) {
+ return true;
+ }
+
+ @override
+ bool visitTypeVariableType(TypeVariableType type, OutputUnit argument) {
+ return false;
+ }
+
+ @override
+ bool visitVoidType(VoidType type, OutputUnit argument) {
+ return true;
+ }
+}
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index c86157d..2641d69 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -286,8 +286,7 @@
visitList(type.optionalParameterTypes, converter),
type.namedParameters,
visitList(type.namedParameterTypes, converter),
- type.typeVariables,
- visitTypedefType(type.typedefType, converter));
+ type.typeVariables);
}
@override
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 28e67b6..f624144 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -43,7 +43,6 @@
import '../universe/class_set.dart';
import '../universe/selector.dart';
import '../universe/world_builder.dart';
-import '../util/emptyset.dart';
import '../world.dart';
import 'closure.dart';
import 'elements.dart';
@@ -102,24 +101,51 @@
return map.toBackendLibrary(entity);
}
- // Convert a front-end map containing K-entities keys to a backend map using
- // J-entities as keys.
- Map<Entity, OutputUnit> convertEntityMap(Map<Entity, OutputUnit> input) {
- var result = <Entity, OutputUnit>{};
- input.forEach((Entity entity, OutputUnit unit) {
- // Closures have both a class and a call-method, we ensure both are
- // included in the corresponding output unit.
+ // Convert front-end maps containing K-class and K-local function keys to a
+ // backend map using J-classes as keys.
+ Map<ClassEntity, OutputUnit> convertClassMap(
+ Map<ClassEntity, OutputUnit> classMap,
+ Map<Local, OutputUnit> localFunctionMap) {
+ var result = <ClassEntity, OutputUnit>{};
+ classMap.forEach((ClassEntity entity, OutputUnit unit) {
+ ClassEntity backendEntity = toBackendEntity(entity);
+ if (backendEntity != null) {
+ // If [entity] isn't used it doesn't have a corresponding backend
+ // entity.
+ result[backendEntity] = unit;
+ }
+ });
+ localFunctionMap.forEach((Local entity, OutputUnit unit) {
+ // Ensure closure classes are included in the output unit corresponding
+ // to the local function.
if (entity is KLocalFunction) {
var closureInfo = _closureDataLookup.getClosureInfo(entity.node);
result[closureInfo.closureClassEntity] = unit;
+ }
+ });
+ return result;
+ }
+
+ // Convert front-end maps containing K-member and K-local function keys to
+ // a backend map using J-members as keys.
+ Map<MemberEntity, OutputUnit> convertMemberMap(
+ Map<MemberEntity, OutputUnit> memberMap,
+ Map<Local, OutputUnit> localFunctionMap) {
+ var result = <MemberEntity, OutputUnit>{};
+ memberMap.forEach((MemberEntity entity, OutputUnit unit) {
+ MemberEntity backendEntity = toBackendEntity(entity);
+ if (backendEntity != null) {
+ // If [entity] isn't used it doesn't have a corresponding backend
+ // entity.
+ result[backendEntity] = unit;
+ }
+ });
+ localFunctionMap.forEach((Local entity, OutputUnit unit) {
+ // Ensure closure call-methods are included in the output unit
+ // corresponding to the local function.
+ if (entity is KLocalFunction) {
+ var closureInfo = _closureDataLookup.getClosureInfo(entity.node);
result[closureInfo.callMethod] = unit;
- } else {
- Entity backendEntity = toBackendEntity(entity);
- if (backendEntity != null) {
- // If [entity] isn't used it doesn't have a corresponding backend
- // entity.
- result[backendEntity] = unit;
- }
}
});
return result;
@@ -131,7 +157,8 @@
return new OutputUnitData.from(
data,
- convertEntityMap,
+ convertClassMap,
+ convertMemberMap,
(m) => convertMap<ConstantValue, OutputUnit>(
m, toBackendConstant, (v) => v));
}
@@ -363,9 +390,7 @@
assignedInstanceMembers: assignedInstanceMembers,
processedMembers: processedMembers,
mixinUses: mixinUses,
- typesImplementedBySubclasses: typesImplementedBySubclasses,
- // TODO(johnniwinther): Support this:
- allTypedefs: new ImmutableEmptySet<TypedefEntity>());
+ typesImplementedBySubclasses: typesImplementedBySubclasses);
}
BackendUsage _convertBackendUsage(
@@ -591,7 +616,6 @@
Iterable<MemberEntity> liveInstanceMembers,
Iterable<MemberEntity> assignedInstanceMembers,
Iterable<MemberEntity> processedMembers,
- Set<TypedefEntity> allTypedefs,
Map<ClassEntity, Set<ClassEntity>> mixinUses,
Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses,
Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
@@ -610,7 +634,6 @@
liveInstanceMembers,
assignedInstanceMembers,
processedMembers,
- allTypedefs,
mixinUses,
typesImplementedBySubclasses,
classHierarchyNodes,
@@ -758,9 +781,8 @@
for (FunctionTypeVariable typeVariable in type.typeVariables) {
_functionTypeVariables.remove(typeVariable);
}
- var typedefType = type.typedefType?.accept(this, null);
return new FunctionType(returnType, parameterTypes, optionalParameterTypes,
- type.namedParameters, namedParameterTypes, typeVariables, typedefType);
+ type.namedParameters, namedParameterTypes, typeVariables);
}
DartType visitInterfaceType(InterfaceType type, _) {
diff --git a/pkg/compiler/lib/src/kernel/deferred_load.dart b/pkg/compiler/lib/src/kernel/deferred_load.dart
index f3f1a9c..b312027 100644
--- a/pkg/compiler/lib/src/kernel/deferred_load.dart
+++ b/pkg/compiler/lib/src/kernel/deferred_load.dart
@@ -20,37 +20,8 @@
KernelDeferredLoadTask(Compiler compiler, this._elementMap) : super(compiler);
- @override
- Iterable<ImportEntity> importsTo(Entity element, LibraryEntity library) {
- ir.NamedNode node;
- String nodeName;
- ir.Library enclosingLibrary;
- if (element is ClassEntity) {
- ClassDefinition definition = _elementMap.getClassDefinition(element);
- if (definition.kind != ClassKind.regular) {
- // You can't import closures.
- return const <ImportEntity>[];
- }
- ir.Class _node = definition.node;
- nodeName = _node.name;
- enclosingLibrary = _node.enclosingLibrary;
- node = _node;
- } else if (element is MemberEntity) {
- ir.Member _node = _elementMap.getMemberDefinition(element).node;
- nodeName = _node.name.name;
- enclosingLibrary = _node.enclosingLibrary;
- node = _node;
- } else if (element is Local ||
- element is LibraryEntity ||
- element is TypeVariableEntity) {
- return const <ImportEntity>[];
- } else if (element is TypedefEntity) {
- throw new UnimplementedError("KernelDeferredLoadTask.importsTo typedef");
- } else {
- throw new UnsupportedError(
- "KernelDeferredLoadTask.importsTo unexpected entity type: "
- "${element.runtimeType}");
- }
+ Iterable<ImportEntity> _findImportsTo(ir.NamedNode node, String nodeName,
+ ir.Library enclosingLibrary, LibraryEntity library) {
List<ImportEntity> imports = [];
ir.Library source = _elementMap.getLibraryNode(library);
for (ir.LibraryDependency dependency in source.dependencies) {
@@ -65,6 +36,25 @@
}
@override
+ Iterable<ImportEntity> classImportsTo(
+ ClassEntity element, LibraryEntity library) {
+ ClassDefinition definition = _elementMap.getClassDefinition(element);
+ if (definition.kind != ClassKind.regular) {
+ // You can't import closures.
+ return const <ImportEntity>[];
+ }
+ ir.Class node = definition.node;
+ return _findImportsTo(node, node.name, node.enclosingLibrary, library);
+ }
+
+ @override
+ Iterable<ImportEntity> memberImportsTo(
+ Entity element, LibraryEntity library) {
+ ir.Member node = _elementMap.getMemberDefinition(element).node;
+ return _findImportsTo(node, node.name.name, node.enclosingLibrary, library);
+ }
+
+ @override
void checkForDeferredErrorCases(LibraryEntity library) {
// Nothing to do. The FE checks for error cases upfront.
}
@@ -77,14 +67,13 @@
}
@override
- void collectConstantsInBody(
- covariant MemberEntity element, Set<ConstantValue> constants) {
+ void collectConstantsInBody(MemberEntity element, Dependencies dependencies) {
ir.Member node = _elementMap.getMemberDefinition(element).node;
// Fetch the internal node in order to skip annotations on the member.
// TODO(sigmund): replace this pattern when the kernel-ast provides a better
// way to skip annotations (issue 31565).
- var visitor = new ConstantCollector(_elementMap, constants);
+ var visitor = new ConstantCollector(_elementMap, dependencies);
if (node is ir.Field) {
node.initializer?.accept(visitor);
return;
@@ -135,9 +124,9 @@
class ConstantCollector extends ir.RecursiveVisitor {
final KernelToElementMapForImpact elementMap;
- final Set<ConstantValue> constants;
+ final Dependencies dependencies;
- ConstantCollector(this.elementMap, this.constants);
+ ConstantCollector(this.elementMap, this.dependencies);
CommonElements get commonElements => elementMap.commonElements;
@@ -145,7 +134,7 @@
ConstantValue constant =
elementMap.getConstantValue(node, requireConstant: required);
if (constant != null) {
- constants.add(constant);
+ dependencies.constants.add(constant);
}
}
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index fe02b86..8154793 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -4,6 +4,7 @@
library dart2js.kernel.element_map;
+import 'package:front_end/src/fasta/util/link.dart' show Link, LinkBuilder;
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/core_types.dart' as ir;
@@ -46,7 +47,6 @@
import '../universe/class_set.dart';
import '../universe/selector.dart';
import '../universe/world_builder.dart';
-import '../util/util.dart' show Link, LinkBuilder;
import '../world.dart';
import 'element_map.dart';
import 'element_map_mixins.dart';
@@ -311,11 +311,12 @@
node.implementedTypes.forEach((ir.Supertype supertype) {
linkBuilder.addLast(processSupertype(supertype));
});
- Link<InterfaceType> interfaces = linkBuilder.toLink();
+ Link<InterfaceType> interfaces =
+ linkBuilder.toLink(const Link<InterfaceType>());
OrderedTypeSetBuilder setBuilder =
new _KernelOrderedTypeSetBuilder(this, cls);
data.orderedTypeSet = setBuilder.createOrderedTypeSet(
- data.supertype, interfaces.reverse());
+ data.supertype, interfaces.reverse(const Link<InterfaceType>()));
data.interfaces = new List<InterfaceType>.from(interfaces.toList());
}
}
@@ -479,7 +480,7 @@
}
return new FunctionType(returnType, parameterTypes, optionalParameterTypes,
- namedParameters, namedParameterTypes, typeVariables, null);
+ namedParameters, namedParameterTypes, typeVariables);
}
@override
@@ -614,15 +615,10 @@
..sort((a, b) => a.compareTo(b));
List<DartType> namedParameterTypes =
new List.filled(namedParameters.length, dynamic);
- data.callType = new FunctionType(
- dynamic,
- requiredParameterTypes,
- optionalParameterTypes,
- namedParameters,
- namedParameterTypes,
+ data.callType = new FunctionType(dynamic, requiredParameterTypes,
+ optionalParameterTypes, namedParameters, namedParameterTypes,
// TODO(johnniwinther): Generate existential types here.
- const <FunctionTypeVariable>[],
- null);
+ const <FunctionTypeVariable>[]);
} else {
// The function type is not valid.
data.callType = const DynamicType();
@@ -841,6 +837,9 @@
/// Mixin that implements the abstract methods in [KernelToElementMapBase].
abstract class ElementCreatorMixin implements KernelToElementMapBase {
+ /// Set to `true` before creating the J-World from the K-World to assert that
+ /// no entities are created late.
+ bool _envIsClosed = false;
ProgramEnv get _env;
EntityDataEnvMap<IndexedLibrary, LibraryData, LibraryEnv> get _libraries;
EntityDataEnvMap<IndexedClass, ClassData, ClassEnv> get _classes;
@@ -885,6 +884,10 @@
LibraryEntity _getLibrary(ir.Library node, [LibraryEnv libraryEnv]) {
return _libraryMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "library for $node.");
Uri canonicalUri = node.importUri;
String name = node.name;
if (name == null) {
@@ -900,6 +903,10 @@
ClassEntity _getClass(ir.Class node, [ClassEnv classEnv]) {
return _classMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "class for $node.");
KLibrary library = _getLibrary(node.enclosingLibrary);
if (classEnv == null) {
classEnv = _libraries.getEnv(library).lookupClass(node.name);
@@ -913,6 +920,10 @@
TypedefEntity _getTypedef(ir.Typedef node) {
return _typedefMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "typedef for $node.");
IndexedLibrary library = _getLibrary(node.enclosingLibrary);
IndexedTypedef typedef = createTypedef(library, node.name);
TypedefType typedefType = new TypedefType(
@@ -926,6 +937,10 @@
TypeVariableEntity _getTypeVariable(ir.TypeParameter node) {
return _typeVariableMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "type variable for $node.");
if (node.parent is ir.Class) {
ir.Class cls = node.parent;
int index = cls.typeParameters.indexOf(node);
@@ -962,6 +977,10 @@
ConstructorEntity _getConstructor(ir.Member node) {
return _constructorMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "constructor for $node.");
MemberDefinition definition;
ir.FunctionNode functionNode;
ClassEntity enclosingClass = _getClass(node.enclosingClass);
@@ -999,6 +1018,10 @@
FunctionEntity _getMethod(ir.Procedure node) {
return _methodMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "function for $node.");
LibraryEntity library;
ClassEntity enclosingClass;
if (node.enclosingClass != null) {
@@ -1048,6 +1071,10 @@
FieldEntity _getField(ir.Field node) {
return _fieldMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "field for $node.");
LibraryEntity library;
ClassEntity enclosingClass;
if (node.enclosingClass != null) {
@@ -1690,12 +1717,6 @@
}
@override
- Iterable<ConstantValue> getTypedefMetadata(TypedefEntity typedef) {
- // TODO(redemption): Support this.
- throw new UnsupportedError('ElementEnvironment.getTypedefMetadata');
- }
-
- @override
Iterable<ConstantValue> getMemberMetadata(covariant IndexedMember member,
{bool includeParameterMetadata: false}) {
// TODO(redemption): Support includeParameterMetadata.
@@ -1705,17 +1726,6 @@
}
@override
- FunctionType getFunctionTypeOfTypedef(TypedefEntity typedef) {
- // TODO(redemption): Support this.
- throw new UnsupportedError('ElementEnvironment.getFunctionTypeOfTypedef');
- }
-
- @override
- TypedefType getTypedefTypeOfTypedef(TypedefEntity typedef) {
- return elementMap._typedefs.getData(typedef).rawType;
- }
-
- @override
bool isEnumClass(ClassEntity cls) {
assert(elementMap.checkFamily(cls));
ClassData classData = elementMap._classes.getData(cls);
@@ -1795,9 +1805,6 @@
}
}
- DartType typedefType =
- node.typedef == null ? null : elementMap.getTypedefType(node.typedef);
-
FunctionType type = new FunctionType(
visitType(node.returnType),
visitTypes(node.positionalParameters
@@ -1808,8 +1815,7 @@
.toList()),
node.namedParameters.map((n) => n.name).toList(),
node.namedParameters.map((n) => visitType(n.type)).toList(),
- typeVariables ?? const <FunctionTypeVariable>[],
- typedefType);
+ typeVariables ?? const <FunctionTypeVariable>[]);
for (ir.TypeParameter typeParameter in node.typeParameters) {
currentFunctionTypeParameters.remove(typeParameter);
}
@@ -2085,7 +2091,6 @@
Iterable<MemberEntity> liveInstanceMembers,
Iterable<MemberEntity> assignedInstanceMembers,
Iterable<MemberEntity> processedMembers,
- Set<TypedefEntity> allTypedefs,
Map<ClassEntity, Set<ClassEntity>> mixinUses,
Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses,
Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
@@ -2104,7 +2109,6 @@
liveInstanceMembers,
assignedInstanceMembers,
processedMembers,
- allTypedefs,
mixinUses,
typesImplementedBySubclasses,
classHierarchyNodes,
@@ -2370,6 +2374,11 @@
assert(newTypeVariable.typeVariableIndex ==
oldTypeVariable.typeVariableIndex);
}
+ // TODO(johnniwinther): We should close the environment in the beginning of
+ // this constructor but currently we need the [MemberEntity] to query if the
+ // member is live, thus potentially creating the [MemberEntity] in the
+ // process. Avoid this.
+ _elementMap._envIsClosed = true;
}
@override
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index c9b9d93..dde76e85 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -297,7 +297,7 @@
ClassEnvImpl.internal(this.cls, this._constructorMap, this._memberMap,
this._setterMap, this._members);
- bool get isUnnamedMixinApplication => cls.isSyntheticMixinImplementation;
+ bool get isUnnamedMixinApplication => cls.isAnonymousMixin;
/// Copied from 'package:kernel/transformations/mixin_full_resolution.dart'.
ir.Constructor _buildForwardingConstructor(
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index 2124d1f..25e576b 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -7,6 +7,7 @@
import 'dart:async';
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
+import 'package:front_end/src/fasta/util/link.dart' show Link;
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
import 'package:kernel/kernel.dart' hide LibraryDependency, Combinator;
@@ -19,10 +20,8 @@
import 'common/tasks.dart' show CompilerTask, Measurer;
import 'common.dart';
import 'elements/entities.dart' show LibraryEntity;
-import 'enqueue.dart' show DeferredAction;
import 'kernel/element_map_impl.dart' show KernelToElementMapForImpactImpl;
import 'resolved_uri_translator.dart';
-import 'util/util.dart' show Link;
/**
* [CompilerTask] for loading libraries and setting up the import/export scopes.
@@ -131,47 +130,7 @@
/// [LibraryElement] for the library and computes the import/export scope,
/// loading and computing the import/export scopes of all required libraries
/// in the process. The method handles cyclic dependency between libraries.
- ///
- /// If [skipFileWithPartOfTag] is `true`, `null` is returned if the
- /// compilation unit for [resolvedUri] contains a `part of` tag. This is only
- /// used for analysis through [Compiler.analyzeUri].
- Future<LoadedLibraries> loadLibrary(Uri resolvedUri,
- {bool skipFileWithPartOfTag: false});
-
- // TODO(johnniwinther): Move these to a separate interface.
- /// Register a deferred action to be performed during resolution.
- void registerDeferredAction(DeferredAction action);
-
- /// Returns the deferred actions registered since the last call to
- /// [pullDeferredActions].
- Iterable<DeferredAction> pullDeferredActions();
-
- /// The locations of js patch-files relative to the sdk-descriptors.
- static const _patchLocations = const <String, String>{
- "async": "_internal/js_runtime/lib/async_patch.dart",
- "cli": "_internal/js_runtime/lib/cli_patch.dart",
- "collection": "_internal/js_runtime/lib/collection_patch.dart",
- "convert": "_internal/js_runtime/lib/convert_patch.dart",
- "core": "_internal/js_runtime/lib/core_patch.dart",
- "developer": "_internal/js_runtime/lib/developer_patch.dart",
- "io": "_internal/js_runtime/lib/io_patch.dart",
- "isolate": "_internal/js_runtime/lib/isolate_patch.dart",
- "math": "_internal/js_runtime/lib/math_patch.dart",
- "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart",
- "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart",
- "_internal": "_internal/js_runtime/lib/internal_patch.dart",
- "_js": "js/_js_client.dart",
- };
-
- /// Returns the location of the patch-file associated with [libraryName]
- /// resolved from [plaformConfigUri].
- ///
- /// Returns null if there is none.
- static Uri resolvePatchUri(String libraryName, Uri platformConfigUri) {
- String patchLocation = _patchLocations[libraryName];
- if (patchLocation == null) return null;
- return platformConfigUri.resolve(patchLocation);
- }
+ Future<LoadedLibraries> loadLibrary(Uri resolvedUri);
}
/// Interface for an entity that provide libraries.
@@ -223,8 +182,7 @@
/// library, so this name is actually a bit of a misnomer).
// TODO(efortuna): Rename this once the Element library loader class goes
// away.
- Future<LoadedLibraries> loadLibrary(Uri resolvedUri,
- {bool skipFileWithPartOfTag: false}) {
+ Future<LoadedLibraries> loadLibrary(Uri resolvedUri) {
return measure(() async {
var isDill = resolvedUri.path.endsWith('.dill');
ir.Component component;
@@ -303,13 +261,6 @@
LibraryEntity lookupLibrary(Uri canonicalUri) {
return _elementMap?.lookupLibrary(canonicalUri);
}
-
- void registerDeferredAction(DeferredAction action) {
- throw new UnimplementedError(
- 'KernelLibraryLoaderTask.registerDeferredAction');
- }
-
- Iterable<DeferredAction> pullDeferredActions() => const <DeferredAction>[];
}
/// Information on the set libraries loaded as a result of a call to
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index dde23a9..cea1634 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -61,7 +61,7 @@
/// Resolved constant "environment" values passed to the compiler via the `-D`
/// flags.
- Map<String, dynamic> environment = const <String, dynamic>{};
+ Map<String, String> environment = const <String, String>{};
/// A possibly null state object for kernel compilation.
fe.InitializedCompilerState kernelInitializedCompilerState;
diff --git a/pkg/compiler/lib/src/ordered_typeset.dart b/pkg/compiler/lib/src/ordered_typeset.dart
index 67c594a..e8d365b 100644
--- a/pkg/compiler/lib/src/ordered_typeset.dart
+++ b/pkg/compiler/lib/src/ordered_typeset.dart
@@ -4,13 +4,14 @@
library ordered_typeset;
+import 'package:front_end/src/fasta/util/link.dart' show Link, LinkBuilder;
+import 'package:front_end/src/fasta/util/link_implementation.dart'
+ show LinkEntry;
+
import 'common.dart';
import 'diagnostics/diagnostic_listener.dart' show DiagnosticReporter;
import 'elements/entities.dart';
import 'elements/types.dart';
-import 'util/util.dart' show Link, LinkBuilder;
-import 'package:front_end/src/fasta/util/link_implementation.dart'
- show LinkEntry;
/**
* An ordered set of the supertypes of a class. The supertypes of a class are
@@ -283,7 +284,7 @@
}
}
return new OrderedTypeSet.internal(
- levels, levels.last, allSupertypes.toLink());
+ levels, levels.last, allSupertypes.toLink(const Link<InterfaceType>()));
}
String toString() {
@@ -291,13 +292,7 @@
for (int depth = 0; depth <= maxDepth; depth++) {
sb.write('$depth: ');
LinkEntry<InterfaceType> first = map[depth];
- if (first.isNotEmpty) {
- sb.write('${first.head}');
- while (first.tail.isNotEmpty) {
- sb.write(', ${first.tail.head}');
- first = first.tail;
- }
- }
+ first.printOn(sb, ", ");
sb.write('\n');
}
return sb.toString();
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index e7c0f61..7b4f019 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -25,8 +25,9 @@
Map<Uri, api.Input> binarySourceFiles = <Uri, api.Input>{};
int dartCharactersRead = 0;
- Future<api.Input> readBytesFromUri(Uri resourceUri, api.InputKind inputKind) {
- api.Input input;
+ Future<api.Input<List<int>>> readBytesFromUri(
+ Uri resourceUri, api.InputKind inputKind) {
+ api.Input<List<int>> input;
switch (inputKind) {
case api.InputKind.UTF8:
input = utf8SourceFiles[resourceUri];
@@ -84,8 +85,9 @@
return null;
}
- Future<api.Input> _readFromFile(Uri resourceUri, api.InputKind inputKind) {
- api.Input input;
+ Future<api.Input<List<int>>> _readFromFile(
+ Uri resourceUri, api.InputKind inputKind) {
+ api.Input<List<int>> input;
try {
input = _readFromFileSync(resourceUri, inputKind);
} catch (e) {
@@ -94,7 +96,8 @@
return new Future.value(input);
}
- Future<api.Input> _readFromHttp(Uri resourceUri, api.InputKind inputKind) {
+ Future<api.Input<List<int>>> _readFromHttp(
+ Uri resourceUri, api.InputKind inputKind) {
assert(resourceUri.scheme == 'http');
HttpClient client = new HttpClient();
return client
@@ -118,7 +121,7 @@
offset += contentPart.length;
}
dartCharactersRead += totalLength;
- api.Input input;
+ api.Input<List<int>> input;
switch (inputKind) {
case api.InputKind.UTF8:
input = utf8SourceFiles[resourceUri] = new CachingUtf8BytesSourceFile(
@@ -141,7 +144,7 @@
relativizeUri(Uri uri) => relativize(cwd, uri, isWindows);
- SourceFile getUtf8SourceFile(Uri resourceUri) {
+ SourceFile<List<int>> getUtf8SourceFile(Uri resourceUri) {
return utf8SourceFiles[resourceUri];
}
@@ -267,7 +270,7 @@
throw 'Unknown kind: $kind (${kind.ordinal})';
}
if (!enableColors) {
- color = (x) => x;
+ color = (String x) => x;
}
if (uri == null) {
print('${color(message)}');
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index c8a203c..65e1636 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -2839,7 +2839,7 @@
ConstantValue value = _elementMap.getFieldConstantValue(field);
if (value != null) {
if (!field.isAssignable) {
- var unit = compiler.backend.outputUnitData.outputUnitForEntity(field);
+ var unit = compiler.backend.outputUnitData.outputUnitForMember(field);
// TODO(sigmund): this is not equivalent to what the old FE does: if
// there is no prefix the old FE wouldn't treat this in any special
// way. Also, if the prefix points to a constant in the main output
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 1e94b01..4e299b0 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -4,6 +4,9 @@
import 'dart:math' as math;
import 'dart:collection' show Queue;
+
+import 'package:front_end/src/fasta/util/link.dart' show Link;
+
import '../common.dart';
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
import '../common/tasks.dart' show CompilerTask;
@@ -31,7 +34,6 @@
import '../universe/selector.dart' show Selector;
import '../universe/use.dart'
show ConstantUse, ConstrainedDynamicUse, StaticUse, TypeUse;
-import '../util/util.dart';
import '../world.dart' show ClosedWorld;
import 'codegen_helpers.dart';
import 'nodes.dart';
@@ -2423,7 +2425,7 @@
void generateThrowWithHelper(FunctionEntity helper, argument,
{SourceInformation sourceInformation}) {
js.Expression jsHelper = _emitter.staticFunctionAccess(helper);
- List arguments = [];
+ List arguments = <js.Expression>[];
if (argument is List) {
argument.forEach((instruction) {
use(instruction);
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 04c906f..cb3258d 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:front_end/src/fasta/util/link.dart' show Link;
+
import '../closure.dart';
import '../common.dart';
import '../compiler.dart' show Compiler;
@@ -1555,7 +1557,7 @@
/// we have to register the instantiated type in the code generator. The
/// [instructionType] of this node is not enough, because we also need the
/// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
- List<DartType> instantiatedTypes;
+ List<InterfaceType> instantiatedTypes;
/// If this node creates a closure class, [callMethod] is the call method of
/// the closure class.
@@ -1759,7 +1761,7 @@
/// contains the type(s) used in the (Dart) `New` expression(s). The
/// [instructionType] of this node is not enough, because we also need the
/// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
- List<DartType> instantiatedTypes;
+ List<InterfaceType> instantiatedTypes;
/** The first input must be the target. */
HInvokeStatic(this.element, inputs, AbstractValue type, this.typeArguments,
diff --git a/pkg/compiler/lib/src/ssa/variable_allocator.dart b/pkg/compiler/lib/src/ssa/variable_allocator.dart
index 7575c22..3bb3c85 100644
--- a/pkg/compiler/lib/src/ssa/variable_allocator.dart
+++ b/pkg/compiler/lib/src/ssa/variable_allocator.dart
@@ -550,9 +550,9 @@
if (instruction is HCheck) {
// Special case this instruction to use the name of its
// input if it has one.
- var temp = instruction;
+ HInstruction temp = instruction;
do {
- temp = temp.checkedInput;
+ temp = (temp as HCheck).checkedInput;
name = names.ownName[temp];
} while (name == null && temp is HCheck);
if (name != null) return addAllocatedName(instruction, name);
diff --git a/pkg/compiler/lib/src/types/abstract_value_domain.dart b/pkg/compiler/lib/src/types/abstract_value_domain.dart
index 6b35ca4..de04b3d 100644
--- a/pkg/compiler/lib/src/types/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/types/abstract_value_domain.dart
@@ -268,4 +268,14 @@
/// Returns whether [selector] invoked on a [receiver] can hit a
/// [noSuchMethod].
bool needsNoSuchMethodHandling(AbstractValue receiver, Selector selector);
+
+ /// Returns `true` if the set of runtime values of [subset] are all in the set
+ /// of runtime values of [superset].
+ bool contains(AbstractValue superset, AbstractValue subset);
+
+ /// Returns the [MemberEntity] that is known to always be hit at runtime
+ /// [receiver].
+ ///
+ /// Returns `null` if 0 or more than 1 member can be hit at runtime.
+ MemberEntity locateSingleMember(AbstractValue receiver, Selector selector);
}
diff --git a/pkg/compiler/lib/src/types/masks.dart b/pkg/compiler/lib/src/types/masks.dart
index 8e4916c..19455cc 100644
--- a/pkg/compiler/lib/src/types/masks.dart
+++ b/pkg/compiler/lib/src/types/masks.dart
@@ -442,4 +442,15 @@
covariant TypeMask receiver, Selector selector) {
return receiver.needsNoSuchMethodHandling(selector, _closedWorld);
}
+
+ @override
+ bool contains(covariant TypeMask superset, covariant TypeMask subset) {
+ return superset.containsMask(subset, _closedWorld);
+ }
+
+ @override
+ MemberEntity locateSingleMember(
+ covariant TypeMask receiver, Selector selector) {
+ return receiver.locateSingleMember(selector, _closedWorld);
+ }
}
diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/types/type_mask.dart
index 50bc096..d7c9c01 100644
--- a/pkg/compiler/lib/src/types/type_mask.dart
+++ b/pkg/compiler/lib/src/types/type_mask.dart
@@ -365,6 +365,5 @@
* Returns the [element] that is known to always be hit at runtime
* on this mask. Returns null if there is none.
*/
- // TODO(johnniwinther): Move this method to [World].
MemberEntity locateSingleMember(Selector selector, ClosedWorld closedWorld);
}
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index 3dd5e16..e747c75 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -6,9 +6,10 @@
import 'dart:collection' show IterableBase;
+import 'package:front_end/src/fasta/util/link.dart' show Link;
+
import '../elements/entities.dart' show ClassEntity;
import '../util/enumset.dart' show EnumSet;
-import '../util/util.dart' show Link;
/// Enum for the different kinds of instantiation of a class.
enum Instantiation {
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index ed3c1b9..f408104 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -384,8 +384,6 @@
ClosedWorld _closedWorldCache;
final Set<MemberEntity> _liveInstanceMembers = new Set<MemberEntity>();
- final Set<TypedefEntity> _allTypedefs = new Set<TypedefEntity>();
-
final Set<ConstantValue> _constantValues = new Set<ConstantValue>();
final Set<Local> genericLocalFunctions = new Set<Local>();
@@ -888,10 +886,6 @@
return uses != null ? uses : const <ClassEntity>[];
}
- void registerTypedef(TypedefEntity typdef) {
- _allTypedefs.add(typdef);
- }
-
void registerUsedElement(MemberEntity element) {
if (element.isInstanceMember && !element.isAbstract) {
_liveInstanceMembers.add(element);
@@ -1063,7 +1057,6 @@
liveInstanceMembers: _liveInstanceMembers,
assignedInstanceMembers: computeAssignedInstanceMembers(),
processedMembers: _processedMembers,
- allTypedefs: _allTypedefs,
mixinUses: classHierarchyBuilder.mixinUses,
typesImplementedBySubclasses: typesImplementedBySubclasses,
classHierarchyNodes: classHierarchyBuilder.classHierarchyNodes,
diff --git a/pkg/compiler/lib/src/util/maplet.dart b/pkg/compiler/lib/src/util/maplet.dart
index febfe5f..b9dc6744 100644
--- a/pkg/compiler/lib/src/util/maplet.dart
+++ b/pkg/compiler/lib/src/util/maplet.dart
@@ -157,7 +157,7 @@
copyTo++;
}
} else {
- Map map = new Map();
+ var map = new Map<K, V>();
forEach((eachKey, eachValue) => map[eachKey] = eachValue);
map[key] = value;
_key = map;
diff --git a/pkg/compiler/lib/src/util/setlet.dart b/pkg/compiler/lib/src/util/setlet.dart
index 08195f0..62ccde0 100644
--- a/pkg/compiler/lib/src/util/setlet.dart
+++ b/pkg/compiler/lib/src/util/setlet.dart
@@ -138,7 +138,7 @@
while (copyTo < CAPACITY) _contents[copyTo++] = null;
} else {
_contents = new Set<E>()
- ..addAll(_contents)
+ ..addAll((_contents as List).cast<E>())
..add(element);
_extra = _MARKER;
}
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index 113a2ed..32944bb 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -10,7 +10,6 @@
export 'emptyset.dart';
export 'maplet.dart';
export 'setlet.dart';
-export 'package:front_end/src/fasta/util/link.dart';
part 'indentation.dart';
@@ -210,7 +209,7 @@
if (isExternal) builder.addLast('external');
if (isCovariant) builder.addLast('covariant');
StringBuffer buffer = new StringBuffer();
- builder.toLink().printOn(buffer, ', ');
+ builder.toLink(const Link<String>()).printOn(buffer, ', ');
return buffer.toString();
}
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 523bca7..9bd4e8a 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -5,6 +5,9 @@
library dart2js.world;
import 'dart:collection' show Queue;
+
+import 'package:front_end/src/fasta/util/link.dart' show Link;
+
import 'common.dart';
import 'common/names.dart';
import 'common_elements.dart' show CommonElements, ElementEnvironment;
@@ -20,13 +23,12 @@
import 'ordered_typeset.dart';
import 'options.dart';
import 'types/abstract_value_domain.dart';
-import 'types/masks.dart' show CommonMasks, TypeMask;
+import 'types/masks.dart' show CommonMasks;
import 'universe/class_set.dart';
import 'universe/function_set.dart' show FunctionSet;
import 'universe/selector.dart' show Selector;
import 'universe/side_effects.dart' show SideEffects, SideEffectsBuilder;
import 'universe/world_builder.dart';
-import 'util/util.dart' show Link;
/// Common superinterface for [OpenWorld] and [ClosedWorld].
abstract class World {}
@@ -282,50 +284,50 @@
/// Returns `true` if the field [element] is known to be effectively final.
bool fieldNeverChanges(MemberEntity element);
- /// Extends the receiver type [mask] for calling [selector] to take live
+ /// Extends the [receiver] type for calling [selector] to take live
/// `noSuchMethod` handlers into account.
- TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask);
+ AbstractValue extendMaskIfReachesAll(
+ Selector selector, AbstractValue receiver);
- /// Returns all resolved typedefs.
- Iterable<TypedefEntity> get allTypedefs;
-
- /// Returns `true` if [selector] on [mask] can hit a `call` method on a
+ /// Returns `true` if [selector] on [receiver] can hit a `call` method on a
/// subclass of `Closure`.
///
/// Every implementation of `Closure` has a 'call' method with its own
/// signature so it cannot be modelled by a [FunctionEntity]. Also,
/// call-methods for tear-off are not part of the element model.
- bool includesClosureCall(Selector selector, TypeMask mask);
+ bool includesClosureCall(Selector selector, AbstractValue receiver);
/// Returns the mask for the potential receivers of a dynamic call to
- /// [selector] on [mask].
+ /// [selector] on [receiver].
///
- /// This will narrow the constraints of [mask] to a [TypeMask] of the
- /// set of classes that actually implement the selected member or implement
- /// the handling 'noSuchMethod' where the selected member is unimplemented.
- TypeMask computeReceiverType(Selector selector, TypeMask mask);
+ /// This will narrow the constraints of [receiver] to an [AbstractValue] of
+ /// the set of classes that actually implement the selected member or
+ /// implement the handling 'noSuchMethod' where the selected member is
+ /// unimplemented.
+ AbstractValue computeReceiverType(Selector selector, AbstractValue receiver);
- /// Returns all the instance members that may be invoked with the
- /// [selector] on a receiver with the given [mask]. The returned elements may
- /// include noSuchMethod handlers that are potential targets indirectly
- /// through the noSuchMethod mechanism.
- Iterable<MemberEntity> locateMembers(Selector selector, TypeMask mask);
+ /// Returns all the instance members that may be invoked with the [selector]
+ /// on the given [receiver]. The returned elements may include noSuchMethod
+ /// handlers that are potential targets indirectly through the noSuchMethod
+ /// mechanism.
+ Iterable<MemberEntity> locateMembers(
+ Selector selector, AbstractValue receiver);
- /// Returns the single [MemberEntity] that matches a call to [selector] on a
- /// receiver of type [mask]. If multiple targets exist, `null` is returned.
- MemberEntity locateSingleMember(Selector selector, TypeMask mask);
+ /// Returns the single [MemberEntity] that matches a call to [selector] on the
+ /// [receiver]. If multiple targets exist, `null` is returned.
+ MemberEntity locateSingleMember(Selector selector, AbstractValue receiver);
- /// Returns the single field that matches a call to [selector] on a
- /// receiver of type [mask]. If multiple targets exist or the single target
- /// is not a field, `null` is returned.
- FieldEntity locateSingleField(Selector selector, TypeMask mask);
+ /// Returns the single field that matches a call to [selector] on the
+ /// [receiver]. If multiple targets exist or the single target is not a field,
+ /// `null` is returned.
+ FieldEntity locateSingleField(Selector selector, AbstractValue receiver);
/// Returns the side effects of executing [element].
SideEffects getSideEffectsOfElement(FunctionEntity element);
- /// Returns the side effects of calling [selector] on a receiver of type
- /// [mask].
- SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask);
+ /// Returns the side effects of calling [selector] on the [receiver].
+ SideEffects getSideEffectsOfSelector(
+ Selector selector, AbstractValue receiver);
/// Returns `true` if [element] is guaranteed not to throw an exception.
bool getCannotThrow(FunctionEntity element);
@@ -386,7 +388,6 @@
abstract class OpenWorld implements World {
void registerUsedElement(MemberEntity element);
- void registerTypedef(TypedefEntity typedef);
ClosedWorld closeWorld();
@@ -431,8 +432,6 @@
FunctionSet _allFunctions;
- final Set<TypedefEntity> _allTypedefs;
-
final Map<ClassEntity, Set<ClassEntity>> mixinUses;
Map<ClassEntity, List<ClassEntity>> _liveMixinUses;
@@ -494,13 +493,11 @@
this.liveInstanceMembers,
this.assignedInstanceMembers,
this.processedMembers,
- Set<TypedefEntity> allTypedefs,
this.mixinUses,
this.typesImplementedBySubclasses,
Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
Map<ClassEntity, ClassSet> classSets)
: this._implementedClasses = implementedClasses,
- this._allTypedefs = allTypedefs,
this._classHierarchyNodes = classHierarchyNodes,
this._classSets = classSets {
_commonMasks = new CommonMasks(this);
@@ -1027,8 +1024,6 @@
return _classSets[cls];
}
- Iterable<TypedefEntity> get allTypedefs => _allTypedefs;
-
void _ensureFunctionSet() {
if (_allFunctions == null) {
// [FunctionSet] is created lazily because it is not used when we switch
@@ -1037,58 +1032,62 @@
}
}
- /// Returns `true` if [selector] on [mask] can hit a `call` method on a
+ /// Returns `true` if [selector] on [receiver] can hit a `call` method on a
/// subclass of `Closure`.
///
/// Every implementation of `Closure` has a 'call' method with its own
/// signature so it cannot be modelled by a [FunctionEntity]. Also,
/// call-methods for tear-off are not part of the element model.
- bool includesClosureCall(Selector selector, TypeMask mask) {
+ bool includesClosureCall(Selector selector, AbstractValue receiver) {
return selector.name == Identifiers.call &&
- (mask == null ||
- mask.containsMask(abstractValueDomain.functionType, closedWorld));
+ (receiver == null ||
+ // TODO(johnniwinther): Should this have been `intersects` instead?
+ abstractValueDomain.contains(
+ receiver, abstractValueDomain.functionType));
}
- TypeMask computeReceiverType(Selector selector, TypeMask mask) {
+ AbstractValue computeReceiverType(Selector selector, AbstractValue receiver) {
_ensureFunctionSet();
- if (includesClosureCall(selector, mask)) {
+ if (includesClosureCall(selector, receiver)) {
return abstractValueDomain.dynamicType;
}
- return _allFunctions.receiverType(selector, mask, abstractValueDomain);
+ return _allFunctions.receiverType(selector, receiver, abstractValueDomain);
}
- Iterable<MemberEntity> locateMembers(Selector selector, TypeMask mask) {
+ Iterable<MemberEntity> locateMembers(
+ Selector selector, AbstractValue receiver) {
_ensureFunctionSet();
- return _allFunctions.filter(selector, mask, abstractValueDomain);
+ return _allFunctions.filter(selector, receiver, abstractValueDomain);
}
- bool hasAnyUserDefinedGetter(Selector selector, TypeMask mask) {
+ bool hasAnyUserDefinedGetter(Selector selector, AbstractValue receiver) {
_ensureFunctionSet();
return _allFunctions
- .filter(selector, mask, abstractValueDomain)
+ .filter(selector, receiver, abstractValueDomain)
.any((each) => each.isGetter);
}
- FieldEntity locateSingleField(Selector selector, TypeMask mask) {
- MemberEntity result = locateSingleMember(selector, mask);
+ FieldEntity locateSingleField(Selector selector, AbstractValue receiver) {
+ MemberEntity result = locateSingleMember(selector, receiver);
return (result != null && result.isField) ? result : null;
}
- MemberEntity locateSingleMember(Selector selector, TypeMask mask) {
- if (includesClosureCall(selector, mask)) {
+ MemberEntity locateSingleMember(Selector selector, AbstractValue receiver) {
+ if (includesClosureCall(selector, receiver)) {
return null;
}
- mask ??= abstractValueDomain.dynamicType;
- return mask.locateSingleMember(selector, this);
+ receiver ??= abstractValueDomain.dynamicType;
+ return abstractValueDomain.locateSingleMember(receiver, selector);
}
- TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) {
+ AbstractValue extendMaskIfReachesAll(
+ Selector selector, AbstractValue receiver) {
bool canReachAll = true;
- if (mask != null) {
+ if (receiver != null) {
canReachAll = backendUsage.isInvokeOnUsed &&
- mask.needsNoSuchMethodHandling(selector, this);
+ abstractValueDomain.needsNoSuchMethodHandling(receiver, selector);
}
- return canReachAll ? abstractValueDomain.dynamicType : mask;
+ return canReachAll ? abstractValueDomain.dynamicType : receiver;
}
bool fieldNeverChanges(MemberEntity element) {
@@ -1110,15 +1109,16 @@
return false;
}
- SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask) {
+ SideEffects getSideEffectsOfSelector(
+ Selector selector, AbstractValue receiver) {
// We're not tracking side effects of closures.
- if (selector.isClosureCall || includesClosureCall(selector, mask)) {
+ if (selector.isClosureCall || includesClosureCall(selector, receiver)) {
return new SideEffects();
}
SideEffects sideEffects = new SideEffects.empty();
_ensureFunctionSet();
for (MemberEntity e
- in _allFunctions.filter(selector, mask, abstractValueDomain)) {
+ in _allFunctions.filter(selector, receiver, abstractValueDomain)) {
if (e.isField) {
if (selector.isGetter) {
if (!fieldNeverChanges(e)) {
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 0a66690..a8478d6 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -522,7 +522,7 @@
JS.Statement _emitClassDeclaration(Class c) {
// Mixins are unrolled in _defineClass.
- if (c.isSyntheticMixinImplementation) return null;
+ if (c.isAnonymousMixin) return null;
// If this class is annotated with `@JS`, then there is nothing to emit.
if (findAnnotation(c, isPublicJSAnnotation) != null) return null;
@@ -820,7 +820,7 @@
/// Defines all constructors for this class as ES5 constructors.
List<JS.Statement> _defineConstructors(Class c, JS.Expression className) {
var body = <JS.Statement>[];
- if (c.isSyntheticMixinImplementation || isMixinAliasClass(c)) {
+ if (c.isAnonymousMixin || isMixinAliasClass(c)) {
// We already handled this when we defined the class.
return body;
}
@@ -1211,7 +1211,7 @@
if (!emitMetadata && member.isStatic) continue;
var name = member.name.name;
- var reifiedType = _getMemberRuntimeType(member, c);
+ var reifiedType = _getMemberRuntimeType(member, c) as FunctionType;
// Don't add redundant signatures for inherited methods whose signature
// did not change. If we are not overriding, or if the thing we are
@@ -1310,7 +1310,7 @@
field.isFinal ? 'finalFieldType(#)' : 'fieldType(#)', [args]);
}
- FunctionType _getMemberRuntimeType(Member member, Class fromClass) {
+ DartType _getMemberRuntimeType(Member member, Class fromClass) {
var f = member.function;
if (f == null) {
return (member as Field).type;
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index dc11518..44a8f0f 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -227,7 +227,7 @@
if (mixedInClass != null) mixins.add(mixedInClass);
var sc = c.superclass;
- for (; sc.isSyntheticMixinImplementation; sc = sc.superclass) {
+ for (; sc.isAnonymousMixin; sc = sc.superclass) {
mixins.add(sc.mixedInClass);
}
return sc;
diff --git a/pkg/dev_compiler/tool/build_pkgs.dart b/pkg/dev_compiler/tool/build_pkgs.dart
index 904aad3..c8b3bf12 100755
--- a/pkg/dev_compiler/tool/build_pkgs.dart
+++ b/pkg/dev_compiler/tool/build_pkgs.dart
@@ -189,7 +189,6 @@
..packagesFileUri = _uriInRepo(".packages")
..strongMode = true
..debugDump = true
- ..chaseDependencies = true
..onError = errorHandler
..reportMessages = true
..target = new DevCompilerTarget();
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index a9faea8..a02b4cf 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -59,7 +59,7 @@
ProcessResult runDdc(String command, List<String> args) {
if (debug) {
// Use unbuilt script. This only works from a source checkout.
- args.insertAll(0, ['--preview-dart-2', '-c', path.join(ddcPath, 'bin', '${command}.dart')]);
+ args.insertAll(0, ['--preview-dart-2', '--enable-asserts', path.join(ddcPath, 'bin', '${command}.dart')]);
command = dartBinary;
} else {
// Use built snapshot.
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart
index 604c0c8..672eb0a 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart
@@ -16,12 +16,12 @@
}
@patch
- static _setCurrent(_Namespace namespace, path) {
+ static _setCurrent(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("Directory_SetCurrent");
}
@patch
- static _createTemp(_Namespace namespace, String path) {
+ static _createTemp(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("Directory._createTemp");
}
@@ -31,22 +31,23 @@
}
@patch
- static _exists(_Namespace namespace, String path) {
+ static _exists(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("Directory._exists");
}
@patch
- static _create(_Namespace namespace, String path) {
+ static _create(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("Directory._create");
}
@patch
- static _deleteNative(_Namespace namespace, String path, bool recursive) {
+ static _deleteNative(
+ _Namespace namespace, Uint8List rawPath, bool recursive) {
throw new UnsupportedError("Directory._deleteNative");
}
@patch
- static _rename(_Namespace namespace, String path, String newPath) {
+ static _rename(_Namespace namespace, Uint8List rawPath, String newPath) {
throw new UnsupportedError("Directory._rename");
}
@@ -54,7 +55,7 @@
static void _fillWithDirectoryListing(
_Namespace namespace,
List<FileSystemEntity> list,
- String path,
+ Uint8List rawPath,
bool recursive,
bool followLinks) {
throw new UnsupportedError("Directory._fillWithDirectoryListing");
@@ -88,7 +89,8 @@
@patch
class FileSystemEntity {
@patch
- static _getTypeNative(_Namespace namespace, String path, bool followLinks) {
+ static _getTypeNative(
+ _Namespace namespace, Uint8List rawPath, bool followLinks) {
throw new UnsupportedError("FileSystemEntity._getType");
}
@@ -98,7 +100,7 @@
}
@patch
- static _resolveSymbolicLinks(_Namespace namespace, String path) {
+ static _resolveSymbolicLinks(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("FileSystemEntity._resolveSymbolicLinks");
}
}
@@ -106,77 +108,77 @@
@patch
class _File {
@patch
- static _exists(_Namespace namespace, String path) {
+ static _exists(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("File._exists");
}
@patch
- static _create(_Namespace namespace, String path) {
+ static _create(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("File._create");
}
@patch
- static _createLink(_Namespace namespace, String path, String target) {
+ static _createLink(_Namespace namespace, Uint8List rawPath, String target) {
throw new UnsupportedError("File._createLink");
}
@patch
- static _linkTarget(_Namespace namespace, String path) {
+ static _linkTarget(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("File._linkTarget");
}
@patch
- static _deleteNative(_Namespace namespace, String path) {
+ static _deleteNative(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("File._deleteNative");
}
@patch
- static _deleteLinkNative(_Namespace namespace, String path) {
+ static _deleteLinkNative(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("File._deleteLinkNative");
}
@patch
- static _rename(_Namespace namespace, String oldPath, String newPath) {
+ static _rename(_Namespace namespace, Uint8List oldPath, String newPath) {
throw new UnsupportedError("File._rename");
}
@patch
- static _renameLink(_Namespace namespace, String oldPath, String newPath) {
+ static _renameLink(_Namespace namespace, Uint8List oldPath, String newPath) {
throw new UnsupportedError("File._renameLink");
}
@patch
- static _copy(_Namespace namespace, String oldPath, String newPath) {
+ static _copy(_Namespace namespace, Uint8List oldPath, String newPath) {
throw new UnsupportedError("File._copy");
}
@patch
- static _lengthFromPath(_Namespace namespace, String path) {
+ static _lengthFromPath(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("File._lengthFromPath");
}
@patch
- static _lastModified(_Namespace namespace, String path) {
+ static _lastModified(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("File._lastModified");
}
@patch
- static _lastAccessed(_Namespace namespace, String path) {
+ static _lastAccessed(_Namespace namespace, Uint8List rawPath) {
throw new UnsupportedError("File._lastAccessed");
}
@patch
- static _setLastModified(_Namespace namespace, String path, int millis) {
+ static _setLastModified(_Namespace namespace, Uint8List rawPath, int millis) {
throw new UnsupportedError("File._setLastModified");
}
@patch
- static _setLastAccessed(_Namespace namespace, String path, int millis) {
+ static _setLastAccessed(_Namespace namespace, Uint8List rawPath, int millis) {
throw new UnsupportedError("File._setLastAccessed");
}
@patch
- static _open(_Namespace namespace, String path, int mode) {
+ static _open(_Namespace namespace, Uint8List rawPath, int mode) {
throw new UnsupportedError("File._open");
}
diff --git a/pkg/dev_compiler/tool/kernel_sdk.dart b/pkg/dev_compiler/tool/kernel_sdk.dart
index f2d5623..38e9e65 100755
--- a/pkg/dev_compiler/tool/kernel_sdk.dart
+++ b/pkg/dev_compiler/tool/kernel_sdk.dart
@@ -31,7 +31,6 @@
var target = new DevCompilerTarget();
var options = new CompilerOptions()
..compileSdk = true
- ..chaseDependencies = true
..packagesFileUri = path.toUri(path.absolute('../../.packages'))
..sdkRoot = path.toUri(inputPath)
..target = target;
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index eea2ab4..4803de0 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -515,33 +515,35 @@
}
/**
- * Calls the function [f] and verifies that it throws an exception.
+ * Calls the function [f] and verifies that it throws a `T`.
* The optional [check] function can provide additional validation
- * that the correct exception is being thrown. For example, to check
- * the type of the exception you could write this:
+ * that the correct object is being thrown. For example, to check
+ * the content of the thrown boject you could write this:
*
- * Expect.throws(myThrowingFunction, (e) => e is MyException);
+ * Expect.throws<MyException>(myThrowingFunction,
+ * (e) => e.myMessage.contains("WARNING"));
+ *
+ * The type variable can be omitted and the type checked in [check]
+ * instead. This was traditionally done before Dart had generic methods.
*
* If `f` fails an expectation (i.e., throws an [ExpectException]), that
* exception is not caught by [Expect.throws]. The test is still considered
* failing.
*/
- static void throws(void f(), [bool check(Object error), String reason]) {
+ static void throws<T>(void f(), [bool check(T error), String reason]) {
String msg = reason == null ? "" : "($reason)";
- if (f is! _Nullary) {
+ if (f is! Function()) {
// Only throws from executing the function body should count as throwing.
// The failure to even call `f` should throw outside the try/catch.
_fail("Expect.throws$msg: Function f not callable with zero arguments");
}
try {
f();
- } catch (e, s) {
+ } on Object catch (e, s) {
// A test failure doesn't count as throwing.
if (e is ExpectException) rethrow;
- if (check != null && !check(e)) {
- _fail("Expect.throws$msg: Unexpected '$e'\n$s");
- }
- return;
+ if (e is T && (check == null || check(e))) return;
+ _fail("Expect.throws$msg: Unexpected '$e'\n$s");
}
_fail('Expect.throws$msg fails: Did not throw');
}
@@ -607,8 +609,9 @@
/// Used in [Expect] because [Expect.identical] shadows the real [identical].
bool _identical(a, b) => identical(a, b);
-typedef _Nullary(); // Expect.throws argument must be this type.
-
+/// Exception thrown on a failed expectation check.
+///
+/// Always recognized by [Expect.throws] as an unexpected error.
class ExpectException implements Exception {
final String message;
ExpectException(this.message);
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 57e667a..e624930 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -131,19 +131,7 @@
/// When this option is `true`, [sdkSummary] must be null.
bool compileSdk = false;
- /// Whether the compiler should read files that are discovered as
- /// dependencies, or only access the files listed explicitly.
- ///
- /// This option has different defaults depending on the API.
- ///
- /// For modular APIs like `kernelForComponent` and `summaryFor` the default
- /// behavior is `false`. These APIs want to ensure that builds are hermetic,
- /// where all files that will be compiled are listed explicitly and all other
- /// dependencies are covered by summary files.
- ///
- /// For whole-program APIs like `kernelForProgram`, this option is true by
- /// default, so they can treat any dependency that is not described in a
- /// summary as if it was explicitly listed as an input.
+ @deprecated
bool chaseDependencies;
/// Whether to interpret Dart sources in strong-mode.
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index f10c806..8d4e803 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -21,7 +21,7 @@
factory IncrementalKernelGenerator(CompilerOptions options, Uri entryPoint,
[Uri initializeFromDillUri]) {
return new IncrementalCompiler(
- new CompilerContext(new ProcessedOptions(options, false, [entryPoint])),
+ new CompilerContext(new ProcessedOptions(options, [entryPoint])),
initializeFromDillUri);
}
diff --git a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
index 94a6d0f..98d8ded 100644
--- a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
@@ -43,7 +43,7 @@
/// an error is reported.
// TODO(sigmund): rename to kernelForScript?
Future<Component> kernelForProgram(Uri source, CompilerOptions options) async {
- var pOptions = new ProcessedOptions(options, false, [source]);
+ var pOptions = new ProcessedOptions(options, [source]);
return await CompilerContext.runWithOptions(pOptions, (context) async {
var component = (await generateKernelInternal())?.component;
if (component == null) return null;
@@ -66,19 +66,10 @@
/// dependencies, build unit dependencies must be acyclic.
///
/// This API is intended for modular compilation. Dependencies to other build
-/// units are specified using [CompilerOptions.inputSummaries].
-///
-/// By default, the compilation process is hermetic, meaning that the only files
-/// which will be read are those listed in [sources],
-/// [CompilerOptions.inputSummaries], and [CompilerOptions.sdkSummary]. If a
-/// source file attempts to refer to a file which is not obtainable from these
-/// URIs, that will result in an error, even if the file exists on the
-/// filesystem.
-///
-/// When [CompilerOptions.chaseDependencies] is true, this default behavior
-/// changes, and any dependency of [sources] that is not listed in
-/// [CompilerOptions.inputSummaries] and [CompilerOptions.sdkSummary] is treated
-/// as an additional source file for the build unit.
+/// units are specified using [CompilerOptions.inputSummaries]. Any dependency
+/// of [sources] that is not listed in [CompilerOptions.inputSummaries] and
+/// [CompilerOptions.sdkSummary] is treated as an additional source file for the
+/// build unit.
///
/// Any `part` declarations found in [sources] must refer to part files which
/// are also listed in the build unit sources, otherwise an error results. (It
@@ -89,6 +80,6 @@
/// summaries.
Future<Component> kernelForComponent(
List<Uri> sources, CompilerOptions options) async {
- return (await generateKernel(new ProcessedOptions(options, true, sources)))
+ return (await generateKernel(new ProcessedOptions(options, sources)))
?.component;
}
diff --git a/pkg/front_end/lib/src/api_prototype/scheme_based_file_system.dart b/pkg/front_end/lib/src/api_prototype/scheme_based_file_system.dart
new file mode 100644
index 0000000..c992ea7
--- /dev/null
+++ b/pkg/front_end/lib/src/api_prototype/scheme_based_file_system.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'file_system.dart';
+
+/// A [FileSystem] that delegates to other file systems based on the URI scheme.
+class SchemeBasedFileSystem implements FileSystem {
+ final Map<String, FileSystem> fileSystemByScheme;
+
+ SchemeBasedFileSystem(this.fileSystemByScheme);
+
+ @override
+ FileSystemEntity entityForUri(Uri uri) {
+ FileSystem delegate = fileSystemByScheme[uri.scheme];
+ if (delegate == null) {
+ throw new FileSystemException(
+ uri,
+ "SchemeBasedFileSystem doesn't handle URIs with "
+ "scheme '${uri.scheme}': $uri");
+ }
+ return delegate.entityForUri(uri);
+ }
+}
diff --git a/pkg/front_end/lib/src/api_prototype/summary_generator.dart b/pkg/front_end/lib/src/api_prototype/summary_generator.dart
index 4a2974c..e230731 100644
--- a/pkg/front_end/lib/src/api_prototype/summary_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/summary_generator.dart
@@ -16,18 +16,7 @@
///
/// Intended to be a part of a modular compilation process.
///
-/// [sources] should be the complete set of source files for a build unit
-/// (including both library and part files).
-///
-/// By default, the compilation process is hermetic, meaning that the only files
-/// which will be read are those listed in [sources],
-/// [CompilerOptions.inputSummaries], and [CompilerOptions.sdkSummary]. If a
-/// source file attempts to refer to a file which is not obtainable from these
-/// URIs, that will result in an error, even if the file exists on the
-/// filesystem.
-///
-/// When [CompilerOptions.chaseDependencies] is true, this default behavior
-/// changes, and any dependency of [sources] that is not listed in
+/// Any dependency of [sources] that is not listed in
/// [CompilerOptions.inputSummaries] and [CompilerOptions.sdkSummary] is treated
/// as an additional source file for the build unit.
///
@@ -42,7 +31,7 @@
/// The return value is a list of bytes to write to the summary file.
Future<List<int>> summaryFor(List<Uri> sources, CompilerOptions options,
{bool truncate: false}) async {
- return (await generateKernel(new ProcessedOptions(options, true, sources),
+ return (await generateKernel(new ProcessedOptions(options, sources),
buildSummary: true, buildComponent: false, truncateSummary: truncate))
?.summary;
}
diff --git a/pkg/front_end/lib/src/api_unstable/build_integration.dart b/pkg/front_end/lib/src/api_unstable/build_integration.dart
new file mode 100644
index 0000000..39fce75
--- /dev/null
+++ b/pkg/front_end/lib/src/api_unstable/build_integration.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export '../api_prototype/file_system.dart';
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 666f32d..943eacf 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -47,7 +47,7 @@
..librariesSpecificationUri = librariesSpecificationUri
..packagesFileUri = packagesFileUri;
- ProcessedOptions processedOpts = new ProcessedOptions(options, false, []);
+ ProcessedOptions processedOpts = new ProcessedOptions(options, []);
return new InitializedCompilerState(options, processedOpts);
}
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index 0b9545f..2fbff4f 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -66,10 +66,9 @@
..inputSummaries = inputSummaries
..target = target
..fileSystem = fileSystem ?? StandardFileSystem.instance
- ..chaseDependencies = true
..reportMessages = true;
- ProcessedOptions processedOpts = new ProcessedOptions(options, true, []);
+ ProcessedOptions processedOpts = new ProcessedOptions(options, []);
return new InitializedCompilerState(options, processedOpts);
}
diff --git a/pkg/front_end/lib/src/api_unstable/summary_worker.dart b/pkg/front_end/lib/src/api_unstable/summary_worker.dart
index 2fdc8e5..0d4bf9f 100644
--- a/pkg/front_end/lib/src/api_unstable/summary_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/summary_worker.dart
@@ -38,10 +38,9 @@
..packagesFileUri = packagesFile
..inputSummaries = inputSummaries
..target = target
- ..fileSystem = fileSystem
- ..chaseDependencies = true;
+ ..fileSystem = fileSystem;
- ProcessedOptions processedOpts = new ProcessedOptions(options, true, []);
+ ProcessedOptions processedOpts = new ProcessedOptions(options, []);
return new InitializedCompilerState(options, processedOpts);
}
diff --git a/pkg/front_end/lib/src/base/libraries_specification.dart b/pkg/front_end/lib/src/base/libraries_specification.dart
index 2f9f553..2a25b30 100644
--- a/pkg/front_end/lib/src/base/libraries_specification.dart
+++ b/pkg/front_end/lib/src/base/libraries_specification.dart
@@ -164,9 +164,10 @@
}
var uri = checkAndResolve(data['uri']);
- var patches;
+ List<Uri> patches;
if (data['patches'] is List) {
- patches = data['patches'].map(baseUri.resolve).toList();
+ patches =
+ data['patches'].map<Uri>((s) => baseUri.resolve(s)).toList();
} else if (data['patches'] is String) {
patches = [checkAndResolve(data['patches'])];
} else if (data['patches'] == null) {
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 0c0dc02..c3072d9 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -172,15 +172,6 @@
bool get throwOnNitsForDebugging => _raw.throwOnNitsForDebugging;
- /// Like [CompilerOptions.chaseDependencies] but with the appropriate default
- /// value filled in.
- bool get chaseDependencies => _raw.chaseDependencies ?? !_modularApi;
-
- /// Whether the compiler was invoked with a modular API.
- ///
- /// Used to determine the default behavior for [chaseDependencies].
- final bool _modularApi;
-
/// The entry-points provided to the compiler.
final List<Uri> inputs;
@@ -189,7 +180,7 @@
/// Initializes a [ProcessedOptions] object wrapping the given [rawOptions].
ProcessedOptions(CompilerOptions rawOptions,
- [this._modularApi = false, this.inputs = const [], this.output])
+ [this.inputs = const [], this.output])
: this._raw = rawOptions,
// TODO(sigmund, ahe): create ticker even earlier or pass in a stopwatch
// collecting time since the start of the VM.
@@ -596,31 +587,8 @@
}
/// Create a [FileSystem] specific to the current options.
- ///
- /// If [chaseDependencies] is false, the resulting file system will be
- /// hermetic.
FileSystem _createFileSystem() {
- var result = _raw.fileSystem;
- if (!chaseDependencies) {
- var allInputs = inputs.toSet();
- allInputs.addAll(_raw.inputSummaries);
- allInputs.addAll(_raw.linkedDependencies);
-
- if (sdkSummary != null) allInputs.add(sdkSummary);
-
- if (_raw.sdkRoot != null) {
- // TODO(sigmund): refine this, we should be more explicit about when
- // sdkRoot and libraries.json are allowed to be used.
- allInputs.add(sdkRoot);
- allInputs.add(sdkRoot.resolve("lib/libraries.json"));
- }
-
- /// Note: Searching the file-system for the package-config is not
- /// supported in hermetic builds.
- if (_raw.packagesFileUri != null) allInputs.add(_raw.packagesFileUri);
- result = new HermeticFileSystem(allInputs, result);
- }
- return result;
+ return _raw.fileSystem;
}
String debugString() {
@@ -648,9 +616,6 @@
writeList('Input Summaries', _raw.inputSummaries);
writeList('Linked Dependencies', _raw.linkedDependencies);
- sb.writeln('Modular: ${_modularApi}');
- sb.writeln('Hermetic: ${!chaseDependencies} (provided: '
- '${_raw.chaseDependencies == null ? null : !_raw.chaseDependencies})');
sb.writeln('Packages uri: ${_raw.packagesFileUri}');
sb.writeln('Packages: ${_packages}');
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 1815328..304d87f 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -24,7 +24,6 @@
show
Builder,
ClassBuilder,
- DynamicTypeBuilder,
ModifierBuilder,
PrefixBuilder,
Scope,
@@ -181,12 +180,7 @@
return 0;
}
- void becomeCoreLibrary(dynamicType) {
- if (scope.local["dynamic"] == null) {
- addBuilder("dynamic",
- new DynamicTypeBuilder<T, dynamic>(dynamicType, this, -1), -1);
- }
- }
+ void becomeCoreLibrary(dynamicType);
void forEach(void f(String name, Builder builder)) {
scope.forEach((String name, Builder builder) {
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
index fc6df24..5febe96 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
@@ -66,8 +66,9 @@
// So, if [arguments] is null, the default types should be retrieved from
// [cls.typeParameters].
if (arguments == null) {
- List<DartType> result =
- new List<DartType>.filled(cls.typeParameters.length, null);
+ List<DartType> result = new List<DartType>.filled(
+ cls.typeParameters.length, null,
+ growable: true);
for (int i = 0; i < result.length; ++i) {
result[i] = cls.typeParameters[i].defaultType;
}
@@ -75,7 +76,8 @@
}
// [arguments] != null
- List<DartType> result = new List<DartType>.filled(arguments.length, null);
+ List<DartType> result =
+ new List<DartType>.filled(arguments.length, null, growable: true);
for (int i = 0; i < result.length; ++i) {
result[i] = arguments[i].build(library);
}
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 2b6c733..5a29dbe 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -9,6 +9,7 @@
import 'package:kernel/ast.dart'
show
Class,
+ DartType,
Field,
Library,
ListLiteral,
@@ -25,6 +26,7 @@
import '../kernel/kernel_builder.dart'
show
Builder,
+ DynamicTypeBuilder,
InvalidTypeBuilder,
KernelInvalidTypeBuilder,
KernelTypeBuilder,
@@ -65,6 +67,16 @@
@override
Library get target => library;
+ void becomeCoreLibrary(dynamicType) {
+ if (scope.local["dynamic"] == null) {
+ addBuilder(
+ "dynamic",
+ new DynamicTypeBuilder<KernelTypeBuilder, DartType>(
+ dynamicType, this, -1),
+ -1);
+ }
+ }
+
void addClass(Class cls) {
DillClassBuilder classBulder = new DillClassBuilder(cls, this);
addBuilder(cls.name, classBulder, cls.fileOffset);
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
index f2666d8..a395dca 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
@@ -45,8 +45,9 @@
// So, if [arguments] is null, the default types should be retrieved from
// [cls.typeParameters].
if (arguments == null) {
- List<DartType> result =
- new List<DartType>.filled(target.typeParameters.length, null);
+ List<DartType> result = new List<DartType>.filled(
+ target.typeParameters.length, null,
+ growable: true);
for (int i = 0; i < result.length; ++i) {
result[i] = target.typeParameters[i].defaultType;
}
@@ -54,7 +55,8 @@
}
// [arguments] != null
- List<DartType> result = new List<DartType>.filled(arguments.length, null);
+ List<DartType> result =
+ new List<DartType>.filled(arguments.length, null, growable: true);
for (int i = 0; i < result.length; ++i) {
result[i] = arguments[i].build(library);
}
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index e1d7ba7..5f91fd5 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -128,17 +128,6 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAnnotationOnEnumConstant = messageAnnotationOnEnumConstant;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAnnotationOnEnumConstant = const MessageCode(
- "AnnotationOnEnumConstant",
- analyzerCode: "ANNOTATION_ON_ENUM_CONSTANT",
- dart2jsCode: "*fatal*",
- message: r"""Enum constants can't have annotations.""",
- tip: r"""Try removing the annotation.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
int
diff --git a/pkg/front_end/lib/src/fasta/get_dependencies.dart b/pkg/front_end/lib/src/fasta/get_dependencies.dart
index 37ee55e..4fa99af 100644
--- a/pkg/front_end/lib/src/fasta/get_dependencies.dart
+++ b/pkg/front_end/lib/src/fasta/get_dependencies.dart
@@ -37,7 +37,7 @@
..packagesFileUri = packages
..sdkSummary = platform
..sdkRoot = sdk;
- var pOptions = new ProcessedOptions(options, false, <Uri>[script]);
+ var pOptions = new ProcessedOptions(options, <Uri>[script]);
return await CompilerContext.runWithOptions(pOptions,
(CompilerContext c) async {
FileSystem fileSystem = c.options.fileSystem;
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 2fc31e8..b0297d0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -89,7 +89,7 @@
SuperIndexedAccessGenerator,
ThisAccessGenerator,
ThisPropertyAccessGenerator,
- TypeDeclarationAccessGenerator,
+ TypeUseGenerator,
UnresolvedNameGenerator,
VariableUseGenerator,
buildIsNull;
@@ -445,7 +445,9 @@
@override
void endMetadataStar(int count) {
debugEvent("MetadataStar");
- push(popList(count) ?? NullValue.Metadata);
+ push(popList(
+ count, new List<Expression>.filled(count, null, growable: true)) ??
+ NullValue.Metadata);
}
@override
@@ -822,7 +824,9 @@
@override
void endArguments(int count, Token beginToken, Token endToken) {
debugEvent("Arguments");
- List arguments = popList(count) ?? <Expression>[];
+ List<dynamic> arguments =
+ new List<dynamic>.filled(count, null, growable: true);
+ popList(count, arguments);
int firstNamedArgumentIndex = arguments.length;
for (int i = 0; i < arguments.length; i++) {
var node = arguments[i];
@@ -877,7 +881,9 @@
}
push(forest.arguments(positional, beginToken, named: named));
} else {
- push(forest.arguments(arguments, beginToken));
+ // TODO(kmillikin): Find a way to avoid allocating a second list in the
+ // case where there were no named arguments, which is a common one.
+ push(forest.arguments(new List<Expression>.from(arguments), beginToken));
}
}
@@ -938,13 +944,15 @@
Expression expression = popForValue();
if (expression is ShadowCascadeExpression) {
push(expression);
- push(new VariableUseGenerator(this, token, expression.variable));
+ push(new VariableUseGenerator<Expression, Statement, Arguments>(
+ this, token, expression.variable));
expression.extend();
} else {
VariableDeclaration variable = new ShadowVariableDeclaration.forValue(
toKernelExpression(expression), functionNestingLevel);
push(new ShadowCascadeExpression(variable));
- push(new VariableUseGenerator(this, token, variable));
+ push(new VariableUseGenerator<Expression, Statement, Arguments>(
+ this, token, variable));
}
}
@@ -1362,8 +1370,9 @@
if (constantContext != ConstantContext.none || member.isField) {
return new UnresolvedNameGenerator(this, token, n);
}
- return new ThisPropertyAccessGenerator(this, token, n,
- lookupInstanceMember(n), lookupInstanceMember(n, isSetter: true));
+ return new ThisPropertyAccessGenerator<Expression, Statement,
+ Arguments>(this, token, n, lookupInstanceMember(n),
+ lookupInstanceMember(n, isSetter: true));
} else if (ignoreMainInGetMainClosure &&
name == "main" &&
member?.name == "_getMainClosure") {
@@ -1378,11 +1387,12 @@
deprecated_addCompileTimeError(
charOffset, "Not a constant expression.");
}
- TypeDeclarationAccessGenerator generator =
- new TypeDeclarationAccessGenerator(
+ TypeUseGenerator<Expression, Statement, Arguments> generator =
+ new TypeUseGenerator<Expression, Statement, Arguments>(
this, token, prefix, charOffset, builder, name);
return (prefix?.deferred == true)
- ? new DeferredAccessGenerator(this, token, prefix, generator)
+ ? new DeferredAccessGenerator<Expression, Statement, Arguments>(
+ this, token, prefix, generator)
: generator;
} else if (builder.isLocal) {
if (constantContext != ConstantContext.none &&
@@ -1399,14 +1409,15 @@
var fact =
typePromoter.getFactForAccess(builder.target, functionNestingLevel);
var scope = typePromoter.currentScope;
- return new ReadOnlyAccessGenerator(
+ return new ReadOnlyAccessGenerator<Expression, Statement, Arguments>(
this,
token,
- new ShadowVariableGet(builder.target, fact, scope)
- ..fileOffset = charOffset,
+ toExpression(new ShadowVariableGet(builder.target, fact, scope)
+ ..fileOffset = charOffset),
name);
} else {
- return new VariableUseGenerator(this, token, builder.target);
+ return new VariableUseGenerator<Expression, Statement, Arguments>(
+ this, token, builder.target);
}
} else if (builder.isInstanceMember) {
if (constantContext != ConstantContext.none &&
@@ -1429,13 +1440,16 @@
getter = builder.target;
setter = lookupInstanceMember(n, isSetter: true);
}
- return new ThisPropertyAccessGenerator(this, token, n, getter, setter);
+ return new ThisPropertyAccessGenerator<Expression, Statement, Arguments>(
+ this, token, n, getter, setter);
} else if (builder.isRegularMethod) {
assert(builder.isStatic || builder.isTopLevel);
- StaticAccessGenerator generator =
- new StaticAccessGenerator(this, token, builder.target, null);
+ StaticAccessGenerator<Expression, Statement, Arguments> generator =
+ new StaticAccessGenerator<Expression, Statement, Arguments>(
+ this, token, builder.target, null);
return (prefix?.deferred == true)
- ? new DeferredAccessGenerator(this, token, prefix, generator)
+ ? new DeferredAccessGenerator<Expression, Statement, Arguments>(
+ this, token, prefix, generator)
: generator;
} else if (builder is PrefixBuilder) {
if (constantContext != ConstantContext.none && builder.deferred) {
@@ -1449,7 +1463,8 @@
}
return builder;
} else if (builder is LoadLibraryBuilder) {
- return new LoadLibraryGenerator(this, token, builder);
+ return new LoadLibraryGenerator<Expression, Statement, Arguments>(
+ this, token, builder);
} else {
if (builder.hasProblem && builder is! AccessErrorBuilder) return builder;
Builder setter;
@@ -1460,8 +1475,9 @@
} else if (builder.isField && !builder.isFinal) {
setter = builder;
}
- StaticAccessGenerator generator =
- new StaticAccessGenerator.fromBuilder(this, builder, token, setter);
+ StaticAccessGenerator<Expression, Statement, Arguments> generator =
+ new StaticAccessGenerator<Expression, Statement,
+ Arguments>.fromBuilder(this, builder, token, setter);
if (constantContext != ConstantContext.none) {
Member readTarget = generator.readTarget;
if (!(readTarget is Field && readTarget.isConst ||
@@ -1472,7 +1488,8 @@
}
}
return (prefix?.deferred == true)
- ? new DeferredAccessGenerator(this, token, prefix, generator)
+ ? new DeferredAccessGenerator<Expression, Statement, Arguments>(
+ this, token, prefix, generator)
: generator;
}
}
@@ -1505,7 +1522,9 @@
String value = unescapeString(token.lexeme);
push(forest.literalString(value, token));
} else {
- List parts = popList(1 + interpolationCount * 2);
+ var count = 1 + interpolationCount * 2;
+ List<Object> parts =
+ popList(count, new List<Object>.filled(count, null, growable: true));
Token first = parts.first;
Token last = parts.last;
Quote quote = analyzeQuote(first.lexeme);
@@ -1581,7 +1600,8 @@
debugEvent("LiteralInt");
int value = int.parse(token.lexeme, onError: (_) => null);
if (value == null) {
- push(new LargeIntAccessGenerator(this, token));
+ push(new LargeIntAccessGenerator<Expression, Statement, Arguments>(
+ this, token));
} else {
push(forest.literalInt(value, token));
}
@@ -1854,14 +1874,11 @@
continueTarget.resolveContinues(forest, body);
}
Expression condition;
- Token rightSeparator;
if (forest.isExpressionStatement(conditionStatement)) {
condition =
forest.getExpressionFromExpressionStatement(conditionStatement);
- rightSeparator = forest.getSemicolon(conditionStatement);
} else {
assert(forest.isEmptyStatement(conditionStatement));
- rightSeparator = forest.getSemicolon(conditionStatement);
}
Statement result = forest.forStatement(
forKeyword,
@@ -1870,7 +1887,7 @@
variables,
leftSeparator,
condition,
- rightSeparator,
+ conditionStatement,
updates,
leftParen.endGroup,
body);
@@ -2032,7 +2049,8 @@
if (prefix is PrefixBuilder) {
name = scopeLookup(prefix.exportScope, suffix.name, beginToken,
isQualified: true, prefix: prefix);
- } else if (prefix is ErroneousExpressionGenerator) {
+ } else if (prefix
+ is ErroneousExpressionGenerator<Expression, Statement, Arguments>) {
push(prefix.buildErroneousTypeNotAPrefix(suffix));
return;
} else {
@@ -2246,7 +2264,10 @@
FormalParameterKind kind = optional("{", beginToken)
? FormalParameterKind.optionalNamed
: FormalParameterKind.optionalPositional;
- push(new OptionalFormals(kind, popList(count) ?? []));
+ var variables =
+ new List<VariableDeclaration>.filled(count, null, growable: true);
+ popList(count, variables);
+ push(new OptionalFormals(kind, variables));
}
@override
@@ -2346,45 +2367,47 @@
@override
void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
debugEvent("CatchBlock");
- Block body = pop();
+ Statement body = pop();
inCatchBlock = pop();
if (catchKeyword != null) {
exitLocalScope();
}
FormalParameters<Expression, Statement, Arguments> catchParameters =
popIfNotNull(catchKeyword);
- DartType type = popIfNotNull(onKeyword) ?? const DynamicType();
- VariableDeclaration exception;
- VariableDeclaration stackTrace;
+ Object type = popIfNotNull(onKeyword);
+ Object exception;
+ Object stackTrace;
if (catchParameters != null) {
- if (catchParameters.required.length > 0) {
+ int requiredCount = catchParameters.required.length;
+ if ((requiredCount == 1 || requiredCount == 2) &&
+ catchParameters.optional == null) {
exception = catchParameters.required[0];
- exception.type = type;
- }
- if (catchParameters.required.length > 1) {
- stackTrace = catchParameters.required[1];
- stackTrace.type = coreTypes.stackTraceClass.rawType;
- }
- if (catchParameters.required.length > 2 ||
- catchParameters.optional != null) {
- body = toKernelStatement(forest.block(
+ forest.setParameterType(exception, type);
+ if (requiredCount == 2) {
+ stackTrace = catchParameters.required[1];
+ forest.setParameterType(
+ stackTrace, coreTypes.stackTraceClass.rawType);
+ }
+ } else {
+ body = forest.block(
catchKeyword,
<Statement>[
toStatement(compileTimeErrorInTry ??=
deprecated_buildCompileTimeErrorStatement(
"Invalid catch arguments.", catchKeyword.next.charOffset))
],
- null));
+ null);
}
}
- push(new Catch(exception, body, guard: type, stackTrace: stackTrace)
- ..fileOffset = offsetForToken(onKeyword ?? catchKeyword));
+ push(forest.catchClause(onKeyword, type, catchKeyword, exception,
+ stackTrace, coreTypes.stackTraceClass.rawType, body));
}
@override
void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
Statement finallyBlock = popStatementIfNotNull(finallyKeyword);
- Object catches = popList(catchCount);
+ Object catches = popList(
+ catchCount, new List<Catch>.filled(catchCount, null, growable: true));
Statement tryBlock = popStatement();
if (compileTimeErrorInTry == null) {
push(forest.tryStatement(
@@ -2408,14 +2431,14 @@
Expression index = popForValue();
var receiver = pop();
if (receiver is ThisAccessGenerator && receiver.isSuper) {
- push(new SuperIndexedAccessGenerator(
+ push(new SuperIndexedAccessGenerator<Expression, Statement, Arguments>(
this,
openSquareBracket,
- toKernelExpression(index),
+ index,
lookupInstanceMember(indexGetName, isSuper: true),
lookupInstanceMember(indexSetName, isSuper: true)));
} else {
- push(IndexedAccessGenerator.make(
+ push(IndexedAccessGenerator.make<Expression, Statement, Arguments>(
this, openSquareBracket, toValue(receiver), index, null, null));
}
}
@@ -2431,7 +2454,8 @@
if (optional("-", token)) {
operator = "unary-";
- if (receiver is LargeIntAccessGenerator) {
+ if (receiver
+ is LargeIntAccessGenerator<Expression, Statement, Arguments>) {
int value =
int.parse("-" + receiver.token.lexeme, onError: (_) => null);
if (value != null) {
@@ -2542,7 +2566,7 @@
prefix.exportScope, identifier.name, identifier.token,
isQualified: true, prefix: prefix);
identifier = null;
- } else if (prefix is TypeDeclarationAccessGenerator) {
+ } else if (prefix is TypeUseGenerator<Expression, Statement, Arguments>) {
type = prefix;
} else if (prefix is Generator) {
String name = suffix == null
@@ -2760,15 +2784,16 @@
var type = pop();
PrefixBuilder deferredPrefix;
int checkOffset;
- if (type is DeferredAccessGenerator) {
- DeferredAccessGenerator generator = type;
+ if (type is DeferredAccessGenerator<Expression, Statement, Arguments>) {
+ DeferredAccessGenerator<Expression, Statement, Arguments> generator =
+ type;
type = generator.generator;
deferredPrefix = generator.builder;
checkOffset = generator.token.charOffset;
}
- if (type is TypeDeclarationAccessGenerator) {
- TypeDeclarationAccessGenerator generator = type;
+ if (type is TypeUseGenerator<Expression, Statement, Arguments>) {
+ TypeUseGenerator<Expression, Statement, Arguments> generator = type;
if (generator.prefix != null) {
nameToken = nameToken.next.next;
}
@@ -2782,8 +2807,9 @@
push(deferredPrefix != null
? wrapInDeferredCheck(expression, deferredPrefix, checkOffset)
: expression);
- } else if (type is ErroneousExpressionGenerator) {
- push(type.buildError(forest.castArguments(arguments)));
+ } else if (type
+ is ErroneousExpressionGenerator<Expression, Statement, Arguments>) {
+ push(type.buildError(arguments));
} else {
push(throwNoSuchMethodError(storeOffset(forest.literalNull(null), offset),
debugName(getNodeName(type), name), arguments, nameToken.charOffset));
@@ -2905,7 +2931,8 @@
@override
void endTypeArguments(int count, Token beginToken, Token endToken) {
debugEvent("TypeArguments");
- push(popList(count));
+ push(
+ popList(count, new List<DartType>.filled(count, null, growable: true)));
}
@override
@@ -3231,19 +3258,20 @@
void handleLabel(Token token) {
debugEvent("Label");
Identifier identifier = pop();
- push(new Label(identifier.name, identifier.token.charOffset));
+ push(forest.label(identifier.token, token));
}
@override
void beginLabeledStatement(Token token, int labelCount) {
debugEvent("beginLabeledStatement");
- List<Label> labels = popList(
- labelCount, new List<Label>.filled(labelCount, null, growable: true));
+ List<Object> labels =
+ new List<Object>.filled(labelCount, null, growable: true);
+ popList(labelCount, labels);
enterLocalScope(null, scope.createNestedLabelScope());
LabelTarget target = new LabelTarget<Statement>(
- member, functionNestingLevel, token.charOffset);
- for (Label label in labels) {
- scope.declareLabel(label.name, target);
+ labels, member, functionNestingLevel, token.charOffset);
+ for (Object label in labels) {
+ scope.declareLabel(forest.getLabelName(label), target);
}
push(target);
}
@@ -3260,9 +3288,7 @@
}
target.breakTarget.resolveBreaks(forest, statement);
}
- // TODO(brianwilkerson): Figure out how to get the labels that are part of
- // the statement.
-// statement = forest.labeledStatement(labels, statement);
+ statement = forest.labeledStatement(target, statement);
if (target.continueTarget.hasUsers) {
if (statement is! LabeledStatement) {
statement = forest.syntheticLabeledStatement(statement);
@@ -3368,12 +3394,14 @@
@override
void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) {
debugEvent("beginSwitchCase");
- List labelsAndExpressions = popList(labelCount + expressionCount);
- List<Label> labels = <Label>[];
+ var count = labelCount + expressionCount;
+ List<Object> labelsAndExpressions =
+ popList(count, new List<Object>.filled(count, null, growable: true));
+ List<Object> labels = <Object>[];
List<Expression> expressions = <Expression>[];
if (labelsAndExpressions != null) {
for (var labelOrExpression in labelsAndExpressions) {
- if (labelOrExpression is Label) {
+ if (forest.isLabel(labelOrExpression)) {
labels.add(labelOrExpression);
} else {
expressions.add(labelOrExpression);
@@ -3381,18 +3409,19 @@
}
}
assert(scope == switchScope);
- for (Label label in labels) {
- if (scope.hasLocalLabel(label.name)) {
+ for (Object label in labels) {
+ String labelName = forest.getLabelName(label);
+ if (scope.hasLocalLabel(labelName)) {
// TODO(ahe): Should validate this is a goto target.
- if (!scope.claimLabel(label.name)) {
+ if (!scope.claimLabel(labelName)) {
addCompileTimeError(
fasta.templateDuplicateLabelInSwitchStatement
- .withArguments(label.name),
- label.charOffset,
- label.name.length);
+ .withArguments(labelName),
+ forest.getLabelOffset(label),
+ labelName.length);
}
} else {
- scope.declareLabel(label.name, createGotoTarget(firstToken.charOffset));
+ scope.declareLabel(labelName, createGotoTarget(firstToken.charOffset));
}
}
push(expressions);
@@ -3415,7 +3444,7 @@
// check this switch case to see if it falls through to the next case.
Statement block = popBlock(statementCount, firstToken, null);
exitLocalScope();
- List<Label> labels = pop();
+ List<Object> labels = pop();
List<Expression> expressions = pop();
List<int> expressionOffsets = <int>[];
for (Expression expression in expressions) {
@@ -3453,10 +3482,10 @@
List<SwitchCase> cases =
new List<SwitchCase>.filled(caseCount, null, growable: true);
for (int i = caseCount - 1; i >= 0; i--) {
- List<Label> labels = pop();
+ List<Object> labels = pop();
SwitchCase current = cases[i] = pop();
- for (Label label in labels) {
- JumpTarget target = switchScope.lookupLabel(label.name);
+ for (Object label in labels) {
+ JumpTarget target = switchScope.lookupLabel(forest.getLabelName(label));
if (target != null) {
target.resolveGotos(forest, current);
}
@@ -3630,7 +3659,7 @@
List<Expression> annotations = pop();
KernelTypeVariableBuilder variable;
Object inScope = scopeLookup(scope, name.name, token);
- if (inScope is TypeDeclarationAccessGenerator) {
+ if (inScope is TypeUseGenerator<Expression, Statement, Arguments>) {
variable = inScope.declaration;
} else {
// Something went wrong when pre-parsing the type variables.
@@ -3651,7 +3680,10 @@
@override
void endTypeVariables(int count, Token beginToken, Token endToken) {
debugEvent("TypeVariables");
- List<KernelTypeVariableBuilder> typeVariables = popList(count);
+ List<KernelTypeVariableBuilder> typeVariables = popList(
+ count,
+ new List<KernelTypeVariableBuilder>.filled(count, null,
+ growable: true));
if (typeVariables != null) {
if (library.loader.target.strongMode) {
List<KernelTypeBuilder> calculatedBounds = calculateBounds(
@@ -4189,15 +4221,6 @@
String toString() => "initialized-identifier($name, $initializer)";
}
-class Label {
- String name;
- int charOffset;
-
- Label(this.name, this.charOffset);
-
- String toString() => "label($name)";
-}
-
class JumpTarget<Statement> extends Builder {
final List<Statement> users = <Statement>[];
@@ -4264,13 +4287,16 @@
}
class LabelTarget<Statement> extends Builder implements JumpTarget<Statement> {
+ final List<Object> labels;
+
final JumpTarget breakTarget;
final JumpTarget continueTarget;
final int functionNestingLevel;
- LabelTarget(MemberBuilder member, this.functionNestingLevel, int charOffset)
+ LabelTarget(this.labels, MemberBuilder member, this.functionNestingLevel,
+ int charOffset)
: breakTarget = new JumpTarget<Statement>(
JumpTargetKind.Break, functionNestingLevel, member, charOffset),
continueTarget = new JumpTarget<Statement>(
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 92b3ac2..ad42775 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -10,17 +10,28 @@
import '../constant_context.dart' show ConstantContext;
import '../fasta_codes.dart'
- show LocatedMessage, messageInvalidInitializer, templateNotAType;
+ show
+ LocatedMessage,
+ messageInvalidInitializer,
+ templateDeferredTypeAnnotation,
+ templateIntegerLiteralIsOutOfRange,
+ templateNotAType;
import '../names.dart' show lengthName;
import '../parser.dart' show lengthForToken, offsetForToken;
-import '../problems.dart' show unsupported;
+import '../problems.dart' show unhandled, unsupported;
import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
-import 'forest.dart' show Forest;
+import 'forest.dart'
+ show
+ Forest,
+ Identifier,
+ LoadLibraryBuilder,
+ PrefixBuilder,
+ TypeDeclarationBuilder;
import 'kernel_ast_api.dart'
show
@@ -30,29 +41,32 @@
Member,
Name,
Procedure,
+ TypeParameterType,
VariableDeclaration;
+import 'kernel_builder.dart'
+ show
+ AccessErrorBuilder,
+ Builder,
+ BuiltinTypeBuilder,
+ FunctionTypeAliasBuilder,
+ KernelClassBuilder,
+ KernelFunctionTypeAliasBuilder,
+ KernelTypeVariableBuilder;
+
import 'kernel_expression_generator.dart'
show IncompleteSendGenerator, SendAccessGenerator;
export 'kernel_expression_generator.dart'
show
- DeferredAccessGenerator,
DelayedAssignment,
DelayedPostfixIncrement,
- ErroneousExpressionGenerator,
IncompleteErrorGenerator,
IncompletePropertyAccessGenerator,
IncompleteSendGenerator,
- LargeIntAccessGenerator,
- LoadLibraryGenerator,
ParenthesizedExpressionGenerator,
- ReadOnlyAccessGenerator,
SendAccessGenerator,
- StaticAccessGenerator,
- SuperIndexedAccessGenerator,
ThisAccessGenerator,
- TypeDeclarationAccessGenerator,
UnresolvedNameGenerator,
buildIsNull;
@@ -164,10 +178,10 @@
offset);
}
- /* kernel.Expression | Generator | Initializer */ doInvocation(
+ /* Expression | Generator | Initializer */ doInvocation(
int offset, Arguments arguments);
- /* kernel.Expression | Generator */ buildPropertyAccess(
+ /* Expression | Generator */ buildPropertyAccess(
IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
if (send is SendAccessGenerator) {
return helper.buildMethodInvocation(
@@ -201,7 +215,7 @@
}
@override
- /* kernel.Expression | Generator */ buildThrowNoSuchMethodError(
+ /* Expression | Generator */ buildThrowNoSuchMethodError(
Expression receiver, Arguments arguments,
{bool isSuper: false,
bool isGetter: false,
@@ -275,15 +289,10 @@
return unsupported("ThisExpression", offsetForToken(token), helper.uri);
} else {
return isNullAware
- ? new NullAwarePropertyAccessGenerator(
- helper,
- token,
- receiver as dynamic /* TODO(ahe): Remove this cast. */,
- name,
- getter,
- setter,
- null)
- : new PropertyAccessGenerator.internal(
+ ? new NullAwarePropertyAccessGenerator<Expression, Statement,
+ Arguments>(helper, token, receiver, name, getter, setter, null)
+ : new PropertyAccessGenerator<Expression, Statement,
+ Arguments>.internal(
helper, token, receiver, name, getter, setter);
}
}
@@ -372,11 +381,11 @@
Procedure getter,
Procedure setter) {
if (helper.forest.isThisExpression(receiver)) {
- return new ThisIndexedAccessGenerator(
+ return new ThisIndexedAccessGenerator<Expression, Statement, Arguments>(
helper, token, index, getter, setter);
} else {
- return new IndexedAccessGenerator.internal(
- helper, token, receiver, index, getter, setter);
+ return new IndexedAccessGenerator<Expression, Statement,
+ Arguments>.internal(helper, token, receiver, index, getter, setter);
}
}
@@ -413,3 +422,378 @@
@override
String get debugName => "ThisIndexedAccessGenerator";
}
+
+abstract class SuperIndexedAccessGenerator<Expression, Statement, Arguments>
+ implements Generator<Expression, Statement, Arguments> {
+ factory SuperIndexedAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ Expression index,
+ Member getter,
+ Member setter) {
+ return helper.forest
+ .superIndexedAccessGenerator(helper, token, index, getter, setter);
+ }
+
+ String get plainNameForRead => "[]";
+
+ String get plainNameForWrite => "[]=";
+
+ String get debugName => "SuperIndexedAccessGenerator";
+}
+
+abstract class StaticAccessGenerator<Expression, Statement, Arguments>
+ implements Generator<Expression, Statement, Arguments> {
+ factory StaticAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ Member readTarget,
+ Member writeTarget) {
+ return helper.forest
+ .staticAccessGenerator(helper, token, readTarget, writeTarget);
+ }
+
+ factory StaticAccessGenerator.fromBuilder(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Builder builder,
+ Token token,
+ Builder builderSetter) {
+ if (builder is AccessErrorBuilder) {
+ AccessErrorBuilder error = builder;
+ builder = error.builder;
+ // We should only see an access error here if we've looked up a setter
+ // when not explicitly looking for a setter.
+ assert(builder.isSetter);
+ } else if (builder.target == null) {
+ return unhandled(
+ "${builder.runtimeType}",
+ "StaticAccessGenerator.fromBuilder",
+ offsetForToken(token),
+ helper.uri);
+ }
+ Member getter = builder.target.hasGetter ? builder.target : null;
+ Member setter = builder.target.hasSetter ? builder.target : null;
+ if (setter == null) {
+ if (builderSetter?.target?.hasSetter ?? false) {
+ setter = builderSetter.target;
+ }
+ }
+ return new StaticAccessGenerator<Expression, Statement, Arguments>(
+ helper, token, getter, setter);
+ }
+
+ Member get readTarget;
+
+ @override
+ String get debugName => "StaticAccessGenerator";
+}
+
+abstract class LoadLibraryGenerator<Expression, Statement, Arguments>
+ implements Generator<Expression, Statement, Arguments> {
+ factory LoadLibraryGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ LoadLibraryBuilder builder) {
+ return helper.forest.loadLibraryGenerator(helper, token, builder);
+ }
+
+ @override
+ String get plainNameForRead => 'loadLibrary';
+
+ @override
+ String get debugName => "LoadLibraryGenerator";
+}
+
+abstract class DeferredAccessGenerator<Expression, Statement, Arguments>
+ implements Generator<Expression, Statement, Arguments> {
+ factory DeferredAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ PrefixBuilder builder,
+ Generator<Expression, Statement, Arguments> generator) {
+ return helper.forest
+ .deferredAccessGenerator(helper, token, builder, generator);
+ }
+
+ PrefixBuilder get builder;
+
+ Generator<Expression, Statement, Arguments> get generator;
+
+ @override
+ buildPropertyAccess(
+ IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
+ var propertyAccess =
+ generator.buildPropertyAccess(send, operatorOffset, isNullAware);
+ if (propertyAccess is Generator) {
+ return new DeferredAccessGenerator<Expression, Statement, Arguments>(
+ helper, token, builder, propertyAccess);
+ } else {
+ Expression expression = propertyAccess;
+ return helper.wrapInDeferredCheck(expression, builder, token.charOffset);
+ }
+ }
+
+ @override
+ String get plainNameForRead {
+ return unsupported(
+ "deferredAccessor.plainNameForRead", offsetForToken(token), uri);
+ }
+
+ @override
+ String get debugName => "DeferredAccessGenerator";
+
+ @override
+ DartType buildTypeWithBuiltArguments(List<DartType> arguments,
+ {bool nonInstanceAccessIsError: false}) {
+ helper.addProblem(
+ templateDeferredTypeAnnotation.withArguments(
+ generator.buildTypeWithBuiltArguments(arguments,
+ nonInstanceAccessIsError: nonInstanceAccessIsError),
+ builder.name),
+ offsetForToken(token),
+ lengthForToken(token));
+ return const InvalidType();
+ }
+
+ @override
+ Expression doInvocation(int offset, Arguments arguments) {
+ return helper.wrapInDeferredCheck(
+ generator.doInvocation(offset, arguments), builder, token.charOffset);
+ }
+
+ @override
+ void printOn(StringSink sink) {
+ sink.write(", builder: ");
+ sink.write(builder);
+ sink.write(", generator: ");
+ sink.write(generator);
+ }
+}
+
+abstract class TypeUseGenerator<Expression, Statement, Arguments>
+ implements Generator<Expression, Statement, Arguments> {
+ factory TypeUseGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ PrefixBuilder prefix,
+ int declarationReferenceOffset,
+ TypeDeclarationBuilder declaration,
+ String plainNameForRead) {
+ return helper.forest.typeUseGenerator(helper, token, prefix,
+ declarationReferenceOffset, declaration, plainNameForRead);
+ }
+
+ PrefixBuilder get prefix;
+
+ TypeDeclarationBuilder get declaration;
+
+ @override
+ String get debugName => "TypeUseGenerator";
+
+ @override
+ DartType buildTypeWithBuiltArguments(List<DartType> arguments,
+ {bool nonInstanceAccessIsError: false}) {
+ if (arguments != null) {
+ int expected = 0;
+ if (declaration is KernelClassBuilder) {
+ expected = declaration.target.typeParameters.length;
+ } else if (declaration is FunctionTypeAliasBuilder) {
+ expected = declaration.target.typeParameters.length;
+ } else if (declaration is KernelTypeVariableBuilder) {
+ // Type arguments on a type variable - error reported elsewhere.
+ } else if (declaration is BuiltinTypeBuilder) {
+ // Type arguments on a built-in type, for example, dynamic or void.
+ expected = 0;
+ } else {
+ return unhandled("${declaration.runtimeType}",
+ "TypeUseGenerator.buildType", offsetForToken(token), helper.uri);
+ }
+ if (arguments.length != expected) {
+ helper.warnTypeArgumentsMismatch(
+ declaration.name, expected, offsetForToken(token));
+ // We ignore the provided arguments, which will in turn return the
+ // raw type below.
+ // TODO(sigmund): change to use an InvalidType and include the raw type
+ // as a recovery node once the IR can represent it (Issue #29840).
+ arguments = null;
+ }
+ }
+
+ DartType type;
+ if (arguments == null) {
+ TypeDeclarationBuilder typeDeclaration = declaration;
+ if (typeDeclaration is KernelClassBuilder) {
+ type = typeDeclaration.buildType(helper.library, null);
+ } else if (typeDeclaration is KernelFunctionTypeAliasBuilder) {
+ type = typeDeclaration.buildType(helper.library, null);
+ }
+ }
+ if (type == null) {
+ type =
+ declaration.buildTypesWithBuiltArguments(helper.library, arguments);
+ }
+ if (type is TypeParameterType) {
+ return helper.validatedTypeVariableUse(
+ type, offsetForToken(token), nonInstanceAccessIsError);
+ }
+ return type;
+ }
+}
+
+abstract class ReadOnlyAccessGenerator<Expression, Statement, Arguments>
+ implements Generator<Expression, Statement, Arguments> {
+ factory ReadOnlyAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ Expression expression,
+ String plainNameForRead) {
+ return helper.forest
+ .readOnlyAccessGenerator(helper, token, expression, plainNameForRead);
+ }
+
+ @override
+ String get debugName => "ReadOnlyAccessGenerator";
+}
+
+abstract class LargeIntAccessGenerator<Expression, Statement, Arguments>
+ implements Generator<Expression, Statement, Arguments> {
+ factory LargeIntAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token) {
+ return helper.forest.largeIntAccessGenerator(helper, token);
+ }
+
+ // TODO(ahe): This should probably be calling unhandled.
+ @override
+ String get plainNameForRead => null;
+
+ @override
+ String get debugName => "LargeIntAccessGenerator";
+
+ Expression buildError() {
+ return helper.buildCompileTimeError(
+ templateIntegerLiteralIsOutOfRange.withArguments(token),
+ offsetForToken(token),
+ lengthForToken(token));
+ }
+
+ @override
+ Expression doInvocation(int offset, Arguments arguments) {
+ return buildError();
+ }
+
+ @override
+ void printOn(StringSink sink) {
+ sink.write(", lexeme: ");
+ sink.write(token.lexeme);
+ }
+}
+
+abstract class ErroneousExpressionGenerator<Expression, Statement, Arguments>
+ implements Generator<Expression, Statement, Arguments> {
+ /// Pass [arguments] that must be evaluated before throwing an error. At
+ /// most one of [isGetter] and [isSetter] should be true and they're passed
+ /// to [ExpressionGeneratorHelper.buildThrowNoSuchMethodError] if it is used.
+ Expression buildError(Arguments arguments,
+ {bool isGetter: false, bool isSetter: false, int offset});
+
+ DartType buildErroneousTypeNotAPrefix(Identifier suffix);
+
+ Name get name => unsupported("name", offsetForToken(token), uri);
+
+ @override
+ String get plainNameForRead => name.name;
+
+ withReceiver(Object receiver, int operatorOffset, {bool isNullAware}) => this;
+
+ @override
+ Initializer buildFieldInitializer(Map<String, int> initializedFields) {
+ return helper.buildInvalidInitializer(
+ buildError(forest.argumentsEmpty(token), isSetter: true));
+ }
+
+ @override
+ doInvocation(int offset, Arguments arguments) {
+ return buildError(arguments, offset: offset);
+ }
+
+ @override
+ buildPropertyAccess(
+ IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
+ return this;
+ }
+
+ @override
+ buildThrowNoSuchMethodError(Expression receiver, Arguments arguments,
+ {bool isSuper: false,
+ bool isGetter: false,
+ bool isSetter: false,
+ bool isStatic: false,
+ String name,
+ int offset,
+ LocatedMessage argMessage}) {
+ return this;
+ }
+
+ @override
+ Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ return buildError(forest.arguments(<Expression>[value], token),
+ isSetter: true);
+ }
+
+ @override
+ Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+ {int offset: -1,
+ bool voidContext: false,
+ Procedure interfaceTarget,
+ bool isPreIncDec: false}) {
+ return buildError(forest.arguments(<Expression>[value], token),
+ isGetter: true);
+ }
+
+ @override
+ Expression buildPrefixIncrement(Name binaryOperator,
+ {int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
+ // TODO(ahe): For the Analyzer, we probably need to build a prefix
+ // increment node that wraps an error.
+ return buildError(
+ forest.arguments(
+ <Expression>[storeOffset(forest.literalInt(1, null), offset)],
+ token),
+ isGetter: true);
+ }
+
+ @override
+ Expression buildPostfixIncrement(Name binaryOperator,
+ {int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
+ // TODO(ahe): For the Analyzer, we probably need to build a post increment
+ // node that wraps an error.
+ return buildError(
+ forest.arguments(
+ <Expression>[storeOffset(forest.literalInt(1, null), offset)],
+ token),
+ isGetter: true);
+ }
+
+ @override
+ Expression buildNullAwareAssignment(
+ Expression value, DartType type, int offset,
+ {bool voidContext: false}) {
+ return buildError(forest.arguments(<Expression>[value], token),
+ isSetter: true);
+ }
+
+ @override
+ Expression buildSimpleRead() =>
+ buildError(forest.argumentsEmpty(token), isGetter: true);
+
+ @override
+ Expression makeInvalidRead() =>
+ buildError(forest.argumentsEmpty(token), isGetter: true);
+
+ @override
+ Expression makeInvalidWrite(Expression value) {
+ return buildError(forest.arguments(<Expression>[value], token),
+ isSetter: true);
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index 1490aff..3acd9df 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -15,6 +15,7 @@
Catch,
ContinueSwitchStatement,
DartType,
+ DynamicType,
EmptyStatement,
Expression,
ExpressionStatement,
@@ -40,14 +41,23 @@
import '../scanner.dart' show Token;
+import 'body_builder.dart' show LabelTarget;
+
import 'kernel_expression_generator.dart'
show
+ KernelDeferredAccessGenerator,
KernelIndexedAccessGenerator,
+ KernelLargeIntAccessGenerator,
+ KernelLoadLibraryGenerator,
KernelNullAwarePropertyAccessGenerator,
KernelPropertyAccessGenerator,
+ KernelReadOnlyAccessGenerator,
+ KernelStaticAccessGenerator,
+ KernelSuperIndexedAccessGenerator,
KernelSuperPropertyAccessGenerator,
KernelThisIndexedAccessGenerator,
KernelThisPropertyAccessGenerator,
+ KernelTypeUseGenerator,
KernelVariableUseGenerator;
import 'kernel_shadow_ast.dart'
@@ -90,7 +100,14 @@
ShadowWhileStatement,
ShadowYieldStatement;
-import 'forest.dart' show ExpressionGeneratorHelper, Forest;
+import 'forest.dart'
+ show
+ ExpressionGeneratorHelper,
+ Forest,
+ Generator,
+ LoadLibraryBuilder,
+ PrefixBuilder,
+ TypeDeclarationBuilder;
/// A shadow tree factory.
class Fangorn extends Forest<Expression, Statement, Token, Arguments> {
@@ -321,6 +338,21 @@
}
@override
+ Catch catchClause(
+ Token onKeyword,
+ DartType exceptionType,
+ Token catchKeyword,
+ VariableDeclaration exceptionParameter,
+ VariableDeclaration stackTraceParameter,
+ DartType stackTraceType,
+ Statement body) {
+ exceptionType ??= const DynamicType();
+ return new Catch(exceptionParameter, body,
+ guard: exceptionType, stackTrace: stackTraceParameter)
+ ..fileOffset = offsetForToken(onKeyword ?? catchKeyword);
+ }
+
+ @override
Expression conditionalExpression(Expression condition, Token question,
Expression thenExpression, Token colon, Expression elseExpression) {
return new ShadowConditionalExpression(
@@ -359,7 +391,7 @@
covariant initialization,
Token leftSeparator,
Expression condition,
- Token rightSeparator,
+ Statement conditionStatement,
List<Expression> updaters,
Token rightParenthesis,
Statement body) {
@@ -385,6 +417,16 @@
}
@override
+ Label label(Token identifier, Token colon) {
+ return new Label(identifier.lexeme, identifier.charOffset);
+ }
+
+ @override
+ Statement labeledStatement(
+ LabelTarget<Statement> target, Statement statement) =>
+ statement;
+
+ @override
Expression notExpression(Expression operand, Token token) {
return new ShadowNot(operand)..fileOffset = offsetForToken(token);
}
@@ -489,7 +531,10 @@
}
@override
- Token getSemicolon(Statement statement) => null;
+ String getLabelName(Label label) => label.name;
+
+ @override
+ int getLabelOffset(Label label) => label.charOffset;
@override
bool isBlock(Object node) => node is Block;
@@ -523,6 +568,9 @@
statement is ExpressionStatement;
@override
+ bool isLabel(covariant node) => node is Label;
+
+ @override
bool isThisExpression(Object node) => node is ThisExpression;
@override
@@ -545,6 +593,11 @@
}
@override
+ void setParameterType(VariableDeclaration parameter, DartType type) {
+ parameter.type = type ?? const DynamicType();
+ }
+
+ @override
KernelVariableUseGenerator variableUseGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
@@ -623,6 +676,72 @@
return new KernelThisIndexedAccessGenerator(
helper, token, index, getter, setter);
}
+
+ @override
+ KernelSuperIndexedAccessGenerator superIndexedAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ Expression index,
+ Member getter,
+ Member setter) {
+ return new KernelSuperIndexedAccessGenerator(
+ helper, token, index, getter, setter);
+ }
+
+ @override
+ KernelStaticAccessGenerator staticAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ Member getter,
+ Member setter) {
+ return new KernelStaticAccessGenerator(helper, token, getter, setter);
+ }
+
+ @override
+ KernelLoadLibraryGenerator loadLibraryGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ LoadLibraryBuilder builder) {
+ return new KernelLoadLibraryGenerator(helper, token, builder);
+ }
+
+ @override
+ KernelDeferredAccessGenerator deferredAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ PrefixBuilder builder,
+ Generator<Expression, Statement, Arguments> generator) {
+ return new KernelDeferredAccessGenerator(helper, token, builder, generator);
+ }
+
+ @override
+ KernelTypeUseGenerator typeUseGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ PrefixBuilder prefix,
+ int declarationReferenceOffset,
+ TypeDeclarationBuilder declaration,
+ String plainNameForRead) {
+ return new KernelTypeUseGenerator(helper, token, prefix,
+ declarationReferenceOffset, declaration, plainNameForRead);
+ }
+
+ @override
+ KernelReadOnlyAccessGenerator readOnlyAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ Expression expression,
+ String plainNameForRead) {
+ return new KernelReadOnlyAccessGenerator(
+ helper, token, expression, plainNameForRead);
+ }
+
+ @override
+ KernelLargeIntAccessGenerator largeIntAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token) {
+ return new KernelLargeIntAccessGenerator(helper, token);
+ }
}
class _VariablesDeclaration extends Statement {
@@ -653,3 +772,14 @@
unsupported("transformChildren", fileOffset, uri);
}
}
+
+/// A data holder used to hold the information about a label that is pushed on
+/// the stack.
+class Label {
+ String name;
+ int charOffset;
+
+ Label(this.name, this.charOffset);
+
+ String toString() => "label($name)";
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 2589526..8509c30 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -12,18 +12,24 @@
Name,
Procedure;
-import 'body_builder.dart' show Identifier;
+import 'body_builder.dart' show Identifier, LabelTarget;
import 'expression_generator.dart' show Generator;
import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
+import 'kernel_builder.dart'
+ show LoadLibraryBuilder, PrefixBuilder, TypeDeclarationBuilder;
+
export 'body_builder.dart' show Identifier, Operator;
export 'expression_generator.dart' show Generator;
export 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
+export 'kernel_builder.dart'
+ show LoadLibraryBuilder, PrefixBuilder, TypeDeclarationBuilder;
+
/// A tree factory.
///
/// For now, the [Location] is always a token.
@@ -173,6 +179,16 @@
Statement breakStatement(
Location breakKeyword, Identifier label, Location semicolon);
+ /// Return a representation of a catch clause.
+ Object catchClause(
+ Location onKeyword,
+ covariant exceptionType,
+ Location catchKeyword,
+ covariant exceptionParameter,
+ covariant stackTraceParameter,
+ covariant stackTraceType,
+ Statement body);
+
/// Return a representation of a conditional expression. The [condition] is
/// the expression preceding the question mark. The [question] is the `?`. The
/// [thenExpression] is the expression following the question mark. The
@@ -209,7 +225,7 @@
covariant initialization,
Location leftSeparator,
Expression condition,
- Location rightSeparator,
+ Statement conditionStatement,
List<Expression> updaters,
Location rightParenthesis,
Statement body);
@@ -225,6 +241,15 @@
Expression isExpression(Expression operand, Location isOperator,
Location notOperator, covariant type);
+ /// Return a representation of the label consisting of the given [identifer]
+ /// followed by the given [colon].
+ Object label(Location identifier, Location colon);
+
+ /// Return a representation of a [statement] that has one or more labels (from
+ /// the [target]) associated with it.
+ Statement labeledStatement(
+ LabelTarget<Statement> target, Statement statement);
+
Expression notExpression(Expression operand, Location location);
/// Return a representation of a parenthesized condition consisting of the
@@ -286,9 +311,11 @@
/// Return the expression from the given expression [statement].
Expression getExpressionFromExpressionStatement(Statement statement);
- /// Return the semicolon at the end of the given [statement], or `null` if the
- /// statement is not terminated by a semicolon.
- Location getSemicolon(Statement statement);
+ /// Return the name of the given [label].
+ String getLabelName(covariant label);
+
+ /// Return the offset of the given [label].
+ int getLabelOffset(covariant label);
bool isBlock(Object node);
@@ -302,6 +329,9 @@
/// expression statement.
bool isExpressionStatement(Statement statement);
+ /// Return `true` if the given [node] is a label.
+ bool isLabel(covariant node);
+
bool isThisExpression(Object node);
bool isVariablesDeclaration(Object node);
@@ -319,6 +349,9 @@
void resolveContinueInSwitch(
covariant Object target, covariant Statement user);
+ /// Set the type of the [parameter] to the given [type].
+ void setParameterType(covariant parameter, covariant type);
+
Generator<Expression, Statement, Arguments> variableUseGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Location location,
@@ -371,6 +404,48 @@
kernel.Procedure getter,
kernel.Procedure setter);
+ Generator<Expression, Statement, Arguments> superIndexedAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Location location,
+ Expression index,
+ kernel.Member getter,
+ kernel.Member setter);
+
+ Generator<Expression, Statement, Arguments> staticAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Location location,
+ kernel.Member getter,
+ kernel.Member setter);
+
+ Generator<Expression, Statement, Arguments> loadLibraryGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Location location,
+ LoadLibraryBuilder builder);
+
+ Generator<Expression, Statement, Arguments> deferredAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Location location,
+ PrefixBuilder builder,
+ Generator<Expression, Statement, Arguments> generator);
+
+ Generator<Expression, Statement, Arguments> typeUseGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Location location,
+ PrefixBuilder prefix,
+ int declarationReferenceOffset,
+ TypeDeclarationBuilder declaration,
+ String plainNameForRead);
+
+ Generator<Expression, Statement, Arguments> readOnlyAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Location location,
+ Expression expression,
+ String plainNameForRead);
+
+ Generator<Expression, Statement, Arguments> largeIntAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Location location);
+
// TODO(ahe): Remove this method when all users are moved here.
kernel.Arguments castArguments(Arguments arguments) {
dynamic a = arguments;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 7272014..2e2c334 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -137,7 +137,7 @@
if (arguments == null && typeVariables != null) {
List<DartType> result =
- new List<DartType>.filled(typeVariables.length, null);
+ new List<DartType>.filled(typeVariables.length, null, growable: true);
for (int i = 0; i < result.length; ++i) {
result[i] = typeVariables[i].defaultType.build(library);
}
@@ -156,7 +156,8 @@
}
// arguments.length == typeVariables.length
- List<DartType> result = new List<DartType>.filled(arguments.length, null);
+ List<DartType> result =
+ new List<DartType>.filled(arguments.length, null, growable: true);
for (int i = 0; i < result.length; ++i) {
result[i] = arguments[i].build(library);
}
@@ -185,7 +186,8 @@
return new Supertype(
cls,
new List<DartType>.filled(
- cls.typeParameters.length, const UnknownType()));
+ cls.typeParameters.length, const UnknownType(),
+ growable: true));
}
}
@@ -215,9 +217,10 @@
// TODO(32049) If type arguments aren't specified, they should
// be inferred. Currently, the inference is not performed.
// The code below is a workaround.
- typeArguments = new List.filled(
+ typeArguments = new List<DartType>.filled(
targetBuilder.target.enclosingClass.typeParameters.length,
- const DynamicType());
+ const DynamicType(),
+ growable: true);
}
builder.setRedirectingFactoryBody(
targetBuilder.target, typeArguments);
@@ -227,9 +230,10 @@
// TODO(32049) If type arguments aren't specified, they should
// be inferred. Currently, the inference is not performed.
// The code below is a workaround.
- typeArguments = new List.filled(
+ typeArguments = new List<DartType>.filled(
targetBuilder.target.enclosingClass.typeParameters.length,
- const DynamicType());
+ const DynamicType(),
+ growable: true);
}
builder.setRedirectingFactoryBody(
targetBuilder.member, typeArguments);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
index 18cca9e..ef2a750 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
@@ -159,14 +159,15 @@
charEndOffset);
members["toString"] = toStringBuilder;
String className = name;
- for (int i = 0; i < constantNamesAndOffsetsAndDocs.length; i += 3) {
- String name = constantNamesAndOffsetsAndDocs[i];
- int charOffset = constantNamesAndOffsetsAndDocs[i + 1];
- String documentationComment = constantNamesAndOffsetsAndDocs[i + 2];
+ for (int i = 0; i < constantNamesAndOffsetsAndDocs.length; i += 4) {
+ List<MetadataBuilder> metadata = constantNamesAndOffsetsAndDocs[i];
+ String name = constantNamesAndOffsetsAndDocs[i + 1];
+ int charOffset = constantNamesAndOffsetsAndDocs[i + 2];
+ String documentationComment = constantNamesAndOffsetsAndDocs[i + 3];
if (members.containsKey(name)) {
parent.addCompileTimeError(templateDuplicatedName.withArguments(name),
charOffset, noLength, parent.fileUri);
- constantNamesAndOffsetsAndDocs[i] = null;
+ constantNamesAndOffsetsAndDocs[i + 1] = null;
continue;
}
if (name == className) {
@@ -175,11 +176,18 @@
charOffset,
noLength,
parent.fileUri);
- constantNamesAndOffsetsAndDocs[i] = null;
+ constantNamesAndOffsetsAndDocs[i + 1] = null;
continue;
}
- KernelFieldBuilder fieldBuilder = new KernelFieldBuilder(null, selfType,
- name, constMask | staticMask, parent, charOffset, null, true);
+ KernelFieldBuilder fieldBuilder = new KernelFieldBuilder(
+ metadata,
+ selfType,
+ name,
+ constMask | staticMask,
+ parent,
+ charOffset,
+ null,
+ true);
metadataCollector?.setDocumentationComment(
fieldBuilder.target, documentationComment);
members[name] = fieldBuilder;
@@ -235,8 +243,8 @@
toStringBuilder.body = new ReturnStatement(
new DirectPropertyGet(new ThisExpression(), nameField));
List<Expression> values = <Expression>[];
- for (int i = 0; i < constantNamesAndOffsetsAndDocs.length; i += 3) {
- String name = constantNamesAndOffsetsAndDocs[i];
+ for (int i = 0; i < constantNamesAndOffsetsAndDocs.length; i += 4) {
+ String name = constantNamesAndOffsetsAndDocs[i + 1];
if (name != null) {
KernelFieldBuilder builder = this[name];
values.add(new StaticGet(builder.build(libraryBuilder)));
@@ -273,8 +281,8 @@
..parent = constructor);
}
int index = 0;
- for (int i = 0; i < constantNamesAndOffsetsAndDocs.length; i += 3) {
- String constant = constantNamesAndOffsetsAndDocs[i];
+ for (int i = 0; i < constantNamesAndOffsetsAndDocs.length; i += 4) {
+ String constant = constantNamesAndOffsetsAndDocs[i + 1];
if (constant != null) {
KernelFieldBuilder field = this[constant];
field.build(libraryBuilder);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
index 218f9f9..e09b708 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
@@ -13,8 +13,6 @@
LocatedMessage,
messageLoadLibraryTakesNoArguments,
messageSuperAsExpression,
- templateDeferredTypeAnnotation,
- templateIntegerLiteralIsOutOfRange,
templateNotAPrefixInTypeAnnotation,
templateUnresolvedPrefixInTypeAnnotation;
@@ -42,22 +40,28 @@
import '../problems.dart' show unhandled, unsupported;
-import '../scope.dart' show AccessErrorBuilder;
-
import 'body_builder.dart' show Identifier, noLocation;
import 'constness.dart' show Constness;
import 'expression_generator.dart'
show
+ DeferredAccessGenerator,
+ ErroneousExpressionGenerator,
ExpressionGenerator,
Generator,
IndexedAccessGenerator,
+ LargeIntAccessGenerator,
+ LoadLibraryGenerator,
NullAwarePropertyAccessGenerator,
PropertyAccessGenerator,
+ ReadOnlyAccessGenerator,
+ StaticAccessGenerator,
+ SuperIndexedAccessGenerator,
SuperPropertyAccessGenerator,
ThisIndexedAccessGenerator,
ThisPropertyAccessGenerator,
+ TypeUseGenerator,
VariableUseGenerator;
import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
@@ -100,7 +104,6 @@
Throw,
TreeNode,
TypeParameter,
- TypeParameterType,
VariableDeclaration,
VariableGet,
VariableSet;
@@ -108,12 +111,8 @@
import 'kernel_builder.dart'
show
Builder,
- BuiltinTypeBuilder,
- FunctionTypeAliasBuilder,
KernelClassBuilder,
- KernelFunctionTypeAliasBuilder,
KernelInvalidTypeBuilder,
- KernelTypeVariableBuilder,
LoadLibraryBuilder,
PrefixBuilder,
TypeDeclarationBuilder;
@@ -276,7 +275,7 @@
final DartType promotedType;
KernelVariableUseGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, Arguments> helper,
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
this.variable,
this.promotedType)
@@ -342,7 +341,7 @@
VariableDeclaration _receiverVariable;
KernelPropertyAccessGenerator.internal(
- ExpressionGeneratorHelper<dynamic, dynamic, Arguments> helper,
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
this.receiver,
this.name,
@@ -510,7 +509,7 @@
final DartType type;
KernelNullAwarePropertyAccessGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
this.receiverExpression,
this.name,
@@ -602,7 +601,7 @@
final Member setter;
KernelSuperPropertyAccessGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
this.name,
this.getter,
@@ -831,7 +830,7 @@
VariableDeclaration indexVariable;
KernelThisIndexedAccessGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
this.index,
this.getter,
@@ -944,6 +943,494 @@
}
}
+class KernelSuperIndexedAccessGenerator extends KernelGenerator
+ with SuperIndexedAccessGenerator<Expression, Statement, Arguments> {
+ final Expression index;
+
+ final Member getter;
+
+ final Member setter;
+
+ VariableDeclaration indexVariable;
+
+ KernelSuperIndexedAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ this.index,
+ this.getter,
+ this.setter)
+ : super(helper, token);
+
+ Expression indexAccess() {
+ indexVariable ??= new VariableDeclaration.forValue(index);
+ return new VariableGet(indexVariable);
+ }
+
+ Expression _makeWriteAndReturn(
+ Expression value, ShadowComplexAssignment complexAssignment) {
+ var valueVariable = new VariableDeclaration.forValue(value);
+ if (setter == null) {
+ helper.warnUnresolvedMethod(indexSetName, offsetForToken(token),
+ isSuper: true);
+ }
+ var write = new SuperMethodInvocation(
+ indexSetName,
+ forest.castArguments(forest.arguments(
+ <Expression>[indexAccess(), new VariableGet(valueVariable)],
+ token)),
+ setter)
+ ..fileOffset = offsetForToken(token);
+ complexAssignment?.write = write;
+ var dummy = new VariableDeclaration.forValue(write);
+ return makeLet(
+ valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
+ }
+
+ @override
+ Expression _makeSimpleRead() {
+ if (getter == null) {
+ helper.warnUnresolvedMethod(indexGetName, offsetForToken(token),
+ isSuper: true);
+ }
+ // TODO(ahe): Use [DirectMethodInvocation] when possible.
+ return new ShadowSuperMethodInvocation(
+ indexGetName,
+ forest.castArguments(forest.arguments(<Expression>[index], token)),
+ getter)
+ ..fileOffset = offsetForToken(token);
+ }
+
+ @override
+ Expression _makeSimpleWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
+ if (setter == null) {
+ helper.warnUnresolvedMethod(indexSetName, offsetForToken(token),
+ isSuper: true);
+ }
+ var write = new SuperMethodInvocation(
+ indexSetName,
+ forest
+ .castArguments(forest.arguments(<Expression>[index, value], token)),
+ setter)
+ ..fileOffset = offsetForToken(token);
+ complexAssignment?.write = write;
+ return write;
+ }
+
+ @override
+ Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+ if (getter == null) {
+ helper.warnUnresolvedMethod(indexGetName, offsetForToken(token),
+ isSuper: true);
+ }
+ var read = new SuperMethodInvocation(
+ indexGetName,
+ forest.castArguments(
+ forest.arguments(<Expression>[indexAccess()], token)),
+ getter)
+ ..fileOffset = offsetForToken(token);
+ complexAssignment?.read = read;
+ return read;
+ }
+
+ @override
+ Expression _makeWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
+ if (setter == null) {
+ helper.warnUnresolvedMethod(indexSetName, offsetForToken(token),
+ isSuper: true);
+ }
+ var write = new SuperMethodInvocation(
+ indexSetName,
+ forest.castArguments(
+ forest.arguments(<Expression>[indexAccess(), value], token)),
+ setter)
+ ..fileOffset = offsetForToken(token);
+ complexAssignment?.write = write;
+ return write;
+ }
+
+ @override
+ Expression _finish(
+ Expression body, ShadowComplexAssignment complexAssignment) {
+ return super._finish(makeLet(indexVariable, body), complexAssignment);
+ }
+
+ @override
+ Expression doInvocation(int offset, Arguments arguments) {
+ return helper.buildMethodInvocation(
+ buildSimpleRead(), callName, arguments, offset,
+ isImplicitCall: true);
+ }
+
+ @override
+ ShadowComplexAssignment startComplexAssignment(Expression rhs) =>
+ new ShadowIndexAssign(null, index, rhs, isSuper: true);
+
+ @override
+ void printOn(StringSink sink) {
+ NameSystem syntheticNames = new NameSystem();
+ sink.write(", index: ");
+ printNodeOn(index, sink, syntheticNames: syntheticNames);
+ sink.write(", getter: ");
+ printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
+ sink.write(", setter: ");
+ printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
+ sink.write(", indexVariable: ");
+ printNodeOn(indexVariable, sink, syntheticNames: syntheticNames);
+ }
+}
+
+class KernelStaticAccessGenerator extends KernelGenerator
+ with StaticAccessGenerator<Expression, Statement, Arguments> {
+ @override
+ final Member readTarget;
+
+ final Member writeTarget;
+
+ KernelStaticAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ this.readTarget,
+ this.writeTarget)
+ : assert(readTarget != null || writeTarget != null),
+ super(helper, token);
+
+ @override
+ String get plainNameForRead => (readTarget ?? writeTarget).name.name;
+
+ @override
+ Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+ if (readTarget == null) {
+ return makeInvalidRead();
+ } else {
+ var read = helper.makeStaticGet(readTarget, token);
+ complexAssignment?.read = read;
+ return read;
+ }
+ }
+
+ @override
+ Expression _makeWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ Expression write;
+ if (writeTarget == null) {
+ write = makeInvalidWrite(value);
+ } else {
+ write = new StaticSet(writeTarget, value);
+ complexAssignment?.write = write;
+ }
+ write.fileOffset = offsetForToken(token);
+ return write;
+ }
+
+ @override
+ Expression doInvocation(int offset, Arguments arguments) {
+ if (helper.constantContext != ConstantContext.none &&
+ !helper.isIdentical(readTarget)) {
+ helper.deprecated_addCompileTimeError(
+ offset, "Not a constant expression.");
+ }
+ if (readTarget == null || isFieldOrGetter(readTarget)) {
+ return helper.buildMethodInvocation(buildSimpleRead(), callName,
+ arguments, offset + (readTarget?.name?.name?.length ?? 0),
+ // This isn't a constant expression, but we have checked if a
+ // constant expression error should be emitted already.
+ isConstantExpression: true,
+ isImplicitCall: true);
+ } else {
+ return helper.buildStaticInvocation(readTarget, arguments,
+ charOffset: offset);
+ }
+ }
+
+ @override
+ ShadowComplexAssignment startComplexAssignment(Expression rhs) =>
+ new ShadowStaticAssignment(rhs);
+
+ @override
+ void printOn(StringSink sink) {
+ NameSystem syntheticNames = new NameSystem();
+ sink.write(", readTarget: ");
+ printQualifiedNameOn(readTarget, sink, syntheticNames: syntheticNames);
+ sink.write(", writeTarget: ");
+ printQualifiedNameOn(writeTarget, sink, syntheticNames: syntheticNames);
+ }
+}
+
+class KernelLoadLibraryGenerator extends KernelGenerator
+ with LoadLibraryGenerator<Expression, Statement, Arguments> {
+ final LoadLibraryBuilder builder;
+
+ KernelLoadLibraryGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ this.builder)
+ : super(helper, token);
+
+ @override
+ Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+ var read =
+ helper.makeStaticGet(builder.createTearoffMethod(helper.forest), token);
+ complexAssignment?.read = read;
+ return read;
+ }
+
+ @override
+ Expression _makeWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ Expression write = makeInvalidWrite(value);
+ write.fileOffset = offsetForToken(token);
+ return write;
+ }
+
+ @override
+ Expression doInvocation(int offset, Arguments arguments) {
+ if (forest.argumentsPositional(arguments).length > 0 ||
+ forest.argumentsNamed(arguments).length > 0) {
+ helper.addProblemErrorIfConst(
+ messageLoadLibraryTakesNoArguments, offset, 'loadLibrary'.length);
+ }
+ return builder.createLoadLibrary(offset, forest);
+ }
+
+ @override
+ void printOn(StringSink sink) {
+ sink.write(", builder: ");
+ sink.write(builder);
+ }
+}
+
+class KernelDeferredAccessGenerator extends KernelGenerator
+ with DeferredAccessGenerator<Expression, Statement, Arguments> {
+ @override
+ final PrefixBuilder builder;
+
+ @override
+ final KernelGenerator generator;
+
+ KernelDeferredAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ this.builder,
+ this.generator)
+ : super(helper, token);
+
+ @override
+ Expression _makeSimpleRead() {
+ return helper.wrapInDeferredCheck(
+ generator._makeSimpleRead(), builder, token.charOffset);
+ }
+
+ @override
+ Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+ return helper.wrapInDeferredCheck(
+ generator._makeRead(complexAssignment), builder, token.charOffset);
+ }
+
+ @override
+ Expression _makeWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ return helper.wrapInDeferredCheck(
+ generator._makeWrite(value, voidContext, complexAssignment),
+ builder,
+ token.charOffset);
+ }
+}
+
+class KernelTypeUseGenerator extends KernelReadOnlyAccessGenerator
+ with TypeUseGenerator<Expression, Statement, Arguments> {
+ /// The import prefix preceding the [declaration] reference, or `null` if
+ /// the reference is not prefixed.
+ @override
+ final PrefixBuilder prefix;
+
+ /// The offset at which the [declaration] is referenced by this generator,
+ /// or `-1` if the reference is implicit.
+ final int declarationReferenceOffset;
+
+ @override
+ final TypeDeclarationBuilder declaration;
+
+ KernelTypeUseGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ this.prefix,
+ this.declarationReferenceOffset,
+ this.declaration,
+ String plainNameForRead)
+ : super(helper, token, null, plainNameForRead);
+
+ @override
+ Expression get expression {
+ if (super.expression == null) {
+ int offset = offsetForToken(token);
+ if (declaration is KernelInvalidTypeBuilder) {
+ KernelInvalidTypeBuilder declaration = this.declaration;
+ helper.addProblemErrorIfConst(
+ declaration.message.messageObject, offset, token.length);
+ super.expression =
+ new Throw(forest.literalString(declaration.message.message, token))
+ ..fileOffset = offset;
+ } else {
+ super.expression = forest.literalType(
+ buildTypeWithBuiltArguments(null, nonInstanceAccessIsError: true),
+ token);
+ }
+ }
+ return super.expression;
+ }
+
+ @override
+ Expression makeInvalidWrite(Expression value) {
+ return buildThrowNoSuchMethodError(
+ forest.literalNull(token),
+ storeOffset(
+ forest.arguments(<Expression>[value], null), value.fileOffset),
+ isSetter: true);
+ }
+
+ @override
+ buildPropertyAccess(
+ IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
+ // `SomeType?.toString` is the same as `SomeType.toString`, not
+ // `(SomeType).toString`.
+ isNullAware = false;
+
+ Name name = send.name;
+ Arguments arguments = send.arguments;
+
+ if (declaration is KernelClassBuilder) {
+ KernelClassBuilder declaration = this.declaration;
+ Builder builder = declaration.findStaticBuilder(
+ name.name, offsetForToken(token), uri, helper.library);
+
+ Generator generator;
+ if (builder == null) {
+ // If we find a setter, [builder] is an [AccessErrorBuilder], not null.
+ if (send is IncompletePropertyAccessGenerator) {
+ generator = new UnresolvedNameGenerator(helper, send.token, name);
+ } else {
+ return helper.buildConstructorInvocation(declaration, send.token,
+ arguments, name.name, null, token.charOffset, Constness.implicit);
+ }
+ } else {
+ Builder setter;
+ if (builder.isSetter) {
+ setter = builder;
+ } else if (builder.isGetter) {
+ setter = declaration.findStaticBuilder(
+ name.name, offsetForToken(token), uri, helper.library,
+ isSetter: true);
+ } else if (builder.isField && !builder.isFinal) {
+ setter = builder;
+ }
+ generator = new StaticAccessGenerator<Expression, Statement,
+ Arguments>.fromBuilder(helper, builder, send.token, setter);
+ }
+
+ return arguments == null
+ ? generator
+ : generator.doInvocation(offsetForToken(send.token), arguments);
+ } else {
+ return super.buildPropertyAccess(send, operatorOffset, isNullAware);
+ }
+ }
+
+ @override
+ Expression doInvocation(int offset, Arguments arguments) {
+ return helper.buildConstructorInvocation(declaration, token, arguments, "",
+ null, token.charOffset, Constness.implicit);
+ }
+}
+
+class KernelReadOnlyAccessGenerator extends KernelGenerator
+ with ReadOnlyAccessGenerator<Expression, Statement, Arguments> {
+ @override
+ final String plainNameForRead;
+
+ Expression expression;
+
+ VariableDeclaration value;
+
+ KernelReadOnlyAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token,
+ this.expression,
+ this.plainNameForRead)
+ : super(helper, token);
+
+ @override
+ Expression _makeSimpleRead() => expression;
+
+ @override
+ Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+ value ??= new VariableDeclaration.forValue(expression);
+ return new VariableGet(value);
+ }
+
+ @override
+ Expression _makeWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ var write = makeInvalidWrite(value);
+ complexAssignment?.write = write;
+ return write;
+ }
+
+ @override
+ Expression _finish(
+ Expression body, ShadowComplexAssignment complexAssignment) =>
+ super._finish(makeLet(value, body), complexAssignment);
+
+ @override
+ Expression doInvocation(int offset, Arguments arguments) {
+ return helper.buildMethodInvocation(buildSimpleRead(), callName, arguments,
+ adjustForImplicitCall(plainNameForRead, offset),
+ isImplicitCall: true);
+ }
+
+ @override
+ void printOn(StringSink sink) {
+ NameSystem syntheticNames = new NameSystem();
+ sink.write(", expression: ");
+ printNodeOn(expression, sink, syntheticNames: syntheticNames);
+ sink.write(", plainNameForRead: ");
+ sink.write(plainNameForRead);
+ sink.write(", value: ");
+ printNodeOn(value, sink, syntheticNames: syntheticNames);
+ }
+}
+
+class KernelLargeIntAccessGenerator extends KernelGenerator
+ with LargeIntAccessGenerator<Expression, Statement, Arguments> {
+ KernelLargeIntAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+ Token token)
+ : super(helper, token);
+
+ @override
+ Expression _makeSimpleRead() => buildError();
+
+ @override
+ Expression _makeSimpleWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ return buildError();
+ }
+
+ @override
+ Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+ return buildError();
+ }
+
+ @override
+ Expression _makeWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ return buildError();
+ }
+}
+
Expression makeLet(VariableDeclaration variable, Expression body) {
if (variable == null) return body;
return new Let(variable, body);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
index 46e7b2a..e384183 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
@@ -15,579 +15,6 @@
/// superclass should use the forest API in a factory method.
part of 'kernel_expression_generator.dart';
-class SuperIndexedAccessGenerator extends KernelGenerator {
- final Expression index;
-
- final Member getter;
-
- final Member setter;
-
- VariableDeclaration indexVariable;
-
- SuperIndexedAccessGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
- Token token,
- this.index,
- this.getter,
- this.setter)
- : super(helper, token);
-
- String get plainNameForRead => "[]";
-
- String get plainNameForWrite => "[]=";
-
- String get debugName => "SuperIndexedAccessGenerator";
-
- indexAccess() {
- indexVariable ??= new VariableDeclaration.forValue(index);
- return new VariableGet(indexVariable);
- }
-
- Expression _makeSimpleRead() {
- if (getter == null) {
- helper.warnUnresolvedMethod(indexGetName, offsetForToken(token),
- isSuper: true);
- }
- // TODO(ahe): Use [DirectMethodInvocation] when possible.
- return new ShadowSuperMethodInvocation(
- indexGetName,
- forest.castArguments(forest.arguments(<Expression>[index], token)),
- getter)
- ..fileOffset = offsetForToken(token);
- }
-
- Expression _makeSimpleWrite(Expression value, bool voidContext,
- ShadowComplexAssignment complexAssignment) {
- if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
- if (setter == null) {
- helper.warnUnresolvedMethod(indexSetName, offsetForToken(token),
- isSuper: true);
- }
- var write = new SuperMethodInvocation(
- indexSetName,
- forest
- .castArguments(forest.arguments(<Expression>[index, value], token)),
- setter)
- ..fileOffset = offsetForToken(token);
- complexAssignment?.write = write;
- return write;
- }
-
- Expression _makeRead(ShadowComplexAssignment complexAssignment) {
- if (getter == null) {
- helper.warnUnresolvedMethod(indexGetName, offsetForToken(token),
- isSuper: true);
- }
- var read = new SuperMethodInvocation(
- indexGetName,
- forest.castArguments(
- forest.arguments(<Expression>[indexAccess()], token)),
- getter)
- ..fileOffset = offsetForToken(token);
- complexAssignment?.read = read;
- return read;
- }
-
- Expression _makeWrite(Expression value, bool voidContext,
- ShadowComplexAssignment complexAssignment) {
- if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
- if (setter == null) {
- helper.warnUnresolvedMethod(indexSetName, offsetForToken(token),
- isSuper: true);
- }
- var write = new SuperMethodInvocation(
- indexSetName,
- forest.castArguments(
- forest.arguments(<Expression>[indexAccess(), value], token)),
- setter)
- ..fileOffset = offsetForToken(token);
- complexAssignment?.write = write;
- return write;
- }
-
- _makeWriteAndReturn(
- Expression value, ShadowComplexAssignment complexAssignment) {
- var valueVariable = new VariableDeclaration.forValue(value);
- if (setter == null) {
- helper.warnUnresolvedMethod(indexSetName, offsetForToken(token),
- isSuper: true);
- }
- var write = new SuperMethodInvocation(
- indexSetName,
- forest.castArguments(forest.arguments(
- <Expression>[indexAccess(), new VariableGet(valueVariable)],
- token)),
- setter)
- ..fileOffset = offsetForToken(token);
- complexAssignment?.write = write;
- var dummy = new VariableDeclaration.forValue(write);
- return makeLet(
- valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
- }
-
- Expression _finish(
- Expression body, ShadowComplexAssignment complexAssignment) {
- return super._finish(makeLet(indexVariable, body), complexAssignment);
- }
-
- Expression doInvocation(int offset, Arguments arguments) {
- return helper.buildMethodInvocation(
- buildSimpleRead(), callName, arguments, offset,
- isImplicitCall: true);
- }
-
- @override
- ShadowComplexAssignment startComplexAssignment(Expression rhs) =>
- new ShadowIndexAssign(null, index, rhs, isSuper: true);
-
- @override
- void printOn(StringSink sink) {
- NameSystem syntheticNames = new NameSystem();
- sink.write(", index: ");
- printNodeOn(index, sink, syntheticNames: syntheticNames);
- sink.write(", getter: ");
- printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
- sink.write(", setter: ");
- printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
- sink.write(", indexVariable: ");
- printNodeOn(indexVariable, sink, syntheticNames: syntheticNames);
- }
-}
-
-class StaticAccessGenerator extends KernelGenerator {
- final Member readTarget;
-
- final Member writeTarget;
-
- StaticAccessGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
- Token token,
- this.readTarget,
- this.writeTarget)
- : assert(readTarget != null || writeTarget != null),
- super(helper, token);
-
- factory StaticAccessGenerator.fromBuilder(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
- Builder builder,
- Token token,
- Builder builderSetter) {
- if (builder is AccessErrorBuilder) {
- AccessErrorBuilder error = builder;
- builder = error.builder;
- // We should only see an access error here if we've looked up a setter
- // when not explicitly looking for a setter.
- assert(builder.isSetter);
- } else if (builder.target == null) {
- return unhandled(
- "${builder.runtimeType}",
- "StaticAccessGenerator.fromBuilder",
- offsetForToken(token),
- helper.uri);
- }
- Member getter = builder.target.hasGetter ? builder.target : null;
- Member setter = builder.target.hasSetter ? builder.target : null;
- if (setter == null) {
- if (builderSetter?.target?.hasSetter ?? false) {
- setter = builderSetter.target;
- }
- }
- return new StaticAccessGenerator(helper, token, getter, setter);
- }
-
- String get plainNameForRead => (readTarget ?? writeTarget).name.name;
-
- String get debugName => "StaticAccessGenerator";
-
- Expression _makeRead(ShadowComplexAssignment complexAssignment) {
- if (readTarget == null) {
- return makeInvalidRead();
- } else {
- var read = helper.makeStaticGet(readTarget, token);
- complexAssignment?.read = read;
- return read;
- }
- }
-
- Expression _makeWrite(Expression value, bool voidContext,
- ShadowComplexAssignment complexAssignment) {
- Expression write;
- if (writeTarget == null) {
- write = makeInvalidWrite(value);
- } else {
- write = new StaticSet(writeTarget, value);
- complexAssignment?.write = write;
- }
- write.fileOffset = offsetForToken(token);
- return write;
- }
-
- Expression doInvocation(int offset, Arguments arguments) {
- if (helper.constantContext != ConstantContext.none &&
- !helper.isIdentical(readTarget)) {
- helper.deprecated_addCompileTimeError(
- offset, "Not a constant expression.");
- }
- if (readTarget == null || isFieldOrGetter(readTarget)) {
- return helper.buildMethodInvocation(buildSimpleRead(), callName,
- arguments, offset + (readTarget?.name?.name?.length ?? 0),
- // This isn't a constant expression, but we have checked if a
- // constant expression error should be emitted already.
- isConstantExpression: true,
- isImplicitCall: true);
- } else {
- return helper.buildStaticInvocation(readTarget, arguments,
- charOffset: offset);
- }
- }
-
- @override
- ShadowComplexAssignment startComplexAssignment(Expression rhs) =>
- new ShadowStaticAssignment(rhs);
-
- @override
- void printOn(StringSink sink) {
- NameSystem syntheticNames = new NameSystem();
- sink.write(", readTarget: ");
- printQualifiedNameOn(readTarget, sink, syntheticNames: syntheticNames);
- sink.write(", writeTarget: ");
- printQualifiedNameOn(writeTarget, sink, syntheticNames: syntheticNames);
- }
-}
-
-class LoadLibraryGenerator extends KernelGenerator {
- final LoadLibraryBuilder builder;
-
- LoadLibraryGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
- Token token,
- this.builder)
- : super(helper, token);
-
- String get plainNameForRead => 'loadLibrary';
-
- String get debugName => "LoadLibraryGenerator";
-
- Expression _makeRead(ShadowComplexAssignment complexAssignment) {
- var read =
- helper.makeStaticGet(builder.createTearoffMethod(helper.forest), token);
- complexAssignment?.read = read;
- return read;
- }
-
- Expression _makeWrite(Expression value, bool voidContext,
- ShadowComplexAssignment complexAssignment) {
- Expression write = makeInvalidWrite(value);
- write.fileOffset = offsetForToken(token);
- return write;
- }
-
- Expression doInvocation(int offset, Arguments arguments) {
- if (forest.argumentsPositional(arguments).length > 0 ||
- forest.argumentsNamed(arguments).length > 0) {
- helper.addProblemErrorIfConst(
- messageLoadLibraryTakesNoArguments, offset, 'loadLibrary'.length);
- }
- return builder.createLoadLibrary(offset, forest);
- }
-
- @override
- void printOn(StringSink sink) {
- sink.write(", builder: ");
- sink.write(builder);
- }
-}
-
-class DeferredAccessGenerator extends KernelGenerator {
- final PrefixBuilder builder;
-
- final KernelGenerator generator;
-
- DeferredAccessGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
- Token token,
- this.builder,
- this.generator)
- : super(helper, token);
-
- String get plainNameForRead {
- return unsupported(
- "deferredAccessor.plainNameForRead", offsetForToken(token), uri);
- }
-
- String get debugName => "DeferredAccessGenerator";
-
- Expression _makeSimpleRead() {
- return helper.wrapInDeferredCheck(
- generator._makeSimpleRead(), builder, token.charOffset);
- }
-
- Expression _makeRead(ShadowComplexAssignment complexAssignment) {
- return helper.wrapInDeferredCheck(
- generator._makeRead(complexAssignment), builder, token.charOffset);
- }
-
- Expression _makeWrite(Expression value, bool voidContext,
- ShadowComplexAssignment complexAssignment) {
- return helper.wrapInDeferredCheck(
- generator._makeWrite(value, voidContext, complexAssignment),
- builder,
- token.charOffset);
- }
-
- buildPropertyAccess(
- IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
- var propertyAccess =
- generator.buildPropertyAccess(send, operatorOffset, isNullAware);
- if (propertyAccess is Generator) {
- return new DeferredAccessGenerator(
- helper, token, builder, propertyAccess);
- } else {
- Expression expression = propertyAccess;
- return helper.wrapInDeferredCheck(expression, builder, token.charOffset);
- }
- }
-
- @override
- DartType buildTypeWithBuiltArguments(List<DartType> arguments,
- {bool nonInstanceAccessIsError: false}) {
- helper.addProblem(
- templateDeferredTypeAnnotation.withArguments(
- generator.buildTypeWithBuiltArguments(arguments,
- nonInstanceAccessIsError: nonInstanceAccessIsError),
- builder.name),
- offsetForToken(token),
- lengthForToken(token));
- return const InvalidType();
- }
-
- Expression doInvocation(int offset, Arguments arguments) {
- return helper.wrapInDeferredCheck(
- generator.doInvocation(offset, arguments), builder, token.charOffset);
- }
-
- @override
- void printOn(StringSink sink) {
- sink.write(", builder: ");
- sink.write(builder);
- sink.write(", generator: ");
- sink.write(generator);
- }
-}
-
-class ReadOnlyAccessGenerator extends KernelGenerator {
- final String plainNameForRead;
-
- Expression expression;
-
- VariableDeclaration value;
-
- ReadOnlyAccessGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
- Token token,
- this.expression,
- this.plainNameForRead)
- : super(helper, token);
-
- String get debugName => "ReadOnlyAccessGenerator";
-
- Expression _makeSimpleRead() => expression;
-
- Expression _makeRead(ShadowComplexAssignment complexAssignment) {
- value ??= new VariableDeclaration.forValue(expression);
- return new VariableGet(value);
- }
-
- Expression _makeWrite(Expression value, bool voidContext,
- ShadowComplexAssignment complexAssignment) {
- var write = makeInvalidWrite(value);
- complexAssignment?.write = write;
- return write;
- }
-
- Expression _finish(
- Expression body, ShadowComplexAssignment complexAssignment) =>
- super._finish(makeLet(value, body), complexAssignment);
-
- Expression doInvocation(int offset, Arguments arguments) {
- return helper.buildMethodInvocation(buildSimpleRead(), callName, arguments,
- adjustForImplicitCall(plainNameForRead, offset),
- isImplicitCall: true);
- }
-
- @override
- void printOn(StringSink sink) {
- NameSystem syntheticNames = new NameSystem();
- sink.write(", expression: ");
- printNodeOn(expression, sink, syntheticNames: syntheticNames);
- sink.write(", plainNameForRead: ");
- sink.write(plainNameForRead);
- sink.write(", value: ");
- printNodeOn(value, sink, syntheticNames: syntheticNames);
- }
-}
-
-class LargeIntAccessGenerator extends KernelGenerator {
- LargeIntAccessGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper, Token token)
- : super(helper, token);
-
- // TODO(ahe): This should probably be calling unhandled.
- String get plainNameForRead => null;
-
- String get debugName => "LargeIntAccessGenerator";
-
- @override
- Expression _makeSimpleRead() => buildError();
-
- @override
- Expression _makeSimpleWrite(Expression value, bool voidContext,
- ShadowComplexAssignment complexAssignment) {
- return buildError();
- }
-
- @override
- Expression _makeRead(ShadowComplexAssignment complexAssignment) {
- return buildError();
- }
-
- @override
- Expression _makeWrite(Expression value, bool voidContext,
- ShadowComplexAssignment complexAssignment) {
- return buildError();
- }
-
- Expression buildError() {
- return helper.buildCompileTimeError(
- templateIntegerLiteralIsOutOfRange.withArguments(token),
- offsetForToken(token),
- lengthForToken(token));
- }
-
- @override
- Expression doInvocation(int offset, Arguments arguments) {
- return buildError();
- }
-
- @override
- void printOn(StringSink sink) {
- sink.write(", lexeme: ");
- sink.write(token.lexeme);
- }
-}
-
-abstract class ErroneousExpressionGenerator implements KernelGenerator {
- /// Pass [arguments] that must be evaluated before throwing an error. At
- /// most one of [isGetter] and [isSetter] should be true and they're passed
- /// to [ExpressionGeneratorHelper.buildThrowNoSuchMethodError] if it is used.
- Expression buildError(Arguments arguments,
- {bool isGetter: false, bool isSetter: false, int offset});
-
- DartType buildErroneousTypeNotAPrefix(Identifier suffix);
-
- Name get name => unsupported("name", offsetForToken(token), uri);
-
- @override
- String get plainNameForRead => name.name;
-
- withReceiver(Object receiver, int operatorOffset, {bool isNullAware}) => this;
-
- @override
- Initializer buildFieldInitializer(Map<String, int> initializedFields) {
- return helper.buildInvalidInitializer(
- buildError(forest.argumentsEmpty(noLocation), isSetter: true));
- }
-
- @override
- doInvocation(int offset, Arguments arguments) {
- return buildError(arguments, offset: offset);
- }
-
- @override
- buildPropertyAccess(
- IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
- return this;
- }
-
- @override
- buildThrowNoSuchMethodError(Expression receiver, Arguments arguments,
- {bool isSuper: false,
- bool isGetter: false,
- bool isSetter: false,
- bool isStatic: false,
- String name,
- int offset,
- LocatedMessage argMessage}) {
- return this;
- }
-
- @override
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
- return buildError(forest.arguments(<Expression>[value], noLocation),
- isSetter: true);
- }
-
- @override
- Expression buildCompoundAssignment(Name binaryOperator, Expression value,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget,
- bool isPreIncDec: false}) {
- return buildError(forest.arguments(<Expression>[value], token),
- isGetter: true);
- }
-
- @override
- Expression buildPrefixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
- // TODO(ahe): For the Analyzer, we probably need to build a prefix
- // increment node that wraps an error.
- return buildError(
- forest.arguments(
- <Expression>[storeOffset(forest.literalInt(1, null), offset)],
- noLocation),
- isGetter: true);
- }
-
- @override
- Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
- // TODO(ahe): For the Analyzer, we probably need to build a post increment
- // node that wraps an error.
- return buildError(
- forest.arguments(
- <Expression>[storeOffset(forest.literalInt(1, null), offset)],
- noLocation),
- isGetter: true);
- }
-
- @override
- Expression buildNullAwareAssignment(
- Expression value, DartType type, int offset,
- {bool voidContext: false}) {
- return buildError(forest.arguments(<Expression>[value], noLocation),
- isSetter: true);
- }
-
- @override
- Expression buildSimpleRead() =>
- buildError(forest.argumentsEmpty(noLocation), isGetter: true);
-
- @override
- Expression makeInvalidRead() =>
- buildError(forest.argumentsEmpty(noLocation), isGetter: true);
-
- @override
- Expression makeInvalidWrite(Expression value) {
- return buildError(forest.arguments(<Expression>[value], noLocation),
- isSetter: true);
- }
-}
-
class ThisAccessGenerator extends KernelGenerator {
final bool isInitializer;
@@ -653,11 +80,11 @@
Member setter =
helper.lookupInstanceMember(name, isSuper: isSuper, isSetter: true);
if (isSuper) {
- return new SuperPropertyAccessGenerator(
- helper, send.token, name, getter, setter);
+ return new SuperPropertyAccessGenerator<Expression, Statement,
+ Arguments>(helper, send.token, name, getter, setter);
} else {
- return new ThisPropertyAccessGenerator(
- helper, send.token, name, getter, setter);
+ return new ThisPropertyAccessGenerator<Expression, Statement,
+ Arguments>(helper, send.token, name, getter, setter);
}
}
}
@@ -791,7 +218,7 @@
}
class UnresolvedNameGenerator extends KernelGenerator
- with ErroneousExpressionGenerator {
+ with ErroneousExpressionGenerator<Expression, Statement, Arguments> {
@override
final Name name;
@@ -849,7 +276,7 @@
}
class IncompleteErrorGenerator extends IncompleteSendGenerator
- with ErroneousExpressionGenerator {
+ with ErroneousExpressionGenerator<Expression, Statement, Arguments> {
final Message message;
IncompleteErrorGenerator(
@@ -1017,7 +444,7 @@
isQualified: true, prefix: prefix);
}
- return PropertyAccessGenerator.make(
+ return PropertyAccessGenerator.make<Expression, Statement, Arguments>(
helper, token, helper.toValue(receiver), name, null, null, isNullAware);
}
@@ -1053,7 +480,7 @@
}
}
-class ParenthesizedExpressionGenerator extends ReadOnlyAccessGenerator {
+class ParenthesizedExpressionGenerator extends KernelReadOnlyAccessGenerator {
ParenthesizedExpressionGenerator(
ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
Token token,
@@ -1068,162 +495,6 @@
}
}
-// TODO(ahe): Rename to TypeUseGenerator.
-class TypeDeclarationAccessGenerator extends ReadOnlyAccessGenerator {
- /// The import prefix preceding the [declaration] reference, or `null` if
- /// the reference is not prefixed.
- final PrefixBuilder prefix;
-
- /// The offset at which the [declaration] is referenced by this generator,
- /// or `-1` if the reference is implicit.
- final int declarationReferenceOffset;
-
- final TypeDeclarationBuilder declaration;
-
- TypeDeclarationAccessGenerator(
- ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
- Token token,
- this.prefix,
- this.declarationReferenceOffset,
- this.declaration,
- String plainNameForRead)
- : super(helper, token, null, plainNameForRead);
-
- String get debugName => "TypeDeclarationAccessGenerator";
-
- Expression get expression {
- if (super.expression == null) {
- int offset = offsetForToken(token);
- if (declaration is KernelInvalidTypeBuilder) {
- KernelInvalidTypeBuilder declaration = this.declaration;
- helper.addProblemErrorIfConst(
- declaration.message.messageObject, offset, token.length);
- super.expression =
- new Throw(forest.literalString(declaration.message.message, token))
- ..fileOffset = offset;
- } else {
- super.expression = forest.literalType(
- buildTypeWithBuiltArguments(null, nonInstanceAccessIsError: true),
- token);
- }
- }
- return super.expression;
- }
-
- Expression makeInvalidWrite(Expression value) {
- return buildThrowNoSuchMethodError(
- forest.literalNull(token),
- storeOffset(
- forest.arguments(<Expression>[value], null), value.fileOffset),
- isSetter: true);
- }
-
- @override
- buildPropertyAccess(
- IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
- // `SomeType?.toString` is the same as `SomeType.toString`, not
- // `(SomeType).toString`.
- isNullAware = false;
-
- Name name = send.name;
- Arguments arguments = send.arguments;
-
- if (declaration is KernelClassBuilder) {
- KernelClassBuilder declaration = this.declaration;
- Builder builder = declaration.findStaticBuilder(
- name.name, offsetForToken(token), uri, helper.library);
-
- Generator generator;
- if (builder == null) {
- // If we find a setter, [builder] is an [AccessErrorBuilder], not null.
- if (send is IncompletePropertyAccessGenerator) {
- generator = new UnresolvedNameGenerator(helper, send.token, name);
- } else {
- return helper.buildConstructorInvocation(declaration, send.token,
- arguments, name.name, null, token.charOffset, Constness.implicit);
- }
- } else {
- Builder setter;
- if (builder.isSetter) {
- setter = builder;
- } else if (builder.isGetter) {
- setter = declaration.findStaticBuilder(
- name.name, offsetForToken(token), uri, helper.library,
- isSetter: true);
- } else if (builder.isField && !builder.isFinal) {
- setter = builder;
- }
- generator = new StaticAccessGenerator.fromBuilder(
- helper, builder, send.token, setter);
- }
-
- return arguments == null
- ? generator
- : generator.doInvocation(offsetForToken(send.token), arguments);
- } else {
- return super.buildPropertyAccess(send, operatorOffset, isNullAware);
- }
- }
-
- @override
- DartType buildTypeWithBuiltArguments(List<DartType> arguments,
- {bool nonInstanceAccessIsError: false}) {
- if (arguments != null) {
- int expected = 0;
- if (declaration is KernelClassBuilder) {
- expected = declaration.target.typeParameters.length;
- } else if (declaration is FunctionTypeAliasBuilder) {
- expected = declaration.target.typeParameters.length;
- } else if (declaration is KernelTypeVariableBuilder) {
- // Type arguments on a type variable - error reported elsewhere.
- } else if (declaration is BuiltinTypeBuilder) {
- // Type arguments on a built-in type, for example, dynamic or void.
- expected = 0;
- } else {
- return unhandled(
- "${declaration.runtimeType}",
- "TypeDeclarationAccessGenerator.buildType",
- offsetForToken(token),
- helper.uri);
- }
- if (arguments.length != expected) {
- helper.warnTypeArgumentsMismatch(
- declaration.name, expected, offsetForToken(token));
- // We ignore the provided arguments, which will in turn return the
- // raw type below.
- // TODO(sigmund): change to use an InvalidType and include the raw type
- // as a recovery node once the IR can represent it (Issue #29840).
- arguments = null;
- }
- }
-
- DartType type;
- if (arguments == null) {
- TypeDeclarationBuilder typeDeclaration = declaration;
- if (typeDeclaration is KernelClassBuilder) {
- type = typeDeclaration.buildType(helper.library, null);
- } else if (typeDeclaration is KernelFunctionTypeAliasBuilder) {
- type = typeDeclaration.buildType(helper.library, null);
- }
- }
- if (type == null) {
- type =
- declaration.buildTypesWithBuiltArguments(helper.library, arguments);
- }
- if (type is TypeParameterType) {
- return helper.validatedTypeVariableUse(
- type, offsetForToken(token), nonInstanceAccessIsError);
- }
- return type;
- }
-
- @override
- Expression doInvocation(int offset, Arguments arguments) {
- return helper.buildConstructorInvocation(declaration, token, arguments, "",
- null, token.charOffset, Constness.implicit);
- }
-}
-
abstract class ContextAwareGenerator
extends Generator<Expression, Statement, Arguments> {
final Generator generator;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
index 99d686f..b83c6d6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
@@ -101,7 +101,7 @@
if (arguments == null && typeVariables != null) {
List<DartType> result =
- new List<DartType>.filled(typeVariables.length, null);
+ new List<DartType>.filled(typeVariables.length, null, growable: true);
for (int i = 0; i < result.length; ++i) {
result[i] = typeVariables[i].defaultType.build(library);
}
@@ -120,7 +120,8 @@
}
// arguments.length == typeVariables.length
- List<DartType> result = new List<DartType>.filled(arguments.length, null);
+ List<DartType> result =
+ new List<DartType>.filled(arguments.length, null, growable: true);
for (int i = 0; i < result.length; ++i) {
result[i] = arguments[i].build(library);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index b5f6854..c25088e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -53,6 +53,7 @@
BuiltinTypeBuilder,
ClassBuilder,
ConstructorReferenceBuilder,
+ DynamicTypeBuilder,
FormalParameterBuilder,
InvalidTypeBuilder,
KernelClassBuilder,
@@ -125,6 +126,16 @@
Uri get uri => library.importUri;
+ void becomeCoreLibrary(dynamicType) {
+ if (scope.local["dynamic"] == null) {
+ addBuilder(
+ "dynamic",
+ new DynamicTypeBuilder<KernelTypeBuilder, DartType>(
+ dynamicType, this, -1),
+ -1);
+ }
+ }
+
KernelTypeBuilder addNamedType(
Object name, List<KernelTypeBuilder> arguments, int charOffset) {
return addType(new KernelNamedTypeBuilder(name, arguments), charOffset);
@@ -138,7 +149,8 @@
KernelTypeBuilder addVoidType(int charOffset) {
return addNamedType("void", null, charOffset)
- ..bind(new VoidTypeBuilder(const VoidType(), this, charOffset));
+ ..bind(new VoidTypeBuilder<KernelTypeBuilder, VoidType>(
+ const VoidType(), this, charOffset));
}
void addClass(
@@ -437,8 +449,7 @@
// TODO(ahe, kmillikin): Should always be true?
// pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart can't
// handle that :(
- application.cls.isSyntheticMixinImplementation =
- !isNamedMixinApplication;
+ application.cls.isAnonymousMixin = !isNamedMixinApplication;
addBuilder(fullname, application, charOffset);
supertype =
addNamedType(fullname, applicationTypeArguments, charOffset);
@@ -976,7 +987,8 @@
boundlessTypeVariables.add(newVariable);
}
for (TypeBuilder newType in newTypes) {
- declaration.addType(new UnresolvedType(newType, -1, null));
+ declaration
+ .addType(new UnresolvedType<KernelTypeBuilder>(newType, -1, null));
}
return copy;
}
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index 787bc90..97944ad 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -158,47 +158,34 @@
static const localFunctionDeclarationContinuation =
const LocalFunctionDeclarationIdentifierContext.continuation();
- /// Identifier is the name appearing in a function expression.
- ///
- /// TODO(paulberry,ahe): What is an example of valid Dart code where this
- /// would occur?
- static const functionExpressionName =
- const IdentifierContext('functionExpressionName');
-
/// Identifier is the start of a reference to a constructor declared
/// elsewhere.
static const constructorReference =
- const IdentifierContext('constructorReference', isScopeReference: true);
+ const ConstructorReferenceIdentifierContext();
/// Identifier is part of a reference to a constructor declared elsewhere, but
/// it's not the first identifier of the reference.
- static const constructorReferenceContinuation = const IdentifierContext(
- 'constructorReferenceContinuation',
- isContinuation: true);
+ static const constructorReferenceContinuation =
+ const ConstructorReferenceIdentifierContext.continuation();
/// Identifier is part of a reference to a constructor declared elsewhere, but
/// it appears after type parameters (e.g. `foo` in `X<Y>.foo`).
static const constructorReferenceContinuationAfterTypeArguments =
- const IdentifierContext(
- 'constructorReferenceContinuationAfterTypeArguments',
- isContinuation: true);
+ const ConstructorReferenceIdentifierContext
+ .continuationAfterTypeArguments();
/// Identifier is the declaration of a label (i.e. it is followed by `:` and
/// then a statement).
- static const labelDeclaration =
- const IdentifierContext('labelDeclaration', inDeclaration: true);
+ static const labelDeclaration = const LabelDeclarationIdentifierContext();
/// Identifier is the start of a reference occurring in a literal symbol (e.g.
/// `foo` in `#foo`).
- static const literalSymbol =
- const IdentifierContext('literalSymbol', inSymbol: true);
+ static const literalSymbol = const LiteralSymbolIdentifierContext();
/// Identifier is part of a reference occurring in a literal symbol, but it's
/// not the first identifier of the reference (e.g. `foo` in `#prefix.foo`).
- static const literalSymbolContinuation = const IdentifierContext(
- 'literalSymbolContinuation',
- inSymbol: true,
- isContinuation: true);
+ static const literalSymbolContinuation =
+ const LiteralSymbolIdentifierContext.continuation();
/// Identifier appears in an expression, and it does not immediately follow a
/// `.`.
@@ -210,9 +197,8 @@
/// Identifier is a reference to a named argument of a function or method
/// invocation (e.g. `foo` in `f(foo: 0);`.
- static const namedArgumentReference = const IdentifierContext(
- 'namedArgumentReference',
- allowedInConstantExpression: true);
+ static const namedArgumentReference =
+ const NamedArgumentReferenceIdentifierContext();
/// Identifier is a name being declared by a local variable declaration.
static const localVariableDeclaration =
@@ -220,7 +206,7 @@
/// Identifier is a reference to a label (e.g. `foo` in `break foo;`).
/// Labels have their own scope.
- static const labelReference = const IdentifierContext('labelReference');
+ static const labelReference = const LabelReferenceIdentifierContext();
final String _name;
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index 18dd095..28e85b6 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -90,6 +90,40 @@
}
}
+/// See [IdentifierContext.constructorReference]
+/// and [IdentifierContext.constructorReferenceContinuation]
+/// and [IdentifierContext.constructorReferenceContinuationAfterTypeArguments].
+class ConstructorReferenceIdentifierContext extends IdentifierContext {
+ const ConstructorReferenceIdentifierContext()
+ : super('constructorReference', isScopeReference: true);
+
+ const ConstructorReferenceIdentifierContext.continuation()
+ : super('constructorReferenceContinuation', isContinuation: true);
+
+ const ConstructorReferenceIdentifierContext.continuationAfterTypeArguments()
+ : super('constructorReferenceContinuationAfterTypeArguments',
+ isContinuation: true);
+
+ @override
+ Token ensureIdentifier(Token token, Parser parser) {
+ Token identifier = token.next;
+ assert(identifier.kind != IDENTIFIER_TOKEN);
+ if (identifier.isIdentifier) {
+ return identifier;
+ }
+
+ // Recovery
+ if (!identifier.isKeywordOrIdentifier) {
+ identifier = parser.insertSyntheticIdentifier(token, this,
+ message: fasta.templateExpectedIdentifier.withArguments(identifier));
+ } else {
+ parser.reportRecoverableErrorWithToken(
+ identifier, fasta.templateExpectedIdentifier);
+ }
+ return identifier;
+ }
+}
+
/// See [IdentifierContext.dottedName].
class DottedNameIdentifierContext extends IdentifierContext {
const DottedNameIdentifierContext() : super('dottedName');
@@ -368,6 +402,28 @@
}
}
+class LiteralSymbolIdentifierContext extends IdentifierContext {
+ const LiteralSymbolIdentifierContext()
+ : super('literalSymbol', inSymbol: true);
+
+ const LiteralSymbolIdentifierContext.continuation()
+ : super('literalSymbolContinuation',
+ inSymbol: true, isContinuation: true);
+
+ @override
+ Token ensureIdentifier(Token token, Parser parser) {
+ Token identifier = token.next;
+ assert(identifier.kind != IDENTIFIER_TOKEN);
+ if (identifier.isIdentifier) {
+ return identifier;
+ }
+
+ // Recovery
+ return parser.insertSyntheticIdentifier(token, this,
+ message: fasta.templateExpectedIdentifier.withArguments(identifier));
+ }
+}
+
/// See [IdentifierContext.localFunctionDeclaration]
/// and [IdentifierContext.localFunctionDeclarationContinuation].
class LocalFunctionDeclarationIdentifierContext extends IdentifierContext {
@@ -405,6 +461,66 @@
}
}
+/// See [IdentifierContext.labelDeclaration].
+class LabelDeclarationIdentifierContext extends IdentifierContext {
+ const LabelDeclarationIdentifierContext()
+ : super('labelDeclaration', inDeclaration: true);
+
+ @override
+ Token ensureIdentifier(Token token, Parser parser) {
+ Token identifier = token.next;
+ assert(identifier.kind != IDENTIFIER_TOKEN);
+ if (identifier.isIdentifier) {
+ return identifier;
+ }
+
+ // Recovery
+ if (isOneOfOrEof(identifier, const [':']) ||
+ looksLikeStartOfNextStatement(identifier)) {
+ identifier = parser.insertSyntheticIdentifier(token, this,
+ message: fasta.templateExpectedIdentifier.withArguments(identifier));
+ } else {
+ parser.reportRecoverableErrorWithToken(
+ identifier, fasta.templateExpectedIdentifier);
+ if (!identifier.isKeywordOrIdentifier) {
+ // When in doubt, consume the token to ensure we make progress
+ // but insert a synthetic identifier to satisfy listeners.
+ identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+ }
+ }
+ return identifier;
+ }
+}
+
+/// See [IdentifierContext.labelReference].
+class LabelReferenceIdentifierContext extends IdentifierContext {
+ const LabelReferenceIdentifierContext() : super('labelReference');
+
+ @override
+ Token ensureIdentifier(Token token, Parser parser) {
+ Token identifier = token.next;
+ assert(identifier.kind != IDENTIFIER_TOKEN);
+ if (identifier.isIdentifier) {
+ return identifier;
+ }
+
+ // Recovery
+ if (isOneOfOrEof(identifier, const [';'])) {
+ identifier = parser.insertSyntheticIdentifier(token, this,
+ message: fasta.templateExpectedIdentifier.withArguments(identifier));
+ } else {
+ parser.reportRecoverableErrorWithToken(
+ identifier, fasta.templateExpectedIdentifier);
+ if (!identifier.isKeywordOrIdentifier) {
+ // When in doubt, consume the token to ensure we make progress
+ // but insert a synthetic identifier to satisfy listeners.
+ identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+ }
+ }
+ return identifier;
+ }
+}
+
/// See [IdentifierContext.libraryName],
/// and [IdentifierContext.libraryNameContinuation]
/// and [IdentifierContext.partName],
@@ -576,6 +692,36 @@
}
}
+/// See [IdentifierContext.namedArgumentReference].
+class NamedArgumentReferenceIdentifierContext extends IdentifierContext {
+ const NamedArgumentReferenceIdentifierContext()
+ : super('namedArgumentReference', allowedInConstantExpression: true);
+
+ @override
+ Token ensureIdentifier(Token token, Parser parser) {
+ Token identifier = token.next;
+ assert(identifier.kind != IDENTIFIER_TOKEN);
+ if (identifier.isIdentifier) {
+ return identifier;
+ }
+
+ // Recovery
+ if (isOneOfOrEof(identifier, const [':'])) {
+ identifier = parser.insertSyntheticIdentifier(token, this,
+ message: fasta.templateExpectedIdentifier.withArguments(identifier));
+ } else {
+ parser.reportRecoverableErrorWithToken(
+ identifier, fasta.templateExpectedIdentifier);
+ if (!identifier.isKeywordOrIdentifier) {
+ // When in doubt, consume the token to ensure we make progress
+ // but insert a synthetic identifier to satisfy listeners.
+ identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+ }
+ }
+ return identifier;
+ }
+}
+
/// See [IdentifierContext.topLevelFunctionDeclaration]
/// and [IdentifierContext.topLevelVariableDeclaration].
class TopLevelDeclarationIdentifierContext extends IdentifierContext {
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 0b81640..1375174 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -90,14 +90,13 @@
TypeParamOrArgInfo,
computeMethodTypeArguments,
computeType,
- computeTypeParam,
computeTypeParamOrArg,
isGeneralizedFunctionType,
isValidTypeReference,
noType,
noTypeParamOrArg;
-import 'util.dart' show optional;
+import 'util.dart' show findNonSyntheticToken, optional;
/// An event generating parser of Dart programs. This parser expects all tokens
/// in a linked list (aka a token stream).
@@ -1597,7 +1596,7 @@
/// ```
/// enumType:
- /// metadata 'enum' id '{' id [',' id]* [','] '}'
+ /// metadata 'enum' id '{' metadata id [',' metadata id]* [','] '}'
/// ;
/// ```
Token parseEnum(Token token) {
@@ -1619,10 +1618,6 @@
break;
}
token = parseMetadataStar(token);
- if (!identical(token.next, next)) {
- listener.handleRecoverableError(
- fasta.messageAnnotationOnEnumConstant, next, token);
- }
token = ensureIdentifier(token, IdentifierContext.enumValueDeclaration);
next = token.next;
count++;
@@ -1673,7 +1668,7 @@
assert(optional('class', token));
Token name =
ensureIdentifier(token, IdentifierContext.classOrNamedMixinDeclaration);
- token = computeTypeParam(name).parseVariables(name, this);
+ token = computeTypeParamOrArg(name, true).parseVariables(name, this);
if (optional('=', token.next)) {
listener.beginNamedMixinApplication(begin, abstractToken, name);
return parseNamedMixinApplication(token, begin, classKeyword);
@@ -1918,72 +1913,14 @@
/// an error, and return the synthetic identifier.
Token ensureIdentifier(Token token, IdentifierContext context) {
assert(context != null);
- Token next = token.next;
- if (next.kind == IDENTIFIER_TOKEN) {
- listener.handleIdentifier(next, context);
- return next;
- }
- Token identifier = context.ensureIdentifier(token, this);
- // TODO(danrubel): Once refactoring is complete,
- // context.ensureIdentifier should never return null.
- if (identifier != null) {
+ Token identifier = token.next;
+ if (identifier.kind != IDENTIFIER_TOKEN) {
+ identifier = context.ensureIdentifier(token, this);
+ assert(identifier != null);
assert(identifier.isKeywordOrIdentifier);
- listener.handleIdentifier(identifier, context);
- return identifier;
}
-
- // TODO(danrubel): Roll everything beyond this point into the
- // ensureIdentifier methods in the various IdentifierContext subclasses.
-
- if (!next.isIdentifier) {
- if (next is ErrorToken) {
- // TODO(brianwilkerson): This preserves the current semantics, but the
- // listener should not be recovering from this case, so this needs to be
- // reworked to recover in this method (probably inside the outermost
- // if statement).
- token =
- reportUnrecoverableErrorWithToken(next, context.recoveryTemplate)
- .next;
- } else if (isIdentifierForRecovery(next, context)) {
- reportRecoverableErrorWithToken(next, context.recoveryTemplate);
- token = next;
- } else if (isPostIdentifierForRecovery(next, context) ||
- isStartOfNextSibling(next, context)) {
- token = insertSyntheticIdentifier(token, context);
- } else if (next.isKeywordOrIdentifier) {
- reportRecoverableErrorWithToken(next, context.recoveryTemplate);
- token = next;
- } else {
- reportRecoverableErrorWithToken(next, context.recoveryTemplate);
- if (context == IdentifierContext.constructorReference) {
- token = insertSyntheticIdentifier(token, context);
- } else {
- token = next;
- }
- }
- } else if (next.type.isBuiltIn && !context.isBuiltInIdentifierAllowed) {
- if (context.inDeclaration) {
- reportRecoverableErrorWithToken(
- next, fasta.templateBuiltInIdentifierInDeclaration);
- } else if (!optional("dynamic", next)) {
- reportRecoverableErrorWithToken(
- next, fasta.templateBuiltInIdentifierAsType);
- }
- token = next;
- } else if (!inPlainSync && next.type.isPseudo) {
- if (optional('await', next)) {
- reportRecoverableError(next, fasta.messageAwaitAsIdentifier);
- } else if (optional('yield', next)) {
- reportRecoverableError(next, fasta.messageYieldAsIdentifier);
- } else if (optional('async', next)) {
- reportRecoverableError(next, fasta.messageAsyncAsIdentifier);
- }
- token = next;
- } else {
- token = next;
- }
- listener.handleIdentifier(token, context);
- return token;
+ listener.handleIdentifier(identifier, context);
+ return identifier;
}
/// Return `true` if the given [token] should be treated like the start of
@@ -2007,84 +1944,6 @@
optional('++', next) ||
optional('--', next);
- /// Return `true` if the given [token] should be treated like an identifier in
- /// the given [context] for the purposes of recovery.
- bool isIdentifierForRecovery(Token token, IdentifierContext context) {
- if (!token.type.isKeyword) {
- return false;
- }
- return isPostIdentifierForRecovery(token.next, context);
- }
-
- /// Return `true` if the given [token] appears to be a token that would be
- /// expected after an identifier in the given [context].
- bool isPostIdentifierForRecovery(Token token, IdentifierContext context) {
- if (token.isEof) {
- return true;
- }
- List<String> followingValues;
- if (context == IdentifierContext.combinator) {
- followingValues = [';'];
- } else if (context == IdentifierContext.constructorReferenceContinuation) {
- followingValues = ['.', ',', '(', ')', '[', ']', '}', ';'];
- } else if (context == IdentifierContext.labelDeclaration) {
- followingValues = [':'];
- } else if (context == IdentifierContext.literalSymbol ||
- context == IdentifierContext.literalSymbolContinuation) {
- followingValues = ['.', ';'];
- } else {
- return false;
- }
- for (String tokenValue in followingValues) {
- if (optional(tokenValue, token)) {
- return true;
- }
- }
- return false;
- }
-
- /// Return `true` if the given [token] appears to be the start of a (virtual)
- /// node that would be a sibling of the current node or one of its parents.
- /// The type of the current node is suggested by the given [context].
- bool isStartOfNextSibling(Token token, IdentifierContext context) {
- if (!token.type.isKeyword) {
- return false;
- }
-
- List<String> statementKeywords() => <String>[
- 'const',
- 'do',
- 'final',
- 'if',
- 'switch',
- 'try',
- 'var',
- 'void',
- 'while'
- ];
-
- // TODO(brianwilkerson): At the moment, this test is entirely based on data
- // that can be represented declaratively. If that proves to be sufficient,
- // then this data can be moved into a field in IdentifierContext and we
- // could create a method to test whether a given token matches one of the
- // patterns.
- List<String> initialKeywords;
- if (context == IdentifierContext.labelDeclaration) {
- initialKeywords = statementKeywords();
- } else if (context ==
- IdentifierContext.localFunctionDeclarationContinuation) {
- initialKeywords = statementKeywords();
- } else {
- return false;
- }
- for (String tokenValue in initialKeywords) {
- if (optional(tokenValue, token)) {
- return true;
- }
- }
- return false;
- }
-
Token expect(String string, Token token) {
// TODO(danrubel): update all uses of expect(';'...) to ensureSemicolon
// then add assert(!identical(';', string));
@@ -2445,7 +2304,7 @@
}
Token beforeType = token;
- TypeInfo typeInfo = computeType(token, false);
+ TypeInfo typeInfo = computeType(token, false, true);
token = typeInfo.skipType(token);
next = token.next;
@@ -2530,8 +2389,8 @@
varFinalOrConst, fasta.templateExtraneousModifier);
}
}
- return parseTopLevelMethod(
- beforeStart, externalToken, beforeType, typeInfo, getOrSet, token);
+ return parseTopLevelMethod(beforeStart, externalToken, beforeType,
+ typeInfo, getOrSet, token.next);
}
if (getOrSet != null) {
@@ -2539,7 +2398,7 @@
getOrSet, fasta.templateExtraneousModifier);
}
return parseFields(beforeStart, externalToken, null, null, varFinalOrConst,
- beforeType, typeInfo, token, true);
+ beforeType, typeInfo, token.next, true);
}
Token parseFields(
@@ -2550,7 +2409,7 @@
Token varFinalOrConst,
Token beforeType,
TypeInfo typeInfo,
- Token beforeName,
+ Token name,
bool isTopLevel) {
if (externalToken != null) {
reportRecoverableError(externalToken, fasta.messageExternalField);
@@ -2563,8 +2422,7 @@
}
if (typeInfo == noType) {
if (varFinalOrConst == null) {
- reportRecoverableError(
- beforeName.next, fasta.messageMissingConstFinalVarOrType);
+ reportRecoverableError(name, fasta.messageMissingConstFinalVarOrType);
}
} else {
if (varFinalOrConst != null && optional('var', varFinalOrConst)) {
@@ -2572,16 +2430,16 @@
}
}
- typeInfo.parseType(beforeType, this);
+ Token token = typeInfo.parseType(beforeType, this);
+ assert(token.next == name);
IdentifierContext context = isTopLevel
? IdentifierContext.topLevelVariableDeclaration
: IdentifierContext.fieldDeclaration;
- Token name = ensureIdentifier(beforeName, context);
+ name = ensureIdentifier(token, context);
int fieldCount = 1;
- Token token =
- parseFieldInitializerOpt(name, name, varFinalOrConst, isTopLevel);
+ token = parseFieldInitializerOpt(name, name, varFinalOrConst, isTopLevel);
while (optional(',', token.next)) {
name = ensureIdentifier(token.next, context);
token = parseFieldInitializerOpt(name, name, varFinalOrConst, isTopLevel);
@@ -2599,17 +2457,17 @@
}
Token parseTopLevelMethod(Token beforeStart, Token externalToken,
- Token beforeType, TypeInfo typeInfo, Token getOrSet, Token beforeName) {
+ Token beforeType, TypeInfo typeInfo, Token getOrSet, Token name) {
listener.beginTopLevelMethod(beforeStart, externalToken);
- typeInfo.parseType(beforeType, this);
- Token name = ensureIdentifier(
- beforeName, IdentifierContext.topLevelFunctionDeclaration);
+ Token token = typeInfo.parseType(beforeType, this);
+ assert(token.next == (getOrSet ?? name));
+ name = ensureIdentifier(
+ getOrSet ?? token, IdentifierContext.topLevelFunctionDeclaration);
- Token token;
bool isGetter = false;
if (getOrSet == null) {
- token = computeTypeParam(name).parseVariables(name, this);
+ token = computeTypeParamOrArg(name, true).parseVariables(name, this);
} else {
isGetter = optional("get", getOrSet);
token = name;
@@ -3101,7 +2959,7 @@
listener.beginMember();
Token beforeType = token;
- TypeInfo typeInfo = computeType(token, false);
+ TypeInfo typeInfo = computeType(token, false, true);
token = typeInfo.skipType(token);
next = token.next;
@@ -3136,7 +2994,7 @@
beforeType,
typeInfo,
getOrSet,
- token);
+ token.next);
listener.endMember();
return token;
} else if (optional('===', next2) ||
@@ -3157,7 +3015,7 @@
beforeType,
typeInfo,
getOrSet,
- token);
+ token.next);
listener.endMember();
return token;
}
@@ -3210,14 +3068,22 @@
beforeType,
typeInfo,
getOrSet,
- token);
+ token.next);
} else {
if (getOrSet != null) {
reportRecoverableErrorWithToken(
getOrSet, fasta.templateExtraneousModifier);
}
- token = parseFields(beforeStart, externalToken, staticToken,
- covariantToken, varFinalOrConst, beforeType, typeInfo, token, false);
+ token = parseFields(
+ beforeStart,
+ externalToken,
+ staticToken,
+ covariantToken,
+ varFinalOrConst,
+ beforeType,
+ typeInfo,
+ token.next,
+ false);
}
listener.endMember();
return token;
@@ -3232,8 +3098,8 @@
Token beforeType,
TypeInfo typeInfo,
Token getOrSet,
- Token beforeName) {
- bool isOperator = getOrSet == null && optional('operator', beforeName.next);
+ Token name) {
+ bool isOperator = getOrSet == null && optional('operator', name);
if (staticToken != null) {
if (isOperator) {
@@ -3266,23 +3132,24 @@
// TODO(danrubel): Consider parsing the name before calling beginMethod
// rather than passing the name token into beginMethod.
- listener.beginMethod(externalToken, staticToken, covariantToken,
- varFinalOrConst, beforeName.next);
+ listener.beginMethod(
+ externalToken, staticToken, covariantToken, varFinalOrConst, name);
- typeInfo.parseType(beforeType, this);
+ Token token = typeInfo.parseType(beforeType, this);
+ assert(token.next == (getOrSet ?? name));
+ token = getOrSet ?? token;
- Token token;
if (isOperator) {
- token = parseOperatorName(beforeName);
+ token = parseOperatorName(token);
} else {
- token = ensureIdentifier(beforeName, IdentifierContext.methodDeclaration);
+ token = ensureIdentifier(token, IdentifierContext.methodDeclaration);
token = parseQualifiedRestOpt(
token, IdentifierContext.methodDeclarationContinuation);
}
bool isGetter = false;
if (getOrSet == null) {
- token = parseTypeVariablesOpt(token);
+ token = computeTypeParamOrArg(token, true).parseVariables(token, this);
} else {
isGetter = optional("get", getOrSet);
listener.handleNoTypeVariables(token.next);
@@ -3291,7 +3158,7 @@
MemberKind kind = staticToken != null
? MemberKind.StaticMethod
: MemberKind.NonStaticMethod;
- checkFormals(beforeName.next, isGetter, token.next, kind);
+ checkFormals(name, isGetter, token.next, kind);
Token beforeParam = token;
token = parseFormalParametersOpt(token, kind);
token = parseInitializersOpt(token);
@@ -3875,12 +3742,9 @@
/// ;
/// ```
Token parseLabel(Token token) {
- // TODO(brianwilkerson): Enable this assert.
- // `parseType` is allowing `void` to be a label.
-// assert(token.next.isIdentifier);
- assert(optional(':', token.next.next));
+ assert(token.next.isIdentifier);
token = ensureIdentifier(token, IdentifierContext.labelDeclaration).next;
- expect(':', token);
+ assert(optional(':', token));
listener.handleLabel(token);
return token;
}
@@ -5959,7 +5823,7 @@
Token covariantToken,
Token varFinalOrConst,
Token beforeType) {
- TypeInfo typeInfo = computeType(beforeType, true);
+ TypeInfo typeInfo = computeType(beforeType, true, true);
Token beforeName = typeInfo.skipType(beforeType);
Token next = beforeName.next;
@@ -5973,12 +5837,6 @@
}
assert((next.isOperator && next.endGroup == null) || optional('===', next));
- if (!next.isUserDefinableOperator) {
- beforeName = next;
- insertSyntheticIdentifier(beforeName, IdentifierContext.methodDeclaration,
- message: fasta.templateInvalidOperator.withArguments(next),
- messageOnToken: next);
- }
Token token = parseMethod(
beforeStart,
@@ -5989,7 +5847,7 @@
beforeType,
typeInfo,
null,
- beforeName);
+ beforeName.next);
listener.endMember();
return token;
}
@@ -6016,7 +5874,7 @@
return reportAndSkipEnumInClass(next);
} else if (identical(value, 'typedef')) {
return reportAndSkipTypedefInClass(next);
- } else if (next.isOperator) {
+ } else if (next.isOperator && next.endGroup == null) {
return parseInvalidOperatorDeclaration(beforeStart, externalToken,
staticToken, covariantToken, varFinalOrConst, beforeType);
}
@@ -6034,7 +5892,7 @@
beforeType,
typeInfo,
getOrSet,
- token);
+ token.next);
} else if (token == beforeStart) {
// TODO(danrubel): Provide a more specific error message for extra ';'.
reportRecoverableErrorWithToken(next, fasta.templateExpectedClassMember);
@@ -6044,8 +5902,16 @@
token = next;
}
} else {
- token = parseFields(beforeStart, externalToken, staticToken,
- covariantToken, varFinalOrConst, beforeType, typeInfo, token, false);
+ token = parseFields(
+ beforeStart,
+ externalToken,
+ staticToken,
+ covariantToken,
+ varFinalOrConst,
+ beforeType,
+ typeInfo,
+ token.next,
+ false);
}
listener.endMember();
@@ -6078,6 +5944,8 @@
if (token is ErrorToken) {
reportErrorToken(token, true);
} else {
+ // Find a non-synthetic token on which to report the error.
+ token = findNonSyntheticToken(token);
listener.handleRecoverableError(message, token, token);
}
}
@@ -6099,6 +5967,8 @@
if (token is ErrorToken) {
reportErrorToken(token, true);
} else {
+ // Find a non-synthetic token on which to report the error.
+ token = findNonSyntheticToken(token);
listener.handleRecoverableError(
template.withArguments(token), token, token);
}
diff --git a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
index b8ab28e..529c38e 100644
--- a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
+++ b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:front_end/src/fasta/util/link.dart';
-
import '../../scanner/token.dart'
show
BeginToken,
@@ -41,49 +39,6 @@
/// Initialize a newly created re-writer.
TokenStreamRewriter();
- /// For every `<` in [unbalancedLt] append a synthetic `>`.
- /// Return the first `<`.
- ///
- /// [unbalancedLt] is a collection of `<` without closing `>` in the reverse
- /// order from which they were encountered in the token stream.
- Token balanceLt(final Token beforeLt, Token end, Link<Token> unbalancedLt) {
- assert(optional('<', beforeLt.next));
- assert(unbalancedLt.isNotEmpty);
-
- BeginToken lt;
- while (unbalancedLt.isNotEmpty) {
- lt = unbalancedLt.head;
- unbalancedLt = unbalancedLt.tail;
- Token next = end.next;
- Token gt;
-
- if (optional('>', next)) {
- gt = next;
- } else if (optional('>>', next)) {
- gt = new SimpleToken(TokenType.GT, next.charOffset)
- ..setNext(new SimpleToken(TokenType.GT, next.charOffset + 1)
- ..setNext(next.next));
- } else if (optional('>=', next)) {
- gt = new SimpleToken(TokenType.GT, next.charOffset)
- ..setNext(new SimpleToken(TokenType.EQ, next.charOffset + 1)
- ..setNext(next.next));
- } else if (optional('>>=', next)) {
- gt = new SimpleToken(TokenType.GT, next.charOffset)
- ..setNext(new SimpleToken(TokenType.GT, next.charOffset + 1)
- ..setNext(new SimpleToken(TokenType.EQ, next.charOffset + 2)
- ..setNext(next.next)));
- } else {
- gt = new SyntheticToken(TokenType.GT, next.charOffset)..setNext(next);
- }
-
- lt.endGroup = gt;
- end.setNext(gt);
- end = gt;
- }
- assert(beforeLt.next == lt);
- return lt;
- }
-
/// Insert a synthetic identifier after [token] and return the new identifier.
Token insertSyntheticIdentifier(Token token) {
Token identifier = new SyntheticStringToken(
@@ -136,31 +91,48 @@
return replacementToken;
}
- /// Split a `>>` token into two separate `>` tokens and return the first `>`.
- /// This sets [start].endGroup to the second `>` and updates the token stream,
- /// but does not set the inner group's endGroup.
- Token splitGtGt(BeginToken start) {
- Token gtgt = start.endGroup;
- assert(gtgt != null);
- assert(optional('>>', gtgt));
+ /// Split a `>>` token into two separate `>` tokens, updates the token stream,
+ /// and returns the first `>`. If [start].endGroup is `>>` then sets
+ /// [start].endGroup to the second `>` but does not set the inner group's
+ /// endGroup, otherwise sets [start].endGroup to the first `>`.
+ Token splitEndGroup(BeginToken start, [Token end]) {
+ end ??= start.endGroup;
+ assert(end != null);
- // A no-op rewriter could simply return `>>` here.
-
- Token gt1 =
- new SimpleToken(TokenType.GT, gtgt.charOffset, gtgt.precedingComments);
- Token gt2 = gt1.setNext(new SimpleToken(TokenType.GT, gt1.charOffset + 1));
- gt2.setNext(gtgt.next);
+ Token gt;
+ if (optional('>>', end)) {
+ gt = new SimpleToken(TokenType.GT, end.charOffset, end.precedingComments)
+ ..setNext(new SimpleToken(TokenType.GT, end.charOffset + 1)
+ ..setNext(end.next));
+ } else if (optional('>=', end)) {
+ gt = new SimpleToken(TokenType.GT, end.charOffset, end.precedingComments)
+ ..setNext(new SimpleToken(TokenType.EQ, end.charOffset + 1)
+ ..setNext(end.next));
+ } else if (optional('>>=', end)) {
+ gt = new SimpleToken(TokenType.GT, end.charOffset, end.precedingComments)
+ ..setNext(new SimpleToken(TokenType.GT, end.charOffset + 1)
+ ..setNext(new SimpleToken(TokenType.EQ, end.charOffset + 2)
+ ..setNext(end.next)));
+ } else {
+ gt = new SyntheticToken(TokenType.GT, end.charOffset)..setNext(end);
+ }
Token token = start;
Token next = token.next;
- while (!identical(next, gtgt)) {
+ while (!identical(next, end)) {
token = next;
next = token.next;
}
- token.setNext(gt1);
+ token.setNext(gt);
- start.endGroup = gt2;
- return gt1;
+ if (start.endGroup != null) {
+ assert(optional('>>', start.endGroup));
+ start.endGroup = gt.next;
+ } else {
+ // Recovery
+ start.endGroup = gt;
+ }
+ return gt;
}
/// Given the [firstToken] in a chain of tokens to be inserted, return the
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart
index 47f587f..c94e6f4 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart
@@ -130,15 +130,19 @@
/// Called by the parser to obtain information about a possible type reference
/// that follows [token]. This does not modify the token stream.
///
+/// If [inDeclaration] is `true`, then this will more aggressively recover
+/// given unbalanced `<` `>` and invalid parameters or arguments.
+///
/// If this method is called by [computeTypeParamOrArg] and the outer group ends
/// with `>>`, then then [innerEndGroup] is set to either `>>` if the token
/// has not been split or the first `>` if the `>>` token has been split.
-TypeInfo computeType(final Token token, bool required, [Token innerEndGroup]) {
+TypeInfo computeType(final Token token, bool required,
+ [bool inDeclaration = false, Token innerEndGroup]) {
Token next = token.next;
if (!isValidTypeReference(next)) {
if (next.type.isBuiltIn) {
TypeParamOrArgInfo typeParamOrArg =
- computeTypeParamOrArg(next, innerEndGroup);
+ computeTypeParamOrArg(next, inDeclaration, innerEndGroup);
if (typeParamOrArg != noTypeParamOrArg) {
// Recovery: built-in `<` ... `>`
if (required || looksLikeName(typeParamOrArg.skip(next).next)) {
@@ -159,7 +163,7 @@
} else if (required && optional('.', next)) {
// Recovery: looks like prefixed type missing the prefix
return new ComplexTypeInfo(
- token, computeTypeParamOrArg(next, innerEndGroup))
+ token, computeTypeParamOrArg(next, inDeclaration, innerEndGroup))
.computePrefixedType(required);
}
return noType;
@@ -185,7 +189,7 @@
// We've seen an identifier.
TypeParamOrArgInfo typeParamOrArg =
- computeTypeParamOrArg(next, innerEndGroup);
+ computeTypeParamOrArg(next, inDeclaration, innerEndGroup);
if (typeParamOrArg != noTypeParamOrArg) {
if (typeParamOrArg == simpleTypeArgument1) {
// We've seen identifier `<` identifier `>`
@@ -215,7 +219,8 @@
next = next.next;
if (isValidTypeReference(next)) {
// We've seen identifier `.` identifier
- typeParamOrArg = computeTypeParamOrArg(next, innerEndGroup);
+ typeParamOrArg =
+ computeTypeParamOrArg(next, inDeclaration, innerEndGroup);
next = next.next;
if (typeParamOrArg == noTypeParamOrArg &&
!isGeneralizedFunctionType(next)) {
@@ -233,7 +238,8 @@
}
// identifier `.` non-identifier
if (required) {
- typeParamOrArg = computeTypeParamOrArg(token.next.next, innerEndGroup);
+ typeParamOrArg =
+ computeTypeParamOrArg(token.next.next, inDeclaration, innerEndGroup);
return new ComplexTypeInfo(token, typeParamOrArg)
.computePrefixedType(required);
}
@@ -255,47 +261,30 @@
}
/// Called by the parser to obtain information about a possible group of type
-/// parameters that follow [token] in a top level or class member declaration.
-/// It assumes that a leading `<` cannot be part of an expression, and thus
-/// tries to more aggressively recover given an unmatched '<'
-TypeParamOrArgInfo computeTypeParam(Token token) {
- if (!optional('<', token.next)) {
- return noTypeParamOrArg;
- }
- TypeParamOrArgInfo typeParam = computeTypeParamOrArgImpl(token);
- if (typeParam != noTypeParamOrArg) {
- return typeParam;
- }
-
- // Recovery
- if (token.next.endGroup == null) {
- // Attempt to find where the missing `>` should be inserted.
- return new ComplexTypeParamOrArgInfo(token).computeRecovery();
- } else {
- // The `<` `>` are balanced but there's still a problem.
- return noTypeParamOrArg;
- }
-}
-
-/// Called by the parser to obtain information about a possible group of type
/// parameters or type arguments that follow [token].
/// This does not modify the token stream.
///
+/// If [inDeclaration] is `true`, then this will more aggressively recover
+/// given unbalanced `<` `>` and invalid parameters or arguments.
+///
/// If this method is called by [computeType] and the outer group ends
/// with `>>`, then then [innerEndGroup] is set to either `>>` if the token
/// has not been split or the first `>` if the `>>` token has been split.
-TypeParamOrArgInfo computeTypeParamOrArg(Token token, [Token innerEndGroup]) {
- return optional('<', token.next)
- ? computeTypeParamOrArgImpl(token, innerEndGroup)
- : noTypeParamOrArg;
-}
-
-TypeParamOrArgInfo computeTypeParamOrArgImpl(Token token,
- [Token innerEndGroup]) {
+TypeParamOrArgInfo computeTypeParamOrArg(Token token,
+ [bool inDeclaration = false, Token innerEndGroup]) {
Token next = token.next;
- assert(optional('<', next));
+ if (!optional('<', next)) {
+ return noTypeParamOrArg;
+ }
Token endGroup = next.endGroup ?? innerEndGroup;
if (endGroup == null) {
+ if (inDeclaration) {
+ // Recovery
+ // Since the leading `<` cannot be part of an expression,
+ // try to more aggressively recover given an unbalanced '<'.
+ return new ComplexTypeParamOrArgInfo(token, inDeclaration)
+ .compute(innerEndGroup);
+ }
return noTypeParamOrArg;
}
Token identifier = next.next;
@@ -306,7 +295,8 @@
return simpleTypeArgument1;
}
// TODO(danrubel): Consider adding additional const for common situations.
- return new ComplexTypeParamOrArgInfo(token).compute(innerEndGroup);
+ return new ComplexTypeParamOrArgInfo(token, inDeclaration)
+ .compute(innerEndGroup);
}
/// Called by the parser to obtain information about a possible group of type
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index a18b898..461ebcc 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -4,7 +4,8 @@
library fasta.parser.type_info_impl;
-import '../../scanner/token.dart' show BeginToken, Token;
+import '../../scanner/token.dart'
+ show BeginToken, SyntheticToken, Token, TokenType;
import '../fasta_codes.dart' as fasta;
@@ -224,6 +225,19 @@
// `typedef` is probably a separate declaration.
(!optional('typedef', token) || !token.next.isIdentifier));
+/// When missing a comma, determine if the given token looks like it should
+/// be part of a collection of type parameters or arguments.
+bool looksLikeTypeParamOrArg(bool inDeclaration, Token token) {
+ if (inDeclaration && token.kind == IDENTIFIER_TOKEN) {
+ Token next = token.next;
+ if (next.kind == IDENTIFIER_TOKEN ||
+ isOneOf(next, const [',', '>', '>>'])) {
+ return true;
+ }
+ }
+ return false;
+}
+
Token skipTypeVariables(Token token) {
assert(optional('<', token));
Token endGroup = token.endGroup;
@@ -358,9 +372,9 @@
assert(identical(token, end) || optional('>', token));
// During recovery, [token] may be a synthetic that was inserted in the
- // middle of the type reference. In this situation, return [end] so that it
- // matches [skipType], and so that the next token to be parsed is correct.
- return token.isSynthetic ? end : token;
+ // middle of the type reference.
+ end = token;
+ return token;
}
@override
@@ -547,10 +561,12 @@
@override
Token skip(Token token) {
token = token.next;
+ assert(optional('<', token));
assert(token.endGroup != null ||
(optional('>', token.next.next) || optional('>>', token.next.next)));
- return token.endGroup ??
- (optional('>>', token.next.next) ? token.next : token.next.next);
+ return (optional('>>', token.endGroup ?? token.next.next)
+ ? token.next
+ : token.next.next);
}
}
@@ -558,17 +574,18 @@
/// The first token in the type var.
final BeginToken start;
+ /// If [inDeclaration] is `true`, then this will more aggressively recover
+ /// given unbalanced `<` `>` and invalid parameters or arguments.
+ final bool inDeclaration;
+
/// The last token in the group (typically `>`).
/// If a `>>` has not yet been split, then this field will be
/// `>>` for the outer group and the token before `>>` for the inner group.
Token end;
- /// A collection of `<` without closing `>` in the reverse order from which
- /// they were encountered in the token stream.
- Link<Token> unbalancedLt = const Link<Token>();
-
- ComplexTypeParamOrArgInfo(Token token)
+ ComplexTypeParamOrArgInfo(Token token, this.inDeclaration)
: assert(optional('<', token.next)),
+ assert(inDeclaration != null),
start = token.next;
/// Parse the tokens and return the receiver or [noTypeParamOrArg] if there
@@ -586,12 +603,12 @@
Token token;
Token next = start;
- do {
- TypeInfo typeInfo = computeType(next, true, innerEndGroup);
+ while (true) {
+ TypeInfo typeInfo = computeType(next, true, inDeclaration, innerEndGroup);
if (typeInfo == noType) {
while (typeInfo == noType && optional('@', next.next)) {
next = skipMetadata(next);
- typeInfo = computeType(next, true, innerEndGroup);
+ typeInfo = computeType(next, true, inDeclaration, innerEndGroup);
}
if (typeInfo == noType && !optional(',', next.next)) {
token = next;
@@ -604,10 +621,17 @@
token = typeInfo.skipType(next);
next = token.next;
if (optional('extends', next) || optional('super', next)) {
- token = computeType(next, true, innerEndGroup).skipType(next);
+ token = computeType(next, true, inDeclaration, innerEndGroup)
+ .skipType(next);
next = token.next;
}
- } while (optional(',', next));
+ if (!optional(',', next)) {
+ if (!looksLikeTypeParamOrArg(inDeclaration, next)) {
+ break;
+ }
+ // Recovery: Missing comma. Continue looping
+ }
+ }
if (next == start.endGroup) {
end = next;
@@ -616,96 +640,62 @@
assert(optional('>', endGroup) || optional('>>', endGroup));
// If `>>`, then the end or last consumed token is the token before `>>`.
end = optional('>>', next) ? token : next;
+ } else if (inDeclaration && start.endGroup == null) {
+ // Recovery: Unbalanced `<`
+ end = token;
} else {
return noTypeParamOrArg;
}
return this;
}
- /// Parse the tokens and return the receiver or [noTypeParamOrArg] if there
- /// are no type parameters or arguments. This does not modify the token
- /// stream.
- ///
- /// This is called when parsing type parameters in a top level
- /// or class member declaration. It assumes that a leading `<` cannot be part
- /// of an expression, and thus tries to more aggressively recover
- /// given an unmatched '<'.
- ///
- TypeParamOrArgInfo computeRecovery() {
- assert(start.endGroup == null);
- unbalancedLt = unbalancedLt.prepend(start);
- Token token = start;
- Token next = token.next;
- while (!next.isEof) {
- if (optional('Function', next)) {
- next = next.next;
- if (optional('<', next)) {
- next = skipTypeVariables(next);
- if (next == null) {
- break;
- }
- next = next.next;
- }
- if (optional('(', next)) {
- next = next.endGroup;
- } else {
- break;
- }
- } else if (optional('<', next)) {
- Token endGroup = skipTypeVariables(next);
- if (endGroup != null) {
- next = endGroup;
- } else {
- unbalancedLt = unbalancedLt.prepend(next);
- }
- } else if (!isValidTypeReference(next) &&
- !isOneOf(next, const ['.', ',', 'extends', 'super'])) {
- break;
- }
- token = next;
- next = token.next;
- }
-
- end = token;
- return this;
- }
-
@override
Token parseArguments(Token token, Parser parser) {
- Token begin = balanceLt(token, parser);
- Token next = begin;
- Token innerEndGroup = processBeginGroup(begin, parser);
- parser.listener.beginTypeArguments(begin);
+ Token next = start;
+ Token innerEndGroup = processBeginGroup(start, parser);
+ parser.listener.beginTypeArguments(start);
int count = 0;
- do {
- TypeInfo typeInfo = computeType(next, true, innerEndGroup);
+ while (true) {
+ TypeInfo typeInfo = computeType(next, true, inDeclaration, innerEndGroup);
if (typeInfo == noType) {
// Recovery
while (typeInfo == noType && optional('@', next.next)) {
parser.reportRecoverableErrorWithToken(
next.next, fasta.templateUnexpectedToken);
next = skipMetadata(next);
- typeInfo = computeType(next, true, innerEndGroup);
+ typeInfo = computeType(next, true, inDeclaration, innerEndGroup);
}
// Fall through to process type (if any) and consume `,`
}
token = typeInfo.ensureTypeOrVoid(next, parser);
next = token.next;
++count;
- } while (optional(',', next));
- end = processEndGroup(token, begin, parser);
- parser.listener.endTypeArguments(count, begin, end);
+ if (!optional(',', next)) {
+ if (!looksLikeTypeParamOrArg(inDeclaration, next)) {
+ break;
+ }
+
+ // Recovery: missing comma
+ parser.reportRecoverableError(
+ next, fasta.templateExpectedButGot.withArguments(','));
+ next = parser.rewriter
+ .insertTokenAfter(
+ token, new SyntheticToken(TokenType.COMMA, next.charOffset))
+ .next;
+ }
+ }
+ end = processEndGroup(token, start, parser);
+ parser.listener.endTypeArguments(count, start, end);
return end;
}
@override
Token parseVariables(Token token, Parser parser) {
- Token begin = balanceLt(token, parser);
- Token next = begin;
- Token innerEndGroup = processBeginGroup(begin, parser);
- parser.listener.beginTypeVariables(begin);
+ Token next = start;
+ Token innerEndGroup = processBeginGroup(start, parser);
+ parser.listener.beginTypeVariables(start);
int count = 0;
- do {
+ while (true) {
parser.listener.beginTypeVariable(next.next);
token = parser.parseMetadataStar(next);
token = parser.ensureIdentifier(
@@ -714,7 +704,7 @@
next = token.next;
if (optional('extends', next) || optional('super', next)) {
extendsOrSuper = next;
- token = computeType(next, true, innerEndGroup)
+ token = computeType(next, true, inDeclaration, innerEndGroup)
.ensureTypeOrVoid(next, parser);
next = token.next;
} else {
@@ -722,72 +712,67 @@
}
parser.listener.endTypeVariable(next, extendsOrSuper);
++count;
- } while (optional(',', next));
- end = processEndGroup(token, begin, parser);
- parser.listener.endTypeVariables(count, begin, end);
+ if (!optional(',', next)) {
+ if (!looksLikeTypeParamOrArg(inDeclaration, next)) {
+ break;
+ }
+
+ // Recovery: missing comma
+ parser.reportRecoverableError(
+ next, fasta.templateExpectedButGot.withArguments(','));
+ next = parser.rewriter
+ .insertTokenAfter(
+ token, new SyntheticToken(TokenType.COMMA, next.charOffset))
+ .next;
+ }
+ }
+ end = processEndGroup(token, start, parser);
+ parser.listener.endTypeVariables(count, start, end);
return end;
}
@override
Token skip(Token token) => end;
-
- /// For every unbalanced `<` append a synthetic `>`. Return the first `<`
- Token balanceLt(Token token, Parser parser) {
- assert(identical(start, token.next));
- if (unbalancedLt.isEmpty) {
- return start;
- }
- Token begin = parser.rewriter.balanceLt(token, end, unbalancedLt);
- assert(begin.endGroup != null);
- if (begin.endGroup.isSynthetic) {
- parser.reportRecoverableError(
- begin.endGroup.next, fasta.templateExpectedButGot.withArguments('>'));
- }
- return begin;
- }
}
Token processBeginGroup(BeginToken start, Parser parser) {
- Token innerEndGroup;
if (start.endGroup != null && optional('>>', start.endGroup)) {
- innerEndGroup = parser.rewriter.splitGtGt(start);
+ return parser.rewriter.splitEndGroup(start);
}
- return innerEndGroup;
+ return null;
}
Token processEndGroup(Token token, BeginToken start, Parser parser) {
Token next = token.next;
if (next == start.endGroup) {
return next;
- } else if (optional('>', next)) {
+ } else if (optional('>', next) && !next.isSynthetic) {
// When `>>` is split, the inner group's endGroup updated here.
assert(start.endGroup == null);
start.endGroup = next;
return next;
- } else if (optional('>>', next)) {
- // In this case, the last consumed token is the token before `>>`.
- return token;
- } else {
- // Recovery
- parser.reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
- if (start.endGroup != null) {
- return start.endGroup;
- }
- while (true) {
- if (optional('>', next)) {
- start.endGroup = next;
- return next;
- }
- if (optional('>>', next)) {
- // In this case, the last consumed token is the token before `>>`.
- return token;
- }
- if (next.isEof) {
- // Sanity check.
- return next;
- }
- token = next;
- next = token.next;
- }
}
+
+ // Recovery
+ if (start.endGroup != null) {
+ // Extraneous tokens between `<` and `>`.
+ parser.reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
+ return start.endGroup;
+ } else if (isOneOf(next, const ['>>', '>=', '>>='])) {
+ // Found single unbalanced `<`.
+ return parser.rewriter.splitEndGroup(start, next);
+ }
+ // Ensure that `>` is inserted after any newly inserted synthetic tokens.
+ while (next.isSynthetic && !next.isEof) {
+ token = next;
+ next = token.next;
+ }
+ // Unbalanced `<` `>`
+ parser.reportRecoverableError(
+ next, fasta.templateExpectedButGot.withArguments('>'));
+ start.endGroup = parser.rewriter
+ .insertTokenAfter(
+ token, new SyntheticToken(TokenType.GT, next.charOffset))
+ .next;
+ return start.endGroup;
}
diff --git a/pkg/front_end/lib/src/fasta/parser/util.dart b/pkg/front_end/lib/src/fasta/parser/util.dart
index bbbd361..96495e7 100644
--- a/pkg/front_end/lib/src/fasta/parser/util.dart
+++ b/pkg/front_end/lib/src/fasta/parser/util.dart
@@ -33,6 +33,16 @@
return token;
}
+/// Return [token] if it is non-synthetic,
+/// otherwise find the next non-synthetic token.
+/// This may return EOF if there are no more non-synthetic tokens in the stream.
+Token findNonSyntheticToken(Token token) {
+ while (token.isSynthetic && !token.isEof) {
+ token = token.next;
+ }
+ return token;
+}
+
/// A null-aware alternative to `token.offset`. If [token] is `null`, returns
/// `TreeNode.noOffset`.
int offsetForToken(Token token) {
@@ -89,7 +99,7 @@
next = token.next;
}
}
- if (optional('(', next)) {
+ if (optional('(', next) && !next.endGroup.isSynthetic) {
token = next.endGroup;
next = token.next;
}
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index b4639f1..58f6ebc 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -9,6 +9,7 @@
AsyncMarker,
Class,
Expression,
+ Field,
InterfaceType,
Library,
LibraryDependency,
@@ -33,8 +34,7 @@
import '../kernel/kernel_body_builder.dart' show KernelBodyBuilder;
-import '../parser.dart'
- show Assert, IdentifierContext, MemberKind, Parser, optional;
+import '../parser.dart' show Assert, MemberKind, Parser, optional;
import '../problems.dart' show internalProblem, unexpected;
@@ -90,7 +90,9 @@
@override
void endMetadataStar(int count) {
debugEvent("MetadataStar");
- push(popList(count)?.first ?? NullValue.Metadata);
+ push(popList(count, new List<Token>.filled(count, null, growable: true))
+ ?.first ??
+ NullValue.Metadata);
}
@override
@@ -272,15 +274,6 @@
}
@override
- void handleIdentifier(Token token, IdentifierContext context) {
- if (context == IdentifierContext.enumValueDeclaration) {
- // Discard the metadata.
- pop();
- }
- super.handleIdentifier(token, context);
- }
-
- @override
void handleQualified(Token period) {
debugEvent("handleQualified");
String suffix = pop();
@@ -574,7 +567,8 @@
}
void buildFields(int count, Token token, bool isTopLevel) {
- List<String> names = popList(count);
+ List<String> names =
+ popList(count, new List<String>.filled(count, null, growable: true));
Builder builder = lookupBuilder(token, null, names.first);
Token metadata = pop();
// TODO(paulberry): don't re-parse the field if we've already parsed it
@@ -640,11 +634,13 @@
void endEnum(Token enumKeyword, Token leftBrace, int count) {
debugEvent("Enum");
- discard(count); // values
+ List metadataAndValues = new List.filled(count * 2, null, growable: true);
+ popList(count * 2, metadataAndValues);
+
String name = pop();
Token metadata = pop();
- Builder enumBuilder = lookupBuilder(enumKeyword, null, name);
+ ClassBuilder enumBuilder = lookupBuilder(enumKeyword, null, name);
Class target = enumBuilder.target;
var metadataConstants = parseMetadata(enumBuilder, metadata);
if (metadataConstants != null) {
@@ -652,6 +648,17 @@
target.addAnnotation(metadataConstant);
}
}
+ for (int i = 0; i < metadataAndValues.length; i += 2) {
+ Token metadata = metadataAndValues[i];
+ String valueName = metadataAndValues[i + 1];
+ Builder builder = enumBuilder.scope.local[valueName];
+ if (metadata != null) {
+ Field field = builder.target;
+ for (var annotation in parseMetadata(builder, metadata)) {
+ field.addAnnotation(annotation);
+ }
+ }
+ }
checkEmpty(enumKeyword.charOffset);
}
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 8244fca..64f66b9 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -10,6 +10,8 @@
import '../builder/builder.dart';
+import '../builder/metadata_builder.dart' show ExpressionMetadataBuilder;
+
import '../combinator.dart' show Combinator;
import '../fasta_codes.dart'
@@ -66,6 +68,13 @@
import '../configuration.dart' show Configuration;
+import '../kernel/kernel_builder.dart'
+ show
+ KernelFormalParameterBuilder,
+ KernelNamedTypeBuilder,
+ KernelTypeBuilder,
+ KernelTypeVariableBuilder;
+
enum MethodBody {
Abstract,
Regular,
@@ -129,7 +138,11 @@
@override
void endMetadataStar(int count) {
debugEvent("MetadataStar");
- push(popList(count) ?? NullValue.Metadata);
+ push(popList(
+ count,
+ new List<ExpressionMetadataBuilder<TypeBuilder>>.filled(count, null,
+ growable: true)) ??
+ NullValue.Metadata);
}
@override
@@ -155,7 +168,9 @@
@override
void endCombinators(int count) {
debugEvent("Combinators");
- push(popList(count) ?? NullValue.Combinators);
+ push(popList(
+ count, new List<Combinator>.filled(count, null, growable: true)) ??
+ NullValue.Combinators);
}
@override
@@ -202,7 +217,9 @@
@override
void endConditionalUris(int count) {
debugEvent("EndConditionalUris");
- push(popList(count) ?? NullValue.ConditionalUris);
+ push(popList(count,
+ new List<Configuration>.filled(count, null, growable: true)) ??
+ NullValue.ConditionalUris);
}
@override
@@ -259,8 +276,6 @@
@override
void handleIdentifier(Token token, IdentifierContext context) {
if (context == IdentifierContext.enumValueDeclaration) {
- // Discard the metadata.
- pop();
super.handleIdentifier(token, context);
push(token.charOffset);
String documentationComment = getDocumentationComment(token);
@@ -388,7 +403,11 @@
@override
void handleClassImplements(Token implementsKeyword, int interfacesCount) {
debugEvent("handleClassImplements");
- push(popList(interfacesCount) ?? NullValue.TypeBuilderList);
+ push(popList(
+ interfacesCount,
+ new List<KernelNamedTypeBuilder>.filled(interfacesCount, null,
+ growable: true)) ??
+ NullValue.TypeBuilderList);
}
@override
@@ -730,7 +749,9 @@
@override
void endTypeArguments(int count, Token beginToken, Token endToken) {
debugEvent("TypeArguments");
- push(popList(count) ?? NullValue.TypeArguments);
+ push(popList(count,
+ new List<KernelTypeBuilder>.filled(count, null, growable: true)) ??
+ NullValue.TypeArguments);
}
@override
@@ -750,13 +771,21 @@
@override
void endTypeList(int count) {
debugEvent("TypeList");
- push(popList(count) ?? NullValue.TypeList);
+ push(popList(
+ count,
+ new List<KernelNamedTypeBuilder>.filled(count, null,
+ growable: true)) ??
+ NullValue.TypeList);
}
@override
void endTypeVariables(int count, Token beginToken, Token endToken) {
debugEvent("TypeVariables");
- push(popList(count) ?? NullValue.TypeVariables);
+ push(popList(
+ count,
+ new List<KernelTypeVariableBuilder>.filled(count, null,
+ growable: true)) ??
+ NullValue.TypeVariables);
}
@override
@@ -819,7 +848,9 @@
// 0. It might be simpler if the parser didn't call this method in that
// case, however, then [beginOptionalFormalParameters] wouldn't always be
// matched by this method.
- List parameters = popList(count) ?? [];
+ var parameters = new List<KernelFormalParameterBuilder>.filled(count, null,
+ growable: true);
+ popList(count, parameters);
for (FormalParameterBuilder parameter in parameters) {
parameter.kind = kind;
}
@@ -910,7 +941,8 @@
@override
void endEnum(Token enumKeyword, Token leftBrace, int count) {
String documentationComment = getDocumentationComment(enumKeyword);
- List constantNamesAndOffsets = popList(count * 3);
+ List<Object> constantNamesAndOffsets = popList(
+ count * 4, new List<Object>.filled(count * 4, null, growable: true));
int charOffset = pop();
String name = pop();
List<MetadataBuilder> metadata = pop();
@@ -1007,7 +1039,8 @@
void endTopLevelFields(Token staticToken, Token covariantToken,
Token varFinalOrConst, int count, Token beginToken, Token endToken) {
debugEvent("endTopLevelFields");
- List fieldsInfo = popList(count * 4);
+ List<Object> fieldsInfo = popList(
+ count * 4, new List<Object>.filled(count * 4, null, growable: true));
TypeBuilder type = pop();
int modifiers = (staticToken != null ? staticMask : 0) |
(covariantToken != null ? covariantMask : 0) |
@@ -1023,7 +1056,8 @@
void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
int count, Token beginToken, Token endToken) {
debugEvent("Fields");
- List fieldsInfo = popList(count * 4);
+ List<Object> fieldsInfo = popList(
+ count * 4, new List<Object>.filled(count * 4, null, growable: true));
TypeBuilder type = pop();
int modifiers = (staticToken != null ? staticMask : 0) |
(covariantToken != null ? covariantMask : 0) |
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 5b02dc9..7507777 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -664,7 +664,7 @@
TypeEnvironment env = new TypeEnvironment(coreTypes, hierarchy,
strongMode: target.strongMode);
- if (cls.isSyntheticMixinImplementation) return;
+ if (cls.isAnonymousMixin) return;
if (env.isSubtypeOf(a.asInterfaceType, b.asInterfaceType)) return;
addProblem(
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
index ef9eda1..dd5fc5d 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
@@ -121,7 +121,7 @@
return value == null ? null : pop();
}
- List popList(int n, [List list]) {
+ List popList(int n, List list) {
if (n == 0) return null;
return stack.popList(n, list);
}
@@ -314,7 +314,9 @@
@override
void handleStringJuxtaposition(int literalCount) {
debugEvent("StringJuxtaposition");
- push(popList(literalCount).join(""));
+ push(popList(literalCount,
+ new List<Expression>.filled(literalCount, null, growable: true))
+ .join(""));
}
@override
@@ -396,16 +398,15 @@
final table = array;
final length = arrayLength;
- final tailList = list ?? new List.filled(count, null, growable: true);
final startIndex = length - count;
for (int i = 0; i < count; i++) {
final value = table[startIndex + i];
- tailList[i] = value is NullValue ? null : value;
+ list[i] = value is NullValue ? null : value;
table[startIndex + i] = null;
}
arrayLength -= count;
- return tailList;
+ return list;
}
List get values {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 58c6532..361dd77 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -1634,7 +1634,7 @@
Supertype baseType, Supertype mixinSupertype) {
if (mixinSupertype.typeArguments.isEmpty) {
// The supertype constraint isn't generic; it doesn't constrain anything.
- } else if (mixinSupertype.classNode.isSyntheticMixinImplementation) {
+ } else if (mixinSupertype.classNode.isAnonymousMixin) {
// We had a mixin M<X0, ..., Xn> with a superclass constraint of the form
// S0 with M0 where S0 and M0 each possibly have type arguments. That has
// been compiled a named mixin application class of the form
diff --git a/pkg/front_end/lib/src/fasta/util/link.dart b/pkg/front_end/lib/src/fasta/util/link.dart
index 86c1c70..4debdc7 100644
--- a/pkg/front_end/lib/src/fasta/util/link.dart
+++ b/pkg/front_end/lib/src/fasta/util/link.dart
@@ -61,7 +61,7 @@
bool get isEmpty => true;
bool get isNotEmpty => false;
- Link<T> reverse() => this;
+ Link<T> reverse(Link<T> tail) => this;
Link<T> reversePrependAll(Link<T> from) {
if (from.isEmpty) return this;
@@ -121,8 +121,6 @@
return true;
}
- Link copyWithout(e) => this;
-
//
// Unsupported Iterable<T> methods.
//
@@ -159,7 +157,7 @@
/// Prepends all elements added to the builder to [tail]. The resulting list
/// is returned and the builder is cleared.
- Link<T> toLink([Link<T> tail = const Link()]);
+ Link<T> toLink(Link<T> tail);
/// Creates a new fixed length containing all added elements. The
/// resulting list is returned and the builder is cleared.
diff --git a/pkg/front_end/lib/src/fasta/util/link_implementation.dart b/pkg/front_end/lib/src/fasta/util/link_implementation.dart
index cc74c01..9849ecb 100644
--- a/pkg/front_end/lib/src/fasta/util/link_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/util/link_implementation.dart
@@ -64,8 +64,7 @@
final T head;
Link<T> tail;
- LinkEntry(this.head, [Link<T> tail])
- : this.tail = ((tail == null) ? const Link() : tail);
+ LinkEntry(this.head, [Link<T> tail]) : tail = tail ?? const Link<Null>();
Link<T> prepend(T element) {
// TODO(ahe): Use new Link<T>, but this cost 8% performance on VM.
@@ -89,8 +88,9 @@
return buffer.toString();
}
- Link<T> reverse() {
- Link<T> result = const Link();
+ @override
+ Link<T> reverse(Link<T> tail) {
+ Link<T> result = tail;
for (Link<T> link = this; link.isNotEmpty; link = link.tail) {
result = result.prepend(link.head);
}
@@ -147,17 +147,6 @@
}
return length;
}
-
- Link copyWithout(e) {
- LinkBuilder copy = new LinkBuilder();
- Link link = this;
- for (; link.isNotEmpty; link = link.tail) {
- if (link.head != e) {
- copy.addLast(link.head);
- }
- }
- return copy.toLink(link);
- }
}
class LinkBuilderImplementation<T> implements LinkBuilder<T> {
@@ -167,7 +156,8 @@
LinkBuilderImplementation();
- Link<T> toLink([Link<T> tail = const Link()]) {
+ @override
+ Link<T> toLink(Link<T> tail) {
if (head == null) return tail;
lastLink.tail = tail;
Link<T> link = head;
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 1e8e061..440aab5 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1940,12 +1940,6 @@
ExpressionNotMetadata:
template: "This can't be used as metadata; metadata should be a reference to a compile-time constant variable, or a call to a constant constructor."
-AnnotationOnEnumConstant:
- template: "Enum constants can't have annotations."
- tip: "Try removing the annotation."
- analyzerCode: ANNOTATION_ON_ENUM_CONSTANT
- dart2jsCode: "*fatal*"
-
ExpectedAnInitializer:
template: "Expected an initializer."
analyzerCode: MISSING_INITIALIZER
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 90c0247..64cdab5 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,7 +1,7 @@
name: front_end
# Currently, front_end API is not stable and users should not
# depend on semver semantics when depending on this package.
-version: 0.1.0
+version: 0.1.1-alpha.0
author: Dart Team <misc@dartlang.org>
description: Front end for compilation of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/front_end
@@ -11,7 +11,7 @@
charcode: '^1.1.1'
convert: '^2.0.1'
crypto: '^2.0.2'
- kernel: 0.3.0
+ kernel: 0.3.1-alpha.0
meta: '^1.1.1'
package_config: '^1.0.1'
path: '^1.3.9'
diff --git a/pkg/front_end/test/fasta/expression_test.dart b/pkg/front_end/test/fasta/expression_test.dart
index ee97b9d..ee56f71 100644
--- a/pkg/front_end/test/fasta/expression_test.dart
+++ b/pkg/front_end/test/fasta/expression_test.dart
@@ -370,7 +370,7 @@
};
final ProcessedOptions options =
- new ProcessedOptions(optionBuilder, false, [entryPoint]);
+ new ProcessedOptions(optionBuilder, [entryPoint]);
final ExternalStateSnapshot snapshot =
new ExternalStateSnapshot(await options.loadSdkSummary(null));
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 53b70fe..50c8ffc 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -53,27 +53,27 @@
import 'package:front_end/src/fasta/kernel/kernel_expression_generator.dart'
show
- DeferredAccessGenerator,
DelayedAssignment,
DelayedPostfixIncrement,
IncompleteErrorGenerator,
IncompletePropertyAccessGenerator,
+ KernelDeferredAccessGenerator,
KernelIndexedAccessGenerator,
+ KernelLargeIntAccessGenerator,
+ KernelLoadLibraryGenerator,
KernelNullAwarePropertyAccessGenerator,
KernelPropertyAccessGenerator,
+ KernelReadOnlyAccessGenerator,
+ KernelStaticAccessGenerator,
+ KernelSuperIndexedAccessGenerator,
KernelSuperPropertyAccessGenerator,
KernelThisIndexedAccessGenerator,
KernelThisPropertyAccessGenerator,
+ KernelTypeUseGenerator,
KernelVariableUseGenerator,
- LargeIntAccessGenerator,
- LoadLibraryGenerator,
ParenthesizedExpressionGenerator,
- ReadOnlyAccessGenerator,
SendAccessGenerator,
- StaticAccessGenerator,
- SuperIndexedAccessGenerator,
ThisAccessGenerator,
- TypeDeclarationAccessGenerator,
UnresolvedNameGenerator;
import 'package:front_end/src/fasta/scanner.dart' show Token, scanString;
@@ -186,15 +186,16 @@
check(
"SuperIndexedAccessGenerator(offset: 4, index: index,"
" getter: $uri::myGetter, setter: $uri::mySetter, indexVariable: null)",
- new SuperIndexedAccessGenerator(helper, token, index, getter, setter));
+ new KernelSuperIndexedAccessGenerator(
+ helper, token, index, getter, setter));
check(
"StaticAccessGenerator(offset: 4, readTarget: $uri::myGetter,"
" writeTarget: $uri::mySetter)",
- new StaticAccessGenerator(helper, token, getter, setter));
+ new KernelStaticAccessGenerator(helper, token, getter, setter));
check(
"LoadLibraryGenerator(offset: 4,"
" builder: Instance of 'LoadLibraryBuilder')",
- new LoadLibraryGenerator(helper, token, loadLibraryBuilder));
+ new KernelLoadLibraryGenerator(helper, token, loadLibraryBuilder));
check(
"ThisAccessGenerator(offset: 4, isInitializer: false, isSuper: false)",
new ThisAccessGenerator(helper, token, false));
@@ -205,25 +206,26 @@
check("IncompletePropertyAccessGenerator(offset: 4, name: bar)",
new IncompletePropertyAccessGenerator(helper, token, name));
check(
- "DeferredAccessGenerator(offset: 4, "
- "builder: Instance of 'PrefixBuilder',"
+ "DeferredAccessGenerator(offset: 4,"
+ " builder: Instance of 'PrefixBuilder',"
" generator: ThisAccessGenerator(offset: 4, isInitializer: false,"
" isSuper: false))",
- new DeferredAccessGenerator(helper, token, prefixBuilder, generator));
+ new KernelDeferredAccessGenerator(
+ helper, token, prefixBuilder, generator));
check(
"ReadOnlyAccessGenerator(offset: 4, expression: expression,"
" plainNameForRead: foo, value: null)",
- new ReadOnlyAccessGenerator(helper, token, expression, "foo"));
+ new KernelReadOnlyAccessGenerator(helper, token, expression, "foo"));
check("LargeIntAccessGenerator(offset: 4, lexeme: myToken)",
- new LargeIntAccessGenerator(helper, token));
+ new KernelLargeIntAccessGenerator(helper, token));
check(
"ParenthesizedExpressionGenerator(offset: 4, expression: expression,"
" plainNameForRead: null, value: null)",
new ParenthesizedExpressionGenerator(helper, token, expression));
check(
- "TypeDeclarationAccessGenerator(offset: 4, expression: T,"
+ "TypeUseGenerator(offset: 4, expression: T,"
" plainNameForRead: foo, value: null)",
- new TypeDeclarationAccessGenerator(
+ new KernelTypeUseGenerator(
helper, token, prefixBuilder, -1, declaration, "foo"));
check("UnresolvedNameGenerator(offset: 4, name: bar)",
new UnresolvedNameGenerator(helper, token, name));
diff --git a/pkg/front_end/test/fasta/incremental_hello_test.dart b/pkg/front_end/test/fasta/incremental_hello_test.dart
index f096675..40fb9d3 100644
--- a/pkg/front_end/test/fasta/incremental_hello_test.dart
+++ b/pkg/front_end/test/fasta/incremental_hello_test.dart
@@ -50,7 +50,7 @@
final Uri helloDart = Uri.base.resolve("pkg/front_end/testcases/hello.dart");
final ProcessedOptions options =
- new ProcessedOptions(optionBuilder, false, [helloDart]);
+ new ProcessedOptions(optionBuilder, [helloDart]);
IncrementalCompiler compiler =
new IncrementalCompiler(new CompilerContext(options));
diff --git a/pkg/front_end/test/fasta/incremental_test.dart b/pkg/front_end/test/fasta/incremental_test.dart
index 3d2fb2a..401d89b 100644
--- a/pkg/front_end/test/fasta/incremental_test.dart
+++ b/pkg/front_end/test/fasta/incremental_test.dart
@@ -227,7 +227,7 @@
};
final ProcessedOptions options =
- new ProcessedOptions(optionBuilder, false, [entryPoint]);
+ new ProcessedOptions(optionBuilder, [entryPoint]);
final ExternalStateSnapshot snapshot =
new ExternalStateSnapshot(await options.loadSdkSummary(null));
diff --git a/pkg/front_end/test/fasta/link_test.dart b/pkg/front_end/test/fasta/link_test.dart
new file mode 100644
index 0000000..5fe7b42
--- /dev/null
+++ b/pkg/front_end/test/fasta/link_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:front_end/src/fasta/util/link.dart' show Link, LinkBuilder;
+
+import 'package:expect/expect.dart' show Expect;
+
+main() {
+ Link<String> strings = const Link<String>().prepend("B").prepend("A");
+ Expect.stringEquals("[ A, B ]", "${strings}");
+ Expect.stringEquals("[ B, A ]", "${strings.reverse(const Link<String>())}");
+
+ strings = (new LinkBuilder<String>()..addLast("A")..addLast("B"))
+ .toLink(const Link<String>());
+
+ Expect.stringEquals("[ A, B ]", "${strings}");
+ Expect.stringEquals("[ B, A ]", "${strings.reverse(const Link<String>())}");
+
+ strings = new LinkBuilder<String>()
+ .toLink(const Link<String>())
+ .prepend("B")
+ .prepend("A");
+
+ Expect.stringEquals("[ A, B ]", "${strings}");
+ Expect.stringEquals("[ B, A ]", "${strings.reverse(const Link<String>())}");
+
+ strings = const Link<String>()
+ .reverse(const Link<String>())
+ .prepend("B")
+ .prepend("A");
+ Expect.stringEquals("[ A, B ]", "${strings}");
+ Expect.stringEquals("[ B, A ]", "${strings.reverse(const Link<String>())}");
+
+ strings = (new LinkBuilder<String>()..addLast("A")..addLast("B"))
+ .toLink(const Link<String>());
+
+ Expect.stringEquals("[ A, B ]", "${strings}");
+ Expect.stringEquals("[ B, A ]", "${strings.reverse(const Link<String>())}");
+
+ Link<int> ints =
+ const Link<int>().prepend(1).reverse(const Link<int>()).tail.prepend(1);
+ Expect.stringEquals("[ 1 ]", "${ints}");
+}
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 4790175..d2d53a5 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -4,7 +4,7 @@
import 'package:front_end/src/fasta/messages.dart';
import 'package:front_end/src/fasta/parser.dart';
-import 'package:front_end/src/fasta/parser/token_stream_rewriter.dart';
+import 'package:front_end/src/fasta/parser/type_continuation.dart';
import 'package:front_end/src/fasta/parser/type_info.dart';
import 'package:front_end/src/fasta/parser/type_info_impl.dart';
import 'package:front_end/src/fasta/scanner.dart';
@@ -229,47 +229,6 @@
simpleTypeWith1Argument.parseType(start, new Parser(listener)));
}
- void test_simpleTypeArgumentsInfo2() {
- final Token start = scanString('before S<C<T>> ;').tokens.next.next;
- expect(start.lexeme, '<');
- final Token expectedEnd = start.next.next.next;
- expect(expectedEnd.next.lexeme, '>>');
-
- expect(simpleTypeWith1Argument.skipType(start), expectedEnd);
- expect(simpleTypeWith1Argument.couldBeExpression, isFalse);
-
- TypeInfoListener listener;
- assertResult(Token actualEnd) {
- expect(actualEnd, expectedEnd);
- expect(listener.calls, [
- 'handleIdentifier C typeReference',
- 'beginTypeArguments <',
- 'handleIdentifier T typeReference',
- 'handleNoTypeArguments >>',
- 'handleType T >>',
- 'endTypeArguments 1 < T',
- 'handleType C >>',
- ]);
- expect(listener.errors, isNull);
- }
-
- listener = new TypeInfoListener();
- assertResult(
- simpleTypeWith1Argument.ensureTypeNotVoid(start, new Parser(listener)));
-
- listener = new TypeInfoListener();
- assertResult(
- simpleTypeWith1Argument.ensureTypeOrVoid(start, new Parser(listener)));
-
- listener = new TypeInfoListener();
- assertResult(
- simpleTypeWith1Argument.parseTypeNotVoid(start, new Parser(listener)));
-
- listener = new TypeInfoListener();
- assertResult(
- simpleTypeWith1Argument.parseType(start, new Parser(listener)));
- }
-
void test_computeType_basic() {
expectInfo(noType, '');
expectInfo(noType, ';');
@@ -564,23 +523,25 @@
// TOOD(danrubel): dynamic, do, other keywords, malformed, recovery
// <T>
- // TODO(danrubel): Improve missing comma recovery
expectTypeParamOrArg(noTypeParamOrArg, 'G<int double> g');
- // expectComplexInfo('G<int double> g',
- // required: true,
- // tokenAfter: 'g',
- // expectedCalls: [
- // 'handleIdentifier G typeReference',
- // 'beginTypeArguments <',
- // 'handleIdentifier int typeReference',
- // 'handleNoTypeArguments double',
- // 'handleType int double',
- // 'endTypeArguments 1 < >',
- // 'handleType G g',
- // ],
- // expectedErrors: [
- // error(codeExpectedToken, 6, 6)
- // ]);
+ expectComplexInfo('G<int double> g',
+ inDeclaration: true,
+ expectedAfter: 'g',
+ expectedCalls: [
+ 'handleIdentifier G typeReference',
+ 'beginTypeArguments <',
+ 'handleIdentifier int typeReference',
+ 'handleNoTypeArguments double' /* was , */,
+ 'handleType int double' /* was , */,
+ 'handleIdentifier double typeReference',
+ 'handleNoTypeArguments >',
+ 'handleType double >',
+ 'endTypeArguments 2 < >',
+ 'handleType G g',
+ ],
+ expectedErrors: [
+ error(codeExpectedButGot, 6, 6)
+ ]);
expectInfo(noType, 'C<>', required: false);
expectComplexInfo('C<>', required: true, expectedCalls: [
@@ -912,43 +873,6 @@
expect(listener.errors, isNull);
}
- void test_simple_parseArguments2() {
- final Token start = scanString('before <S<T>> after').tokens.next.next;
- Token t = start.next.next;
- expect(t.next.lexeme, '>>');
- final TypeInfoListener listener = new TypeInfoListener();
-
- expect(simpleTypeArgument1.parseArguments(start, new Parser(listener)), t);
- expect(listener.calls, [
- 'beginTypeArguments <',
- 'handleIdentifier T typeReference',
- 'handleNoTypeArguments >>',
- 'handleType T >>',
- 'endTypeArguments 1 < T'
- ]);
- expect(listener.errors, isNull);
- }
-
- void test_simple_parseVariables2() {
- final Token start = scanString('before <S<T>> after').tokens.next.next;
- Token t = start.next.next;
- expect(t.next.lexeme, '>>');
- final TypeInfoListener listener = new TypeInfoListener();
-
- expect(simpleTypeArgument1.parseVariables(start, new Parser(listener)), t);
- expect(listener.calls, [
- 'beginTypeVariables <',
- 'beginTypeVariable T',
- 'beginMetadataStar T',
- 'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
- 'handleNoType T',
- 'endTypeVariable T null',
- 'endTypeVariables 1 < T',
- ]);
- expect(listener.errors, isNull);
- }
-
void test_computeTypeParamOrArg_basic() {
expectTypeParamOrArg(noTypeParamOrArg, '');
expectTypeParamOrArg(noTypeParamOrArg, 'a');
@@ -969,7 +893,7 @@
Token gtgt = start.next.next.next;
expect(gtgt.lexeme, '>>');
- TypeParamOrArgInfo typeVarInfo = computeTypeParamOrArg(start, gtgt);
+ TypeParamOrArgInfo typeVarInfo = computeTypeParamOrArg(start, false, gtgt);
expect(typeVarInfo, simpleTypeArgument1, reason: source);
}
@@ -1017,17 +941,6 @@
'handleType S >',
'endTypeArguments 1 < >'
]);
- expectComplexTypeArg('<S<T>>', splitGtGt: false, expectedCalls: [
- 'beginTypeArguments <',
- 'handleIdentifier S typeReference',
- 'beginTypeArguments <',
- 'handleIdentifier T typeReference',
- 'handleNoTypeArguments >>',
- 'handleType T >>',
- 'endTypeArguments 1 < T',
- 'handleType S >>',
- 'endTypeArguments 1 < >>'
- ]);
expectComplexTypeArg('<S<Function()>>', expectedCalls: [
'beginTypeArguments <',
'handleIdentifier S typeReference',
@@ -1042,20 +955,6 @@
'handleType S >',
'endTypeArguments 1 < >'
]);
- expectComplexTypeArg('<S<Function()>>', splitGtGt: false, expectedCalls: [
- 'beginTypeArguments <',
- 'handleIdentifier S typeReference',
- 'beginTypeArguments <',
- 'handleNoTypeVariables (',
- 'beginFunctionType Function',
- 'handleNoType <',
- 'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
- 'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
- 'endFunctionType Function >>',
- 'endTypeArguments 1 < )',
- 'handleType S >>',
- 'endTypeArguments 1 < >>'
- ]);
expectComplexTypeArg('<S<void Function()>>', expectedCalls: [
'beginTypeArguments <',
'handleIdentifier S typeReference',
@@ -1070,22 +969,6 @@
'handleType S >',
'endTypeArguments 1 < >'
]);
- expectComplexTypeArg('<S<void Function()>>',
- splitGtGt: false,
- expectedCalls: [
- 'beginTypeArguments <',
- 'handleIdentifier S typeReference',
- 'beginTypeArguments <',
- 'handleNoTypeVariables (',
- 'beginFunctionType void', // was 'beginFunctionType Function'
- 'handleVoidKeyword void', // was 'handleNoType <'
- 'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
- 'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
- 'endFunctionType Function >>',
- 'endTypeArguments 1 < )',
- 'handleType S >>',
- 'endTypeArguments 1 < >>'
- ]);
}
void test_computeTypeArg_complex_recovery() {
@@ -1107,18 +990,6 @@
'handleType S extends',
'endTypeArguments 1 < >',
]);
- expectComplexTypeArg('<S extends List<T>>',
- splitGtGt: false,
- expectedErrors: [
- error(codeUnexpectedToken, 3, 7)
- ],
- expectedCalls: [
- 'beginTypeArguments <',
- 'handleIdentifier S typeReference',
- 'handleNoTypeArguments extends',
- 'handleType S extends',
- 'endTypeArguments 1 < >>',
- ]);
expectComplexTypeArg('<@A S,T>', expectedErrors: [
error(codeUnexpectedToken, 1, 1)
], expectedCalls: [
@@ -1156,6 +1027,14 @@
'handleType T >',
'endTypeArguments 2 < >'
]);
+ expectComplexTypeArg('<S T>',
+ inDeclaration: true, expectedErrors: [error(codeExpectedButGot, 3, 1)]);
+ expectComplexTypeArg('<S',
+ inDeclaration: true, expectedErrors: [error(codeExpectedButGot, 2, 0)]);
+ expectComplexTypeArg('<@Foo S', inDeclaration: true, expectedErrors: [
+ error(codeUnexpectedToken, 1, 1),
+ error(codeExpectedButGot, 7, 0)
+ ]);
}
void test_computeTypeParam_complex() {
@@ -1215,24 +1094,6 @@
'endTypeVariable > extends',
'endTypeVariables 1 < >',
]);
- expectComplexTypeParam('<S extends List<T>>',
- splitGtGt: false,
- expectedCalls: [
- 'beginTypeVariables <',
- 'beginTypeVariable S',
- 'beginMetadataStar S',
- 'endMetadataStar 0',
- 'handleIdentifier S typeVariableDeclaration',
- 'handleIdentifier List typeReference',
- 'beginTypeArguments <',
- 'handleIdentifier T typeReference',
- 'handleNoTypeArguments >>',
- 'handleType T >>',
- 'endTypeArguments 1 < T',
- 'handleType List >>',
- 'endTypeVariable >> extends',
- 'endTypeVariables 1 < >>',
- ]);
expectComplexTypeParam('<R, S extends void Function()>', expectedCalls: [
'beginTypeVariables <',
'beginTypeVariable R',
@@ -1364,21 +1225,14 @@
'endTypeVariable < null',
'endTypeVariables 1 < >',
]);
- expectComplexTypeParam('<S<T>>',
- expectedErrors: [
- error(codeUnexpectedToken, 2, 1),
- ],
- splitGtGt: false,
- expectedCalls: [
- 'beginTypeVariables <',
- 'beginTypeVariable S',
- 'beginMetadataStar S',
- 'endMetadataStar 0',
- 'handleIdentifier S typeVariableDeclaration',
- 'handleNoType S',
- 'endTypeVariable < null',
- 'endTypeVariables 1 < >>',
- ]);
+ expectComplexTypeParam('<S T>', inDeclaration: true, expectedErrors: [
+ error(codeExpectedButGot, 3, 1),
+ ]);
+ expectComplexTypeParam('<S', inDeclaration: true, expectedErrors: [
+ error(codeExpectedButGot, 2, 0),
+ ]);
+ expectComplexTypeParam('<@Foo S',
+ inDeclaration: true, expectedErrors: [error(codeExpectedButGot, 7, 0)]);
}
}
@@ -1393,17 +1247,18 @@
void expectComplexInfo(String source,
{bool required,
+ bool inDeclaration = false,
String expectedAfter,
List<String> expectedCalls,
List<ExpectedError> expectedErrors}) {
if (required == null) {
- computeComplex(source, scan(source), true, expectedAfter, expectedCalls,
- expectedErrors);
- computeComplex(source, scan(source), false, expectedAfter, expectedCalls,
- expectedErrors);
+ computeComplex(source, scan(source), true, inDeclaration, expectedAfter,
+ expectedCalls, expectedErrors);
+ computeComplex(source, scan(source), false, inDeclaration, expectedAfter,
+ expectedCalls, expectedErrors);
} else {
- computeComplex(source, scan(source), required, expectedAfter, expectedCalls,
- expectedErrors);
+ computeComplex(source, scan(source), required, inDeclaration, expectedAfter,
+ expectedCalls, expectedErrors);
}
}
@@ -1425,9 +1280,10 @@
}
TypeInfo compute(expectedInfo, String source, Token start, bool required,
- {Token innerEndGroup}) {
+ {bool inDeclaration = false, Token innerEndGroup}) {
int expectedGtGtAndNullEndCount = countGtGtAndNullEnd(start);
- TypeInfo typeInfo = computeType(start, required, innerEndGroup);
+ TypeInfo typeInfo =
+ computeType(start, required, inDeclaration, innerEndGroup);
expect(typeInfo, expectedInfo, reason: source);
expect(countGtGtAndNullEnd(start), expectedGtGtAndNullEndCount,
reason: 'computeType should not modify the token stream');
@@ -1438,12 +1294,14 @@
String source,
Token start,
bool required,
+ bool inDeclaration,
String expectedAfter,
List<String> expectedCalls,
List<ExpectedError> expectedErrors) {
int expectedGtGtAndNullEndCount = countGtGtAndNullEnd(start);
- ComplexTypeInfo typeInfo =
- compute(const isInstanceOf<ComplexTypeInfo>(), source, start, required);
+ ComplexTypeInfo typeInfo = compute(
+ const isInstanceOf<ComplexTypeInfo>(), source, start, required,
+ inDeclaration: inDeclaration);
expect(typeInfo.start, start.next, reason: source);
expect(typeInfo.couldBeExpression, isFalse);
expectEnd(expectedAfter, typeInfo.skipType(start));
@@ -1455,29 +1313,35 @@
expectEnd(expectedAfter, actualEnd);
if (expectedCalls != null) {
- // TypeInfoListener listener2 = new TypeInfoListener();
- // new Parser(listener2).parseType(start, TypeContinuation.Required);
- // print('[');
- // for (String call in listener2.calls) {
- // print("'$call',");
- // }
- // print(']');
-
- expect(listener.calls, expectedCalls, reason: source);
+ try {
+ expect(listener.calls, expectedCalls, reason: source);
+ } catch (e) {
+ TypeInfoListener listener2 = new TypeInfoListener();
+ new Parser(listener2).parseType(start, TypeContinuation.Required);
+ print('[');
+ for (String call in listener2.calls) {
+ print("'$call',");
+ }
+ print(']');
+ rethrow;
+ }
}
expect(listener.errors, expectedErrors, reason: source);
return typeInfo;
}
void expectComplexTypeArg(String source,
- {bool splitGtGt: true,
+ {bool inDeclaration = false,
String expectedAfter,
List<String> expectedCalls,
List<ExpectedError> expectedErrors}) {
Token start = scan(source);
int expectedGtGtAndNullEndCount = countGtGtAndNullEnd(start);
ComplexTypeParamOrArgInfo typeVarInfo = computeVar(
- const isInstanceOf<ComplexTypeParamOrArgInfo>(), source, start);
+ const isInstanceOf<ComplexTypeParamOrArgInfo>(),
+ source,
+ start,
+ inDeclaration);
expect(typeVarInfo.start, start.next, reason: source);
expectEnd(expectedAfter, typeVarInfo.skip(start));
@@ -1487,16 +1351,8 @@
TypeInfoListener listener = new TypeInfoListener();
Parser parser = new Parser(listener);
- if (!splitGtGt) {
- parser.cachedRewriter = new TokenStreamNonRewriter();
- }
Token actualEnd = typeVarInfo.parseArguments(start, parser);
expectEnd(expectedAfter, actualEnd);
- if (!splitGtGt) {
- expect(countGtGtAndNullEnd(start), expectedGtGtAndNullEndCount,
- reason: 'TypeParamOrArgInfo.parseArguments'
- ' should not modify the token stream');
- }
if (expectedCalls != null) {
try {
@@ -1516,14 +1372,17 @@
}
void expectComplexTypeParam(String source,
- {bool splitGtGt: true,
+ {bool inDeclaration = false,
String expectedAfter,
List<String> expectedCalls,
List<ExpectedError> expectedErrors}) {
Token start = scan(source);
int expectedGtGtAndNullEndCount = countGtGtAndNullEnd(start);
ComplexTypeParamOrArgInfo typeVarInfo = computeVar(
- const isInstanceOf<ComplexTypeParamOrArgInfo>(), source, start);
+ const isInstanceOf<ComplexTypeParamOrArgInfo>(),
+ source,
+ start,
+ inDeclaration);
expect(typeVarInfo.start, start.next, reason: source);
expectEnd(expectedAfter, typeVarInfo.skip(start));
@@ -1533,16 +1392,8 @@
TypeInfoListener listener = new TypeInfoListener(metadataAllowed: true);
Parser parser = new Parser(listener);
- if (!splitGtGt) {
- parser.cachedRewriter = new TokenStreamNonRewriter();
- }
Token actualEnd = typeVarInfo.parseVariables(start, parser);
expectEnd(expectedAfter, actualEnd);
- if (!splitGtGt) {
- expect(countGtGtAndNullEnd(start), expectedGtGtAndNullEndCount,
- reason: 'TypeParamOrArgInfo.parseVariables'
- ' should not modify the token stream');
- }
if (expectedCalls != null) {
try {
@@ -1562,17 +1413,18 @@
}
void expectTypeParamOrArg(expectedInfo, String source,
- {bool splitGtGt: true,
+ {bool inDeclaration = false,
String expectedAfter,
List<String> expectedCalls,
List<ExpectedError> expectedErrors}) {
Token start = scan(source);
- computeVar(expectedInfo, source, start);
+ computeVar(expectedInfo, source, start, inDeclaration);
}
-TypeParamOrArgInfo computeVar(expectedInfo, String source, Token start) {
+TypeParamOrArgInfo computeVar(
+ expectedInfo, String source, Token start, bool inDeclaration) {
int expectedGtGtAndNullEndCount = countGtGtAndNullEnd(start);
- TypeParamOrArgInfo typeVarInfo = computeTypeParamOrArg(start);
+ TypeParamOrArgInfo typeVarInfo = computeTypeParamOrArg(start, inDeclaration);
expect(typeVarInfo, expectedInfo, reason: source);
expect(countGtGtAndNullEnd(start), expectedGtGtAndNullEndCount,
reason: 'computeTypeParamOrArg should not modify the token stream');
@@ -1812,15 +1664,3 @@
@override
String toString() => 'error(${code.name}, $start, $length)';
}
-
-class TokenStreamNonRewriter implements TokenStreamRewriter {
- @override
- Token splitGtGt(BeginToken start) {
- Token gtgt = start.endGroup;
- assert(gtgt != null);
- assert(optional('>>', gtgt));
- return gtgt;
- }
-
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/pkg/front_end/test/fasta/testing/analyzer_diet_listener.dart b/pkg/front_end/test/fasta/testing/analyzer_diet_listener.dart
index e0f5f3e..01ac3d2 100644
--- a/pkg/front_end/test/fasta/testing/analyzer_diet_listener.dart
+++ b/pkg/front_end/test/fasta/testing/analyzer_diet_listener.dart
@@ -58,7 +58,8 @@
@override
void buildFields(int count, Token token, bool isTopLevel) {
- List<String> names = popList(count);
+ List<String> names =
+ popList(count, new List<String>.filled(count, null, growable: true));
Builder builder = lookupBuilder(token, null, names.first);
Token metadata = pop();
AstBuilder listener =
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index ee0b49b..39f0bfc 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -247,7 +247,7 @@
File generated = new File.fromUri(uri);
StdioProcess process;
try {
- var args = [];
+ var args = <String>[];
if (context.strongMode) {
args.add('--strong');
args.add('--reify-generic-functions');
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index 5089798..156b814 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -444,9 +444,7 @@
TestIncrementalCompiler(CompilerOptions options, Uri entryPoint,
[Uri initializeFrom])
- : super(
- new CompilerContext(
- new ProcessedOptions(options, false, [entryPoint])),
+ : super(new CompilerContext(new ProcessedOptions(options, [entryPoint])),
initializeFrom);
@override
diff --git a/pkg/front_end/test/incremental_utils.dart b/pkg/front_end/test/incremental_utils.dart
index c8480bf..ef4626a 100644
--- a/pkg/front_end/test/incremental_utils.dart
+++ b/pkg/front_end/test/incremental_utils.dart
@@ -33,7 +33,7 @@
int empty = 0;
for (Library lib in component.libraries) {
for (Class c in lib.classes) {
- if (c.isSyntheticMixinImplementation) {
+ if (c.isAnonymousMixin) {
for (Procedure p in c.procedures) {
if (p.function.body is EmptyStatement) {
empty++;
diff --git a/pkg/front_end/test/kernel_generator_test.dart b/pkg/front_end/test/kernel_generator_test.dart
index 736cb2f..2ad6012 100644
--- a/pkg/front_end/test/kernel_generator_test.dart
+++ b/pkg/front_end/test/kernel_generator_test.dart
@@ -177,26 +177,9 @@
expect(errors, isEmpty);
});
- test('compiler by default is hermetic', () async {
+ test('compiler is not hermetic by default', () async {
var errors = [];
var options = new CompilerOptions()..onError = (e) => errors.add(e);
- var sources = {
- 'a.dart': 'import "b.dart"; a() => print("hi");',
- 'b.dart': ''
- };
- await compileUnit(['a.dart'], sources, options: options);
- expect(errors.first.message, contains('Invalid access'));
- errors.clear();
-
- await compileUnit(['a.dart', 'b.dart'], sources, options: options);
- expect(errors, isEmpty);
- });
-
- test('chaseDependencies=true removes hermetic restriction', () async {
- var errors = [];
- var options = new CompilerOptions()
- ..chaseDependencies = true
- ..onError = (e) => errors.add(e);
await compileUnit([
'a.dart'
], {
diff --git a/pkg/front_end/test/scheme_based_file_system_test.dart b/pkg/front_end/test/scheme_based_file_system_test.dart
new file mode 100644
index 0000000..be40f65
--- /dev/null
+++ b/pkg/front_end/test/scheme_based_file_system_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:front_end/src/api_prototype/file_system.dart';
+import 'package:front_end/src/api_prototype/scheme_based_file_system.dart';
+
+import 'package:test/test.dart';
+
+main() {
+ test('lookup of registered schemes is handled', () {
+ var fs1 = new MockFileSystem('scheme1');
+ var fs2 = new MockFileSystem('scheme2');
+ var fileSystem =
+ new SchemeBasedFileSystem({'scheme1': fs1, 'scheme2': fs2});
+
+ MockFileSystemEntity e1 =
+ fileSystem.entityForUri(Uri.parse('scheme1:a.dart'));
+ MockFileSystemEntity e2 =
+ fileSystem.entityForUri(Uri.parse('scheme2:a.dart'));
+ expect(e1.fileSystem, fs1);
+ expect(e2.fileSystem, fs2);
+ });
+
+ test('lookup of an unregistered scheme will throw', () {
+ var fileSystem =
+ new SchemeBasedFileSystem({'scheme1': new MockFileSystem('scheme1')});
+ expect(() => fileSystem.entityForUri(Uri.parse('scheme2:a.dart')),
+ throwsA((e) => e is FileSystemException));
+ });
+}
+
+class MockFileSystem implements FileSystem {
+ String scheme;
+ MockFileSystem(this.scheme);
+
+ @override
+ FileSystemEntity entityForUri(Uri uri) {
+ if (uri.scheme != scheme) throw "unsupported";
+ return new MockFileSystemEntity(uri, this);
+ }
+}
+
+class MockFileSystemEntity implements FileSystemEntity {
+ final Uri uri;
+ final FileSystem fileSystem;
+ MockFileSystemEntity(this.uri, this.fileSystem);
+
+ noSuchMethod(m) => super.noSuchMethod(m);
+}
diff --git a/pkg/front_end/test/src/base/processed_options_test.dart b/pkg/front_end/test/src/base/processed_options_test.dart
index 2ce4498..8d29cbe 100644
--- a/pkg/front_end/test/src/base/processed_options_test.dart
+++ b/pkg/front_end/test/src/base/processed_options_test.dart
@@ -239,8 +239,8 @@
.entityForUri(Uri.parse('org-dartlang-test:///base/location/.packages'))
.writeAsStringSync('foo:baz\n');
var raw = new CompilerOptions()..fileSystem = fileSystem;
- var processed = new ProcessedOptions(raw, false,
- [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
+ var processed = new ProcessedOptions(
+ raw, [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
var uriTranslator = await processed.getUriTranslator();
checkPackageExpansion('foo', 'base/location/baz', uriTranslator.packages);
}
@@ -259,8 +259,8 @@
.entityForUri(Uri.parse('org-dartlang-test:///base/.packages'))
.writeAsStringSync('foo:baz\n');
var raw = new CompilerOptions()..fileSystem = fileSystem;
- var processed = new ProcessedOptions(raw, false,
- [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
+ var processed = new ProcessedOptions(
+ raw, [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
var uriTranslator = await processed.getUriTranslator();
checkPackageExpansion('foo', 'base/baz', uriTranslator.packages);
}
@@ -282,8 +282,8 @@
.entityForUri(Uri.parse('org-dartlang-test:///base/.packages'))
.writeAsStringSync('foo:baz\n');
var raw = new CompilerOptions()..fileSystem = fileSystem;
- var processed = new ProcessedOptions(raw, false,
- [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
+ var processed = new ProcessedOptions(
+ raw, [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
var uriTranslator = await processed.getUriTranslator();
checkPackageExpansion(
'foo', 'base/location/packages/foo', uriTranslator.packages);
@@ -299,8 +299,8 @@
var raw = new CompilerOptions()
..fileSystem = fileSystem
..onError = (e) => errors.add(e);
- var processed = new ProcessedOptions(raw, false,
- [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
+ var processed = new ProcessedOptions(
+ raw, [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
var uriTranslator = await processed.getUriTranslator();
expect(errors, isEmpty);
expect(uriTranslator.packages.asMap(), isEmpty);
@@ -342,7 +342,7 @@
var raw = new CompilerOptions()
..fileSystem = fileSystem
..onError = (e) => errors.add(e);
- var options = new ProcessedOptions(raw, false, [Uri.parse('foo.dart')]);
+ var options = new ProcessedOptions(raw, [Uri.parse('foo.dart')]);
var result = await options.validateOptions();
expect(errors.single.message,
startsWith(_stringPrefixOf(templateInputFileNotFound)));
@@ -368,7 +368,7 @@
..sdkRoot = sdkRoot
..fileSystem = fileSystem
..onError = (e) => errors.add(e);
- var options = new ProcessedOptions(raw, false, [Uri.parse('foo.dart')]);
+ var options = new ProcessedOptions(raw, [Uri.parse('foo.dart')]);
var result = await options.validateOptions();
// Note: we check this first so test failures show the cause directly.
expect(errors, isEmpty);
@@ -385,7 +385,7 @@
..sdkRoot = sdkRoot
..fileSystem = fileSystem
..onError = (e) => errors.add(e);
- var options = new ProcessedOptions(raw, false, [Uri.parse('foo.dart')]);
+ var options = new ProcessedOptions(raw, [Uri.parse('foo.dart')]);
expect(await options.validateOptions(), isFalse);
expect(errors.first.message,
startsWith(_stringPrefixOf(templateSdkRootNotFound)));
@@ -403,7 +403,7 @@
..sdkSummary = sdkSummary
..fileSystem = fileSystem
..onError = (e) => errors.add(e);
- var options = new ProcessedOptions(raw, false, [Uri.parse('foo.dart')]);
+ var options = new ProcessedOptions(raw, [Uri.parse('foo.dart')]);
var result = await options.validateOptions();
expect(errors, isEmpty);
expect(result, isTrue);
@@ -419,7 +419,7 @@
..sdkSummary = sdkSummary
..fileSystem = fileSystem
..onError = (e) => errors.add(e);
- var options = new ProcessedOptions(raw, false, [Uri.parse('foo.dart')]);
+ var options = new ProcessedOptions(raw, [Uri.parse('foo.dart')]);
expect(await options.validateOptions(), isFalse);
expect(errors.single.message,
startsWith(_stringPrefixOf(templateSdkSummaryNotFound)));
@@ -440,7 +440,7 @@
..sdkRoot = sdkRoot
..fileSystem = fileSystem
..onError = (e) => errors.add(e);
- var options = new ProcessedOptions(raw, false, [Uri.parse('foo.dart')]);
+ var options = new ProcessedOptions(raw, [Uri.parse('foo.dart')]);
var result = await options.validateOptions();
expect(errors, isEmpty);
expect(result, isTrue);
@@ -458,7 +458,7 @@
..sdkSummary = sdkSummary
..fileSystem = fileSystem
..onError = (e) => errors.add(e);
- var options = new ProcessedOptions(raw, false, [Uri.parse('foo.dart')]);
+ var options = new ProcessedOptions(raw, [Uri.parse('foo.dart')]);
expect(await options.validateOptions(), isFalse);
expect(errors.single.message,
startsWith(_stringPrefixOf(templateSdkSummaryNotFound)));
diff --git a/pkg/front_end/test/src/incremental/kernel_driver_test.dart b/pkg/front_end/test/src/incremental/kernel_driver_test.dart
index 7568239..0b33811 100644
--- a/pkg/front_end/test/src/incremental/kernel_driver_test.dart
+++ b/pkg/front_end/test/src/incremental/kernel_driver_test.dart
@@ -987,7 +987,6 @@
..fileSystem = fileSystem
..sdkRoot = Uri.parse('org-dartlang-test:///sdk/')
..compileSdk = true
- ..chaseDependencies = true
..strongMode = true
..target = new NoneTarget(new TargetFlags(strongMode: true));
var inputs = [Uri.parse('dart:core')];
diff --git a/pkg/front_end/test/summary_generator_test.dart b/pkg/front_end/test/summary_generator_test.dart
index 435e5ec..3588ea8 100644
--- a/pkg/front_end/test/summary_generator_test.dart
+++ b/pkg/front_end/test/summary_generator_test.dart
@@ -118,14 +118,10 @@
component.libraries.single.importUri.path.endsWith('b.dart'), isTrue);
});
- test('summarization by default is hermetic', () async {
+ test('summarization by default is not hermetic', () async {
var errors = [];
var options = new CompilerOptions()..onError = (e) => errors.add(e);
await summarize(['b.dart'], allSources, options: options);
- expect(errors.first.toString(), contains('Invalid access'));
- errors.clear();
-
- await summarize(['a.dart', 'b.dart'], allSources, options: options);
expect(errors, isEmpty);
});
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart b/pkg/front_end/testcases/annotation_on_enum_values.dart
new file mode 100644
index 0000000..29dba81
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for 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 test checks that annotations on enum values are preserved by the
+// compiler.
+
+const int hest = 42;
+
+class Fisk<T> {
+ final T x;
+ const Fisk.fisk(this.x);
+}
+
+enum Foo {
+ @hest bar,
+ @Fisk.fisk(hest) baz,
+ cafebabe,
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.direct.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.direct.expect
new file mode 100644
index 0000000..246f4cb
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart.direct.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Fisk<T extends core::Object = dynamic> extends core::Object {
+ final field self::Fisk::T x;
+ const constructor fisk(self::Fisk::T x) → void
+ : self::Fisk::x = x, super core::Object::•()
+ ;
+}
+class Foo extends core::Object {
+ final field core::int index;
+ final field core::String _name;
+ static const field core::List<self::Foo> values = const <self::Foo>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
+ @self::hest
+ static const field self::Foo bar = const self::Foo::•(0, "Foo.bar");
+ @self::Fisk::fisk<dynamic>(self::hest)
+ static const field self::Foo baz = const self::Foo::•(1, "Foo.baz");
+ static const field self::Foo cafebabe = const self::Foo::•(2, "Foo.cafebabe");
+ const constructor •(core::int index, core::String _name) → void
+ : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
+ ;
+ method toString() → core::String
+ return this.{=self::Foo::_name};
+}
+static const field core::int hest = 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.direct.transformed.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.direct.transformed.expect
new file mode 100644
index 0000000..246f4cb
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart.direct.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Fisk<T extends core::Object = dynamic> extends core::Object {
+ final field self::Fisk::T x;
+ const constructor fisk(self::Fisk::T x) → void
+ : self::Fisk::x = x, super core::Object::•()
+ ;
+}
+class Foo extends core::Object {
+ final field core::int index;
+ final field core::String _name;
+ static const field core::List<self::Foo> values = const <self::Foo>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
+ @self::hest
+ static const field self::Foo bar = const self::Foo::•(0, "Foo.bar");
+ @self::Fisk::fisk<dynamic>(self::hest)
+ static const field self::Foo baz = const self::Foo::•(1, "Foo.baz");
+ static const field self::Foo cafebabe = const self::Foo::•(2, "Foo.cafebabe");
+ const constructor •(core::int index, core::String _name) → void
+ : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
+ ;
+ method toString() → core::String
+ return this.{=self::Foo::_name};
+}
+static const field core::int hest = 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
new file mode 100644
index 0000000..02c5c32
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Fisk<T extends core::Object = dynamic> extends core::Object {
+ final field self::Fisk::T x;
+ const constructor fisk(self::Fisk::T x) → void
+ ;
+}
+class Foo extends core::Object {
+ final field core::int index;
+ final field core::String _name;
+ static const field core::List<self::Foo> values = const <self::Foo>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
+ static const field self::Foo bar = const self::Foo::•(0, "Foo.bar");
+ static const field self::Foo baz = const self::Foo::•(1, "Foo.baz");
+ static const field self::Foo cafebabe = const self::Foo::•(2, "Foo.cafebabe");
+ const constructor •(core::int index, core::String _name) → void
+ : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
+ ;
+ method toString() → core::String
+ return this.{=self::Foo::_name};
+}
+static const field core::int hest;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.strong.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.strong.expect
new file mode 100644
index 0000000..2c026ab
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart.strong.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Fisk<T extends core::Object = dynamic> extends core::Object {
+ final field self::Fisk::T x;
+ const constructor fisk(self::Fisk::T x) → void
+ : self::Fisk::x = x, super core::Object::•()
+ ;
+}
+class Foo extends core::Object {
+ final field core::int index;
+ final field core::String _name;
+ static const field core::List<self::Foo> values = const <self::Foo>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
+ @self::hest
+ static const field self::Foo bar = const self::Foo::•(0, "Foo.bar");
+ @self::Fisk::fisk<core::int>(self::hest)
+ static const field self::Foo baz = const self::Foo::•(1, "Foo.baz");
+ static const field self::Foo cafebabe = const self::Foo::•(2, "Foo.cafebabe");
+ const constructor •(core::int index, core::String _name) → void
+ : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
+ ;
+ method toString() → core::String
+ return this.{=self::Foo::_name};
+}
+static const field core::int hest = 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.strong.transformed.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..2c026ab
--- /dev/null
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Fisk<T extends core::Object = dynamic> extends core::Object {
+ final field self::Fisk::T x;
+ const constructor fisk(self::Fisk::T x) → void
+ : self::Fisk::x = x, super core::Object::•()
+ ;
+}
+class Foo extends core::Object {
+ final field core::int index;
+ final field core::String _name;
+ static const field core::List<self::Foo> values = const <self::Foo>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
+ @self::hest
+ static const field self::Foo bar = const self::Foo::•(0, "Foo.bar");
+ @self::Fisk::fisk<core::int>(self::hest)
+ static const field self::Foo baz = const self::Foo::•(1, "Foo.baz");
+ static const field self::Foo cafebabe = const self::Foo::•(2, "Foo.cafebabe");
+ const constructor •(core::int index, core::String _name) → void
+ : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
+ ;
+ method toString() → core::String
+ return this.{=self::Foo::_name};
+}
+static const field core::int hest = 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/ast_builder.status b/pkg/front_end/testcases/ast_builder.status
index 1301285..6e166ec 100644
--- a/pkg/front_end/testcases/ast_builder.status
+++ b/pkg/front_end/testcases/ast_builder.status
@@ -4,6 +4,7 @@
# Status file for the ast_builder_test.dart test suite. This is testing
# generating analyzer ASTs and connecting up type inference information.
+annotation_on_enum_values: Crash
annotation_top: Crash
argument_mismatch: Fail
bug32629: Fail
diff --git a/pkg/front_end/testcases/bug33196.dart b/pkg/front_end/testcases/bug33196.dart
new file mode 100644
index 0000000..e2f01f1
--- /dev/null
+++ b/pkg/front_end/testcases/bug33196.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+main() {
+ var result = returnsString();
+ print(result.runtimeType);
+}
+
+FutureOr<String> returnsString() async {
+ return "oh no";
+}
diff --git a/pkg/front_end/testcases/bug33196.dart.direct.expect b/pkg/front_end/testcases/bug33196.dart.direct.expect
new file mode 100644
index 0000000..4baad60
--- /dev/null
+++ b/pkg/front_end/testcases/bug33196.dart.direct.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+static method main() → dynamic {
+ dynamic result = self::returnsString();
+ core::print(result.runtimeType);
+}
+static method returnsString() → asy::FutureOr<core::String> async {
+ return "oh no";
+}
diff --git a/pkg/front_end/testcases/bug33196.dart.direct.transformed.expect b/pkg/front_end/testcases/bug33196.dart.direct.transformed.expect
new file mode 100644
index 0000000..4fbc43e
--- /dev/null
+++ b/pkg/front_end/testcases/bug33196.dart.direct.transformed.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+static method main() → dynamic {
+ dynamic result = self::returnsString();
+ core::print(result.runtimeType);
+}
+static method returnsString() → asy::FutureOr<core::String> /* originally async */ {
+ final asy::Completer<core::String> :async_completer = asy::Completer::sync<core::String>();
+ asy::FutureOr<core::String> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ :return_value = "oh no";
+ break #L1;
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/testcases/bug33196.dart.outline.expect b/pkg/front_end/testcases/bug33196.dart.outline.expect
new file mode 100644
index 0000000..e640af1
--- /dev/null
+++ b/pkg/front_end/testcases/bug33196.dart.outline.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method main() → dynamic
+ ;
+static method returnsString() → asy::FutureOr<core::String>
+ ;
diff --git a/pkg/front_end/testcases/bug33196.dart.strong.expect b/pkg/front_end/testcases/bug33196.dart.strong.expect
new file mode 100644
index 0000000..d8e9475
--- /dev/null
+++ b/pkg/front_end/testcases/bug33196.dart.strong.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ asy::FutureOr<core::String> result = self::returnsString();
+ core::print(result.{core::Object::runtimeType});
+}
+static method returnsString() → asy::FutureOr<core::String> async {
+ return "oh no";
+}
diff --git a/pkg/front_end/testcases/bug33196.dart.strong.transformed.expect b/pkg/front_end/testcases/bug33196.dart.strong.transformed.expect
new file mode 100644
index 0000000..2a550b1
--- /dev/null
+++ b/pkg/front_end/testcases/bug33196.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ asy::FutureOr<core::String> result = self::returnsString();
+ core::print(result.{core::Object::runtimeType});
+}
+static method returnsString() → asy::FutureOr<core::String> /* originally async */ {
+ final asy::Completer<core::String> :async_completer = asy::Completer::sync<core::String>();
+ asy::FutureOr<core::String> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ :return_value = "oh no";
+ break #L1;
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/testcases/bug33206.dart b/pkg/front_end/testcases/bug33206.dart
new file mode 100644
index 0000000..79892c5
--- /dev/null
+++ b/pkg/front_end/testcases/bug33206.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+class X {
+ final x;
+ final y;
+
+ X(this.x, this.y);
+
+ toString() => "X($x, $y)";
+}
+
+class Y {
+ f(_) {}
+}
+
+Future<List<Object>> f1() async {
+ return [1];
+}
+
+List<Object> f2() => [2];
+
+Future<Object> f3() async {
+ return 3;
+}
+
+Future<X> foo() async {
+ return X(Y()..f(await f1())..f(f2()), await f3());
+}
+
+Future<void> main() async {
+ print(await foo());
+}
diff --git a/pkg/front_end/testcases/bug33206.dart.direct.expect b/pkg/front_end/testcases/bug33206.dart.direct.expect
new file mode 100644
index 0000000..45898a6
--- /dev/null
+++ b/pkg/front_end/testcases/bug33206.dart.direct.expect
@@ -0,0 +1,34 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class X extends core::Object {
+ final field dynamic x;
+ final field dynamic y;
+ constructor •(dynamic x, dynamic y) → void
+ : self::X::x = x, self::X::y = y, super core::Object::•()
+ ;
+ method toString() → dynamic
+ return "X(${this.{self::X::x}}, ${this.{self::X::y}})";
+}
+class Y extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method f(dynamic _) → dynamic {}
+}
+static method f1() → asy::Future<core::List<core::Object>> async {
+ return <dynamic>[1];
+}
+static method f2() → core::List<core::Object>
+ return <dynamic>[2];
+static method f3() → asy::Future<core::Object> async {
+ return 3;
+}
+static method foo() → asy::Future<self::X> async {
+ return new self::X::•(let final dynamic #t1 = new self::Y::•() in let final dynamic #t2 = #t1.f(await self::f1()) in let final dynamic #t3 = #t1.f(self::f2()) in #t1, await self::f3());
+}
+static method main() → asy::Future<void> async {
+ core::print(await self::foo());
+}
diff --git a/pkg/front_end/testcases/bug33206.dart.direct.transformed.expect b/pkg/front_end/testcases/bug33206.dart.direct.transformed.expect
new file mode 100644
index 0000000..9d44bff
--- /dev/null
+++ b/pkg/front_end/testcases/bug33206.dart.direct.transformed.expect
@@ -0,0 +1,137 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class X extends core::Object {
+ final field dynamic x;
+ final field dynamic y;
+ constructor •(dynamic x, dynamic y) → void
+ : self::X::x = x, self::X::y = y, super core::Object::•()
+ ;
+ method toString() → dynamic
+ return "X(${this.{self::X::x}}, ${this.{self::X::y}})";
+}
+class Y extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method f(dynamic _) → dynamic {}
+}
+static method f1() → asy::Future<core::List<core::Object>> /* originally async */ {
+ final asy::Completer<core::List<core::Object>> :async_completer = asy::Completer::sync<core::List<core::Object>>();
+ asy::FutureOr<core::List<core::Object>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ :return_value = <dynamic>[1];
+ break #L1;
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method f2() → core::List<core::Object>
+ return <dynamic>[2];
+static method f3() → asy::Future<core::Object> /* originally async */ {
+ final asy::Completer<core::Object> :async_completer = asy::Completer::sync<core::Object>();
+ asy::FutureOr<core::Object> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ :return_value = 3;
+ break #L2;
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method foo() → asy::Future<self::X> /* originally async */ {
+ final asy::Completer<self::X> :async_completer = asy::Completer::sync<self::X>();
+ asy::FutureOr<self::X> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L3:
+ {
+ final dynamic #t1 = new self::Y::•();
+ [yield] let dynamic #t2 = asy::_awaitHelper(self::f1(), :async_op_then, :async_op_error, :async_op) in null;
+ final dynamic #t3 = #t1.f(:result);
+ final dynamic #t4 = #t1.f(self::f2());
+ [yield] let dynamic #t5 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
+ :return_value = new self::X::•(#t1, :result);
+ break #L3;
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method main() → asy::Future<void> /* originally async */ {
+ final asy::Completer<void> :async_completer = asy::Completer::sync<void>();
+ asy::FutureOr<void> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L4:
+ {
+ [yield] let dynamic #t6 = asy::_awaitHelper(self::foo(), :async_op_then, :async_op_error, :async_op) in null;
+ core::print(:result);
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/testcases/bug33206.dart.outline.expect b/pkg/front_end/testcases/bug33206.dart.outline.expect
new file mode 100644
index 0000000..bc0040e
--- /dev/null
+++ b/pkg/front_end/testcases/bug33206.dart.outline.expect
@@ -0,0 +1,29 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class X extends core::Object {
+ final field dynamic x;
+ final field dynamic y;
+ constructor •(dynamic x, dynamic y) → void
+ ;
+ method toString() → dynamic
+ ;
+}
+class Y extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method f(dynamic _) → dynamic
+ ;
+}
+static method f1() → asy::Future<core::List<core::Object>>
+ ;
+static method f2() → core::List<core::Object>
+ ;
+static method f3() → asy::Future<core::Object>
+ ;
+static method foo() → asy::Future<self::X>
+ ;
+static method main() → asy::Future<void>
+ ;
diff --git a/pkg/front_end/testcases/bug33206.dart.strong.expect b/pkg/front_end/testcases/bug33206.dart.strong.expect
new file mode 100644
index 0000000..027b1f8
--- /dev/null
+++ b/pkg/front_end/testcases/bug33206.dart.strong.expect
@@ -0,0 +1,34 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class X extends core::Object {
+ final field dynamic x;
+ final field dynamic y;
+ constructor •(dynamic x, dynamic y) → void
+ : self::X::x = x, self::X::y = y, super core::Object::•()
+ ;
+ method toString() → core::String
+ return "X(${this.{self::X::x}}, ${this.{self::X::y}})";
+}
+class Y extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method f(dynamic _) → dynamic {}
+}
+static method f1() → asy::Future<core::List<core::Object>> async {
+ return <core::Object>[1];
+}
+static method f2() → core::List<core::Object>
+ return <core::Object>[2];
+static method f3() → asy::Future<core::Object> async {
+ return 3;
+}
+static method foo() → asy::Future<self::X> async {
+ return new self::X::•(let final self::Y #t1 = new self::Y::•() in let final dynamic #t2 = #t1.{self::Y::f}(await self::f1()) in let final dynamic #t3 = #t1.{self::Y::f}(self::f2()) in #t1, await self::f3());
+}
+static method main() → asy::Future<void> async {
+ core::print(await self::foo());
+}
diff --git a/pkg/front_end/testcases/bug33206.dart.strong.transformed.expect b/pkg/front_end/testcases/bug33206.dart.strong.transformed.expect
new file mode 100644
index 0000000..cf29898
--- /dev/null
+++ b/pkg/front_end/testcases/bug33206.dart.strong.transformed.expect
@@ -0,0 +1,137 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class X extends core::Object {
+ final field dynamic x;
+ final field dynamic y;
+ constructor •(dynamic x, dynamic y) → void
+ : self::X::x = x, self::X::y = y, super core::Object::•()
+ ;
+ method toString() → core::String
+ return "X(${this.{self::X::x}}, ${this.{self::X::y}})";
+}
+class Y extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method f(dynamic _) → dynamic {}
+}
+static method f1() → asy::Future<core::List<core::Object>> /* originally async */ {
+ final asy::Completer<core::List<core::Object>> :async_completer = asy::Completer::sync<core::List<core::Object>>();
+ asy::FutureOr<core::List<core::Object>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ :return_value = <core::Object>[1];
+ break #L1;
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method f2() → core::List<core::Object>
+ return <core::Object>[2];
+static method f3() → asy::Future<core::Object> /* originally async */ {
+ final asy::Completer<core::Object> :async_completer = asy::Completer::sync<core::Object>();
+ asy::FutureOr<core::Object> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ :return_value = 3;
+ break #L2;
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method foo() → asy::Future<self::X> /* originally async */ {
+ final asy::Completer<self::X> :async_completer = asy::Completer::sync<self::X>();
+ asy::FutureOr<self::X> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L3:
+ {
+ final self::Y #t1 = new self::Y::•();
+ [yield] let dynamic #t2 = asy::_awaitHelper(self::f1(), :async_op_then, :async_op_error, :async_op) in null;
+ final dynamic #t3 = #t1.{self::Y::f}(:result);
+ final dynamic #t4 = #t1.{self::Y::f}(self::f2());
+ [yield] let dynamic #t5 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
+ :return_value = new self::X::•(#t1, :result);
+ break #L3;
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method main() → asy::Future<void> /* originally async */ {
+ final asy::Completer<void> :async_completer = asy::Completer::sync<void>();
+ asy::FutureOr<void> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L4:
+ {
+ [yield] let dynamic #t6 = asy::_awaitHelper(self::foo(), :async_op_then, :async_op_error, :async_op) in null;
+ core::print(:result);
+ }
+ :async_completer.{asy::Completer::complete}(:return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ asy::Future::microtask<dynamic>(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/tool/_fasta/bulk_compile.dart b/pkg/front_end/tool/_fasta/bulk_compile.dart
index fd4e09b..770ad9d 100644
--- a/pkg/front_end/tool/_fasta/bulk_compile.dart
+++ b/pkg/front_end/tool/_fasta/bulk_compile.dart
@@ -43,7 +43,6 @@
..fileSystem = (new FileBackedMemoryFileSystem()
..entities[mainUri.path] =
(new MemoryFileSystemEntity(mainUri)..bytes = <int>[])),
- false,
<Uri>[mainUri]);
Future<Null> compile(String source) {
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index c504e29..c804b1e 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -300,7 +300,6 @@
..sdkSummary = options["--platform"]
..librariesSpecificationUri = resolveFile(arguments[1])
..setExitCodeOnProblem = true
- ..chaseDependencies = true
..packagesFileUri = packages
..strongMode = strongMode
..target = target
@@ -311,7 +310,6 @@
..debugDump = dumpIr
..verbose = verbose
..verify = verify,
- false,
<Uri>[Uri.parse(arguments[0])],
resolveFile(arguments[2]));
} else if (arguments.isEmpty) {
@@ -352,7 +350,7 @@
inputs.add(resolveFile(argument));
}
}
- return new ProcessedOptions(compilerOptions, false, inputs, output);
+ return new ProcessedOptions(compilerOptions, inputs, output);
}
dynamic withGlobalOptions(
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index a8b6a15..026bccd 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -129,8 +129,7 @@
Future<bool> batchCompile(CompilerOptions options, Uri input, Uri output) {
return CompilerContext.runWithOptions(
- new ProcessedOptions(options, false, <Uri>[input], output),
- batchCompileImpl);
+ new ProcessedOptions(options, <Uri>[input], output), batchCompileImpl);
}
Future<bool> batchCompileImpl(CompilerContext c) async {
diff --git a/pkg/front_end/tool/_fasta/generate_messages_test.dart b/pkg/front_end/tool/_fasta/generate_messages_test.dart
index f242f01..d351316 100644
--- a/pkg/front_end/tool/_fasta/generate_messages_test.dart
+++ b/pkg/front_end/tool/_fasta/generate_messages_test.dart
@@ -14,7 +14,8 @@
asyncTest(() async {
Uri generatedFile = await computeGeneratedFile();
String generated = await generateMessagesFile();
- String actual = await new File.fromUri(generatedFile).readAsString();
+ String actual = (await new File.fromUri(generatedFile).readAsString())
+ .replaceAll('\r\n', '\n');
Expect.stringEquals(
generated, actual, "${generatedFile.path} is out of date");
});
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index de09e9a..75a58f7 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -233,7 +233,6 @@
..onError = onErrorHandler(strongMode)
..strongMode = strongMode
..target = createTarget(isFlutter: false, strongMode: strongMode)
- ..chaseDependencies = true
..packagesFileUri = Uri.base.resolve('.packages')
..compileSdk = compileSdk;
if (!compileSdk) {
diff --git a/pkg/front_end/tool/incremental_perf.dart b/pkg/front_end/tool/incremental_perf.dart
index 02a4bb7..0f8f161 100644
--- a/pkg/front_end/tool/incremental_perf.dart
+++ b/pkg/front_end/tool/incremental_perf.dart
@@ -127,8 +127,7 @@
var dir = Directory.systemTemp.createTempSync("ikg-cache");
compilerOptions.byteStore = createByteStore(cache, dir.path);
- final processedOptions =
- new ProcessedOptions(compilerOptions, false, [entryUri]);
+ final processedOptions = new ProcessedOptions(compilerOptions, [entryUri]);
final UriTranslator uriTranslator = await processedOptions.getUriTranslator();
collector.start("Initial compilation");
diff --git a/pkg/js_ast/lib/src/builder.dart b/pkg/js_ast/lib/src/builder.dart
index 8366dd0..1de3981 100644
--- a/pkg/js_ast/lib/src/builder.dart
+++ b/pkg/js_ast/lib/src/builder.dart
@@ -1254,7 +1254,7 @@
VariableDeclarationList finishVariableDeclarationList(
Declaration firstVariable) {
- var initialization = [];
+ var initialization = <VariableInitialization>[];
void declare(Declaration declaration) {
Expression initializer = null;
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 13b28bf..d94fb18 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -131,7 +131,7 @@
type ComponentFile {
UInt32 magic = 0x90ABCDEF;
- UInt32 formatVersion = 6;
+ UInt32 formatVersion = 7;
Library[] libraries;
UriSource sourceMap;
List<CanonicalName> canonicalNames;
@@ -286,11 +286,14 @@
UriReference fileUri;
FileOffset fileOffset;
FileOffset fileEndOffset;
- Byte flags (isAbstract, isEnum, xx); // Where xx is index into ClassLevel
+ Byte flags (levelBit0, levelBit1, isAbstract, isEnum, isAnonymousMixin,
+ isEliminatedMixin); // Where level is index into ClassLevel
StringReference name;
List<Expression> annotations;
List<TypeParameter> typeParameters;
Option<DartType> superClass;
+ // For transformed mixin application classes (isEliminatedMixin),
+ // original mixedInType is pulled into the end of implementedClasses.
Option<DartType> mixedInType;
List<DartType> implementedClasses;
List<Field> fields;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index afe96c6..f7367b9 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -696,10 +696,28 @@
/// applications.
@coq
String name;
- bool isAbstract;
+
+ // Must match serialized bit positions.
+ static const int LevelMask = 0x3; // Bits 0 and 1.
+ static const int FlagAbstract = 1 << 2;
+ static const int FlagEnum = 1 << 3;
+ static const int FlagAnonymousMixin = 1 << 4;
+ static const int FlagEliminatedMixin = 1 << 5;
+
+ int flags = 0;
+
+ bool get isAbstract => flags & FlagAbstract != 0;
+
+ void set isAbstract(bool value) {
+ flags = value ? (flags | FlagAbstract) : (flags & ~FlagAbstract);
+ }
/// Whether this class is an enum.
- bool isEnum = false;
+ bool get isEnum => flags & FlagEnum != 0;
+
+ void set isEnum(bool value) {
+ flags = value ? (flags | FlagEnum) : (flags & ~FlagEnum);
+ }
/// Whether this class is a synthetic implementation created for each
/// mixed-in class. For example the following code:
@@ -714,7 +732,22 @@
/// abstract class A&B&C&D extends A&B&C mixedIn D {}
/// class Z extends A&B&C&D {}
/// All X&Y classes are marked as synthetic.
- bool isSyntheticMixinImplementation;
+ bool get isAnonymousMixin => flags & FlagAnonymousMixin != 0;
+
+ void set isAnonymousMixin(bool value) {
+ flags =
+ value ? (flags | FlagAnonymousMixin) : (flags & ~FlagAnonymousMixin);
+ }
+
+ /// Whether this class was transformed from a mixin application.
+ /// In such case, its mixed-in type was pulled into the end of implemented
+ /// types list.
+ bool get isEliminatedMixin => flags & FlagEliminatedMixin != 0;
+
+ void set isEliminatedMixin(bool value) {
+ flags =
+ value ? (flags | FlagEliminatedMixin) : (flags & ~FlagEliminatedMixin);
+ }
/// The URI of the source file this class was loaded from.
Uri fileUri;
@@ -750,8 +783,8 @@
Class(
{this.name,
- this.isAbstract: false,
- this.isSyntheticMixinImplementation: false,
+ bool isAbstract: false,
+ bool isAnonymousMixin: false,
this.supertype,
this.mixedInType,
List<TypeParameter> typeParameters,
@@ -775,6 +808,8 @@
setParents(this.procedures, this);
setParents(this.fields, this);
setParents(this.redirectingFactoryConstructors, this);
+ this.isAbstract = isAbstract;
+ this.isAnonymousMixin = isAnonymousMixin;
}
void computeCanonicalNames() {
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index b75a3a3..5e01828 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -847,10 +847,8 @@
node.fileOffset = readOffset();
node.fileEndOffset = readOffset();
int flags = readByte();
- node.isAbstract = flags & 0x1 != 0;
- node.isEnum = flags & 0x2 != 0;
- node.isSyntheticMixinImplementation = flags & 0x4 != 0;
- int levelIndex = (flags >> 3) & 0x3;
+ node.flags = flags & ~Class.LevelMask;
+ int levelIndex = flags & Class.LevelMask;
var level = ClassLevel.values[levelIndex + 1];
if (level.index >= node.level.index) {
node.level = level;
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 156d80b..ed89e92 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -725,25 +725,18 @@
}
}
- int _encodeClassFlags(bool isAbstract, bool isEnum,
- bool isSyntheticMixinImplementation, ClassLevel level) {
- int abstractFlag = isAbstract ? 1 : 0;
- int isEnumFlag = isEnum ? 2 : 0;
- int isSyntheticMixinImplementationFlag =
- isSyntheticMixinImplementation ? 4 : 0;
- int levelFlags = (level.index - 1) << 3;
- return abstractFlag |
- isEnumFlag |
- isSyntheticMixinImplementationFlag |
- levelFlags;
+ int _encodeClassFlags(int flags, ClassLevel level) {
+ assert((flags & Class.LevelMask) == 0);
+ final levelIndex = level.index - 1;
+ assert((levelIndex & Class.LevelMask) == levelIndex);
+ return flags | levelIndex;
}
@override
void visitClass(Class node) {
classOffsets.add(getBufferOffset());
- int flags = _encodeClassFlags(node.isAbstract, node.isEnum,
- node.isSyntheticMixinImplementation, node.level);
+ int flags = _encodeClassFlags(node.flags, node.level);
if (node.canonicalName == null) {
throw 'Missing canonical name for $node';
}
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 1d016af..9bb574b0 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -135,7 +135,7 @@
/// Internal version of kernel binary format.
/// Bump it when making incompatible changes in kernel binaries.
/// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
- static const int BinaryFormatVersion = 6;
+ static const int BinaryFormatVersion = 7;
}
abstract class ConstantTag {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 3a9a036..ab527e5 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -23,7 +23,7 @@
{HandleAmbiguousSupertypes onAmbiguousSupertypes,
MixinInferrer mixinInferrer}) {
onAmbiguousSupertypes ??= (Class cls, Supertype a, Supertype b) {
- if (!cls.isSyntheticMixinImplementation) {
+ if (!cls.isAnonymousMixin) {
// See https://github.com/dart-lang/sdk/issues/32091
throw "$cls can't implement both $a and $b";
}
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 5553fd03..3a461aa1 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -52,7 +52,7 @@
return _activeFileUri == null ? TreeNode.noOffset : fileOffset;
}
- TreeNode clone(TreeNode node) {
+ T clone<T extends TreeNode>(T node) {
final Uri activeFileUriSaved = _activeFileUri;
if (node is FileUriNode) _activeFileUri = node.fileUri ?? _activeFileUri;
final TreeNode result = node.accept(this)
diff --git a/pkg/kernel/lib/transformations/async.dart b/pkg/kernel/lib/transformations/async.dart
index 72a0d20..21da8d9 100644
--- a/pkg/kernel/lib/transformations/async.dart
+++ b/pkg/kernel/lib/transformations/async.dart
@@ -454,15 +454,12 @@
}
TreeNode visitLet(Let expr) {
- var shouldName = seenAwait;
-
- seenAwait = false;
var body = expr.body.accept(this);
VariableDeclaration variable = expr.variable;
if (seenAwait) {
- // The body in `let var x = initializer in body` contained an await. We
- // will produce the sequence of statements:
+ // There is an await in the body of `let var x = initializer in body` or
+ // to its right. We will produce the sequence of statements:
//
// <initializer's statements>
// var x = <initializer's value>
@@ -488,7 +485,6 @@
} else {
// The body in `let x = initializer in body` did not contain an await. We
// can leave a let expression.
- seenAwait = shouldName;
return transform(expr, () {
// The body has already been translated.
expr.body = body..parent = expr;
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index d31f70a..05b814d 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -956,12 +956,15 @@
FunctionNode rewrite() {
var statements = <Statement>[];
- // The original function return type should be Future<T> because the
- // function is async. If it was, we make a Completer<T>. Otherwise
- // We will make a malformed type.
- // In an "Future<FooBar> foo() async {}" function the body can either return
- // a "FooBar" or a "Future<FooBar>" => a "FutureOr<FooBar>".
- final DartType valueType = elementTypeFromReturnType(helper.futureClass);
+ // The original function return type should be Future<T> or FutureOr<T>
+ // because the function is async. If it was, we make a Completer<T>,
+ // otherwise we make a malformed type. In a "Future<T> foo() async {}"
+ // function the body can either return a "T" or a "Future<T>" => a
+ // "FutureOr<T>".
+ DartType valueType = elementTypeFromReturnType(helper.futureClass);
+ if (valueType == const DynamicType()) {
+ valueType = elementTypeFromReturnType(helper.futureOrClass);
+ }
final DartType returnType =
new InterfaceType(helper.futureOrClass, <DartType>[valueType]);
var completerTypeArguments = <DartType>[valueType];
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index a2f392620..d546fe4 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -232,11 +232,15 @@
}
}
- // This class implements the mixin type.
+ // This class implements the mixin type. Also, backends rely on the fact
+ // that eliminated mixin is appended into the end of interfaces list.
class_.implementedTypes.add(class_.mixedInType);
// This class is now a normal class.
class_.mixedInType = null;
+
+ // Leave breadcrumbs for backends (e.g. for dart:mirrors implementation).
+ class_.isEliminatedMixin = true;
}
Constructor buildForwardingConstructor(
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index d84856f..db043a8 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -1,7 +1,7 @@
name: kernel
# Currently, kernel API is not stable and users should
# not depend on semver semantics when depending on this package.
-version: 0.3.0
+version: 0.3.1-alpha.0
author: Dart Team <misc@dartlang.org>
description: Dart IR (Intermediate Representation)
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
@@ -14,7 +14,7 @@
package_config: ^1.0.0
dev_dependencies:
analyzer: '>=0.31.0 <0.33.0'
- front_end: 0.1.0
+ front_end: 0.1.1-alpha.0
test: ^0.12.15+6
stack_trace: ^1.6.6
ansicolor: ^0.0.9
diff --git a/pkg/testing/lib/src/analyze.dart b/pkg/testing/lib/src/analyze.dart
index 4471201..f9a23ee 100644
--- a/pkg/testing/lib/src/analyze.dart
+++ b/pkg/testing/lib/src/analyze.dart
@@ -46,18 +46,23 @@
String optionsPath = json["options"];
Uri optionsUri = optionsPath == null ? null : base.resolve(optionsPath);
- List<Uri> uris = new List<Uri>.from(
- json["uris"].map((String relative) => base.resolve(relative)));
+ List<Uri> uris = json["uris"].map<Uri>((relative) {
+ String r = relative;
+ return base.resolve(r);
+ }).toList();
List<RegExp> exclude =
- new List<RegExp>.from(json["exclude"].map((String p) => new RegExp(p)));
+ json["exclude"].map<RegExp>((p) => new RegExp(p)).toList();
Map gitGrep = json["git grep"];
List<String> gitGrepPathspecs;
List<String> gitGrepPatterns;
if (gitGrep != null) {
- gitGrepPathspecs = gitGrep["pathspecs"] ?? const <String>["."];
- gitGrepPatterns = gitGrep["patterns"];
+ gitGrepPathspecs = gitGrep["pathspecs"] == null
+ ? const <String>["."]
+ : new List<String>.from(gitGrep["pathspecs"]);
+ if (gitGrep["patterns"] != null)
+ gitGrepPatterns = new List<String>.from(gitGrep["patterns"]);
}
return new Analyze(
diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart
index f93a31b..2a82f99 100644
--- a/pkg/testing/lib/src/chain.dart
+++ b/pkg/testing/lib/src/chain.dart
@@ -63,9 +63,9 @@
Uri uri = base.resolve(path);
Uri statusFile = base.resolve(json["status"]);
List<RegExp> pattern =
- new List<RegExp>.from(json["pattern"].map((String p) => new RegExp(p)));
+ json["pattern"].map<RegExp>((p) => new RegExp(p)).toList();
List<RegExp> exclude =
- new List<RegExp>.from(json["exclude"].map((String p) => new RegExp(p)));
+ json["exclude"].map<RegExp>((p) => new RegExp(p)).toList();
bool processMultitests = json["process-multitests"] ?? false;
return new Chain(name, kind, source, uri, statusFile, pattern, exclude,
processMultitests);
diff --git a/pkg/testing/lib/src/error_handling.dart b/pkg/testing/lib/src/error_handling.dart
index b0f2bac..bf13cb0 100644
--- a/pkg/testing/lib/src/error_handling.dart
+++ b/pkg/testing/lib/src/error_handling.dart
@@ -10,7 +10,7 @@
import 'dart:isolate' show ReceivePort;
-Future withErrorHandling(Future f()) async {
+Future<T> withErrorHandling<T>(Future<T> f()) async {
final ReceivePort port = new ReceivePort();
try {
return await f();
@@ -20,6 +20,7 @@
if (trace != null) {
stderr.writeln(trace);
}
+ return null;
} finally {
port.close();
}
diff --git a/pkg/testing/lib/src/expectation.dart b/pkg/testing/lib/src/expectation.dart
index 3ba1af80..8c8e7e9 100644
--- a/pkg/testing/lib/src/expectation.dart
+++ b/pkg/testing/lib/src/expectation.dart
@@ -78,7 +78,7 @@
const ExpectationSet(this.internalMap);
- operator [](String name) {
+ Expectation operator [](String name) {
return internalMap[name.toLowerCase()] ??
(throw "No expectation named: '$name'.");
}
diff --git a/pkg/testing/lib/src/run.dart b/pkg/testing/lib/src/run.dart
index c628a7a..a06d328 100644
--- a/pkg/testing/lib/src/run.dart
+++ b/pkg/testing/lib/src/run.dart
@@ -206,8 +206,10 @@
Future<Null> main() async {
if ($isVerbose) enableVerboseOutput();
- Map<String, String> environment = json.decode('${json.encode(environment)}');
- Set<String> selectors = json.decode('${json.encode(selectors)}').toSet();
+ Map<String, String> environment =
+ new Map<String, String>.from(json.decode('${json.encode(environment)}'));
+ Set<String> selectors =
+ new Set<String>.from(json.decode('${json.encode(selectors)}'));
await runTests(<String, Function> {
${splitLines(dart.toString().trim()).join(' ')}
});
diff --git a/pkg/testing/lib/src/run_tests.dart b/pkg/testing/lib/src/run_tests.dart
index d1860a1..ce0849d 100644
--- a/pkg/testing/lib/src/run_tests.dart
+++ b/pkg/testing/lib/src/run_tests.dart
@@ -39,11 +39,11 @@
Set<String> get skip => commaSeparated("--skip=");
Set<String> commaSeparated(String prefix) {
- return options.expand((String s) {
+ return new Set<String>.from(options.expand((String s) {
if (!s.startsWith(prefix)) return const [];
s = s.substring(prefix.length);
return s.split(",");
- }).toSet();
+ }));
}
Map<String, String> get environment {
@@ -167,8 +167,8 @@
print("Running tests took: ${sw.elapsed}.");
});
-Future<Null> runTests(Map<String, Function> tests) =>
- withErrorHandling(() async {
+Future<void> runTests(Map<String, Function> tests) =>
+ withErrorHandling<void>(() async {
int completed = 0;
for (String name in tests.keys) {
StringBuffer sb = new StringBuffer();
diff --git a/pkg/testing/lib/src/test_dart.dart b/pkg/testing/lib/src/test_dart.dart
index 98e2b82..8ac8457 100644
--- a/pkg/testing/lib/src/test_dart.dart
+++ b/pkg/testing/lib/src/test_dart.dart
@@ -29,7 +29,9 @@
factory TestDart.fromJsonMap(Uri base, Map json, String name, String kind) {
String common = json["common"] ?? "";
String processes = json["processes"] ?? "-j${Platform.numberOfProcessors}";
- List<String> commandLines = json["command-lines"] ?? <String>[];
+ List<String> commandLines = json["command-lines"] == null
+ ? new List<String>.from(json["command-lines"])
+ : <String>[];
return new TestDart(name, common, processes, commandLines);
}
diff --git a/pkg/testing/lib/src/test_dart/status_file_parser.dart b/pkg/testing/lib/src/test_dart/status_file_parser.dart
index 30b32c8..c756341 100644
--- a/pkg/testing/lib/src/test_dart/status_file_parser.dart
+++ b/pkg/testing/lib/src/test_dart/status_file_parser.dart
@@ -39,7 +39,7 @@
Section(this.statusFile, this.condition, this.lineNumber)
: testRules = new List<TestRule>();
- bool isEnabled(environment) =>
+ bool isEnabled(Map<String, String> environment) =>
condition == null || condition.evaluate(environment);
String toString() {
@@ -48,15 +48,15 @@
}
Future<TestExpectations> ReadTestExpectations(List<String> statusFilePaths,
- Map environment, ExpectationSet expectationSet) {
+ Map<String, String> environment, ExpectationSet expectationSet) {
var testExpectations = new TestExpectations(expectationSet);
return Future.wait(statusFilePaths.map((String statusFile) {
return ReadTestExpectationsInto(testExpectations, statusFile, environment);
})).then((_) => testExpectations);
}
-Future ReadTestExpectationsInto(
- TestExpectations expectations, String statusFilePath, environment) {
+Future<void> ReadTestExpectationsInto(TestExpectations expectations,
+ String statusFilePath, Map<String, String> environment) {
var completer = new Completer();
List<Section> sections = new List<Section>();
@@ -75,7 +75,7 @@
return completer.future;
}
-void ReadConfigurationInto(Path path, sections, onDone) {
+void ReadConfigurationInto(Path path, List<Section> sections, void onDone()) {
StatusFile statusFile = new StatusFile(path);
File file = new File(path.toNativePath());
if (!file.existsSync()) {
@@ -152,25 +152,25 @@
// Only create one copy of each Set<Expectation>.
// We just use .toString as a key, so we may make a few
// sets that only differ in their toString element order.
- static Map _cachedSets = new Map();
+ static Map<String, Set<Expectation>> _cachedSets = {};
final ExpectationSet expectationSet;
- Map _map;
+ Map<String, Set<Expectation>> _map;
bool _preprocessed = false;
- Map _regExpCache;
- Map _keyToRegExps;
+ Map<String, RegExp> _regExpCache;
+ Map<String, List<RegExp>> _keyToRegExps;
/**
* Create a TestExpectations object. See the [expectations] method
* for an explanation of matching.
*/
- TestExpectations(this.expectationSet) : _map = new Map();
+ TestExpectations(this.expectationSet) : _map = {};
/**
* Add a rule to the expectations.
*/
- void addRule(testRule, environment) {
+ void addRule(TestRule testRule, Map<String, String> environment) {
// Once we have started using the expectations we cannot add more
// rules.
if (_preprocessed) {
@@ -193,7 +193,7 @@
* "^$keyComponent\$" matches the corresponding filename component.
*/
Set<Expectation> expectations(String filename) {
- var result = new Set();
+ var result = new Set<Expectation>();
var splitFilename = filename.split('/');
// Create mapping from keys to list of RegExps once and for all.
@@ -224,13 +224,13 @@
void _preprocessForMatching() {
if (_preprocessed) return;
- _keyToRegExps = new Map();
- _regExpCache = new Map();
+ _keyToRegExps = {};
+ _regExpCache = {};
_map.forEach((key, expectations) {
if (_keyToRegExps[key] != null) return;
var splitKey = key.split('/');
- var regExps = new List(splitKey.length);
+ var regExps = new List<RegExp>(splitKey.length);
for (var i = 0; i < splitKey.length; i++) {
var component = splitKey[i];
var regExp = _regExpCache[component];
diff --git a/pkg/testing/lib/src/test_root.dart b/pkg/testing/lib/src/test_root.dart
index 16aa0c4..9e3b65e 100644
--- a/pkg/testing/lib/src/test_root.dart
+++ b/pkg/testing/lib/src/test_root.dart
@@ -75,8 +75,9 @@
Uri packages = uri.resolve(data["packages"]);
- List<Suite> suites = new List<Suite>.from(
- data["suites"].map((Map json) => new Suite.fromJsonMap(uri, json)));
+ List<Suite> suites = data["suites"]
+ .map<Suite>((json) => new Suite.fromJsonMap(uri, json))
+ .toList();
Analyze analyze = await Analyze.fromJsonMap(uri, data["analyze"], suites);
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index ba848ff..8bd4fe4 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -178,7 +178,7 @@
Future<Component> compileInternal(Uri script) async {
return requireMain
? kernelForProgram(script, options)
- : kernelForComponent([script], options..chaseDependencies = true);
+ : kernelForComponent([script], options);
}
}
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 1c7c2f8..0bf5ffb 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -441,7 +441,8 @@
final IOSink sink = new File(_kernelBinaryFilename).openWrite();
sink.add(serializeProcedure(procedure));
await sink.close();
- _outputStream.writeln('$boundaryKey $_kernelBinaryFilename');
+ _outputStream
+ .writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
_kernelBinaryFilename = _kernelBinaryFilenameIncremental;
} else {
_outputStream.writeln(boundaryKey);
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 7e7762f..332017e 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -117,12 +117,6 @@
// when building a platform dill file for VM/JIT case.
mixin_deduplication.transformComponent(component);
- if (useGlobalTypeFlowAnalysis) {
- globalTypeFlow.transformComponent(coreTypes, component, entryPoints);
- } else {
- devirtualization.transformComponent(coreTypes, component);
- }
-
if (enableConstantEvaluation) {
await _performConstantEvaluation(source, compilerOptions, component,
coreTypes, environmentDefines, strongMode, enableAsserts);
@@ -130,6 +124,12 @@
if (errorDetector.hasCompilationErrors) return;
}
+ if (useGlobalTypeFlowAnalysis) {
+ globalTypeFlow.transformComponent(coreTypes, component, entryPoints);
+ } else {
+ devirtualization.transformComponent(coreTypes, component);
+ }
+
no_dynamic_invocations_annotator.transformComponent(component);
}
}
@@ -145,8 +145,7 @@
final vmConstants =
new vm_constants.VmConstantsBackend(environmentDefines, coreTypes);
- final processedOptions =
- new ProcessedOptions(compilerOptions, false, [source]);
+ final processedOptions = new ProcessedOptions(compilerOptions, [source]);
// Run within the context, so we have uri source tokens...
await CompilerContext.runWithOptions(processedOptions,
@@ -159,8 +158,8 @@
final typeEnvironment =
new TypeEnvironment(coreTypes, hierarchy, strongMode: strongMode);
- // TODO(kustermann): We should use the entrypoints manifest to find out
- // which fields need to be preserved and remove the rest.
+ // TFA will remove constants fields which are unused (and respects the
+ // vm/embedder entrypoints).
constants.transformComponent(component, vmConstants,
keepFields: true,
strongMode: true,
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index 2daf9a0..68ade75 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -79,7 +79,7 @@
_transformSupertype(c);
}
- if (!c.isSyntheticMixinImplementation) {
+ if (!c.isAnonymousMixin) {
return c;
}
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 71ee83e..40a3e79 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -611,20 +611,65 @@
}
}
+/// Keeps track of number of cached [_Invocation] objects with
+/// a particular selector and provides approximation if needed.
+class _SelectorApproximation {
+ /// Approximation [_Invocation] with raw arguments is created and used
+ /// after number of [_Invocation] objects with same selector but
+ /// different arguments reaches this limit.
+ static const int maxInvocationsPerSelector = 5000;
+
+ int count = 0;
+ _Invocation approximation;
+}
+
+/// Maintains ([Selector], [Args]) => [_Invocation] cache.
+/// Invocations are cached in order to reuse previously calculated result.
class _InvocationsCache {
+ final TypeFlowAnalysis _typeFlowAnalysis;
final Set<_Invocation> _invocations = new Set<_Invocation>();
+ final Map<Selector, _SelectorApproximation> _approximations =
+ <Selector, _SelectorApproximation>{};
+
+ _InvocationsCache(this._typeFlowAnalysis);
_Invocation getInvocation(Selector selector, Args<Type> args) {
+ ++Statistics.invocationsQueriedInCache;
_Invocation invocation = (selector is DirectSelector)
? new _DirectInvocation(selector, args)
: new _DispatchableInvocation(selector, args);
_Invocation result = _invocations.lookup(invocation);
- if (result == null) {
- bool added = _invocations.add(invocation);
- assertx(added);
- result = invocation;
+ if (result != null) {
+ return result;
}
- return result;
+
+ if (selector is InterfaceSelector) {
+ // Detect if there are too many invocations per selector. In such case,
+ // approximate extra invocations with a single invocation with raw
+ // arguments.
+
+ final sa = (_approximations[selector] ??= new _SelectorApproximation());
+
+ if (sa.count >= _SelectorApproximation.maxInvocationsPerSelector) {
+ if (sa.approximation == null) {
+ final rawArgs =
+ _typeFlowAnalysis.summaryCollector.rawArguments(selector);
+ sa.approximation = new _DispatchableInvocation(selector, rawArgs);
+ Statistics.approximateInvocationsCreated++;
+ }
+ Statistics.approximateInvocationsUsed++;
+ return sa.approximation;
+ }
+
+ ++sa.count;
+ Statistics.maxInvocationsCachedPerSelector =
+ max(Statistics.maxInvocationsCachedPerSelector, sa.count);
+ }
+
+ bool added = _invocations.add(invocation);
+ assertx(added);
+ ++Statistics.invocationsAddedToCache;
+ return invocation;
}
}
@@ -1010,6 +1055,7 @@
void process() {
while (pending.isNotEmpty) {
assertx(callStack.isEmpty && processing.isEmpty);
+ Statistics.iterationsOverInvocationsWorkList++;
processInvocation(pending.first);
}
}
@@ -1060,6 +1106,7 @@
// Invocation is still pending - it was invalidated while being processed.
// Move result to invalidatedResult.
if (_isPending(invocation)) {
+ Statistics.invocationsInvalidatedDuringProcessing++;
invocation.invalidatedResult = result;
invocation.result = null;
}
@@ -1095,7 +1142,7 @@
final NativeCodeOracle nativeCodeOracle;
_ClassHierarchyCache hierarchyCache;
SummaryCollector summaryCollector;
- _InvocationsCache _invocationsCache = new _InvocationsCache();
+ _InvocationsCache _invocationsCache;
_WorkList workList;
final Map<Member, Summary> _summaries = <Member, Summary>{};
@@ -1108,6 +1155,7 @@
hierarchyCache = new _ClassHierarchyCache(this, hierarchy);
summaryCollector =
new SummaryCollector(environment, this, nativeCodeOracle);
+ _invocationsCache = new _InvocationsCache(this);
workList = new _WorkList(this);
if (entryPointsJSONFiles != null) {
@@ -1186,6 +1234,11 @@
/// ---- Implementation of [EntryPointsListener] interface. ----
@override
+ void addDirectFieldAccess(Field field, Type value) {
+ getFieldValue(field).setValue(value, this);
+ }
+
+ @override
void addRawCall(Selector selector) {
if (kPrintDebug) {
debugPrint("ADD RAW CALL: $selector");
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index e01aed4..d3f72d6 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -24,6 +24,9 @@
/// Add call by the given selector with arbitrary ('raw') arguments.
void addRawCall(Selector selector);
+ /// Sets the type of the given field.
+ void addDirectFieldAccess(Field field, Type value);
+
/// Add instantiation of the given class.
ConcreteType addAllocatedClass(Class c);
}
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 01e6738..4e260da 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -253,9 +253,12 @@
Map<VariableDeclaration, Join> _variables;
Join _returnValue;
Parameter _receiver;
+ ConstantAllocationCollector constantAllocationCollector;
SummaryCollector(
- this._environment, this._entryPointsListener, this._nativeCodeOracle);
+ this._environment, this._entryPointsListener, this._nativeCodeOracle) {
+ constantAllocationCollector = new ConstantAllocationCollector(this);
+ }
Summary createSummary(Member member) {
debugPrint("===== ${member} =====");
@@ -444,10 +447,17 @@
_summary.add(param);
assertx(param.index < _summary.parameterCount);
if (param.index >= _summary.requiredParameterCount) {
- // TODO(alexmarkov): get actual type of constant initializer
- param.defaultValue = (initializer != null)
- ? new Type.fromStatic(initializer.getStaticType(_environment))
- : _nullType;
+ if (initializer != null) {
+ if (initializer is ConstantExpression) {
+ param.defaultValue =
+ constantAllocationCollector.typeFor(initializer.constant);
+ } else {
+ param.defaultValue =
+ new Type.fromStatic(initializer.getStaticType(_environment));
+ }
+ } else {
+ param.defaultValue = _nullType;
+ }
} else {
assertx(initializer == null);
}
@@ -1182,6 +1192,11 @@
@override
visitInvalidInitializer(InvalidInitializer node) {}
+
+ @override
+ TypeExpr visitConstantExpression(ConstantExpression node) {
+ return constantAllocationCollector.typeFor(node.constant);
+ }
}
class EmptyEntryPointsListener implements EntryPointsListener {
@@ -1192,6 +1207,9 @@
void addRawCall(Selector selector) {}
@override
+ void addDirectFieldAccess(Field field, Type value) {}
+
+ @override
ConcreteType addAllocatedClass(Class c) {
final classId = (_classIds[c] ??= new IntClassId(++_classIdCounter));
return new ConcreteType(classId, c.rawType);
@@ -1213,3 +1231,91 @@
}
}
}
+
+class ConstantAllocationCollector extends ConstantVisitor<Type> {
+ final SummaryCollector summaryCollector;
+
+ final Map<Constant, Type> constants = <Constant, Type>{};
+
+ ConstantAllocationCollector(this.summaryCollector);
+
+ // Ensures the transtive graph of [constant] got scanned for potential
+ // allocations and field types. Returns the [Type] of this constant.
+ Type typeFor(Constant constant) {
+ return constants.putIfAbsent(constant, () => constant.accept(this));
+ }
+
+ @override
+ defaultConstant(Constant constant) {
+ throw 'There is no support for constant "$constant" in TFA yet!';
+ }
+
+ @override
+ Type visitNullConstant(NullConstant constant) {
+ return summaryCollector._nullType;
+ }
+
+ @override
+ Type visitBoolConstant(BoolConstant constant) {
+ return summaryCollector._boolType;
+ }
+
+ @override
+ Type visitIntConstant(IntConstant constant) {
+ return summaryCollector._intType;
+ }
+
+ @override
+ Type visitDoubleConstant(DoubleConstant constant) {
+ return summaryCollector._doubleType;
+ }
+
+ @override
+ Type visitStringConstant(StringConstant constant) {
+ return summaryCollector._stringType;
+ }
+
+ @override
+ Type visitMapConstant(MapConstant node) {
+ throw 'The kernel2kernel constants transformation desugars const maps!';
+ }
+
+ @override
+ Type visitListConstant(ListConstant constant) {
+ for (final Constant entry in constant.entries) {
+ typeFor(entry);
+ }
+ return new Type.cone(constant.getType(summaryCollector._environment));
+ }
+
+ @override
+ Type visitInstanceConstant(InstanceConstant constant) {
+ final resultType =
+ summaryCollector._entryPointsListener.addAllocatedClass(constant.klass);
+ constant.fieldValues.forEach((Reference fieldReference, Constant value) {
+ summaryCollector._entryPointsListener
+ .addDirectFieldAccess(fieldReference.asField, typeFor(value));
+ });
+ return resultType;
+ }
+
+ @override
+ Type visitTearOffConstant(TearOffConstant constant) {
+ final Procedure procedure = constant.procedure;
+ summaryCollector._entryPointsListener
+ .addRawCall(new DirectSelector(procedure));
+ return new Type.cone(constant.getType(summaryCollector._environment));
+ }
+
+ @override
+ Type visitPartialInstantiationConstant(
+ PartialInstantiationConstant constant) {
+ constant.tearOffConstant.accept(this);
+ return new Type.cone(constant.getType(summaryCollector._environment));
+ }
+
+ @override
+ Type visitTypeLiteralConstant(TypeLiteralConstant constant) {
+ return new Type.cone(constant.getType(summaryCollector._environment));
+ }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index ce9998f..b3a037a 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -297,11 +297,13 @@
final Set<Member> _usedMembers = new Set<Member>();
final Set<Typedef> _usedTypedefs = new Set<Typedef>();
_TreeShakerTypeVisitor typeVisitor;
+ _TreeShakerConstantVisitor constantVisitor;
_TreeShakerPass1 _pass1;
_TreeShakerPass2 _pass2;
TreeShaker(Component component, this.typeFlowAnalysis) {
typeVisitor = new _TreeShakerTypeVisitor(this);
+ constantVisitor = new _TreeShakerConstantVisitor(this, typeVisitor);
_pass1 = new _TreeShakerPass1(this);
_pass2 = new _TreeShakerPass2(this);
}
@@ -652,6 +654,12 @@
}
@override
+ TreeNode visitConstantExpression(ConstantExpression node) {
+ shaker.constantVisitor.analyzeConstant(node.constant);
+ return node;
+ }
+
+ @override
TreeNode visitStaticSet(StaticSet node) {
node.transformChildren(this);
if (_isUnreachable(node)) {
@@ -889,3 +897,75 @@
return node; // Do not traverse into other nodes.
}
}
+
+class _TreeShakerConstantVisitor extends ConstantVisitor<Null> {
+ final TreeShaker shaker;
+ final _TreeShakerTypeVisitor typeVisitor;
+ final Set<Constant> constants = new Set<Constant>();
+ final Set<InstanceConstant> instanceConstants = new Set<InstanceConstant>();
+
+ _TreeShakerConstantVisitor(this.shaker, this.typeVisitor);
+
+ analyzeConstant(Constant constant) {
+ if (constants.add(constant)) {
+ constant.accept(this);
+ }
+ }
+
+ @override
+ defaultConstant(Constant constant) {
+ throw 'There is no support for constant "$constant" in TFA yet!';
+ }
+
+ @override
+ visitNullConstant(NullConstant constant) {}
+
+ @override
+ visitBoolConstant(BoolConstant constant) {}
+
+ @override
+ visitIntConstant(IntConstant constant) {}
+
+ @override
+ visitDoubleConstant(DoubleConstant constant) {}
+
+ @override
+ visitStringConstant(StringConstant constant) {}
+
+ @override
+ visitMapConstant(MapConstant node) {
+ throw 'The kernel2kernel constants transformation desugars const maps!';
+ }
+
+ @override
+ visitListConstant(ListConstant constant) {
+ for (final Constant entry in constant.entries) {
+ analyzeConstant(entry);
+ }
+ }
+
+ @override
+ visitInstanceConstant(InstanceConstant constant) {
+ instanceConstants.add(constant);
+ shaker.addClassUsedInType(constant.klass);
+ constant.fieldValues.forEach((Reference fieldRef, Constant value) {
+ shaker.addUsedMember(fieldRef.asField);
+ analyzeConstant(value);
+ });
+ }
+
+ @override
+ visitTearOffConstant(TearOffConstant constant) {
+ shaker.addUsedMember(constant.procedure);
+ }
+
+ @override
+ visitPartialInstantiationConstant(PartialInstantiationConstant constant) {
+ analyzeConstant(constant.tearOffConstant);
+ }
+
+ @override
+ visitTypeLiteralConstant(TypeLiteralConstant constant) {
+ constant.type.accept(typeVisitor);
+ }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index de0d7a0..3ce56e8 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -78,6 +78,13 @@
static int maxInvalidationsPerInvocation = 0;
static int recursiveInvocationsApproximated = 0;
static int typeConeSpecializations = 0;
+ static int iterationsOverInvocationsWorkList = 0;
+ static int invocationsInvalidatedDuringProcessing = 0;
+ static int invocationsQueriedInCache = 0;
+ static int invocationsAddedToCache = 0;
+ static int maxInvocationsCachedPerSelector = 0;
+ static int approximateInvocationsCreated = 0;
+ static int approximateInvocationsUsed = 0;
static int classesDropped = 0;
static int membersDropped = 0;
static int methodBodiesDropped = 0;
@@ -97,6 +104,13 @@
maxInvalidationsPerInvocation = 0;
recursiveInvocationsApproximated = 0;
typeConeSpecializations = 0;
+ iterationsOverInvocationsWorkList = 0;
+ invocationsInvalidatedDuringProcessing = 0;
+ invocationsQueriedInCache = 0;
+ invocationsAddedToCache = 0;
+ maxInvocationsCachedPerSelector = 0;
+ approximateInvocationsCreated = 0;
+ approximateInvocationsUsed = 0;
classesDropped = 0;
membersDropped = 0;
methodBodiesDropped = 0;
@@ -117,6 +131,13 @@
${maxInvalidationsPerInvocation} maximum invalidations per invocation
${recursiveInvocationsApproximated} recursive invocations approximated
${typeConeSpecializations} type cones specialized
+ ${iterationsOverInvocationsWorkList} iterations over invocations work list
+ ${invocationsInvalidatedDuringProcessing} invocations invalidated during processing
+ ${invocationsQueriedInCache} invocations queried in cache
+ ${invocationsAddedToCache} invocations added to cache
+ ${maxInvocationsCachedPerSelector} maximum invocations cached per selector
+ ${approximateInvocationsCreated} approximate invocations created
+ ${approximateInvocationsUsed} times approximate invocation is used
${classesDropped} classes dropped
${membersDropped} members dropped
${methodBodiesDropped} method bodies dropped
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index ba2cf03..2a35304 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -519,16 +519,12 @@
receivedResults.stream.listen((String outputFilenameAndErrorCount) {
if (count == 0) {
// First request is to 'compile', which results in full kernel file.
- int delim = outputFilenameAndErrorCount.lastIndexOf(' ');
- expect(delim > 0, equals(true));
- String outputFilename =
- outputFilenameAndErrorCount.substring(0, delim);
- int errorsCount = int
- .parse(outputFilenameAndErrorCount.substring(delim + 1).trim());
+ CompilationResult result =
+ new CompilationResult.parse(outputFilenameAndErrorCount);
expect(dillFile.existsSync(), equals(true));
- expect(outputFilename, dillFile.path);
- expect(errorsCount, equals(0));
+ expect(result.filename, dillFile.path);
+ expect(result.errorsCount, equals(0));
streamController.add('accept\n'.codeUnits);
// 'compile-expression <boundarykey>
@@ -558,7 +554,11 @@
// Second request is to 'compile-expression', which results in
// kernel file with a function that wraps compiled expression.
expect(outputFilenameAndErrorCount, isNotNull);
- File outputFile = new File(outputFilenameAndErrorCount);
+ CompilationResult result =
+ new CompilationResult.parse(outputFilenameAndErrorCount);
+
+ expect(result.errorsCount, equals(0));
+ File outputFile = new File(result.filename);
expect(outputFile.existsSync(), equals(true));
expect(outputFile.lengthSync(), isPositive);
@@ -567,11 +567,10 @@
} else {
expect(count, 3);
// Third request is to 'compile' non-existent file, that should fail.
- int delim = outputFilenameAndErrorCount.lastIndexOf(' ');
- expect(delim > 0, equals(true));
- int errorsCount = int
- .parse(outputFilenameAndErrorCount.substring(delim + 1).trim());
- expect(errorsCount, greaterThan(0));
+ expect(outputFilenameAndErrorCount, isNotNull);
+ CompilationResult result =
+ new CompilationResult.parse(outputFilenameAndErrorCount);
+ expect(result.errorsCount, greaterThan(0));
allDone.complete(true);
}
});
@@ -623,16 +622,13 @@
int count = 0;
Completer<bool> allDone = new Completer<bool>();
receivedResults.stream.listen((String outputFilenameAndErrorCount) {
- int delim = outputFilenameAndErrorCount.lastIndexOf(' ');
- expect(delim > 0, equals(true));
- String outputFilename = outputFilenameAndErrorCount.substring(0, delim);
- int errorsCount =
- int.parse(outputFilenameAndErrorCount.substring(delim + 1).trim());
+ CompilationResult result =
+ new CompilationResult.parse(outputFilenameAndErrorCount);
if (count == 0) {
// First request is to 'compile', which results in full kernel file.
expect(dillFile.existsSync(), equals(true));
- expect(outputFilename, dillFile.path);
- expect(errorsCount, 0);
+ expect(result.filename, dillFile.path);
+ expect(result.errorsCount, 0);
count += 1;
streamController.add('accept\n'.codeUnits);
var file2 = new File('${tempDir.path}/bar.dart')..createSync();
@@ -646,8 +642,8 @@
// Second request is to 'recompile', which results in incremental
// kernel file.
var dillIncFile = new File('${dillFile.path}.incremental.dill');
- expect(outputFilename, dillIncFile.path);
- expect(errorsCount, 0);
+ expect(result.filename, dillIncFile.path);
+ expect(result.errorsCount, 0);
expect(dillIncFile.existsSync(), equals(true));
allDone.complete(true);
}
@@ -699,16 +695,13 @@
int count = 0;
Completer<bool> allDone = new Completer<bool>();
receivedResults.stream.listen((String outputFilenameAndErrorCount) {
- int delim = outputFilenameAndErrorCount.lastIndexOf(' ');
- expect(delim > 0, equals(true));
- String outputFilename = outputFilenameAndErrorCount.substring(0, delim);
- int errorsCount =
- int.parse(outputFilenameAndErrorCount.substring(delim + 1).trim());
+ CompilationResult result =
+ new CompilationResult.parse(outputFilenameAndErrorCount);
switch (count) {
case 0:
expect(dillFile.existsSync(), equals(true));
- expect(outputFilename, dillFile.path);
- expect(errorsCount, 2);
+ expect(result.filename, dillFile.path);
+ expect(result.errorsCount, 2);
count += 1;
streamController.add('accept\n'.codeUnits);
var file2 = new File('${tempDir.path}/bar.dart')..createSync();
@@ -720,8 +713,8 @@
break;
case 1:
var dillIncFile = new File('${dillFile.path}.incremental.dill');
- expect(outputFilename, dillIncFile.path);
- expect(errorsCount, 1);
+ expect(result.filename, dillIncFile.path);
+ expect(result.errorsCount, 1);
count += 1;
streamController.add('accept\n'.codeUnits);
var file2 = new File('${tempDir.path}/bar.dart')..createSync();
@@ -733,8 +726,8 @@
break;
case 2:
var dillIncFile = new File('${dillFile.path}.incremental.dill');
- expect(outputFilename, dillIncFile.path);
- expect(errorsCount, 0);
+ expect(result.filename, dillIncFile.path);
+ expect(result.errorsCount, 0);
expect(dillIncFile.existsSync(), equals(true));
allDone.complete(true);
}
@@ -811,3 +804,15 @@
return vmDirectory;
}
}
+
+class CompilationResult {
+ String filename;
+ int errorsCount;
+
+ CompilationResult.parse(String filenameAndErrorCount) {
+ int delim = filenameAndErrorCount.lastIndexOf(' ');
+ expect(delim > 0, equals(true));
+ filename = filenameAndErrorCount.substring(0, delim);
+ errorsCount = int.parse(filenameAndErrorCount.substring(delim + 1).trim());
+ }
+}
diff --git a/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index 64908b5..d707213 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -17,6 +17,7 @@
OPTIONS=()
GEN_KERNEL_OPTIONS=()
PACKAGES=
+BUILD_ELF=0
ARGV=()
for arg in "$@"; do
@@ -35,6 +36,9 @@
-D* )
GEN_KERNEL_OPTIONS+=("$arg")
;;
+ --build-elf)
+ BUILD_ELF=1
+ ;;
--*)
OPTIONS+=("$arg")
;;
@@ -52,6 +56,13 @@
SOURCE_FILE="${ARGV[0]}"
SNAPSHOT_FILE="${ARGV[1]}"
+if [ $BUILD_ELF -eq 1 ]; then
+ DART_BOOTSTRAP_OUT="${SNAPSHOT_FILE}.S"
+else
+ OPTIONS=("--use-blobs" "${OPTIONS[@]}")
+ DART_BOOTSTRAP_OUT="${SNAPSHOT_FILE}"
+fi
+
function follow_links() {
file="$1"
while [ -h "$file" ]; do
@@ -95,12 +106,16 @@
"$SOURCE_FILE"
# Step 2: Generate snapshot from the Kernel binary.
-exec "$BIN_DIR"/dart_bootstrap \
+"$BIN_DIR"/dart_bootstrap \
--strong \
--reify-generic-functions \
--limit-ints-to-64-bits \
--snapshot-kind=app-aot \
- --use-blobs \
- --snapshot="$SNAPSHOT_FILE" \
+ --snapshot="$DART_BOOTSTRAP_OUT" \
"${OPTIONS[@]}" \
"$SNAPSHOT_FILE.dill"
+
+# Step 3: Assemble the assembly file into an ELF object.
+if [ $BUILD_ELF -eq 1 ]; then
+ gcc -shared -o "$SNAPSHOT_FILE" "$DART_BOOTSTRAP_OUT"
+fi
\ No newline at end of file
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 2062431..2d4aa56 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -40,7 +40,10 @@
config("dart_precompiled_runtime_config") {
defines = []
- defines += [ "DART_PRECOMPILED_RUNTIME" ]
+ defines += [
+ "DART_PRECOMPILED_RUNTIME",
+ "EXCLUDE_CFE_AND_KERNEL_PLATFORM",
+ ]
}
# Controls DART_PRECOMPILER #define.
@@ -149,9 +152,7 @@
if (is_fuchsia) {
import("//build/config/scudo/scudo.gni")
- include_dirs += [
- "//zircon/system/ulib/zx/include",
- ]
+ include_dirs += [ "//zircon/system/ulib/zx/include" ]
if (!use_scudo) {
defines += [ "DART_USE_JEMALLOC" ]
include_dirs += [ "//zircon/third_party/ulib/jemalloc/include" ]
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 970dad7..577560e 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -901,6 +901,9 @@
}
defines = extra_defines
+ if (exclude_kernel_service) {
+ defines += [ "EXCLUDE_CFE_AND_KERNEL_PLATFORM" ]
+ }
if (dart_use_tcmalloc) {
deps += [ "//third_party/tcmalloc" ]
@@ -955,9 +958,6 @@
if (dart_runtime_mode != "release") {
extra_deps += [ "../observatory:standalone_observatory_archive" ]
}
- if (dart_runtime_mode != "release") {
- extra_deps += [ ":dart_kernel_platform_cc" ]
- }
extra_sources = [
"builtin_nolib.cc",
"dfe.cc",
@@ -971,6 +971,9 @@
if (dart_runtime_mode == "release") {
extra_sources += [ "observatory_assets_empty.cc" ]
}
+ if (!exclude_kernel_service) {
+ extra_deps += [ ":dart_kernel_platform_cc" ]
+ }
}
dart_executable("dart_precompiled_runtime") {
@@ -1038,9 +1041,6 @@
":generate_web_sql_cc_file",
"..:libdart_nosnapshot_with_precompiler",
]
- if (dart_runtime_mode != "release") {
- extra_deps += [ ":dart_kernel_platform_cc" ]
- }
extra_defines = [ "NO_OBSERVATORY" ]
extra_sources = [
"builtin.cc",
@@ -1073,6 +1073,9 @@
"$target_gen_dir/web_gl_gen.cc",
"$target_gen_dir/web_sql_gen.cc",
]
+ if (!exclude_kernel_service) {
+ extra_deps += [ ":dart_kernel_platform_cc" ]
+ }
}
executable("process_test") {
diff --git a/runtime/bin/common_patch.dart b/runtime/bin/common_patch.dart
index 0e46769..d5db154 100644
--- a/runtime/bin/common_patch.dart
+++ b/runtime/bin/common_patch.dart
@@ -23,7 +23,7 @@
import "dart:collection" show HashMap;
-import "dart:convert" show Encoding;
+import "dart:convert" show Encoding, utf8;
import "dart:developer" show registerExtension;
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index a5d1d83..df3d515 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -85,7 +85,9 @@
int64_t DartUtils::GetIntegerValue(Dart_Handle value_obj) {
int64_t value = 0;
Dart_Handle result = Dart_IntegerToInt64(value_obj, &value);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
return value;
}
@@ -102,7 +104,9 @@
intptr_t DartUtils::GetIntptrValue(Dart_Handle value_obj) {
int64_t value = 0;
Dart_Handle result = Dart_IntegerToInt64(value_obj, &value);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
if (value < kIntptrMin || kIntptrMax < value) {
Dart_PropagateError(Dart_NewApiError("Value outside intptr_t range"));
}
@@ -113,28 +117,85 @@
bool valid = Dart_IsInteger(value_obj);
if (valid) {
Dart_Handle result = Dart_IntegerFitsIntoInt64(value_obj, &valid);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
}
if (!valid) return false;
Dart_Handle result = Dart_IntegerToInt64(value_obj, value);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
return true;
}
const char* DartUtils::GetStringValue(Dart_Handle str_obj) {
const char* cstring = NULL;
Dart_Handle result = Dart_StringToCString(str_obj, &cstring);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
return cstring;
}
bool DartUtils::GetBooleanValue(Dart_Handle bool_obj) {
bool value = false;
Dart_Handle result = Dart_BooleanValue(bool_obj, &value);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
return value;
}
+bool DartUtils::GetNativeBooleanArgument(Dart_NativeArguments args,
+ intptr_t index) {
+ bool value = false;
+ Dart_Handle result = Dart_GetNativeBooleanArgument(args, index, &value);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ return value;
+}
+
+int64_t DartUtils::GetNativeIntegerArgument(Dart_NativeArguments args,
+ intptr_t index) {
+ int64_t value = 0;
+ Dart_Handle result = Dart_GetNativeIntegerArgument(args, index, &value);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ return value;
+}
+
+intptr_t DartUtils::GetNativeIntptrArgument(Dart_NativeArguments args,
+ intptr_t index) {
+ int64_t value = GetNativeIntegerArgument(args, index);
+ if (value < kIntptrMin || kIntptrMax < value) {
+ Dart_PropagateError(Dart_NewApiError("Value outside intptr_t range"));
+ }
+ return static_cast<intptr_t>(value);
+}
+
+const char* DartUtils::GetNativeStringArgument(Dart_NativeArguments args,
+ intptr_t index) {
+ char* tmp = NULL;
+ Dart_Handle result =
+ Dart_GetNativeStringArgument(args, index, reinterpret_cast<void**>(&tmp));
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ if (tmp != NULL) {
+ return tmp;
+ }
+ const char* cstring = NULL;
+ result = Dart_StringToCString(result, &cstring);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ ASSERT(cstring != NULL);
+ return cstring;
+}
+
Dart_Handle DartUtils::SetIntegerField(Dart_Handle handle,
const char* name,
int64_t val) {
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 2ae7ca6..7c4a735 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -103,7 +103,23 @@
// Returns the boolean value of a Dart object. If the object is not
// a boolean value an API error is propagated.
static bool GetBooleanValue(Dart_Handle bool_obj);
-
+ // Returns the boolean value of the argument at index. If the argument
+ // is not a boolean value an API error is propagated.
+ static bool GetNativeBooleanArgument(Dart_NativeArguments args,
+ intptr_t index);
+ // Returns the integer value of the argument at index. If the argument
+ // is not an integer value an API error is propagated.
+ static int64_t GetNativeIntegerArgument(Dart_NativeArguments args,
+ intptr_t index);
+ // Returns the intptr_t value of the argument at index. If the argument
+ // is not an integer value or the value is outside the intptr_t range an
+ // API error is propagated.
+ static intptr_t GetNativeIntptrArgument(Dart_NativeArguments args,
+ intptr_t index);
+ // Returns the string value of the argument at index. If the argument
+ // is not a string value an API error is propagated.
+ static const char* GetNativeStringArgument(Dart_NativeArguments args,
+ intptr_t index);
static Dart_Handle SetIntegerField(Dart_Handle handle,
const char* name,
int64_t val);
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 2f55937..de20ad9 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -2,11 +2,17 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+#include <cstdlib>
+#include <memory>
+
#include "bin/directory.h"
#include "bin/dartutils.h"
+#include "bin/io_buffer.h"
#include "bin/log.h"
#include "bin/namespace.h"
+#include "bin/typed_data_utils.h"
+#include "bin/utils.h"
#include "include/dart_api.h"
#include "platform/assert.h"
@@ -28,14 +34,23 @@
void FUNCTION_NAME(Directory_SetCurrent)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
Dart_Handle path = Dart_GetNativeArgument(args, 1);
- if (Dart_IsError(path) || !Dart_IsString(path)) {
- Dart_SetReturnValue(args, DartUtils::NewDartArgumentError(NULL));
- return;
+ OSError os_error;
+ ASSERT(!Dart_IsError(path));
+ bool result;
+ {
+ TypedDataScope data(path);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ result = Directory::SetCurrent(namespc, name);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
}
- if (Directory::SetCurrent(namespc, DartUtils::GetStringValue(path))) {
+ if (result) {
Dart_SetBooleanReturnValue(args, true);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
@@ -44,24 +59,47 @@
static const int kDoesNotExist = 0;
Namespace* namespc = Namespace::GetNamespace(args, 0);
Dart_Handle path = Dart_GetNativeArgument(args, 1);
- Directory::ExistsResult result =
- Directory::Exists(namespc, DartUtils::GetStringValue(path));
+ OSError os_error;
+ Directory::ExistsResult result;
+ {
+ TypedDataScope data(path);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ result = Directory::Exists(namespc, name);
+ if ((result != Directory::DOES_NOT_EXIST) &&
+ (result != Directory::EXISTS)) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (result == Directory::EXISTS) {
Dart_SetIntegerReturnValue(args, kExists);
} else if (result == Directory::DOES_NOT_EXIST) {
Dart_SetIntegerReturnValue(args, kDoesNotExist);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(Directory_Create)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
Dart_Handle path = Dart_GetNativeArgument(args, 1);
- if (Directory::Create(namespc, DartUtils::GetStringValue(path))) {
+ OSError os_error;
+ bool result;
+ {
+ TypedDataScope data(path);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ result = Directory::Create(namespc, name);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
+ if (result) {
Dart_SetBooleanReturnValue(args, true);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
@@ -74,42 +112,68 @@
void FUNCTION_NAME(Directory_CreateTemp)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
Dart_Handle path = Dart_GetNativeArgument(args, 1);
- if (!Dart_IsString(path)) {
- Dart_SetReturnValue(
- args, DartUtils::NewDartArgumentError(
- "Prefix argument of CreateSystemTempSync is not a String"));
- return;
+ OSError os_error;
+ const char* result = NULL;
+ {
+ TypedDataScope data(path);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ result = Directory::CreateTemp(namespc, name);
+ if (result == NULL) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
}
- const char* result =
- Directory::CreateTemp(namespc, DartUtils::GetStringValue(path));
if (result != NULL) {
Dart_SetReturnValue(args, DartUtils::NewString(result));
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(Directory_Delete)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
Dart_Handle path = Dart_GetNativeArgument(args, 1);
- Dart_Handle recursive = Dart_GetNativeArgument(args, 2);
- if (Directory::Delete(namespc, DartUtils::GetStringValue(path),
- DartUtils::GetBooleanValue(recursive))) {
+ OSError os_error;
+ bool result;
+ {
+ TypedDataScope data(path);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ result = Directory::Delete(namespc, name,
+ DartUtils::GetNativeBooleanArgument(args, 2));
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
+ if (result) {
Dart_SetBooleanReturnValue(args, true);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(Directory_Rename)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
Dart_Handle path = Dart_GetNativeArgument(args, 1);
- Dart_Handle newPath = Dart_GetNativeArgument(args, 2);
- if (Directory::Rename(namespc, DartUtils::GetStringValue(path),
- DartUtils::GetStringValue(newPath))) {
+ OSError os_error;
+ bool result;
+ {
+ TypedDataScope data(path);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ result = Directory::Rename(namespc, name,
+ DartUtils::GetNativeStringArgument(args, 2));
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
+ if (result) {
Dart_SetBooleanReturnValue(args, true);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
@@ -119,17 +183,22 @@
// The list that we should fill.
Dart_Handle results = Dart_GetNativeArgument(args, 1);
Dart_Handle path = Dart_GetNativeArgument(args, 2);
- Dart_Handle recursive = Dart_GetNativeArgument(args, 3);
- Dart_Handle follow_links = Dart_GetNativeArgument(args, 4);
-
Dart_Handle dart_error;
+ const char* name;
+ {
+ TypedDataScope data(path);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ // We need to release our typed data before creating SyncDirectoryListing
+ // since it allocates objects which require us to not be holding typed data
+ // that has been acquired.
+ name = data.GetScopedCString();
+ }
{
// Pass the list that should hold the directory listing to the
// SyncDirectoryListing object, which adds elements to it.
- SyncDirectoryListing sync_listing(results, namespc,
- DartUtils::GetStringValue(path),
- DartUtils::GetBooleanValue(recursive),
- DartUtils::GetBooleanValue(follow_links));
+ SyncDirectoryListing sync_listing(
+ results, namespc, name, DartUtils::GetNativeBooleanArgument(args, 3),
+ DartUtils::GetNativeBooleanArgument(args, 4));
Directory::List(&sync_listing);
dart_error = sync_listing.dart_error();
}
@@ -206,12 +275,14 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString path(request[1]);
- return Directory::Create(namespc, path.CString()) ? CObject::True()
- : CObject::NewOSError();
+ CObjectUint8Array path(request[1]);
+ return Directory::Create(namespc,
+ reinterpret_cast<const char*>(path.Buffer()))
+ ? CObject::True()
+ : CObject::NewOSError();
}
CObject* Directory::DeleteRequest(const CObjectArray& request) {
@@ -220,13 +291,15 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 3) || !request[1]->IsString() ||
+ if ((request.Length() != 3) || !request[1]->IsUint8Array() ||
!request[2]->IsBool()) {
return CObject::IllegalArgumentError();
}
- CObjectString path(request[1]);
+ CObjectUint8Array path(request[1]);
CObjectBool recursive(request[2]);
- return Directory::Delete(namespc, path.CString(), recursive.Value())
+ return Directory::Delete(namespc,
+ reinterpret_cast<const char*>(path.Buffer()),
+ recursive.Value())
? CObject::True()
: CObject::NewOSError();
}
@@ -239,11 +312,12 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString path(request[1]);
- Directory::ExistsResult result = Directory::Exists(namespc, path.CString());
+ CObjectUint8Array path(request[1]);
+ Directory::ExistsResult result =
+ Directory::Exists(namespc, reinterpret_cast<const char*>(path.Buffer()));
if (result == Directory::EXISTS) {
return new CObjectInt32(CObject::NewInt32(kExists));
} else if (result == Directory::DOES_NOT_EXIST) {
@@ -259,11 +333,12 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString path(request[1]);
- const char* result = Directory::CreateTemp(namespc, path.CString());
+ CObjectUint8Array path(request[1]);
+ const char* result = Directory::CreateTemp(
+ namespc, reinterpret_cast<const char*>(path.Buffer()));
if (result == NULL) {
return CObject::NewOSError();
}
@@ -286,15 +361,16 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 4) || !request[1]->IsString() ||
+ if ((request.Length() != 4) || !request[1]->IsUint8Array() ||
!request[2]->IsBool() || !request[3]->IsBool()) {
return CreateIllegalArgumentError();
}
- CObjectString path(request[1]);
+ CObjectUint8Array path(request[1]);
CObjectBool recursive(request[2]);
CObjectBool follow_links(request[3]);
AsyncDirectoryListing* dir_listing = new AsyncDirectoryListing(
- namespc, path.CString(), recursive.Value(), follow_links.Value());
+ namespc, reinterpret_cast<const char*>(path.Buffer()), recursive.Value(),
+ follow_links.Value());
if (dir_listing->error()) {
// Report error now, so we capture the correct OSError.
CObject* err = CObject::NewOSError();
@@ -357,13 +433,15 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 3) || !request[1]->IsString() ||
+ if ((request.Length() != 3) || !request[1]->IsUint8Array() ||
!request[2]->IsString()) {
return CObject::IllegalArgumentError();
}
- CObjectString path(request[1]);
+ CObjectUint8Array path(request[1]);
CObjectString new_path(request[2]);
- return Directory::Rename(namespc, path.CString(), new_path.CString())
+ return Directory::Rename(namespc,
+ reinterpret_cast<const char*>(path.Buffer()),
+ new_path.CString())
? CObject::True()
: CObject::NewOSError();
}
@@ -372,7 +450,14 @@
const char* arg) {
array_->SetAt(index_++, new CObjectInt32(CObject::NewInt32(type)));
if (arg != NULL) {
- array_->SetAt(index_++, new CObjectString(CObject::NewString(arg)));
+ size_t len = strlen(arg);
+ Dart_CObject* io_buffer = CObject::NewIOBuffer(len);
+ uint8_t* data = io_buffer->value.as_external_typed_data.data;
+ strncpy(reinterpret_cast<char*>(data), arg, len);
+
+ CObjectExternalUint8Array* external_array =
+ new CObjectExternalUint8Array(io_buffer);
+ array_->SetAt(index_++, external_array);
} else {
array_->SetAt(index_++, CObject::Null());
}
@@ -410,8 +495,23 @@
}
bool SyncDirectoryListing::HandleDirectory(const char* dir_name) {
- Dart_Handle dir_name_dart = DartUtils::NewString(dir_name);
- Dart_Handle dir = Dart_New(directory_type_, Dart_Null(), 1, &dir_name_dart);
+ // Allocates a Uint8List for dir_name, and invokes the Directory.fromRawPath
+ // constructor. This avoids/delays interpreting the UTF-8 bytes in dir_name.
+ // Later, client code may either choose to access FileSystemEntity.path.
+ // FileSystemEntity.path will trigger UTF-8 decoding and return a path with
+ // non-UTF-8 characters replaced with U+FFFD.
+
+ size_t dir_name_length = strlen(dir_name);
+ uint8_t* buffer = NULL;
+ Dart_Handle dir_name_dart = IOBuffer::Allocate(dir_name_length, &buffer);
+ if (Dart_IsNull(dir_name_dart)) {
+ dart_error_ = DartUtils::NewDartOSError();
+ return false;
+ }
+ memmove(buffer, dir_name, dir_name_length);
+ Dart_Handle constructor_name = from_raw_path_string_;
+ Dart_Handle dir =
+ Dart_New(directory_type_, constructor_name, 1, &dir_name_dart);
Dart_Handle result = Dart_Invoke(results_, add_string_, 1, &dir);
if (Dart_IsError(result)) {
dart_error_ = result;
@@ -421,8 +521,22 @@
}
bool SyncDirectoryListing::HandleLink(const char* link_name) {
- Dart_Handle link_name_dart = DartUtils::NewString(link_name);
- Dart_Handle link = Dart_New(link_type_, Dart_Null(), 1, &link_name_dart);
+ // Allocates a Uint8List for dir_name, and invokes the Directory.fromRawPath
+ // constructor. This avoids/delays interpreting the UTF-8 bytes in dir_name.
+ // Later, client code may either choose to access FileSystemEntity.path.
+ // FileSystemEntity.path will trigger UTF-8 decoding and return a path with
+ // non-UTF-8 characters replaced with U+FFFD.
+
+ size_t link_name_length = strlen(link_name);
+ uint8_t* buffer = NULL;
+ Dart_Handle link_name_dart = IOBuffer::Allocate(link_name_length, &buffer);
+ if (Dart_IsNull(link_name_dart)) {
+ dart_error_ = DartUtils::NewDartOSError();
+ return false;
+ }
+ memmove(buffer, link_name, link_name_length);
+ Dart_Handle constructor_name = from_raw_path_string_;
+ Dart_Handle link = Dart_New(link_type_, constructor_name, 1, &link_name_dart);
Dart_Handle result = Dart_Invoke(results_, add_string_, 1, &link);
if (Dart_IsError(result)) {
dart_error_ = result;
@@ -432,8 +546,22 @@
}
bool SyncDirectoryListing::HandleFile(const char* file_name) {
- Dart_Handle file_name_dart = DartUtils::NewString(file_name);
- Dart_Handle file = Dart_New(file_type_, Dart_Null(), 1, &file_name_dart);
+ // Allocates a Uint8List for dir_name, and invokes the Directory.fromRawPath
+ // constructor. This avoids/delays interpreting the UTF-8 bytes in dir_name.
+ // Later, client code may either choose to access FileSystemEntity.path.
+ // FileSystemEntity.path will trigger UTF-8 decoding and return a path with
+ // non-UTF-8 characters replaced with U+FFFD.
+
+ size_t file_name_length = strlen(file_name);
+ uint8_t* buffer = NULL;
+ Dart_Handle file_name_dart = IOBuffer::Allocate(file_name_length, &buffer);
+ if (Dart_IsNull(file_name_dart)) {
+ dart_error_ = DartUtils::NewDartOSError();
+ return false;
+ }
+ memmove(buffer, file_name, file_name_length);
+ Dart_Handle constructor_name = from_raw_path_string_;
+ Dart_Handle file = Dart_New(file_type_, constructor_name, 1, &file_name_dart);
Dart_Handle result = Dart_Invoke(results_, add_string_, 1, &file);
if (Dart_IsError(result)) {
dart_error_ = result;
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index 0ab2606..4216e84 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -211,6 +211,7 @@
results_(results),
dart_error_(Dart_Null()) {
add_string_ = DartUtils::NewString("add");
+ from_raw_path_string_ = DartUtils::NewString("fromRawPath");
directory_type_ = DartUtils::GetDartType(DartUtils::kIOLibURL, "Directory");
file_type_ = DartUtils::GetDartType(DartUtils::kIOLibURL, "File");
link_type_ = DartUtils::GetDartType(DartUtils::kIOLibURL, "Link");
@@ -226,6 +227,7 @@
private:
Dart_Handle results_;
Dart_Handle add_string_;
+ Dart_Handle from_raw_path_string_;
Dart_Handle directory_type_;
Dart_Handle file_type_;
Dart_Handle link_type_;
diff --git a/runtime/bin/directory_patch.dart b/runtime/bin/directory_patch.dart
index 55a33fa..ca15f32 100644
--- a/runtime/bin/directory_patch.dart
+++ b/runtime/bin/directory_patch.dart
@@ -9,27 +9,30 @@
@patch
static _current(_Namespace namespace) native "Directory_Current";
@patch
- static _setCurrent(_Namespace namespace, path) native "Directory_SetCurrent";
+ static _setCurrent(_Namespace namespace, Uint8List rawPath)
+ native "Directory_SetCurrent";
@patch
- static _createTemp(_Namespace namespace, String path)
+ static _createTemp(_Namespace namespace, Uint8List rawPath)
native "Directory_CreateTemp";
@patch
static String _systemTemp(_Namespace namespace) native "Directory_SystemTemp";
@patch
- static _exists(_Namespace namespace, String path) native "Directory_Exists";
+ static _exists(_Namespace namespace, Uint8List rawPath)
+ native "Directory_Exists";
@patch
- static _create(_Namespace namespace, String path) native "Directory_Create";
+ static _create(_Namespace namespace, Uint8List rawPath)
+ native "Directory_Create";
@patch
- static _deleteNative(_Namespace namespace, String path, bool recursive)
+ static _deleteNative(_Namespace namespace, Uint8List rawPath, bool recursive)
native "Directory_Delete";
@patch
- static _rename(_Namespace namespace, String path, String newPath)
+ static _rename(_Namespace namespace, Uint8List rawPath, String newPath)
native "Directory_Rename";
@patch
static void _fillWithDirectoryListing(
_Namespace namespace,
List<FileSystemEntity> list,
- String path,
+ Uint8List rawPath,
bool recursive,
bool followLinks) native "Directory_FillWithDirectoryListing";
}
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index 4d0804b..16eee9d 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -340,7 +340,7 @@
msg->id = id;
msg->dart_port = dart_port;
msg->data = data;
- zx_status_t status = zx_port_queue(port_handle_, &pkt, 1);
+ zx_status_t status = zx_port_queue(port_handle_, &pkt);
if (status != ZX_OK) {
// This is a FATAL because the VM won't work at all if we can't send any
// messages to the EventHandler thread.
@@ -511,7 +511,7 @@
millis == kInfinityTimeout
? ZX_TIME_INFINITE
: zx_deadline_after(ZX_MSEC(millis)),
- &pkt, 1);
+ &pkt);
if (status == ZX_ERR_TIMED_OUT) {
handler_impl->HandleTimeout();
} else if (status != ZX_OK) {
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index 978db7a..115bf3f 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -11,6 +11,7 @@
#include "bin/embedded_dart_io.h"
#include "bin/io_buffer.h"
#include "bin/namespace.h"
+#include "bin/typed_data_utils.h"
#include "bin/utils.h"
#include "include/dart_api.h"
#include "include/dart_tools_api.h"
@@ -75,8 +76,7 @@
void FUNCTION_NAME(File_SetPointer)(Dart_NativeArguments args) {
Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
- intptr_t file_pointer =
- DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
+ intptr_t file_pointer = DartUtils::GetNativeIntptrArgument(args, 1);
File* file = reinterpret_cast<File*>(file_pointer);
Dart_WeakPersistentHandle handle = Dart_NewWeakPersistentHandle(
dart_this, reinterpret_cast<void*>(file), sizeof(*file), ReleaseFile);
@@ -86,28 +86,41 @@
void FUNCTION_NAME(File_Open)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* filename =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- int64_t mode = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 2));
- File::DartFileOpenMode dart_file_mode =
- static_cast<File::DartFileOpenMode>(mode);
- File::FileOpenMode file_mode = File::DartModeToFileMode(dart_file_mode);
- // Check that the file exists before opening it only for
- // reading. This is to prevent the opening of directories as
- // files. Directories can be opened for reading using the posix
- // 'open' call.
- File* file = File::Open(namespc, filename, file_mode);
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ File* file = NULL;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* filename = data.GetCString();
+
+ int64_t mode = DartUtils::GetNativeIntegerArgument(args, 2);
+ File::DartFileOpenMode dart_file_mode =
+ static_cast<File::DartFileOpenMode>(mode);
+ File::FileOpenMode file_mode = File::DartModeToFileMode(dart_file_mode);
+ // Check that the file exists before opening it only for
+ // reading. This is to prevent the opening of directories as
+ // files. Directories can be opened for reading using the posix
+ // 'open' call.
+ file = File::Open(namespc, filename, file_mode);
+ if (file == NULL) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (file != NULL) {
Dart_SetIntegerReturnValue(args, reinterpret_cast<intptr_t>(file));
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_Exists)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* filename =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* filename = data.GetCString();
bool exists = File::Exists(namespc, filename);
Dart_SetBooleanReturnValue(args, exists);
}
@@ -221,8 +234,8 @@
// integers and have the property that end <=
// list.length. Therefore, it is safe to extract their value as
// intptr_t.
- intptr_t start = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 2));
- intptr_t end = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3));
+ intptr_t start = DartUtils::GetNativeIntptrArgument(args, 2);
+ intptr_t end = DartUtils::GetNativeIntptrArgument(args, 3);
intptr_t length = end - start;
intptr_t array_len = 0;
Dart_Handle result = Dart_ListLength(buffer_obj, &array_len);
@@ -254,8 +267,8 @@
// integers and have the property that (offset + length) <=
// list.length. Therefore, it is safe to extract their value as
// intptr_t.
- intptr_t start = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 2));
- intptr_t end = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3));
+ intptr_t start = DartUtils::GetNativeIntptrArgument(args, 2);
+ intptr_t end = DartUtils::GetNativeIntptrArgument(args, 3);
// The buffer object passed in has to be an Int8List or Uint8List object.
// Acquire a direct pointer to the data area of the buffer object.
@@ -346,60 +359,117 @@
void FUNCTION_NAME(File_LengthFromPath)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* path = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- int64_t return_value = File::LengthFromPath(namespc, path);
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ int64_t return_value;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* path = data.GetCString();
+ return_value = File::LengthFromPath(namespc, path);
+ if (return_value < 0) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (return_value >= 0) {
Dart_SetIntegerReturnValue(args, return_value);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_LastModified)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* name = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- int64_t return_value = File::LastModified(namespc, name);
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ int64_t return_value;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* raw_name = data.GetCString();
+ return_value = File::LastModified(namespc, raw_name);
+ if (return_value < 0) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (return_value >= 0) {
Dart_SetIntegerReturnValue(args, return_value * kMillisecondsPerSecond);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_SetLastModified)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* name = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
int64_t millis;
if (!DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 2), &millis)) {
Dart_ThrowException(DartUtils::NewDartArgumentError(
"The second argument must be a 64-bit int."));
}
- if (!File::SetLastModified(namespc, name, millis)) {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ bool result;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ result = File::SetLastModified(namespc, name, millis);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
+ if (!result) {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_LastAccessed)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* name = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- int64_t return_value = File::LastAccessed(namespc, name);
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ int64_t return_value;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ return_value = File::LastAccessed(namespc, name);
+ if (return_value < 0) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (return_value >= 0) {
Dart_SetIntegerReturnValue(args, return_value * kMillisecondsPerSecond);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_SetLastAccessed)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* name = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
int64_t millis;
if (!DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 2), &millis)) {
Dart_ThrowException(DartUtils::NewDartArgumentError(
"The second argument must be a 64-bit int."));
}
- if (!File::SetLastAccessed(namespc, name, millis)) {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ bool result;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ result = File::SetLastAccessed(namespc, name, millis);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
+ if (!result) {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
@@ -438,135 +508,212 @@
void FUNCTION_NAME(File_Create)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* str = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- bool result = File::Create(namespc, str);
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ bool result;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* path = data.GetCString();
+ result = File::Create(namespc, path);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (result) {
Dart_SetBooleanReturnValue(args, result);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_CreateLink)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- if (Dart_IsString(Dart_GetNativeArgument(args, 1)) &&
- Dart_IsString(Dart_GetNativeArgument(args, 2))) {
- const char* name =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- const char* target =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 2));
- if (!File::CreateLink(namespc, name, target)) {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ bool result;
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ const char* target = DartUtils::GetNativeStringArgument(args, 2);
+ result = File::CreateLink(namespc, name, target);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
}
- } else {
- Dart_Handle err =
- DartUtils::NewDartArgumentError("Non-string argument to Link.create");
- Dart_SetReturnValue(args, err);
+ }
+ if (!result) {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_LinkTarget)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- if (Dart_IsString(Dart_GetNativeArgument(args, 1))) {
- const char* name =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- const char* target = File::LinkTarget(namespc, name);
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ const char* target = NULL;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* name = data.GetCString();
+ target = File::LinkTarget(namespc, name);
if (target == NULL) {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
- } else {
- Dart_SetReturnValue(args, DartUtils::NewString(target));
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
}
+ }
+ if (target == NULL) {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
} else {
- Dart_Handle err =
- DartUtils::NewDartArgumentError("Non-string argument to Link.target");
- Dart_SetReturnValue(args, err);
+ Dart_SetReturnValue(args, DartUtils::NewString(target));
}
}
void FUNCTION_NAME(File_Delete)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* str = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- bool result = File::Delete(namespc, str);
+ bool result;
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* path = data.GetCString();
+ result = File::Delete(namespc, path);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (result) {
Dart_SetBooleanReturnValue(args, result);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_DeleteLink)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* str = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- bool result = File::DeleteLink(namespc, str);
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ bool result;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* path = data.GetCString();
+ result = File::DeleteLink(namespc, path);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (result) {
Dart_SetBooleanReturnValue(args, result);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_Rename)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* old_path =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- const char* new_path =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 2));
- bool result = File::Rename(namespc, old_path, new_path);
+ Dart_Handle old_path_handle = Dart_GetNativeArgument(args, 1);
+ bool result;
+ OSError os_error;
+ {
+ TypedDataScope old_path_data(old_path_handle);
+ ASSERT(old_path_data.type() == Dart_TypedData_kUint8);
+ const char* old_path = old_path_data.GetCString();
+ const char* new_path = DartUtils::GetNativeStringArgument(args, 2);
+ result = File::Rename(namespc, old_path, new_path);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (result) {
Dart_SetBooleanReturnValue(args, result);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_RenameLink)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* old_path =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- const char* new_path =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 2));
- bool result = File::RenameLink(namespc, old_path, new_path);
+ Dart_Handle old_path_handle = Dart_GetNativeArgument(args, 1);
+ bool result;
+ OSError os_error;
+ {
+ TypedDataScope old_path_data(old_path_handle);
+ ASSERT(old_path_data.type() == Dart_TypedData_kUint8);
+ const char* old_path = old_path_data.GetCString();
+ const char* new_path = DartUtils::GetNativeStringArgument(args, 2);
+ result = File::RenameLink(namespc, old_path, new_path);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (result) {
Dart_SetBooleanReturnValue(args, result);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_Copy)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* old_path =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- const char* new_path =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 2));
- bool result = File::Copy(namespc, old_path, new_path);
+ Dart_Handle old_path_handle = Dart_GetNativeArgument(args, 1);
+ bool result;
+ OSError os_error;
+ {
+ TypedDataScope old_path_data(old_path_handle);
+ ASSERT(old_path_data.type() == Dart_TypedData_kUint8);
+ const char* old_path = old_path_data.GetCString();
+ const char* new_path = DartUtils::GetNativeStringArgument(args, 2);
+ result = File::Copy(namespc, old_path, new_path);
+ if (!result) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (result) {
Dart_SetBooleanReturnValue(args, result);
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_ResolveSymbolicLinks)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- const char* str = DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- const char* path = File::GetCanonicalPath(namespc, str);
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ const char* path = NULL;
+ OSError os_error;
+ {
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* str = data.GetCString();
+ path = File::GetCanonicalPath(namespc, str);
+ if (path == NULL) {
+ // Errors must be caught before TypedDataScope data is destroyed.
+ os_error.Reload();
+ }
+ }
if (path != NULL) {
Dart_SetReturnValue(args, DartUtils::NewString(path));
} else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
}
}
void FUNCTION_NAME(File_OpenStdio)(Dart_NativeArguments args) {
- const int64_t fd =
- DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
+ const int64_t fd = DartUtils::GetNativeIntegerArgument(args, 0);
File* file = File::OpenStdio(static_cast<int>(fd));
Dart_SetIntegerReturnValue(args, reinterpret_cast<intptr_t>(file));
}
void FUNCTION_NAME(File_GetStdioHandleType)(Dart_NativeArguments args) {
- int64_t fd = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
+ int64_t fd = DartUtils::GetNativeIntegerArgument(args, 0);
ASSERT((fd == STDIN_FILENO) || (fd == STDOUT_FILENO) ||
(fd == STDERR_FILENO));
File::StdioHandleType type = File::GetStdioHandleType(static_cast<int>(fd));
@@ -575,78 +722,55 @@
void FUNCTION_NAME(File_GetType)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- if (Dart_IsString(Dart_GetNativeArgument(args, 1)) &&
- Dart_IsBoolean(Dart_GetNativeArgument(args, 2))) {
- const char* str =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- bool follow_links =
- DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2));
- File::Type type = File::GetType(namespc, str, follow_links);
- Dart_SetIntegerReturnValue(args, static_cast<int>(type));
- } else {
- Dart_Handle err = DartUtils::NewDartArgumentError(
- "Non-string argument to FileSystemEntity.type");
- Dart_SetReturnValue(args, err);
- }
+ Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
+ TypedDataScope data(path_handle);
+ ASSERT(data.type() == Dart_TypedData_kUint8);
+ const char* path = data.GetCString();
+ bool follow_links = DartUtils::GetNativeBooleanArgument(args, 2);
+ File::Type type = File::GetType(namespc, path, follow_links);
+ Dart_SetIntegerReturnValue(args, static_cast<int>(type));
}
void FUNCTION_NAME(File_Stat)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- if (Dart_IsString(Dart_GetNativeArgument(args, 1))) {
- const char* path =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
+ const char* path = DartUtils::GetNativeStringArgument(args, 1);
- int64_t stat_data[File::kStatSize];
- File::Stat(namespc, path, stat_data);
- if (stat_data[File::kType] == File::kDoesNotExist) {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
- } else {
- Dart_Handle returned_data =
- Dart_NewTypedData(Dart_TypedData_kInt64, File::kStatSize);
- if (Dart_IsError(returned_data)) {
- Dart_PropagateError(returned_data);
- }
- Dart_TypedData_Type data_type_unused;
- void* data_location;
- intptr_t data_length_unused;
- Dart_Handle status =
- Dart_TypedDataAcquireData(returned_data, &data_type_unused,
- &data_location, &data_length_unused);
- if (Dart_IsError(status)) {
- Dart_PropagateError(status);
- }
- memmove(data_location, stat_data, File::kStatSize * sizeof(int64_t));
- status = Dart_TypedDataReleaseData(returned_data);
- if (Dart_IsError(status)) {
- Dart_PropagateError(status);
- }
- Dart_SetReturnValue(args, returned_data);
- }
- } else {
- Dart_Handle err = DartUtils::NewDartArgumentError(
- "Non-string argument to FileSystemEntity.stat");
- Dart_SetReturnValue(args, err);
+ int64_t stat_data[File::kStatSize];
+ File::Stat(namespc, path, stat_data);
+ if (stat_data[File::kType] == File::kDoesNotExist) {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ return;
}
+ Dart_Handle returned_data =
+ Dart_NewTypedData(Dart_TypedData_kInt64, File::kStatSize);
+ if (Dart_IsError(returned_data)) {
+ Dart_PropagateError(returned_data);
+ }
+ Dart_TypedData_Type data_type_unused;
+ void* data_location;
+ intptr_t data_length_unused;
+ Dart_Handle status = Dart_TypedDataAcquireData(
+ returned_data, &data_type_unused, &data_location, &data_length_unused);
+ if (Dart_IsError(status)) {
+ Dart_PropagateError(status);
+ }
+ memmove(data_location, stat_data, File::kStatSize * sizeof(int64_t));
+ status = Dart_TypedDataReleaseData(returned_data);
+ if (Dart_IsError(status)) {
+ Dart_PropagateError(status);
+ }
+ Dart_SetReturnValue(args, returned_data);
}
void FUNCTION_NAME(File_AreIdentical)(Dart_NativeArguments args) {
Namespace* namespc = Namespace::GetNamespace(args, 0);
- if (Dart_IsString(Dart_GetNativeArgument(args, 1)) &&
- Dart_IsString(Dart_GetNativeArgument(args, 2))) {
- const char* path_1 =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
- const char* path_2 =
- DartUtils::GetStringValue(Dart_GetNativeArgument(args, 2));
- File::Identical result = File::AreIdentical(namespc, path_1, path_2);
- if (result == File::kError) {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
- } else {
- Dart_SetBooleanReturnValue(args, result == File::kIdentical);
- }
+ const char* path_1 = DartUtils::GetNativeStringArgument(args, 1);
+ const char* path_2 = DartUtils::GetNativeStringArgument(args, 2);
+ File::Identical result = File::AreIdentical(namespc, path_1, path_2);
+ if (result == File::kError) {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError());
} else {
- Dart_Handle err = DartUtils::NewDartArgumentError(
- "Non-string argument to FileSystemEntity.identical");
- Dart_SetReturnValue(args, err);
+ Dart_SetBooleanReturnValue(args, result == File::kIdentical);
}
}
@@ -761,11 +885,12 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString filename(request[1]);
- return CObject::Bool(File::Exists(namespc, filename.CString()));
+ CObjectUint8Array filename(request[1]);
+ return CObject::Bool(
+ File::Exists(namespc, reinterpret_cast<const char*>(filename.Buffer())));
}
CObject* File::CreateRequest(const CObjectArray& request) {
@@ -774,12 +899,13 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString filename(request[1]);
- return File::Create(namespc, filename.CString()) ? CObject::True()
- : CObject::NewOSError();
+ CObjectUint8Array filename(request[1]);
+ return File::Create(namespc, reinterpret_cast<const char*>(filename.Buffer()))
+ ? CObject::True()
+ : CObject::NewOSError();
}
CObject* File::OpenRequest(const CObjectArray& request) {
@@ -788,16 +914,17 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 3) || !request[1]->IsString() ||
+ if ((request.Length() != 3) || !request[1]->IsUint8Array() ||
!request[2]->IsInt32()) {
return CObject::IllegalArgumentError();
}
- CObjectString filename(request[1]);
+ CObjectUint8Array filename(request[1]);
CObjectInt32 mode(request[2]);
File::DartFileOpenMode dart_file_mode =
static_cast<File::DartFileOpenMode>(mode.Value());
File::FileOpenMode file_mode = File::DartModeToFileMode(dart_file_mode);
- File* file = File::Open(namespc, filename.CString(), file_mode);
+ File* file = File::Open(
+ namespc, reinterpret_cast<const char*>(filename.Buffer()), file_mode);
if (file == NULL) {
return CObject::NewOSError();
}
@@ -811,12 +938,13 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::False();
}
- CObjectString filename(request[1]);
- return File::Delete(namespc, filename.CString()) ? CObject::True()
- : CObject::NewOSError();
+ CObjectUint8Array filename(request[1]);
+ return File::Delete(namespc, reinterpret_cast<const char*>(filename.Buffer()))
+ ? CObject::True()
+ : CObject::NewOSError();
}
CObject* File::RenameRequest(const CObjectArray& request) {
@@ -825,13 +953,14 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 3) || !request[1]->IsString() ||
+ if ((request.Length() != 3) || !request[1]->IsUint8Array() ||
!request[2]->IsString()) {
return CObject::IllegalArgumentError();
}
- CObjectString old_path(request[1]);
+ CObjectUint8Array old_path(request[1]);
CObjectString new_path(request[2]);
- return File::Rename(namespc, old_path.CString(), new_path.CString())
+ return File::Rename(namespc, reinterpret_cast<const char*>(old_path.Buffer()),
+ new_path.CString())
? CObject::True()
: CObject::NewOSError();
}
@@ -842,13 +971,14 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 3) || !request[1]->IsString() ||
+ if ((request.Length() != 3) || !request[1]->IsUint8Array() ||
!request[2]->IsString()) {
return CObject::IllegalArgumentError();
}
- CObjectString old_path(request[1]);
+ CObjectUint8Array old_path(request[1]);
CObjectString new_path(request[2]);
- return File::Copy(namespc, old_path.CString(), new_path.CString())
+ return File::Copy(namespc, reinterpret_cast<const char*>(old_path.Buffer()),
+ new_path.CString())
? CObject::True()
: CObject::NewOSError();
}
@@ -859,11 +989,12 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString filename(request[1]);
- const char* result = File::GetCanonicalPath(namespc, filename.CString());
+ CObjectUint8Array filename(request[1]);
+ const char* result = File::GetCanonicalPath(
+ namespc, reinterpret_cast<const char*>(filename.Buffer()));
if (result == NULL) {
return CObject::NewOSError();
}
@@ -960,12 +1091,12 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString filepath(request[1]);
- const int64_t return_value =
- File::LengthFromPath(namespc, filepath.CString());
+ CObjectUint8Array filepath(request[1]);
+ const int64_t return_value = File::LengthFromPath(
+ namespc, reinterpret_cast<const char*>(filepath.Buffer()));
if (return_value < 0) {
return CObject::NewOSError();
}
@@ -978,11 +1109,12 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString filepath(request[1]);
- const int64_t return_value = File::LastAccessed(namespc, filepath.CString());
+ CObjectUint8Array filepath(request[1]);
+ const int64_t return_value = File::LastAccessed(
+ namespc, reinterpret_cast<const char*>(filepath.Buffer()));
if (return_value < 0) {
return CObject::NewOSError();
}
@@ -996,13 +1128,14 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 3) || !request[1]->IsString() ||
+ if ((request.Length() != 3) || !request[1]->IsUint8Array() ||
!request[2]->IsInt32OrInt64()) {
return CObject::IllegalArgumentError();
}
- CObjectString filepath(request[1]);
+ CObjectUint8Array filepath(request[1]);
const int64_t millis = CObjectInt32OrInt64ToInt64(request[2]);
- return File::SetLastAccessed(namespc, filepath.CString(), millis)
+ return File::SetLastAccessed(
+ namespc, reinterpret_cast<const char*>(filepath.Buffer()), millis)
? CObject::Null()
: CObject::NewOSError();
}
@@ -1013,11 +1146,12 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 2) || !request[1]->IsString()) {
+ if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString filepath(request[1]);
- const int64_t return_value = File::LastModified(namespc, filepath.CString());
+ CObjectUint8Array filepath(request[1]);
+ const int64_t return_value = File::LastModified(
+ namespc, reinterpret_cast<const char*>(filepath.Buffer()));
if (return_value < 0) {
return CObject::NewOSError();
}
@@ -1031,13 +1165,14 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if ((request.Length() != 3) || !request[1]->IsString() ||
+ if ((request.Length() != 3) || !request[1]->IsUint8Array() ||
!request[2]->IsInt32OrInt64()) {
return CObject::IllegalArgumentError();
}
- CObjectString filepath(request[1]);
+ CObjectUint8Array filepath(request[1]);
const int64_t millis = CObjectInt32OrInt64ToInt64(request[2]);
- return File::SetLastModified(namespc, filepath.CString(), millis)
+ return File::SetLastModified(
+ namespc, reinterpret_cast<const char*>(filepath.Buffer()), millis)
? CObject::Null()
: CObject::NewOSError();
}
@@ -1230,12 +1365,14 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if (!request[1]->IsString() || !request[2]->IsString()) {
+ if (!request[1]->IsUint8Array() || !request[2]->IsString()) {
return CObject::IllegalArgumentError();
}
- CObjectString link_name(request[1]);
+ CObjectUint8Array link_name(request[1]);
CObjectString target_name(request[2]);
- return File::CreateLink(namespc, link_name.CString(), target_name.CString())
+ return File::CreateLink(namespc,
+ reinterpret_cast<const char*>(link_name.Buffer()),
+ target_name.CString())
? CObject::True()
: CObject::NewOSError();
}
@@ -1246,12 +1383,14 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if (!request[1]->IsString()) {
+ if (!request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString link_path(request[1]);
- return File::DeleteLink(namespc, link_path.CString()) ? CObject::True()
- : CObject::NewOSError();
+ CObjectUint8Array link_path(request[1]);
+ return File::DeleteLink(namespc,
+ reinterpret_cast<const char*>(link_path.Buffer()))
+ ? CObject::True()
+ : CObject::NewOSError();
}
CObject* File::RenameLinkRequest(const CObjectArray& request) {
@@ -1260,12 +1399,14 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if (!request[1]->IsString() || !request[2]->IsString()) {
+ if (!request[1]->IsUint8Array() || !request[2]->IsString()) {
return CObject::IllegalArgumentError();
}
- CObjectString old_path(request[1]);
+ CObjectUint8Array old_path(request[1]);
CObjectString new_path(request[2]);
- return File::RenameLink(namespc, old_path.CString(), new_path.CString())
+ return File::RenameLink(namespc,
+ reinterpret_cast<const char*>(old_path.Buffer()),
+ new_path.CString())
? CObject::True()
: CObject::NewOSError();
}
@@ -1276,11 +1417,12 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if (!request[1]->IsString()) {
+ if (!request[1]->IsUint8Array()) {
return CObject::IllegalArgumentError();
}
- CObjectString link_path(request[1]);
- const char* target = File::LinkTarget(namespc, link_path.CString());
+ CObjectUint8Array link_path(request[1]);
+ const char* target = File::LinkTarget(
+ namespc, reinterpret_cast<const char*>(link_path.Buffer()));
if (target == NULL) {
return CObject::NewOSError();
}
@@ -1293,13 +1435,14 @@
}
Namespace* namespc = CObjectToNamespacePointer(request[0]);
RefCntReleaseScope<Namespace> rs(namespc);
- if (!request[1]->IsString() || !request[2]->IsBool()) {
+ if (!request[1]->IsUint8Array() || !request[2]->IsBool()) {
return CObject::IllegalArgumentError();
}
- CObjectString path(request[1]);
+ CObjectUint8Array path(request[1]);
CObjectBool follow_links(request[2]);
File::Type type =
- File::GetType(namespc, path.CString(), follow_links.Value());
+ File::GetType(namespc, reinterpret_cast<const char*>(path.Buffer()),
+ follow_links.Value());
return new CObjectInt32(CObject::NewInt32(type));
}
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 247c480..99ee6ac 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -7,46 +7,48 @@
@patch
class _File {
@patch
- static _exists(_Namespace namespace, String path) native "File_Exists";
+ static _exists(_Namespace namespace, Uint8List rawPath) native "File_Exists";
@patch
- static _create(_Namespace namespace, String path) native "File_Create";
+ static _create(_Namespace namespace, Uint8List rawPath) native "File_Create";
@patch
- static _createLink(_Namespace namespace, String path, String target)
+ static _createLink(_Namespace namespace, Uint8List rawPath, String target)
native "File_CreateLink";
@patch
- static _linkTarget(_Namespace namespace, String path)
+ static _linkTarget(_Namespace namespace, Uint8List rawPath)
native "File_LinkTarget";
@patch
- static _deleteNative(_Namespace namespace, String path) native "File_Delete";
+ static _deleteNative(_Namespace namespace, Uint8List rawPath)
+ native "File_Delete";
@patch
- static _deleteLinkNative(_Namespace namespace, String path)
+ static _deleteLinkNative(_Namespace namespace, Uint8List rawPath)
native "File_DeleteLink";
@patch
- static _rename(_Namespace namespace, String oldPath, String newPath)
+ static _rename(_Namespace namespace, Uint8List oldPath, String newPath)
native "File_Rename";
@patch
- static _renameLink(_Namespace namespace, String oldPath, String newPath)
+ static _renameLink(_Namespace namespace, Uint8List oldPath, String newPath)
native "File_RenameLink";
@patch
- static _copy(_Namespace namespace, String oldPath, String newPath)
+ static _copy(_Namespace namespace, Uint8List oldPath, String newPath)
native "File_Copy";
@patch
- static _lengthFromPath(_Namespace namespace, String path)
+ static _lengthFromPath(_Namespace namespace, Uint8List rawPath)
native "File_LengthFromPath";
@patch
- static _lastModified(_Namespace namespace, String path)
+ static _lastModified(_Namespace namespace, Uint8List rawPath)
native "File_LastModified";
@patch
- static _setLastModified(_Namespace namespace, String path, int millis)
+ static _setLastModified(_Namespace namespace, Uint8List rawPath, int millis)
native "File_SetLastModified";
@patch
- static _lastAccessed(_Namespace namespace, String path)
+ static _lastAccessed(_Namespace namespace, Uint8List rawPath)
native "File_LastAccessed";
@patch
- static _setLastAccessed(_Namespace namespace, String path, int millis)
+ static _setLastAccessed(_Namespace namespace, Uint8List rawPath, int millis)
native "File_SetLastAccessed";
@patch
- static _open(_Namespace namespace, String path, int mode) native "File_Open";
+ static _open(_Namespace namespace, Uint8List rawPath, int mode)
+ native "File_Open";
@patch
static int _openStdio(int fd) native "File_OpenStdio";
}
@@ -289,8 +291,9 @@
rewriteMove(event, getIsDir(event));
}
}
- } else if (event == RawSocketEvent.closed) {} else if (event ==
- RawSocketEvent.readClosed) {} else {
+ } else if (event == RawSocketEvent.closed) {
+ } else if (event == RawSocketEvent.readClosed) {
+ } else {
assert(false);
}
events.addAll(stops);
diff --git a/runtime/bin/file_system_entity_patch.dart b/runtime/bin/file_system_entity_patch.dart
index 3aecd66..973e6b6 100644
--- a/runtime/bin/file_system_entity_patch.dart
+++ b/runtime/bin/file_system_entity_patch.dart
@@ -13,12 +13,12 @@
@patch
class FileSystemEntity {
@patch
- static _getTypeNative(_Namespace namespace, String path, bool followLinks)
- native "File_GetType";
+ static _getTypeNative(_Namespace namespace, Uint8List rawPath,
+ bool followLinks) native "File_GetType";
@patch
static _identicalNative(_Namespace namespace, String path1, String path2)
native "File_AreIdentical";
@patch
- static _resolveSymbolicLinks(_Namespace namespace, String path)
+ static _resolveSymbolicLinks(_Namespace namespace, Uint8List path)
native "File_ResolveSymbolicLinks";
}
diff --git a/runtime/bin/io_impl_sources.gni b/runtime/bin/io_impl_sources.gni
index 1e46f4d..94477a7 100644
--- a/runtime/bin/io_impl_sources.gni
+++ b/runtime/bin/io_impl_sources.gni
@@ -101,4 +101,6 @@
"sync_socket_linux.cc",
"sync_socket_macos.cc",
"sync_socket_win.cc",
+ "typed_data_utils.h",
+ "typed_data_utils.cc",
]
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 5a495e8..d46910b 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -345,7 +345,10 @@
// relative URIs and perform other related tasks. We need Loader to be
// initialized for this to work because loading from Kernel binary
// bypasses normal source code loading paths that initialize it.
- Loader::InitForSnapshot(script_uri);
+ const char* resolved_script_uri = NULL;
+ result = Dart_StringToCString(uri, &resolved_script_uri);
+ CHECK_RESULT(result);
+ Loader::InitForSnapshot(resolved_script_uri);
}
Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),
@@ -615,7 +618,13 @@
platform_kernel_buffer_size = kernel_buffer_size;
}
if (platform_kernel_buffer == NULL) {
+#if defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
+ FATAL(
+ "Binary built with --exclude-kernel-service. Cannot run"
+ " from source.");
+#else
FATAL("platform_program cannot be NULL.");
+#endif // defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
}
// TODO(sivachandra): When the platform program is unavailable, check if
// application kernel binary is self contained or an incremental binary.
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index 43f01ca..d8ff3d0 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -205,7 +205,7 @@
static void SendShutdownMessage() {
zx_port_packet_t pkt;
pkt.key = kShutdownPacketKey;
- zx_status_t status = zx_port_queue(port_, &pkt, 1);
+ zx_status_t status = zx_port_queue(port_, &pkt);
if (status != ZX_OK) {
Log::PrintErr("ExitCodeHandler: zx_port_queue failed: %s\n",
zx_status_get_string(status));
@@ -219,7 +219,7 @@
zx_port_packet_t pkt;
while (true) {
- zx_status_t status = zx_port_wait(port_, ZX_TIME_INFINITE, &pkt, 1);
+ zx_status_t status = zx_port_wait(port_, ZX_TIME_INFINITE, &pkt);
if (status != ZX_OK) {
FATAL1("ExitCodeHandler: zx_port_wait failed: %s\n",
zx_status_get_string(status));
@@ -397,7 +397,7 @@
}
while ((out_tmp != NULL) || (err_tmp != NULL) || (exit_tmp != NULL)) {
zx_port_packet_t pkt;
- status = zx_port_wait(port, ZX_TIME_INFINITE, &pkt, 1);
+ status = zx_port_wait(port, ZX_TIME_INFINITE, &pkt);
if (status != ZX_OK) {
Log::PrintErr("Process::Wait: zx_port_wait failed: %s\n",
zx_status_get_string(status));
diff --git a/runtime/bin/typed_data_utils.cc b/runtime/bin/typed_data_utils.cc
new file mode 100644
index 0000000..6c08ca5
--- /dev/null
+++ b/runtime/bin/typed_data_utils.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "bin/typed_data_utils.h"
+#include "platform/assert.h"
+
+namespace dart {
+namespace bin {
+
+TypedDataScope::TypedDataScope(Dart_Handle data) : data_handle_(data) {
+ Dart_Handle result;
+ result = Dart_TypedDataAcquireData(data, &type_, &data_, &length_);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+}
+
+void TypedDataScope::Release() {
+ if (data_handle_ == NULL) {
+ return;
+ }
+ Dart_Handle result = Dart_TypedDataReleaseData(data_handle_);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ data_handle_ = NULL;
+ data_ = NULL;
+ length_ = 0;
+ type_ = Dart_TypedData_kInvalid;
+}
+
+intptr_t TypedDataScope::size_in_bytes() const {
+ switch (type_) {
+ case Dart_TypedData_kByteData:
+ case Dart_TypedData_kInt8:
+ case Dart_TypedData_kUint8:
+ case Dart_TypedData_kUint8Clamped:
+ return length_;
+ case Dart_TypedData_kInt16:
+ case Dart_TypedData_kUint16:
+ return length_ * 2;
+ case Dart_TypedData_kInt32:
+ case Dart_TypedData_kUint32:
+ case Dart_TypedData_kFloat32:
+ return length_ * 4;
+ case Dart_TypedData_kInt64:
+ case Dart_TypedData_kUint64:
+ case Dart_TypedData_kFloat64:
+ return length_ * 8;
+ case Dart_TypedData_kFloat32x4:
+ return length_ * 16;
+ default:
+ UNREACHABLE();
+ }
+}
+
+const char* TypedDataScope::GetScopedCString() const {
+ char* buf = reinterpret_cast<char*>(Dart_ScopeAllocate(size_in_bytes()));
+ strncpy(buf, GetCString(), size_in_bytes());
+ return buf;
+}
+
+} // namespace bin
+} // namespace dart
diff --git a/runtime/bin/typed_data_utils.h b/runtime/bin/typed_data_utils.h
new file mode 100644
index 0000000..ff8c57a
--- /dev/null
+++ b/runtime/bin/typed_data_utils.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_BIN_TYPED_DATA_UTILS_H_
+#define RUNTIME_BIN_TYPED_DATA_UTILS_H_
+
+#include "include/dart_api.h"
+#include "platform/globals.h"
+
+namespace dart {
+namespace bin {
+
+class TypedDataScope {
+ public:
+ explicit TypedDataScope(Dart_Handle data);
+ ~TypedDataScope() { Release(); }
+
+ void Release();
+
+ const char* GetCString() const {
+ return reinterpret_cast<const char*>(data_);
+ }
+
+ const char* GetScopedCString() const;
+
+ void* data() const { return data_; }
+ intptr_t length() const { return length_; }
+ intptr_t size_in_bytes() const;
+ Dart_TypedData_Type type() const { return type_; }
+
+ private:
+ Dart_Handle data_handle_;
+ void* data_;
+ intptr_t length_;
+ Dart_TypedData_Type type_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(TypedDataScope);
+};
+
+} // namespace bin
+} // namespace dart
+
+#endif // RUNTIME_BIN_TYPED_DATA_UTILS_H_
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index 234a969..a5ec66b 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -27,6 +27,9 @@
}
virtual ~OSError() { free(message_); }
+ // Reload this OSError with the current OS error, discarding the previous.
+ void Reload();
+
SubSystem sub_system() { return sub_system_; }
int code() { return code_; }
char* message() { return message_; }
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index a705997..ed6b5de 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -18,12 +18,11 @@
namespace bin {
OSError::OSError() : sub_system_(kSystem), code_(0), message_(NULL) {
- set_sub_system(kSystem);
- set_code(errno);
- const int kBufferSize = 1024;
- char error_message[kBufferSize];
- Utils::StrError(errno, error_message, kBufferSize);
- SetMessage(error_message);
+ Reload();
+}
+
+void OSError::Reload() {
+ SetCodeAndMessage(kSystem, errno);
}
void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
diff --git a/runtime/bin/utils_fuchsia.cc b/runtime/bin/utils_fuchsia.cc
index e1f3dca..4c8b208 100644
--- a/runtime/bin/utils_fuchsia.cc
+++ b/runtime/bin/utils_fuchsia.cc
@@ -17,11 +17,11 @@
namespace bin {
OSError::OSError() : sub_system_(kSystem), code_(0), message_(NULL) {
- set_sub_system(kSystem);
- set_code(errno);
- const int kBufferSize = 1024;
- char error_buf[kBufferSize];
- SetMessage(Utils::StrError(errno, error_buf, kBufferSize));
+ Reload();
+}
+
+void OSError::Reload() {
+ SetCodeAndMessage(kSystem, errno);
}
void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index 3e27c0c..b87778a 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -18,11 +18,11 @@
namespace bin {
OSError::OSError() : sub_system_(kSystem), code_(0), message_(NULL) {
- set_sub_system(kSystem);
- set_code(errno);
- const int kBufferSize = 1024;
- char error_buf[kBufferSize];
- SetMessage(Utils::StrError(errno, error_buf, kBufferSize));
+ Reload();
+}
+
+void OSError::Reload() {
+ SetCodeAndMessage(kSystem, errno);
}
void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index bec7153..52066bc 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -21,12 +21,11 @@
namespace bin {
OSError::OSError() : sub_system_(kSystem), code_(0), message_(NULL) {
- set_sub_system(kSystem);
- set_code(errno);
- const int kBufferSize = 1024;
- char error_message[kBufferSize];
- Utils::StrError(errno, error_message, kBufferSize);
- SetMessage(error_message);
+ Reload();
+}
+
+void OSError::Reload() {
+ SetCodeAndMessage(kSystem, errno);
}
void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index 99e9fb8..f4764b4 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -32,13 +32,11 @@
}
OSError::OSError() : sub_system_(kSystem), code_(0), message_(NULL) {
- set_code(GetLastError());
+ Reload();
+}
- static const int kMaxMessageLength = 256;
- wchar_t message[kMaxMessageLength];
- FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
- char* utf8 = StringUtilsWin::WideToUtf8(message);
- SetMessage(utf8);
+void OSError::Reload() {
+ SetCodeAndMessage(kSystem, GetLastError());
}
void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
diff --git a/runtime/lib/convert_patch.dart b/runtime/lib/convert_patch.dart
index b2e7ed2..a2c802d 100644
--- a/runtime/lib/convert_patch.dart
+++ b/runtime/lib/convert_patch.dart
@@ -63,6 +63,7 @@
parser.chunk = input;
parser.chunkEnd = input.length;
parser.parse(0);
+ parser.close();
return parser.result;
}
@@ -398,6 +399,7 @@
static const int KWD_NULL = 0; // Prefix of "null" seen.
static const int KWD_TRUE = 4; // Prefix of "true" seen.
static const int KWD_FALSE = 8; // Prefix of "false" seen.
+ static const int KWD_BOM = 12; // Prefix of BOM seen.
static const int KWD_COUNT_SHIFT = 4; // Prefix length in bits 4+.
// Mask used to mask off two lower bits.
@@ -439,8 +441,11 @@
* ..0ddd0011 : Partial 'null' keyword.
* ..0ddd0111 : Partial 'true' keyword.
* ..0ddd1011 : Partial 'false' keyword.
- * For all three keywords, the `ddd` bits encode the number
+ * ..0ddd1111 : Partial UTF-8 BOM byte seqeuence ("\xEF\xBB\xBF").
+ * For all keywords, the `ddd` bits encode the number
* of letters seen.
+ * The BOM byte sequence is only used by [_JsonUtf8Parser],
+ * and only at the very beginning of input.
*/
int partialState = NO_PARTIAL;
@@ -789,7 +794,8 @@
int keywordType = partialState & KWD_TYPE_MASK;
int count = partialState >> KWD_COUNT_SHIFT;
int keywordTypeIndex = keywordType >> KWD_TYPE_SHIFT;
- String keyword = const ["null", "true", "false"][keywordTypeIndex];
+ String keyword =
+ const ["null", "true", "false", "\xEF\xBB\xBF"][keywordTypeIndex];
assert(count < keyword.length);
do {
if (position == chunkEnd) {
@@ -798,13 +804,19 @@
return chunkEnd;
}
int expectedChar = keyword.codeUnitAt(count);
- if (getChar(position) != expectedChar) return fail(position);
+ if (getChar(position) != expectedChar) {
+ if (count == 0) {
+ assert(keywordType == KWD_BOM);
+ return position;
+ }
+ return fail(position);
+ }
position++;
count++;
} while (count < keyword.length);
if (keywordType == KWD_NULL) {
listener.handleNull();
- } else {
+ } else if (keywordType != KWD_BOM) {
listener.handleBool(keywordType == KWD_TRUE);
}
return position;
@@ -1255,7 +1267,7 @@
fail(position, "Missing expected digit");
} else {
// If it doesn't even start out as a numeral.
- fail(position, "Unexpected character");
+ fail(position);
}
}
if (digit == 0) {
@@ -1660,7 +1672,7 @@
position++;
} else {
throw new FormatException(
- "Unexepected UTF-8 continuation byte", utf8, position);
+ "Unexpected UTF-8 continuation byte", utf8, position);
}
} else if (char < 0xE0) {
// C0-DF
@@ -1726,7 +1738,11 @@
int chunkEnd;
_JsonUtf8Parser(_JsonListener listener, this.allowMalformed)
- : super(listener);
+ : super(listener) {
+ // Starts out checking for an optional BOM (KWD_BOM, count = 0).
+ partialState =
+ _ChunkedJsonParser.PARTIAL_KEYWORD | _ChunkedJsonParser.KWD_BOM;
+ }
int getChar(int position) => chunk[position];
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 3524eef..1651cfa 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -313,7 +313,7 @@
return CreateTypedefMirror(cls, type, is_declaration, owner_mirror);
}
- const Array& args = Array::Handle(Array::New(9));
+ const Array& args = Array::Handle(Array::New(10));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, type);
// Note that the VM does not consider mixin application aliases to be mixin
@@ -328,8 +328,9 @@
args.SetAt(4, Bool::Get(cls.is_abstract()));
args.SetAt(5, Bool::Get(cls.IsGeneric()));
args.SetAt(6, Bool::Get(cls.is_mixin_app_alias()));
- args.SetAt(7, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
- args.SetAt(8, Bool::Get(cls.is_enum_class()));
+ args.SetAt(7, Bool::Get(cls.is_transformed_mixin_application()));
+ args.SetAt(8, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
+ args.SetAt(9, Bool::Get(cls.is_enum_class()));
return CreateMirror(Symbols::_LocalClassMirror(), args);
}
@@ -993,7 +994,13 @@
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
- const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
+ AbstractType& mixin_type = AbstractType::Handle();
+ if (cls.is_transformed_mixin_application()) {
+ const Array& interfaces = Array::Handle(cls.interfaces());
+ mixin_type ^= interfaces.At(interfaces.Length() - 1);
+ } else {
+ mixin_type = cls.mixin();
+ }
ASSERT(mixin_type.IsNull() || mixin_type.IsFinalized());
return mixin_type.raw();
}
@@ -1005,7 +1012,13 @@
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
- const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
+ AbstractType& mixin_type = AbstractType::Handle();
+ if (cls.is_transformed_mixin_application()) {
+ const Array& interfaces = Array::Handle(cls.interfaces());
+ mixin_type ^= interfaces.At(interfaces.Length() - 1);
+ } else {
+ mixin_type = cls.mixin();
+ }
if (mixin_type.IsNull()) {
return mixin_type.raw();
}
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 5c42dc4..eb0becb 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -356,7 +356,16 @@
DeclarationMirror _owner;
final bool isAbstract;
final bool _isGeneric;
+
+ // Only used for Dart 1 named mixin applications.
+ // TODO(alexmarkov): Clean up after Dart 1 is gone.
final bool _isMixinAlias;
+
+ // Since Dart 2, mixins are erased by kernel transformation.
+ // Resulting classes have this flag set, and mixed-in type is pulled into
+ // the end of interfaces list.
+ final bool _isTransformedMixinApplication;
+
final bool _isGenericDeclaration;
final bool isEnum;
Type _instantiator;
@@ -369,6 +378,7 @@
this.isAbstract,
this._isGeneric,
this._isMixinAlias,
+ this._isTransformedMixinApplication,
this._isGenericDeclaration,
this.isEnum)
: this._simpleName = _s(simpleName),
@@ -443,6 +453,9 @@
var interfaceTypes = isOriginalDeclaration
? _nativeInterfaces(_reflectedType)
: _nativeInterfacesInstantiated(_reflectedType);
+ if (_isTransformedMixinApplication) {
+ interfaceTypes = interfaceTypes.sublist(0, interfaceTypes.length - 1);
+ }
var interfaceMirrors = new List<ClassMirror>();
for (var interfaceType in interfaceTypes) {
interfaceMirrors.add(reflectType(interfaceType));
@@ -570,6 +583,7 @@
new UnmodifiableMapView<Symbol, DeclarationMirror>(decls);
}
+ // Note: returns correct result only for Dart 1 anonymous mixin applications.
bool get _isAnonymousMixinApplication {
if (_isMixinAlias) return false; // Named mixin application.
if (mixin == this) return false; // Not a mixin application.
@@ -579,7 +593,7 @@
List<TypeVariableMirror> _typeVariables;
List<TypeVariableMirror> get typeVariables {
if (_typeVariables == null) {
- if (_isAnonymousMixinApplication) {
+ if (!_isTransformedMixinApplication && _isAnonymousMixinApplication) {
return _typeVariables = const <TypeVariableMirror>[];
}
_typeVariables = new List<TypeVariableMirror>();
@@ -600,7 +614,8 @@
List<TypeMirror> _typeArguments;
List<TypeMirror> get typeArguments {
if (_typeArguments == null) {
- if (_isGenericDeclaration || _isAnonymousMixinApplication) {
+ if (_isGenericDeclaration ||
+ (!_isTransformedMixinApplication && _isAnonymousMixinApplication)) {
_typeArguments = const <TypeMirror>[];
} else {
_typeArguments = new UnmodifiableListView<TypeMirror>(
@@ -734,7 +749,7 @@
final _functionReflectee;
_LocalFunctionTypeMirror(reflectee, this._functionReflectee, reflectedType)
: super(reflectee, reflectedType, null, null, false, false, false, false,
- false);
+ false, false);
bool get _isAnonymousMixinApplication => false;
diff --git a/runtime/observatory/BUILD.gn b/runtime/observatory/BUILD.gn
index badb8cb..61ddc8f 100644
--- a/runtime/observatory/BUILD.gn
+++ b/runtime/observatory/BUILD.gn
@@ -43,12 +43,12 @@
"--command",
"build",
rebase_path("web/main.dart"),
- rebase_path("$root_gen_dir/observatory/web/main.dart.js"),
+ rebase_path("$target_gen_dir/observatory/web/main.dart.js"),
rebase_path("dart2js.packages"),
]
outputs = [
- "$root_gen_dir/observatory/web/main.dart.js",
+ "$target_gen_dir/observatory/web/main.dart.js",
]
}
@@ -59,32 +59,28 @@
inputs = [
script,
- "$root_gen_dir/observatory/web/main.dart.js",
+ "$target_gen_dir/observatory/web/main.dart.js",
]
args = build_args + [
"--silent=True",
"--directory",
- rebase_path("$root_out_dir/observatory"),
+ rebase_path("$target_out_dir/observatory"),
"--command",
"deploy",
- rebase_path("$root_out_dir/observatory/deployed"),
+ rebase_path("$target_out_dir/observatory/deployed"),
rebase_path("web"),
rebase_path("lib"),
- rebase_path("$root_gen_dir/observatory/web/main.dart.js"),
+ rebase_path("$target_gen_dir/observatory/web/main.dart.js"),
rebase_path("../../third_party/observatory_pub_packages/packages"),
]
outputs = [
- "$root_out_dir/observatory/deployed/web/main.dart.js",
+ "$target_out_dir/observatory/deployed/web/main.dart.js",
]
}
template("observatory_archive") {
- assert(defined(invoker.inner_namespace),
- "Need inner_namespace in $target_name")
- assert(defined(invoker.outer_namespace),
- "Need outer_namespace in $target_name")
enable_compression = false
if (defined(invoker.compress) && invoker.compress) {
enable_compression = true
@@ -95,42 +91,97 @@
]
inputs = [
- "$root_out_dir/observatory/deployed/web/main.dart.js",
+ "$target_out_dir/observatory/deployed/web/main.dart.js",
]
- inner_namespace = invoker.inner_namespace
- outer_namespace = invoker.outer_namespace
output_name = target_name
+ output = "$target_gen_dir/${output_name}.tar"
+ outputs = [
+ output,
+ ]
+
script = "../tools/create_archive.py"
args = [
- "--output",
- rebase_path("$root_gen_dir/observatory/${output_name}.cc"),
"--tar_output",
- rebase_path("$root_gen_dir/observatory/${output_name}.tar"),
- "--outer_namespace",
- outer_namespace,
- "--inner_namespace",
- inner_namespace,
- "--name",
- "observatory_assets_archive",
+ rebase_path(output),
"--client_root",
- rebase_path("$root_out_dir/observatory/deployed/web/"),
+ rebase_path("$target_out_dir/observatory/deployed/web/"),
]
if (enable_compression) {
args += [ "--compress" ]
}
+ }
+}
+observatory_archive("compressed_observatory_archive") {
+ compress = true
+}
+
+observatory_archive("observatory_archive") {
+ compress = false
+}
+
+# Generates a .cc file containing the bytes of the observatory archive in a C
+# array.
+#
+# Parameters:
+# inner_namespace (required):
+# The inner C++ namespace that the C array lives in.
+#
+# outer_namespace (required):
+# The outer C++ namespace that the C array lives in.
+#
+# archive_file (required):
+# The path to the observatory archive.
+#
+template("observatory_archive_source") {
+ assert(defined(invoker.inner_namespace),
+ "Need inner_namespace in $target_name")
+ assert(defined(invoker.outer_namespace),
+ "Need outer_namespace in $target_name")
+ assert(defined(invoker.archive_file), "Need archive_file in $target_name")
+
+ action(target_name) {
+ forward_variables_from(invoker, [ "deps" ])
+
+ inputs = [
+ invoker.archive_file,
+ ]
+
+ output = "$target_gen_dir/${target_name}.cc"
outputs = [
- "$root_gen_dir/observatory/${output_name}.cc",
- "$root_gen_dir/observatory/${output_name}.tar",
+ output,
+ ]
+
+ script = "../tools/create_archive.py"
+ args = [
+ "--tar_input",
+ rebase_path(invoker.archive_file),
+ "--output",
+ rebase_path(output),
+ "--outer_namespace",
+ invoker.outer_namespace,
+ "--inner_namespace",
+ invoker.inner_namespace,
+ "--name",
+ "observatory_assets_archive",
]
}
}
-observatory_archive("embedded_archive_observatory") {
+observatory_archive_source("embedded_archive_observatory") {
outer_namespace = "dart"
inner_namespace = "observatory"
+
+ # TODO(zra): In a Fuchsia build, use a prebuilt Observatory archive.
+ archive_target = ":observatory_archive"
+ deps = [
+ archive_target,
+ ]
+ archive_dir = get_label_info(archive_target, "target_gen_dir")
+ archive_name = get_label_info(archive_target, "name")
+ archive_file = "${archive_dir}/${archive_name}.tar"
}
source_set("embedded_observatory_archive") {
@@ -139,14 +190,22 @@
]
sources = [
- rebase_path("$root_gen_dir/observatory/embedded_archive_observatory.cc"),
+ rebase_path("$target_gen_dir/embedded_archive_observatory.cc"),
]
}
-observatory_archive("standalone_archive_observatory") {
- compress = true
+observatory_archive_source("standalone_archive_observatory") {
outer_namespace = "dart"
inner_namespace = "bin"
+
+ # TODO(zra): In a Fuchsia build, use a prebuilt Observatory archive.
+ archive_target = ":compressed_observatory_archive"
+ deps = [
+ archive_target,
+ ]
+ archive_dir = get_label_info(archive_target, "target_gen_dir")
+ archive_name = get_label_info(archive_target, "name")
+ archive_file = "${archive_dir}/${archive_name}.tar"
}
source_set("standalone_observatory_archive") {
@@ -155,6 +214,6 @@
]
sources = [
- rebase_path("$root_gen_dir/observatory/standalone_archive_observatory.cc"),
+ rebase_path("$target_gen_dir/standalone_archive_observatory.cc"),
]
}
diff --git a/runtime/observatory/bin/shell.dart b/runtime/observatory/bin/shell.dart
index ae4e7ff..a0cb274 100644
--- a/runtime/observatory/bin/shell.dart
+++ b/runtime/observatory/bin/shell.dart
@@ -29,7 +29,8 @@
void main() {
String addr = 'ws://localhost:8181/ws';
- new WebSocketVM(new WebSocketVMTarget(addr)).load().then((VM vm) {
+ new WebSocketVM(new WebSocketVMTarget(addr)).load().then((serviceObject) {
+ VM vm = serviceObject;
Isolate isolate = vm.isolates.first;
repl(vm, isolate, 'isolate ${isolate.id}');
});
diff --git a/runtime/observatory/lib/service.dart b/runtime/observatory/lib/service.dart
index 10028cb..9af0604 100644
--- a/runtime/observatory/lib/service.dart
+++ b/runtime/observatory/lib/service.dart
@@ -14,5 +14,6 @@
import 'package:observatory/event.dart' show createEventFromServiceEvent;
import 'package:observatory/models.dart' as M;
import 'package:observatory/tracer.dart';
+import 'package:observatory/service_common.dart';
part 'src/service/object.dart';
diff --git a/runtime/observatory/lib/src/allocation_profile/allocation_profile.dart b/runtime/observatory/lib/src/allocation_profile/allocation_profile.dart
index b8f9f03..d84be6c 100644
--- a/runtime/observatory/lib/src/allocation_profile/allocation_profile.dart
+++ b/runtime/observatory/lib/src/allocation_profile/allocation_profile.dart
@@ -47,7 +47,7 @@
accumulators.addAll(new Map.fromIterable(values, value: (_) => classes));
});
final List<M.ClassHeapStats> result = <M.ClassHeapStats>[];
- members.forEach((ClassHeapStats member) {
+ members.forEach((M.ClassHeapStats member) {
if (accumulators.containsKey(member.clazz.id)) {
accumulators[member.clazz.id].add(member);
} else {
diff --git a/runtime/observatory/lib/src/app/application.dart b/runtime/observatory/lib/src/app/application.dart
index 8ea5b0a..79e85ef 100644
--- a/runtime/observatory/lib/src/app/application.dart
+++ b/runtime/observatory/lib/src/app/application.dart
@@ -20,7 +20,7 @@
VM _vm;
VM get vm => _vm;
- static bool isConnectedVMTarget(WebSocketVMTarget target) {
+ static bool isConnectedVMTarget(M.Target target) {
if (app._vm is CommonWebSocketVM) {
if ((app._vm as CommonWebSocketVM).target == target) {
return app._vm.isConnected;
diff --git a/runtime/observatory/lib/src/app/location_manager.dart b/runtime/observatory/lib/src/app/location_manager.dart
index 38dd94c..cf77504 100644
--- a/runtime/observatory/lib/src/app/location_manager.dart
+++ b/runtime/observatory/lib/src/app/location_manager.dart
@@ -161,7 +161,7 @@
event.preventDefault();
// 'currentTarget' is the dom element that would process the event.
// If we use 'target' we might get an <em> element or somesuch.
- var target = event.currentTarget;
+ Element target = event.currentTarget;
go(target.attributes['href']);
}
}
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 67fcc89..248cacc 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -170,7 +170,8 @@
app.locationManager.go(Uris.vmConnect());
return;
}
- app.vm.reload().then((VM vm) {
+ app.vm.reload().then((serviceObject) {
+ VM vm = serviceObject;
container.children = [
new VMViewElement(vm, _vmrepository, app.events, app.notifications,
new IsolateRepository(app.vm), _scriptRepository,
@@ -706,7 +707,8 @@
return;
}
final editor = getEditor(uri);
- app.vm.reload().then((VM vm) async {
+ app.vm.reload().then((serviceObject) async {
+ VM vm = serviceObject;
// Preload all isolates to avoid sorting problems.
await Future.wait(vm.isolates.map((i) => i.load()));
container.children = [
diff --git a/runtime/observatory/lib/src/elements/allocation_profile.dart b/runtime/observatory/lib/src/elements/allocation_profile.dart
index 5fb89b4..f11e63a 100644
--- a/runtime/observatory/lib/src/elements/allocation_profile.dart
+++ b/runtime/observatory/lib/src/elements/allocation_profile.dart
@@ -455,7 +455,8 @@
_r.dirty();
}
- void _updateCollectionLine(Element e, M.ClassHeapStats item, index) {
+ void _updateCollectionLine(Element e, itemDynamic, index) {
+ M.ClassHeapStats item = itemDynamic;
e.children[0].text = Utils.formatSize(_getAccumulatedSize(item));
e.children[1].text = '${_getAccumulatedInstances(item)}';
e.children[2].text = Utils.formatSize(_getCurrentSize(item));
diff --git a/runtime/observatory/lib/src/elements/class_allocation_profile.dart b/runtime/observatory/lib/src/elements/class_allocation_profile.dart
index 2b7979d..36df884 100644
--- a/runtime/observatory/lib/src/elements/class_allocation_profile.dart
+++ b/runtime/observatory/lib/src/elements/class_allocation_profile.dart
@@ -75,7 +75,7 @@
children = const [];
return;
}
- final content = [
+ final content = <HtmlElement>[
new SampleBufferControlElement(_vm, _progress, _progressStream,
selectedTag: _tag, queue: _r.queue)
..onTagChange.listen((e) {
diff --git a/runtime/observatory/lib/src/elements/class_tree.dart b/runtime/observatory/lib/src/elements/class_tree.dart
index 2a74a06..904014c 100644
--- a/runtime/observatory/lib/src/elements/class_tree.dart
+++ b/runtime/observatory/lib/src/elements/class_tree.dart
@@ -188,7 +188,8 @@
return children;
}
- Iterable<M.Class> _children(M.Class cls) {
+ Iterable<M.Class> _children(classDynamic) {
+ M.Class cls = classDynamic;
return _subclasses[cls.id];
}
}
diff --git a/runtime/observatory/lib/src/elements/class_view.dart b/runtime/observatory/lib/src/elements/class_view.dart
index b9f612f..95c5279 100644
--- a/runtime/observatory/lib/src/elements/class_view.dart
+++ b/runtime/observatory/lib/src/elements/class_view.dart
@@ -252,7 +252,7 @@
new ButtonElement()
..text = 'disable'
..onClick.listen((e) async {
- e.target.disabled = true;
+ (e.target as ButtonElement).disabled = true;
await _profiles.disable(_isolate, _cls);
_loadProfile = true;
_refresh();
@@ -263,7 +263,7 @@
new ButtonElement()
..text = 'enable'
..onClick.listen((e) async {
- e.target.disabled = true;
+ (e.target as ButtonElement).disabled = true;
await _profiles.enable(_isolate, _cls);
_refresh();
})
diff --git a/runtime/observatory/lib/src/elements/containers/virtual_collection.dart b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
index b9bea3e..810de3a 100644
--- a/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
+++ b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
@@ -246,7 +246,7 @@
}
}
- Iterable<dynamic> _doSearch(String search) {
+ Iterable<dynamic> _doSearch(Pattern search) {
return _items.where((item) => _search(search, item));
}
}
diff --git a/runtime/observatory/lib/src/elements/context_ref.dart b/runtime/observatory/lib/src/elements/context_ref.dart
index 5b6bcb0..25b1fa5 100644
--- a/runtime/observatory/lib/src/elements/context_ref.dart
+++ b/runtime/observatory/lib/src/elements/context_ref.dart
@@ -65,7 +65,7 @@
}
void render() {
- var children = [
+ var children = <HtmlElement>[
new AnchorElement(href: Uris.inspect(_isolate, object: _context))
..children = [
new SpanElement()
diff --git a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
index 559a8988..c4caa7c 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
@@ -188,7 +188,10 @@
];
}
- static _getChildren(M.CallTreeNode node) => node.children;
+ static Iterable<M.CallTreeNode> _getChildren(nodeDynamic) {
+ M.CallTreeNode node = nodeDynamic;
+ return node.children;
+ }
static const String _expandedIcon = '▼';
static const String _collapsedIcon = '►';
diff --git a/runtime/observatory/lib/src/elements/cpu_profile_table.dart b/runtime/observatory/lib/src/elements/cpu_profile_table.dart
index d140e3c..3e141a1 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile_table.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile_table.dart
@@ -222,7 +222,8 @@
return element;
}
- void _updateFunction(Element e, M.ProfileFunction item, int index) {
+ void _updateFunction(Element e, itemDynamic, int index) {
+ M.ProfileFunction item = itemDynamic;
if (item == _selected) {
e.classes = ['function-item', 'selected'];
} else {
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 5cda2a5..119e352 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -65,7 +65,7 @@
var commands = debugger.cmd.matchCommand([], false);
commands.sort((a, b) => a.name.compareTo(b.name));
con.print('List of commands:\n');
- for (var command in commands) {
+ for (DebuggerCommand command in commands) {
con.print('${_nameAndAlias(command).padRight(12)} '
'- ${command.helpShort}');
}
@@ -88,7 +88,7 @@
return new Future.value(null);
}
con.print('');
- for (var command in commands) {
+ for (DebuggerCommand command in commands) {
con.printBold(_nameAndAlias(command));
con.print(command.helpLong);
@@ -101,7 +101,7 @@
if (subCommands.isNotEmpty) {
subCommands.sort((a, b) => a.name.compareTo(b.name));
con.print('Subcommands:\n');
- for (var subCommand in subCommands) {
+ for (DebuggerCommand subCommand in subCommands) {
con.print(' ${subCommand.fullName.padRight(16)} '
'- ${subCommand.helpShort}');
}
@@ -657,7 +657,7 @@
Future run(List<String> args) async {
if (args.length == 0) {
for (var name in _options.keys) {
- var getHandler = _options[name][2];
+ dynamic getHandler = _options[name][2];
var value = await getHandler(debugger, name);
debugger.console.print("${name} = ${value}");
}
@@ -668,7 +668,7 @@
debugger.console.print("unrecognized option: $name");
return;
} else {
- var getHandler = optionInfo[2];
+ dynamic getHandler = optionInfo[2];
var value = await getHandler(debugger, name);
debugger.console.print("${name} = ${value}");
}
@@ -680,12 +680,12 @@
debugger.console.print("unrecognized option: $name");
return;
}
- var validValues = optionInfo[0];
+ dynamic validValues = optionInfo[0];
if (!validValues.contains(value)) {
debugger.console.print("'${value}' is not in ${validValues}");
return;
}
- var setHandler = optionInfo[1];
+ dynamic setHandler = optionInfo[1];
await setHandler(debugger, name, value);
} else {
debugger.console.print("set expects 0, 1, or 2 arguments");
@@ -696,7 +696,7 @@
if (args.length < 1 || args.length > 2) {
return new Future.value([args.join('')]);
}
- var result = [];
+ var result = <String>[];
if (args.length == 1) {
var prefix = args[0];
for (var option in _options.keys) {
@@ -931,7 +931,7 @@
}
toRemove.add(bptToRemove);
}
- List pending = [];
+ List<Future> pending = [];
for (var bpt in toRemove) {
pending.add(debugger.isolate.removeBreakpoint(bpt));
}
@@ -1041,7 +1041,7 @@
if (args.length != 1) {
return new Future.value([args.join('')]);
}
- var result = [];
+ var result = <String>[];
for (var isolate in debugger.vm.isolates) {
var str = isolate.number.toString();
if (str.startsWith(args[0])) {
@@ -1086,7 +1086,7 @@
}
// Refresh all isolates first.
- var pending = [];
+ var pending = <Future>[];
for (var isolate in debugger.vm.isolates) {
pending.add(isolate.reload());
}
@@ -1508,7 +1508,8 @@
breakOnException = isolate.exceptionsPauseInfo;
}
- isolate.reload().then((response) {
+ isolate.reload().then((serviceObject) {
+ S.Isolate response = serviceObject;
if (response.isSentinel) {
// The isolate has gone away. The IsolateExit event will
// clear the isolate for the debugger page.
@@ -1516,7 +1517,7 @@
}
// TODO(turnidge): Currently the debugger relies on all libs
// being loaded. Fix this.
- var pending = [];
+ var pending = <Future>[];
for (var lib in response.libraries) {
if (!lib.loaded) {
pending.add(lib.load());
@@ -1697,20 +1698,20 @@
void onEvent(S.ServiceEvent event) {
switch (event.kind) {
case S.ServiceEvent.kVMUpdate:
- var vm = event.owner;
+ S.VM vm = event.owner;
console.print("VM ${vm.displayName} renamed to '${vm.name}'");
break;
case S.ServiceEvent.kIsolateStart:
{
- var iso = event.owner;
+ S.Isolate iso = event.owner;
console.print("Isolate ${iso.number} '${iso.name}' has been created");
}
break;
case S.ServiceEvent.kIsolateExit:
{
- var iso = event.owner;
+ S.Isolate iso = event.owner;
if (iso == isolate) {
console.print("The current isolate ${iso.number} '${iso.name}' "
"has exited");
@@ -1735,7 +1736,7 @@
break;
case S.ServiceEvent.kIsolateUpdate:
- var iso = event.owner;
+ S.Isolate iso = event.owner;
console.print("Isolate ${iso.number} renamed to '${iso.name}'");
break;
@@ -1914,7 +1915,7 @@
await isolate.addBreakpoint(script, line);
} else {
// TODO(turnidge): Clear this breakpoint at current column.
- var pending = [];
+ var pending = <Future>[];
for (var bpt in bpts) {
pending.add(isolate.removeBreakpoint(bpt));
}
@@ -2019,7 +2020,7 @@
assert(objects != null);
assert(scripts != null);
assert(events != null);
- final e = document.createElement(tag.name);
+ final DebuggerPageElement e = document.createElement(tag.name);
final debugger = new ObservatoryDebugger(isolate);
debugger.page = e;
debugger.objects = objects;
@@ -2210,7 +2211,7 @@
assert(objects != null);
assert(scripts != null);
assert(events != null);
- final e = document.createElement(tag.name);
+ final DebuggerStackElement e = document.createElement(tag.name);
e._isolate = isolate;
e._debugger = debugger;
e._scroller = scroller;
diff --git a/runtime/observatory/lib/src/elements/eval_box.dart b/runtime/observatory/lib/src/elements/eval_box.dart
index 6f6191a..ca167b5 100644
--- a/runtime/observatory/lib/src/elements/eval_box.dart
+++ b/runtime/observatory/lib/src/elements/eval_box.dart
@@ -133,7 +133,7 @@
];
}
- TextInputElement _createEvalTextArea() {
+ TextAreaElement _createEvalTextArea() {
var area = new TextAreaElement()
..classes = ['textbox']
..placeholder = 'evaluate an expression'
diff --git a/runtime/observatory/lib/src/elements/heap_map.dart b/runtime/observatory/lib/src/elements/heap_map.dart
index 6e313e8..f11f825 100644
--- a/runtime/observatory/lib/src/elements/heap_map.dart
+++ b/runtime/observatory/lib/src/elements/heap_map.dart
@@ -181,7 +181,7 @@
var pagePixels = _pageHeight * _fragmentationData.width;
var index = new PixelReference(_fragmentationData, point).index;
var pageIndex = index ~/ pagePixels;
- var pageOffset = index % pagePixels;
+ num pageOffset = index % pagePixels;
var pages = _fragmentation['pages'];
if (pageIndex < 0 || pageIndex >= pages.length) {
return null;
@@ -289,9 +289,8 @@
if (gc != null) {
params['gc'] = gc;
}
- return isolate
- .invokeRpc('_getHeapMap', params)
- .then((S.ServiceMap response) {
+ return isolate.invokeRpc('_getHeapMap', params).then((serviceObject) {
+ S.ServiceMap response = serviceObject;
assert(response['type'] == 'HeapMap');
_fragmentation = response;
_updateFragmentationData();
diff --git a/runtime/observatory/lib/src/elements/heap_snapshot.dart b/runtime/observatory/lib/src/elements/heap_snapshot.dart
index 59296ec..a6b0953 100644
--- a/runtime/observatory/lib/src/elements/heap_snapshot.dart
+++ b/runtime/observatory/lib/src/elements/heap_snapshot.dart
@@ -188,7 +188,7 @@
VirtualTreeElement _tree;
List<Element> _createReport() {
- var report = [
+ var report = <HtmlElement>[
new DivElement()
..classes = ['content-centered-big']
..children = [
@@ -397,7 +397,8 @@
static const int kMaxChildren = 100;
static const int kMinRetainedSize = 4096;
- static Iterable _getChildrenDominator(M.HeapSnapshotDominatorNode node) {
+ static Iterable _getChildrenDominator(nodeDynamic) {
+ M.HeapSnapshotDominatorNode node = nodeDynamic;
final list = node.children.toList();
list.sort((a, b) => b.retainedSize - a.retainedSize);
return list
@@ -405,8 +406,8 @@
.take(kMaxChildren);
}
- static Iterable _getChildrenMergedDominator(
- M.HeapSnapshotMergedDominatorNode node) {
+ static Iterable _getChildrenMergedDominator(nodeDynamic) {
+ M.HeapSnapshotMergedDominatorNode node = nodeDynamic;
final list = node.children.toList();
list.sort((a, b) => b.retainedSize - a.retainedSize);
return list
diff --git a/runtime/observatory/lib/src/elements/memory/allocations.dart b/runtime/observatory/lib/src/elements/memory/allocations.dart
index 329e6ba..64f9595 100644
--- a/runtime/observatory/lib/src/elements/memory/allocations.dart
+++ b/runtime/observatory/lib/src/elements/memory/allocations.dart
@@ -221,7 +221,8 @@
_r.dirty();
}
- void _updateCollectionLine(Element e, M.ClassHeapStats item, index) {
+ void _updateCollectionLine(Element e, itemDynamic, index) {
+ M.ClassHeapStats item = itemDynamic;
e.children[0].text = Utils.formatSize(_getAccumulatedSize(item));
e.children[1].text = '${_getAccumulatedInstances(item)}';
e.children[2].text = Utils.formatSize(_getCurrentSize(item));
diff --git a/runtime/observatory/lib/src/elements/memory/snapshot.dart b/runtime/observatory/lib/src/elements/memory/snapshot.dart
index fd91ebc..d6adcf3e 100644
--- a/runtime/observatory/lib/src/elements/memory/snapshot.dart
+++ b/runtime/observatory/lib/src/elements/memory/snapshot.dart
@@ -186,7 +186,8 @@
static const int kMaxChildren = 100;
static const int kMinRetainedSize = 4096;
- static Iterable _getChildrenDominator(M.HeapSnapshotDominatorNode node) {
+ static Iterable _getChildrenDominator(nodeDynamic) {
+ M.HeapSnapshotDominatorNode node = nodeDynamic;
final list = node.children.toList();
list.sort((a, b) => b.retainedSize - a.retainedSize);
return list
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index f6ded1c..6937c9e 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -94,10 +94,10 @@
if (loc.tokenPos != null) {
line = _loadedScript.tokenToLine(loc.tokenPos);
} else {
- line = loc.line;
+ line = (loc as dynamic).line;
}
} else {
- line = loc.line;
+ line = (loc as dynamic).line;
}
if ((line == null) || ((line >= _startLine) && (line <= _endLine))) {
_r.dirty();
@@ -170,7 +170,7 @@
void _scrollToCurrentPos() {
var lines = getElementsByClassName(makeLineClass(_currentLine));
if (lines.length > 0) {
- lines[0].scrollIntoView();
+ (lines[0] as dynamic).scrollIntoView();
}
}
@@ -227,7 +227,7 @@
reports.add(S.Isolate.kProfileReport);
}
S.Isolate isolate = _isolate as S.Isolate;
- var sourceReport =
+ dynamic sourceReport =
await isolate.getSourceReport(reports, script, _startPos, _endPos);
_possibleBreakpointLines =
S.getPossibleBreakpointLines(sourceReport, script);
@@ -355,8 +355,9 @@
}
Future loadDeclarationsOfLibrary(S.Library lib) {
- return lib.load().then((lib) {
- var loads = [];
+ return lib.load().then((serviceObject) {
+ S.Library lib = serviceObject;
+ var loads = <Future>[];
for (var func in lib.functions) {
loads.add(func.load());
}
@@ -371,8 +372,9 @@
}
Future loadDeclarationsOfClass(S.Class cls) {
- return cls.load().then((cls) {
- var loads = [];
+ return cls.load().then((serviceObject) {
+ S.Class cls = serviceObject;
+ var loads = <Future>[];
for (var func in cls.functions) {
loads.add(func.load());
}
@@ -431,9 +433,9 @@
}
}
if (targetUri.scheme == 'package') {
- targetUri = "packages/${targetUri.path}";
+ var targetUriString = "packages/${targetUri.path}";
for (M.Library l in script.isolate.libraries) {
- if (targetUri.toString() == l.uri) {
+ if (targetUriString == l.uri) {
return l;
}
}
@@ -814,7 +816,7 @@
});
} else {
// Existing breakpoint. Remove it.
- List pending = [];
+ List<Future> pending = [];
for (var bpt in line.breakpoints) {
pending.add(line.script.isolate.removeBreakpoint(bpt));
}
@@ -928,7 +930,7 @@
/// children have been added, and only supports one node at a time.
static void _makeCssClassUncopyable(Element root, String className) {
var noCopyNodes = root.getElementsByClassName(className);
- for (var node in noCopyNodes) {
+ for (HtmlElement node in noCopyNodes) {
node.style.setProperty('-moz-user-select', 'none');
node.style.setProperty('-khtml-user-select', 'none');
node.style.setProperty('-webkit-user-select', 'none');
@@ -938,11 +940,11 @@
root.onCopy.listen((event) {
// Mark the nodes as hidden before the copy happens, then mark them as
// visible on the next event loop turn.
- for (var node in noCopyNodes) {
+ for (HtmlElement node in noCopyNodes) {
node.style.visibility = 'hidden';
}
Timer.run(() {
- for (var node in noCopyNodes) {
+ for (HtmlElement node in noCopyNodes) {
node.style.visibility = 'visible';
}
});
@@ -1065,7 +1067,7 @@
BreakpointAnnotation(M.IsolateRef isolate, M.ObjectRepository objects,
RenderingQueue queue, this.bpt)
: super(isolate, objects, queue) {
- var script = bpt.location.script;
+ S.Script script = bpt.location.script;
var location = bpt.location;
if (location.tokenPos != null) {
var pos = location.tokenPos;
@@ -1089,7 +1091,7 @@
if (element == null) {
return; // TODO(rmacnak): Handling overlapping annotations.
}
- var script = bpt.location.script;
+ S.Script script = bpt.location.script;
var pos = bpt.location.tokenPos;
int line = script.tokenToLine(pos);
int column = script.tokenToCol(pos);
diff --git a/runtime/observatory/lib/src/models/objects/instance.dart b/runtime/observatory/lib/src/models/objects/instance.dart
index 982d6d8..1a1b8d4 100644
--- a/runtime/observatory/lib/src/models/objects/instance.dart
+++ b/runtime/observatory/lib/src/models/objects/instance.dart
@@ -420,37 +420,37 @@
///
/// Provided for instance kinds:
/// RegExp
- Function get oneByteFunction;
+ FunctionRef get oneByteFunction;
/// [optional]
///
/// Provided for instance kinds:
/// RegExp
- Function get twoByteFunction;
+ FunctionRef get twoByteFunction;
/// [optional]
///
/// Provided for instance kinds:
/// RegExp
- Function get externalOneByteFunction;
+ FunctionRef get externalOneByteFunction;
/// [optional]
///
/// Provided for instance kinds:
/// RegExp
- Function get externalTwoByteFunction;
+ FunctionRef get externalTwoByteFunction;
/// [optional]
///
/// Provided for instance kinds:
/// RegExp
- Instance get oneByteBytecode;
+ InstanceRef get oneByteBytecode;
/// [optional]
///
/// Provided for instance kinds:
/// RegExp
- Instance get twoByteBytecode;
+ InstanceRef get twoByteBytecode;
}
abstract class BoundField {
diff --git a/runtime/observatory/lib/src/repositories/allocation_profile.dart b/runtime/observatory/lib/src/repositories/allocation_profile.dart
index 8698428..a1f364f 100644
--- a/runtime/observatory/lib/src/repositories/allocation_profile.dart
+++ b/runtime/observatory/lib/src/repositories/allocation_profile.dart
@@ -21,7 +21,7 @@
if (reset) {
params['reset'] = true;
}
- final response = await isolate.invokeRpc(_api, params);
+ final dynamic response = await isolate.invokeRpc(_api, params);
Map defaults;
if (combine) {
defaults = await isolate.vm.invokeRpcNoUpgrade(_defaultsApi, {});
diff --git a/runtime/observatory/lib/src/repositories/sample_profile.dart b/runtime/observatory/lib/src/repositories/sample_profile.dart
index 6778262..3dace5a 100644
--- a/runtime/observatory/lib/src/repositories/sample_profile.dart
+++ b/runtime/observatory/lib/src/repositories/sample_profile.dart
@@ -146,7 +146,7 @@
class ClassSampleProfileRepository implements M.ClassSampleProfileRepository {
Stream<SampleProfileLoadingProgressEvent> get(
- M.Isolate i, M.ClassRef c, M.SampleProfileTag t,
+ covariant M.Isolate i, M.ClassRef c, M.SampleProfileTag t,
{bool clear: false, bool forceFetch: false}) {
S.Isolate isolate = i as S.Isolate;
S.Class cls = c as S.Class;
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 26ff6ab..6c52677 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -654,6 +654,7 @@
abstract class VM extends ServiceObjectOwner implements M.VM {
VM get vm => this;
Isolate get isolate => null;
+ WebSocketVMTarget get target;
// TODO(turnidge): The connection should not be stored in the VM object.
bool get isDisconnected;
@@ -813,7 +814,7 @@
// Note that this function does not reload the isolate if it found
// in the cache.
- Future<ServiceObject> getIsolate(String isolateId) {
+ Future<Isolate> getIsolate(String isolateId) {
if (!loaded) {
// Trigger a VM load, then get the isolate.
return load().then((_) => getIsolate(isolateId)).catchError(_ignoreError);
@@ -1077,6 +1078,9 @@
}
return new Future.value(response);
}
+
+ @override
+ WebSocketVMTarget get target => throw new UnimplementedError();
}
/// Snapshot in time of tag counters.
diff --git a/runtime/observatory/lib/utils.dart b/runtime/observatory/lib/utils.dart
index 4957014..4167fb5 100644
--- a/runtime/observatory/lib/utils.dart
+++ b/runtime/observatory/lib/utils.dart
@@ -96,7 +96,8 @@
}
}
- static String formatSize(int bytes) {
+ static String formatSize(bytesDynamic) {
+ int bytes = bytesDynamic;
const int digits = 1;
const int bytesPerKB = 1024;
const int bytesPerMB = 1024 * bytesPerKB;
diff --git a/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.dart b/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.dart
index 472bc70..5fe996a 100644
--- a/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/allocation_profile/element_test.dart
@@ -89,7 +89,7 @@
e
.querySelectorAll(rTag)
.sublist(1, 4)
- .forEach((NavRefreshElement e) => e.refresh());
+ .forEach((e) => (e as NavRefreshElement).refresh());
e.remove();
await e.onRendered.first;
expect(e.children.length, isZero, reason: 'is empty');
diff --git a/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart b/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
index 727eb0b..e2c74f5 100644
--- a/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
+import 'package:observatory/models.dart' as M;
import 'package:unittest/unittest.dart';
import 'package:observatory/src/elements/flag_list.dart';
import 'package:observatory/src/elements/nav/notify.dart';
@@ -32,7 +33,7 @@
const FlagMock(name: 'f2', comment: 'c2', modified: false),
const FlagMock(name: 'f3', comment: 'c3', modified: false),
];
- final flags = []..addAll(modified)..addAll(unmodifed);
+ final flags = <M.Flag>[]..addAll(modified)..addAll(unmodifed);
final repository = new FlagsRepositoryMock(list: flags);
final e = new FlagListElement(vm, events, repository, notifications);
document.body.append(e);
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/instance.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/instance.dart
index aa72df2..df07d2c 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/instance.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/instance.dart
@@ -50,7 +50,7 @@
final M.ContextRef closureContext;
final int offset;
final int count;
- final Iterable<dynamic> typedElements;
+ final List<dynamic> typedElements;
final Iterable<M.BoundField> fields;
final Iterable<M.NativeField> nativeFields;
final Iterable<M.Guarded<M.ObjectRef>> elements;
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart
index 13c521f..0beeaea 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart
@@ -44,7 +44,7 @@
final ClassSampleProfileRepositoryMockToggleCallback _disable;
Stream<M.SampleProfileLoadingProgressEvent> get(
- M.Isolate isolate, M.ClassRef cls, M.SampleProfileTag tag,
+ covariant M.Isolate isolate, M.ClassRef cls, M.SampleProfileTag tag,
{bool clear: false, bool forceFetch: false}) {
if (_get != null) {
return _get(isolate, cls, tag, clear, forceFetch);
@@ -52,14 +52,14 @@
return null;
}
- Future enable(M.Isolate isolate, M.ClassRef cls) {
+ Future enable(covariant M.Isolate isolate, M.ClassRef cls) {
if (_enable != null) {
return _enable(isolate, cls);
}
return new Future.value();
}
- Future disable(M.Isolate isolate, M.ClassRef cls) {
+ Future disable(covariant M.Isolate isolate, M.ClassRef cls) {
if (_disable != null) {
return _disable(isolate, cls);
}
diff --git a/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart b/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
index 4d917e1..6a982a0 100644
--- a/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
+++ b/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
@@ -78,7 +78,8 @@
expect(await futureBpt2.location.getColumn(), equals(3));
// The first breakpoint hits before value is modified.
- expect((await rootLib.evaluate('value')).valueAsString, equals('0'));
+ expect(((await rootLib.evaluate('value')) as Instance).valueAsString,
+ equals('0'));
stream = await isolate.vm.getEventStream(VM.kDebugStream);
completer = new Completer();
@@ -92,7 +93,8 @@
await completer.future;
// The second breakpoint hits after value has been modified once.
- expect((await rootLib.evaluate('value')).valueAsString, equals('1'));
+ expect(((await rootLib.evaluate('value')) as Instance).valueAsString,
+ equals('1'));
// Remove the breakpoints.
expect(
@@ -148,7 +150,9 @@
expect(await latentBpt2.location.getColumn(), equals(3));
// The first breakpoint hits before value is modified.
- expect((await rootLib.evaluate('deferredLib.value')).valueAsString,
+ expect(
+ ((await rootLib.evaluate('deferredLib.value')) as Instance)
+ .valueAsString,
equals('0'));
stream = await isolate.vm.getEventStream(VM.kDebugStream);
@@ -163,7 +167,9 @@
await completer.future;
// The second breakpoint hits after value has been modified once.
- expect((await rootLib.evaluate('deferredLib.value')).valueAsString,
+ expect(
+ ((await rootLib.evaluate('deferredLib.value')) as Instance)
+ .valueAsString,
equals('-1'));
// Remove the breakpoints.
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index d93a63c..afebf2f 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -2,6 +2,116 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
+[ $compiler == app_jitk ]
+add_breakpoint_rpc_test: RuntimeError
+async_generator_breakpoint_test: RuntimeError
+async_next_test: RuntimeError
+async_scope_test: RuntimeError
+async_single_step_exception_test: RuntimeError
+async_single_step_into_test: RuntimeError
+async_single_step_out_test: RuntimeError
+async_star_single_step_into_test: RuntimeError
+async_star_step_out_test: RuntimeError
+async_step_out_test: RuntimeError
+awaiter_async_stack_contents_test: RuntimeError
+bad_reload_test: RuntimeError
+break_on_activation_test: RuntimeError
+break_on_function_test: RuntimeError
+breakpoint_in_parts_class_test: RuntimeError
+breakpoint_two_args_checked_test: RuntimeError
+causal_async_stack_contents_test: RuntimeError
+causal_async_stack_presence_test: RuntimeError
+causal_async_star_stack_contents_test: RuntimeError
+causal_async_star_stack_presence_test: RuntimeError
+complex_reload_test: RuntimeError
+coverage_leaf_function_test: RuntimeError
+coverage_optimized_function_test: RuntimeError
+debugger_inspect_test: Skip # Timeout
+debugger_location_second_test: RuntimeError
+debugger_location_test: RuntimeError
+debugging_inlined_finally_test: RuntimeError
+debugging_test: RuntimeError
+developer_service_get_isolate_id_test: RuntimeError
+eval_internal_class_test: RuntimeError
+eval_test: RuntimeError
+evaluate_activation_in_method_class_test: RuntimeError
+evaluate_activation_test/instance: RuntimeError
+evaluate_activation_test/none: RuntimeError
+evaluate_activation_test/scope: RuntimeError
+evaluate_async_closure_test: RuntimeError
+evaluate_class_type_parameters_test: RuntimeError
+evaluate_in_async_activation_test: RuntimeError
+evaluate_in_async_star_activation_test: RuntimeError
+evaluate_in_frame_rpc_test: RuntimeError
+evaluate_in_frame_with_scope_test: RuntimeError
+evaluate_in_sync_star_activation_test: RuntimeError
+evaluate_with_scope_test: RuntimeError
+get_instances_rpc_test: RuntimeError
+get_object_rpc_test: RuntimeError
+get_retaining_path_rpc_test: RuntimeError
+get_source_report_test: RuntimeError
+get_stack_rpc_test: RuntimeError
+get_user_level_retaining_path_rpc_test: RuntimeError
+get_vm_rpc_test: RuntimeError
+get_vm_timeline_rpc_test: RuntimeError
+instance_field_order_rpc_test: RuntimeError
+issue_25465_test: RuntimeError
+issue_27238_test: RuntimeError
+issue_27287_test: RuntimeError
+local_variable_declaration_test: RuntimeError
+mixin_break_test: RuntimeError
+next_through_assign_call_test: RuntimeError
+next_through_assign_int_test: RuntimeError
+next_through_call_on_field_in_class_test: RuntimeError
+next_through_call_on_field_test: RuntimeError
+next_through_call_on_static_field_in_class_test: RuntimeError
+next_through_catch_test: RuntimeError
+next_through_closure_test: RuntimeError
+next_through_create_list_and_map_test: RuntimeError
+next_through_for_each_loop_test: RuntimeError
+next_through_for_loop_with_break_and_continue_test: RuntimeError
+next_through_function_expression_test: RuntimeError
+next_through_implicit_call_test: RuntimeError
+next_through_is_and_as_test: RuntimeError
+next_through_multi_catch_test: RuntimeError
+next_through_new_test: RuntimeError
+next_through_operator_bracket_on_super_test: RuntimeError
+next_through_operator_bracket_on_this_test: RuntimeError
+next_through_operator_bracket_test: RuntimeError
+next_through_simple_async_test: RuntimeError
+next_through_simple_async_with_returns_test: RuntimeError
+next_through_simple_linear_2_test: RuntimeError
+next_through_simple_linear_test: RuntimeError
+parameters_in_scope_at_entry_test: RuntimeError
+pause_on_exceptions_test: Skip # Timeout
+pause_on_unhandled_async_exceptions2_test: RuntimeError
+pause_on_unhandled_async_exceptions_test: RuntimeError
+positive_token_pos_test: RuntimeError
+process_service_test: RuntimeError
+regress_28443_test: RuntimeError
+regress_28980_test: RuntimeError
+rewind_optimized_out_test: RuntimeError
+rewind_test: RuntimeError
+set_library_debuggable_test: RuntimeError
+set_name_rpc_test: RuntimeError
+set_vm_name_rpc_test: RuntimeError
+steal_breakpoint_test: RuntimeError
+step_into_async_no_await_test: RuntimeError
+step_over_await_test: RuntimeError
+step_through_arithmetic_test: RuntimeError
+step_through_constructor_calls_test: RuntimeError
+step_through_constructor_test: RuntimeError
+step_through_function_2_test: RuntimeError
+step_through_function_test: RuntimeError
+step_through_getter_test: RuntimeError
+step_through_property_get_test: RuntimeError
+step_through_property_set_test: RuntimeError
+step_through_setter_test: RuntimeError
+step_through_switch_test: RuntimeError
+step_through_switch_with_continue_test: RuntimeError
+unused_changes_in_last_reload_test: RuntimeError
+valid_source_locations_test: RuntimeError
+
# Kernel works slightly different. There are kernel specific versions.
# These are the non-kernel specific versions so skip tests and allow errors.
[ $compiler == dartk ]
@@ -34,6 +144,10 @@
[ $arch == simdbc64 && $compiler == dartk && $mode == debug ]
eval_test: Pass, Slow
+[ $compiler == app_jitk && $mode == debug ]
+code_test: RuntimeError
+step_test: RuntimeError
+
[ $compiler == dartk && $mode == debug ]
isolate_lifecycle_test: Skip # Flaky.
pause_idle_isolate_test: Skip # Flaky
@@ -139,6 +253,3 @@
set_name_rpc_test: RuntimeError # Please triage.
unused_changes_in_last_reload_test: Skip # Times out on sim architectures.
valid_source_locations_test: Pass, Slow, Timeout # Issue 33087
-
-[ $compiler == fasta && $strong ]
-add_breakpoint_rpc_test: CompileTimeError
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 517d182..8c09582 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -151,10 +151,6 @@
#define NOT_IN_PRECOMPILED(code) code
#endif // defined(DART_PRECOMPILED_RUNTIME)
-#if defined(DART_PRECOMPILED_RUNTIME) || defined(PRODUCT)
-#define EXCLUDE_CFE_AND_KERNEL_PLATFORM 1
-#endif // defined(DART_PRECOMPILED_RUNTIME)
-
namespace dart {
struct simd128_value_t {
diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni
index f6586e2..cfff1af 100644
--- a/runtime/runtime_args.gni
+++ b/runtime/runtime_args.gni
@@ -81,4 +81,8 @@
# Whether the runtime should interpret called functions for which bytecode
# is provided by kernel, rather than compile them before execution.
dart_use_interpreter = false
+
+ # Whether the VM includes the kernel service in all modes (debug, release,
+ # product).
+ exclude_kernel_service = false
}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 2cf1c6e..92c4f22 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -26,6 +26,12 @@
[ $compiler == app_jit ]
dart/snapshot_version_test: Fail, OK # Expects to find script snapshot relative to Dart source.
+[ $compiler == app_jitk ]
+dart/data_uri_import_test/utf16: MissingRuntimeError
+dart/redirection_type_shuffling_test/00: RuntimeError
+dart/redirection_type_shuffling_test/none: RuntimeError
+dart/snapshot_version_test: RuntimeError
+
[ $compiler == dart2analyzer ]
dart/byte_array_optimized_test: CompileTimeError # int64
dart/byte_array_test: CompileTimeError # int64
@@ -117,6 +123,9 @@
cc/Profiler_TrivialRecordAllocation: Skip
cc/Profiler_TypedArrayAllocation: Skip
+[ $arch == x64 && $compiler == dartk && $system == windows && $strong ]
+cc/Profiler_BasicSourcePosition: Fail # http://dartbug.com/33224
+
[ $arch == x64 && $system == windows ]
cc/Profiler_BinaryOperatorSourcePositionOptimized: Pass, Fail # Issue 31137
cc/Profiler_ClosureAllocation: Pass, Fail # Issue 31137
diff --git a/runtime/tools/create_archive.py b/runtime/tools/create_archive.py
index c1fc70d..2857db4 100755
--- a/runtime/tools/create_archive.py
+++ b/runtime/tools/create_archive.py
@@ -16,7 +16,7 @@
import tempfile
import gzip
-def makeArchive(tar_path, client_root, compress, files):
+def CreateTarArchive(tar_path, client_root, compress, files):
mode_string = 'w'
tar = tarfile.open(tar_path, mode=mode_string)
for input_file_name in files:
@@ -42,7 +42,35 @@
gz.write(uncompressed)
gz.close()
-def writeCCFile(output_file,
+
+def MakeArchive(options):
+ if not options.client_root:
+ sys.stderr.write('--client_root not specified')
+ return -1
+
+ files = [ ]
+ for dirname, dirnames, filenames in os.walk(options.client_root):
+ # strip out all dot files.
+ filenames = [f for f in filenames if not f[0] == '.']
+ dirnames[:] = [d for d in dirnames if not d[0] == '.']
+ for f in filenames:
+ src_path = os.path.join(dirname, f)
+ if (os.path.isdir(src_path)):
+ continue
+ files.append(src_path)
+
+ # Ensure consistent file ordering for reproducible builds.
+ files.sort()
+
+ # Write out archive.
+ CreateTarArchive(options.tar_output,
+ options.client_root,
+ options.compress,
+ files)
+ return 0
+
+
+def WriteCCFile(output_file,
outer_namespace,
inner_namespace,
name,
@@ -89,13 +117,41 @@
open(output_file, 'w').write(cc_text)
-def main(args):
+
+def MakeCCFile(options):
+ if not options.output:
+ sys.stderr.write('--output not specified\n')
+ return -1
+ if not options.name:
+ sys.stderr.write('--name not specified\n')
+ return -1
+ if not options.tar_input:
+ sys.stderr.write('--tar_input not specified\n')
+ return -1
+
+ # Read it back in.
+ with open(options.tar_input, 'rb') as tar_file:
+ tar_archive = tar_file.read()
+
+ # Write CC file.
+ WriteCCFile(options.output,
+ options.outer_namespace,
+ options.inner_namespace,
+ options.name,
+ tar_archive)
+ return 0
+
+
+def Main(args):
try:
# Parse input.
parser = OptionParser()
parser.add_option("--output",
action="store", type="string",
help="output file name")
+ parser.add_option("--tar_input",\
+ action="store", type="string",
+ help="input tar archive")
parser.add_option("--tar_output",
action="store", type="string",
help="tar output file name")
@@ -116,51 +172,11 @@
help="root directory client resources")
(options, args) = parser.parse_args()
- if not options.output:
- sys.stderr.write('--output not specified\n')
- return -1
- if not options.tar_output:
- sys.stderr.write('--tar_output not specified\n')
- return -1
- if not options.name:
- sys.stderr.write('--name not specified\n')
- return -1
- if not options.client_root:
- sys.stderr.write('--client_root not specified')
- return -1
- files = [ ]
-
- for dirname, dirnames, filenames in os.walk(options.client_root):
- # strip out all dot files.
- filenames = [f for f in filenames if not f[0] == '.']
- dirnames[:] = [d for d in dirnames if not d[0] == '.']
- for f in filenames:
- src_path = os.path.join(dirname, f)
- if (os.path.isdir(src_path)):
- continue
- files.append(src_path)
-
- # Ensure consistent file ordering for reproducible builds.
- files.sort()
-
- # Write out archive.
- makeArchive(options.tar_output,
- options.client_root,
- options.compress,
- files)
-
- # Read it back in.
- with open(options.tar_output, 'rb') as tar_file:
- tar_archive = tar_file.read()
-
- # Write CC file.
- writeCCFile(options.output,
- options.outer_namespace,
- options.inner_namespace,
- options.name,
- tar_archive)
- return 0
+ if options.tar_output:
+ return MakeArchive(options)
+ else:
+ return MakeCCFile(options)
except Exception, inst:
sys.stderr.write('create_resources.py exception\n')
@@ -168,5 +184,6 @@
sys.stderr.write('\n')
return -1
+
if __name__ == '__main__':
- sys.exit(main(sys.argv))
+ sys.exit(Main(sys.argv))
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 2d94185..3d4eea8 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -3150,6 +3150,31 @@
return Type::New(mixin_app_class, mixin_app_args, mixin_app_type.token_pos());
}
+// For a class used as an interface marks this class and all its superclasses
+// implemented.
+//
+// Does not mark its interfaces implemented because those would already be
+// marked as such.
+static void MarkImplemented(Zone* zone, const Class& iface) {
+ if (iface.is_implemented()) {
+ return;
+ }
+
+ Class& cls = Class::Handle(zone, iface.raw());
+ AbstractType& type = AbstractType::Handle(zone);
+
+ while (!cls.is_implemented()) {
+ cls.set_is_implemented();
+
+ type = cls.super_type();
+ if (type.IsNull() || type.IsObjectType()) {
+ break;
+ }
+ ASSERT(type.IsResolved());
+ cls = type.type_class();
+ }
+}
+
// Recursively walks the graph of explicitly declared super type and
// interfaces, resolving unresolved super types and interfaces.
// Reports an error if there is an interface reference that cannot be
@@ -3328,9 +3353,10 @@
}
}
}
- interface_class.set_is_implemented();
+
// Now resolve the super interfaces.
ResolveSuperTypeAndInterfaces(interface_class, visited);
+ MarkImplemented(zone, interface_class);
}
visited->RemoveLast();
cls.set_is_cycle_free();
diff --git a/runtime/vm/compiler/assembler/disassembler_arm64.cc b/runtime/vm/compiler/assembler/disassembler_arm64.cc
index 2fb2b93..f5b49f7 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm64.cc
@@ -614,9 +614,7 @@
} else if (format[1] == 'f') {
ASSERT(STRING_STARTS_WITH(format, "sf"));
if (instr->SFField() == 1) {
- // TODO(zra): If we don't use the w form much, we can omit printing
- // this x.
- Print("x");
+ // 64-bit width is most commonly used, no need to print "x".
} else {
Print("w");
}
@@ -1142,13 +1140,13 @@
int32_t mask = B31 | B30 | B29 | B23 | B22 | B21 | B15 | MiscDP3SourceMask;
int32_t bits = instr->InstructionBits() & mask;
- if (bits == MADD) {
+ if (bits == MADD || bits == MADDW) {
if (zero_operand) {
Format(instr, "mul'sf 'rd, 'rn, 'rm");
} else {
Format(instr, "madd'sf 'rd, 'rn, 'rm, 'ra");
}
- } else if (bits == MSUB) {
+ } else if (bits == MSUB || bits == MSUBW) {
if (zero_operand) {
Format(instr, "mneg'sf 'rd, 'rn, 'rm");
} else {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index ddea9fe..93d70f3 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -3362,8 +3362,9 @@
return GetCachedConstant(offset, &result_);
}
-Instance& StreamingConstantEvaluator::EvaluateExpression(intptr_t offset,
- bool reset_position) {
+RawInstance* StreamingConstantEvaluator::EvaluateExpression(
+ intptr_t offset,
+ bool reset_position) {
ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
if (!GetCachedConstant(offset, &result_)) {
ASSERT(IsAllowedToEvaluate());
@@ -3481,9 +3482,7 @@
builder_->SkipExpression();
}
}
- // We return a new `ZoneHandle` here on purpose: The intermediate language
- // instructions do not make a copy of the handle, so we do it.
- return Instance::ZoneHandle(Z, result_.raw());
+ return result_.raw();
}
Instance& StreamingConstantEvaluator::EvaluateListLiteral(intptr_t offset,
@@ -3538,7 +3537,7 @@
return Instance::ZoneHandle(Z, result_.raw());
}
-Object& StreamingConstantEvaluator::EvaluateExpressionSafe(intptr_t offset) {
+RawObject* StreamingConstantEvaluator::EvaluateExpressionSafe(intptr_t offset) {
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
return EvaluateExpression(offset);
@@ -3547,7 +3546,7 @@
Error& error = Error::Handle(Z);
error = thread->sticky_error();
thread->clear_sticky_error();
- return error;
+ return error.raw();
}
}
@@ -3695,8 +3694,9 @@
void StreamingConstantEvaluator::EvaluateMethodInvocation() {
builder_->ReadPosition(); // read position.
// This method call wasn't cached, so receiver et al. isn't cached either.
- const Instance& receiver =
- EvaluateExpression(builder_->ReaderOffset(), false); // read receiver.
+ const Instance& receiver = Instance::Handle(
+ Z,
+ EvaluateExpression(builder_->ReaderOffset(), false)); // read receiver.
Class& klass =
Class::Handle(Z, isolate_->class_table()->At(receiver.GetClassId()));
ASSERT(!klass.IsNull());
@@ -3721,8 +3721,9 @@
void StreamingConstantEvaluator::EvaluateDirectMethodInvocation() {
builder_->ReadPosition(); // read position.
- const Instance& receiver =
- EvaluateExpression(builder_->ReaderOffset(), false); // read receiver.
+ const Instance& receiver = Instance::Handle(
+ Z,
+ EvaluateExpression(builder_->ReaderOffset(), false)); // read receiver.
NameIndex kernel_name =
builder_->ReadCanonicalNameReference(); // read target_reference.
@@ -3828,7 +3829,7 @@
Instance* receiver = NULL;
const TypeArguments* type_arguments_argument = NULL;
if (!constructor.IsFactory()) {
- receiver = &Instance::ZoneHandle(Z, Instance::New(klass, Heap::kOld));
+ receiver = &Instance::Handle(Z, Instance::New(klass, Heap::kOld));
if (type_arguments != NULL) {
receiver->SetTypeArguments(*type_arguments);
}
@@ -3991,9 +3992,10 @@
const Array& const_list =
Array::ZoneHandle(Z, Array::New(length, Heap::kOld));
const_list.SetTypeArguments(type_arguments);
+ Instance& expression = Instance::Handle(Z);
for (intptr_t i = 0; i < length; ++i) {
- const Instance& expression = EvaluateExpression(
- builder_->ReaderOffset(), false); // read ith expression.
+ expression = EvaluateExpression(builder_->ReaderOffset(),
+ false); // read ith expression.
const_list.SetAt(i, expression);
}
const_list.MakeImmutable();
@@ -4008,13 +4010,13 @@
intptr_t length = builder_->ReadListLength(); // read length of entries.
// This MapLiteral wasn't cached, so content isn't cached either.
- Array& const_kv_array =
- Array::ZoneHandle(Z, Array::New(2 * length, Heap::kOld));
+ Array& const_kv_array = Array::Handle(Z, Array::New(2 * length, Heap::kOld));
+ Instance& temp = Instance::Handle(Z);
for (intptr_t i = 0; i < length; ++i) {
- const_kv_array.SetAt(2 * i + 0, EvaluateExpression(builder_->ReaderOffset(),
- false)); // read key.
- const_kv_array.SetAt(2 * i + 1, EvaluateExpression(builder_->ReaderOffset(),
- false)); // read value.
+ temp = EvaluateExpression(builder_->ReaderOffset(), false); // read key.
+ const_kv_array.SetAt(2 * i + 0, temp);
+ temp = EvaluateExpression(builder_->ReaderOffset(), false); // read value.
+ const_kv_array.SetAt(2 * i + 1, temp);
}
const_kv_array.MakeImmutable();
@@ -4050,8 +4052,9 @@
if (tag == kNothing) {
local->SetConstValue(Instance::ZoneHandle(Z, Instance::null()));
} else {
- local->SetConstValue(EvaluateExpression(
- builder_->ReaderOffset(), false)); // read rest of initializer.
+ local->SetConstValue(Instance::ZoneHandle(
+ Z, EvaluateExpression(builder_->ReaderOffset(),
+ false))); // read rest of initializer.
}
EvaluateExpression(builder_->ReaderOffset(), false); // read body
@@ -4059,8 +4062,9 @@
void StreamingConstantEvaluator::EvaluatePartialTearoffInstantiation() {
// This method call wasn't cached, so receiver et al. isn't cached either.
- const Instance& receiver =
- EvaluateExpression(builder_->ReaderOffset(), false); // read receiver.
+ const Instance& receiver = Instance::Handle(
+ Z,
+ EvaluateExpression(builder_->ReaderOffset(), false)); // read receiver.
if (!receiver.IsClosure()) {
H.ReportError(script_, TokenPosition::kNoSource, "Expected closure.");
}
@@ -4069,26 +4073,16 @@
// read type arguments.
intptr_t num_type_args = builder_->ReadListLength();
const TypeArguments* type_args = &T.BuildTypeArguments(num_type_args);
- // Even if all dynamic types are passed in, we need to put a vector in here to
- // distinguish this partially applied tearoff from a normal tearoff. This is
- // necessary because the tearoff wrapper (BuildGraphOfImplicitClosureFunction)
- // needs to throw NSM if type arguments are passed to a partially applied
- // tearoff.
- if (type_args->IsNull()) {
- type_args =
- &TypeArguments::ZoneHandle(Z, TypeArguments::New(num_type_args));
- for (intptr_t i = 0; i < num_type_args; ++i) {
- type_args->SetTypeAt(i, Type::ZoneHandle(Z, Type::DynamicType()));
- }
- }
// Create new closure with the type arguments inserted, and other things
// copied over.
Closure& new_closure = Closure::Handle(
- Z, Closure::New(TypeArguments::Handle(
- Z, old_closure.instantiator_type_arguments()),
- *type_args, Function::Handle(Z, old_closure.function()),
- Context::Handle(Z, old_closure.context()), Heap::kOld));
+ Z,
+ Closure::New(
+ TypeArguments::Handle(Z, old_closure.instantiator_type_arguments()),
+ TypeArguments::Handle(old_closure.function_type_arguments()),
+ *type_args, Function::Handle(Z, old_closure.function()),
+ Context::Handle(Z, old_closure.context()), Heap::kOld));
result_ = H.Canonicalize(new_closure);
}
@@ -4159,7 +4153,7 @@
(receiver != NULL ? 1 : 0) + (type_args != NULL ? 1 : 0);
// Build up arguments.
- const Array& arguments = Array::ZoneHandle(
+ const Array& arguments = Array::Handle(
Z, Array::New(extra_arguments + argument_count, H.allocation_space()));
intptr_t pos = 0;
if (receiver != NULL) {
@@ -4180,7 +4174,7 @@
// List of named.
list_length = builder_->ReadListLength(); // read list length.
const Array& names =
- Array::ZoneHandle(Z, Array::New(list_length, H.allocation_space()));
+ Array::Handle(Z, Array::New(list_length, H.allocation_space()));
for (intptr_t i = 0; i < list_length; ++i) {
String& name = H.DartSymbolObfuscate(
builder_->ReadStringReference()); // read ith name index.
@@ -5105,7 +5099,8 @@
flow_graph_builder_->CheckStackOverflowInPrologue(field_helper.position_);
if (field_helper.IsConst()) {
// this will (potentially) read the initializer, but reset the position.
- body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
+ body += Constant(Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(ReaderOffset())));
SkipExpression(); // read the initializer.
} else {
body += BuildExpression(); // read initializer.
@@ -5163,7 +5158,8 @@
// contain because it would detect spurious circular initialization when it
// checks for the transition sentinel.
ASSERT(initializer_tag == kSomething);
- body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
+ body += Constant(Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(ReaderOffset())));
} else {
// The field always has an initializer because static fields without
// initializers are initialized eagerly and do not have implicit getters.
@@ -5214,8 +5210,8 @@
if (tag == kSomething) {
// this will (potentially) read the initializer,
// but reset the position.
- default_value =
- &constant_evaluator_.EvaluateExpression(ReaderOffset());
+ default_value = &Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
SkipExpression(); // read (actual) initializer.
} else {
default_value = &Instance::ZoneHandle(Z, Instance::null());
@@ -5242,8 +5238,8 @@
if (tag == kSomething) {
// this will (potentially) read the initializer,
// but reset the position.
- default_value =
- &constant_evaluator_.EvaluateExpression(ReaderOffset());
+ default_value = &Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
SkipExpression(); // read (actual) initializer.
} else {
default_value = &Instance::ZoneHandle(Z, Instance::null());
@@ -8452,7 +8448,8 @@
const Field& field =
Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
if (field.is_const()) {
- return Constant(constant_evaluator_.EvaluateExpression(offset));
+ return Constant(Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(offset)));
} else {
const Class& owner = Class::Handle(Z, field.Owner());
const String& getter_name = H.DartGetterName(target);
@@ -8474,7 +8471,8 @@
return StaticCall(position, function, 0, Array::null_array(),
ICData::kStatic, &result_type);
} else if (H.IsMethod(target)) {
- return Constant(constant_evaluator_.EvaluateExpression(offset));
+ return Constant(Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(offset)));
} else {
UNIMPLEMENTED();
}
@@ -8551,7 +8549,8 @@
intptr_t argument_count = PeekArgumentsCount() + 1;
if ((argument_count == 1) && (token_kind == Token::kNEGATE)) {
- const Object& result = constant_evaluator_.EvaluateExpressionSafe(offset);
+ const Object& result = Object::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpressionSafe(offset));
if (!result.IsError()) {
SkipArguments(); // read arguments.
SkipCanonicalNameReference(); // read interface_target_reference.
@@ -8560,7 +8559,8 @@
} else if ((argument_count == 2) &&
Token::IsBinaryArithmeticOperator(token_kind) &&
IsNumberLiteral(PeekArgumentsFirstPositionalTag())) {
- const Object& result = constant_evaluator_.EvaluateExpressionSafe(offset);
+ const Object& result = Object::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpressionSafe(offset));
if (!result.IsError()) {
SkipArguments(); // read arguments.
SkipCanonicalNameReference(); // read interface_target_reference.
@@ -9355,7 +9355,8 @@
intptr_t offset = ReaderOffset() - 1; // EvaluateExpression needs the tag.
SkipStringReference(); // read index into string table.
- return Constant(constant_evaluator_.EvaluateExpression(offset));
+ return Constant(
+ Instance::ZoneHandle(Z, constant_evaluator_.EvaluateExpression(offset)));
}
Fragment StreamingFlowGraphBuilder::BuildTypeLiteral(TokenPosition* position) {
@@ -10208,8 +10209,8 @@
TargetEntryInstr* otherwise;
TokenPosition position = ReadPosition(); // read jth position.
- current_instructions +=
- Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
+ current_instructions += Constant(Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(ReaderOffset())));
SkipExpression(); // read jth expression.
current_instructions += PushArgument();
current_instructions += LoadLocal(scopes()->switch_variable);
@@ -10666,8 +10667,9 @@
instructions += NullConstant();
} else {
if (helper.IsConst()) {
- const Instance& constant_value = constant_evaluator_.EvaluateExpression(
- ReaderOffset()); // read initializer form current position.
+ const Instance& constant_value = Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(
+ ReaderOffset())); // read initializer form current position.
variable->SetConstValue(constant_value);
instructions += Constant(constant_value);
SkipExpression(); // skip initializer.
@@ -11048,8 +11050,8 @@
Tag tag = ReadTag(); // read (first part of) initializer.
if (tag == kSomething) {
// this will (potentially) read the initializer, but reset the position.
- Instance& constant =
- constant_evaluator_.EvaluateExpression(ReaderOffset());
+ Instance& constant = Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
SkipExpression(); // read (actual) initializer.
param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
constant);
@@ -11097,7 +11099,8 @@
Array::Handle(Z, Array::New(list_length, H.allocation_space()));
for (intptr_t i = 0; i < list_length; ++i) {
// this will (potentially) read the expression, but reset the position.
- Instance& value = constant_evaluator_.EvaluateExpression(ReaderOffset());
+ Instance& value = Instance::ZoneHandle(
+ Z, constant_evaluator_.EvaluateExpression(ReaderOffset()));
SkipExpression(); // read (actual) initializer.
metadata_values.SetAt(i, value);
}
@@ -11341,10 +11344,8 @@
: Object::bool_false().raw();
break;
case kIntConstant: {
- temp_instance_ = const_evaluator_
- .EvaluateExpression(builder_.ReaderOffset(),
- false /* reset position */)
- .raw();
+ temp_instance_ = const_evaluator_.EvaluateExpression(
+ builder_.ReaderOffset(), false /* reset position */);
break;
}
case kDoubleConstant: {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index ce7dc4d..859d443 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -431,8 +431,10 @@
};
enum Flag {
- kIsAbstract = 1,
- kIsEnumClass = 2,
+ kIsAbstract = 1 << 2,
+ kIsEnumClass = 1 << 3,
+ kIsAnonymousMixin = 1 << 4,
+ kIsEliminatedMixin = 1 << 5,
};
explicit ClassHelper(KernelReaderHelper* helper)
@@ -447,9 +449,13 @@
void SetNext(Field field) { next_read_ = field; }
void SetJustRead(Field field) { next_read_ = field + 1; }
- bool is_abstract() { return flags_ & Flag::kIsAbstract; }
+ bool is_abstract() const { return flags_ & Flag::kIsAbstract; }
- bool is_enum_class() { return flags_ & Flag::kIsEnumClass; }
+ bool is_enum_class() const { return flags_ & Flag::kIsEnumClass; }
+
+ bool is_transformed_mixin_application() const {
+ return flags_ & Flag::kIsEliminatedMixin;
+ }
NameIndex canonical_name_;
TokenPosition position_;
@@ -923,12 +929,12 @@
bool IsCached(intptr_t offset);
- Instance& EvaluateExpression(intptr_t offset, bool reset_position = true);
+ RawInstance* EvaluateExpression(intptr_t offset, bool reset_position = true);
Instance& EvaluateListLiteral(intptr_t offset, bool reset_position = true);
Instance& EvaluateMapLiteral(intptr_t offset, bool reset_position = true);
Instance& EvaluateConstructorInvocation(intptr_t offset,
bool reset_position = true);
- Object& EvaluateExpressionSafe(intptr_t offset);
+ RawObject* EvaluateExpressionSafe(intptr_t offset);
private:
bool IsAllowedToEvaluate();
diff --git a/runtime/vm/compiler/intrinsifier_arm64.cc b/runtime/vm/compiler/intrinsifier_arm64.cc
index d14b824..ef7fb20 100644
--- a/runtime/vm/compiler/intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/intrinsifier_arm64.cc
@@ -1175,6 +1175,9 @@
// --qh
__ sub(R6, R6, Operand(1));
+ // Continue while loop.
+ __ b(&qh_adj_loop);
+
__ Bind(&qh_ok);
// R0 = qd = qh << 32
__ orr(R0, ZR, Operand(R6, LSL, 32));
@@ -1227,6 +1230,9 @@
// --ql
__ sub(R6, R6, Operand(1));
+ // Continue while loop.
+ __ b(&ql_adj_loop);
+
__ Bind(&ql_ok);
// qd |= ql;
__ orr(R0, R0, Operand(R6));
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 95b3f87..9294a1b 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -522,8 +522,10 @@
enum MiscDP3SourceOp {
MiscDP3SourceMask = 0x1f000000,
MiscDP3SourceFixed = DPRegisterFixed | B28 | B24,
- MADD = MiscDP3SourceFixed,
- MSUB = MiscDP3SourceFixed | B15,
+ MADDW = MiscDP3SourceFixed,
+ MADD = MiscDP3SourceFixed | B31,
+ MSUBW = MiscDP3SourceFixed | B15,
+ MSUB = MiscDP3SourceFixed | B31 | B15,
SMULH = MiscDP3SourceFixed | B31 | B22,
UMULH = MiscDP3SourceFixed | B31 | B23 | B22,
SMADDL = MiscDP3SourceFixed | B31 | B21,
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 09ce27c..e845697 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -700,15 +700,21 @@
#elif defined(TARGET_ARCH_IA32)
buffer.AddString(" ia32");
#elif defined(TARGET_ARCH_X64)
-#if defined(_WIN64)
+#if defined(TARGET_OS_WINDOWS)
buffer.AddString(" x64-win");
#else
buffer.AddString(" x64-sysv");
#endif
#elif defined(TARGET_ARCH_DBC)
- buffer.AddString(" dbc");
-#elif defined(TARGET_ARCH_DBC64)
+#if defined(ARCH_IS_32_BIT)
+ buffer.AddString(" dbc32");
+#elif defined(ARCH_IS_64_BIT)
buffer.AddString(" dbc64");
+#else
+#error What word size?
+#endif
+#else
+#error What architecture?
#endif
}
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 61af137..d927ba9 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -801,6 +801,8 @@
#define FLAG_FOR_NONPRODUCT(action)
#endif
+#define FLAG_FOR_PRODUCT(action) action
+
#define SET_FROM_FLAG(when, name, bitname, isolate_flag, flag) \
FLAG_FOR_##when(isolate_flags_ = bitname##Bit::update( \
api_flags.isolate_flag, isolate_flags_));
@@ -809,6 +811,7 @@
#undef FLAG_FOR_NONPRODUCT
#undef FLAG_FOR_PRECOMPILER
+#undef FLAG_FOR_PRODUCT
#undef SET_FROM_FLAG
set_use_dart_frontend(api_flags.use_dart_frontend);
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 28c0795..6584382 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -138,10 +138,10 @@
V(NONPRODUCT, type_checks, EnableTypeChecks, enable_type_checks, \
FLAG_enable_type_checks) \
V(NONPRODUCT, asserts, EnableAsserts, enable_asserts, FLAG_enable_asserts) \
- V(NONPRODUCT, reify_generic_functions, ReifyGenericFunctions, \
+ V(PRODUCT, reify_generic_functions, ReifyGenericFunctions, \
reify_generic_functions, FLAG_reify_generic_functions) \
- V(NONPRODUCT, sync_async, SyncAsync, sync_async, FLAG_sync_async) \
- V(NONPRODUCT, strong, Strong, strong, FLAG_strong) \
+ V(PRODUCT, sync_async, SyncAsync, sync_async, FLAG_sync_async) \
+ V(PRODUCT, strong, Strong, strong, FLAG_strong) \
V(NONPRODUCT, error_on_bad_type, ErrorOnBadType, enable_error_on_bad_type, \
FLAG_error_on_bad_type) \
V(NONPRODUCT, error_on_bad_override, ErrorOnBadOverride, \
@@ -718,6 +718,8 @@
#define FLAG_FOR_NONPRODUCT(from_field, from_flag) (from_flag)
#endif
+#define FLAG_FOR_PRODUCT(from_field, from_flag) (from_field)
+
#define DECLARE_GETTER(when, name, bitname, isolate_flag_name, flag_name) \
bool name() const { \
const bool false_by_default = false; \
@@ -727,6 +729,7 @@
ISOLATE_FLAG_LIST(DECLARE_GETTER)
#undef FLAG_FOR_NONPRODUCT
#undef FLAG_FOR_PRECOMPILER
+#undef FLAG_FOR_PRODUCT
#undef DECLARE_GETTER
#if defined(PRODUCT)
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index ba05ff0..70a967b 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
// package:kernel/binary.md.
static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
-static const uint32_t kBinaryFormatVersion = 6;
+static const uint32_t kBinaryFormatVersion = 7;
// Keep in sync with package:kernel/lib/binary/tag.dart
#define KERNEL_TAG_LIST(V) \
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 607c1e9..e7f45d2 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -967,6 +967,10 @@
klass->set_interfaces(interfaces);
if (class_helper->is_abstract()) klass->set_is_abstract();
+
+ if (class_helper->is_transformed_mixin_application()) {
+ klass->set_is_transformed_mixin_application();
+ }
}
// Workaround for http://dartbug.com/32087: currently Kernel front-end
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index de61db2..d379d22 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3792,6 +3792,11 @@
set_state_bits(MixinTypeAppliedBit::update(true, raw_ptr()->state_bits_));
}
+void Class::set_is_transformed_mixin_application() const {
+ set_state_bits(
+ TransformedMixinApplicationBit::update(true, raw_ptr()->state_bits_));
+}
+
void Class::set_is_fields_marked_nullable() const {
set_state_bits(FieldsMarkedNullableBit::update(true, raw_ptr()->state_bits_));
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 1d8dc12..ee04799 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1311,6 +1311,17 @@
}
void set_is_mixin_type_applied() const;
+ // Tests if this is a mixin application class which was desugared
+ // to a normal class by kernel mixin transformation
+ // (pkg/kernel/lib/transformations/mixin_full_resolution.dart).
+ //
+ // In such case, its mixed-in type was pulled into the end of
+ // interfaces list.
+ bool is_transformed_mixin_application() const {
+ return TransformedMixinApplicationBit::decode(raw_ptr()->state_bits_);
+ }
+ void set_is_transformed_mixin_application() const;
+
bool is_fields_marked_nullable() const {
return FieldsMarkedNullableBit::decode(raw_ptr()->state_bits_);
}
@@ -1470,6 +1481,7 @@
kFieldsMarkedNullableBit = 11,
kCycleFreeBit = 12,
kEnumBit = 13,
+ kTransformedMixinApplicationBit = 14,
kIsAllocatedBit = 15,
};
class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
@@ -1494,6 +1506,8 @@
: public BitField<uint16_t, bool, kFieldsMarkedNullableBit, 1> {};
class CycleFreeBit : public BitField<uint16_t, bool, kCycleFreeBit, 1> {};
class EnumBit : public BitField<uint16_t, bool, kEnumBit, 1> {};
+ class TransformedMixinApplicationBit
+ : public BitField<uint16_t, bool, kTransformedMixinApplicationBit, 1> {};
class IsAllocatedBit : public BitField<uint16_t, bool, kIsAllocatedBit, 1> {};
void set_name(const String& value) const;
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 3db2d65..5493d43 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -2552,7 +2552,7 @@
const int32_t alu_out = ra_val - (rn_val * rm_val);
set_wregister(rd, alu_out, R31IsZR);
}
- } else if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 2) &&
+ } else if ((instr->Bits(29, 3) == 4) && (instr->Bits(21, 3) == 2) &&
(instr->Bit(15) == 0)) {
ASSERT(ra == R31); // Should-Be-One
// Format(instr, "smulh 'rd, 'rn, 'rm");
@@ -2568,7 +2568,7 @@
const int64_t alu_out = static_cast<int64_t>(res >> 64);
#endif // HOST_OS_WINDOWS
set_register(instr, rd, alu_out, R31IsZR);
- } else if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 6) &&
+ } else if ((instr->Bits(29, 3) == 4) && (instr->Bits(21, 3) == 6) &&
(instr->Bit(15) == 0)) {
ASSERT(ra == R31); // Should-Be-One
// Format(instr, "umulh 'rd, 'rn, 'rm");
diff --git a/sdk/bin/dartdevk b/sdk/bin/dartdevk
index f6111dc..6d75105 100755
--- a/sdk/bin/dartdevk
+++ b/sdk/bin/dartdevk
@@ -43,4 +43,4 @@
DEV_COMPILER="$DART_ROOT/pkg/dev_compiler/bin/dartdevk.dart"
-exec "$DART" "--packages=$DART_ROOT/.packages" "${EXTRA_VM_OPTIONS[@]}" "$DEV_COMPILER" "$@"
+exec "$DART" "--preview-dart-2" "--packages=$DART_ROOT/.packages" "${EXTRA_VM_OPTIONS[@]}" "$DEV_COMPILER" "$@"
diff --git a/sdk/bin/dartdevk.bat b/sdk/bin/dartdevk.bat
index 154162a..79c09c5 100644
--- a/sdk/bin/dartdevk.bat
+++ b/sdk/bin/dartdevk.bat
@@ -34,7 +34,7 @@
set DEV_COMPILER=%DART_ROOT%\pkg\dev_compiler\bin\dartdevk.dart
-"%DART%" "--packages=%DART_ROOT%\.packages" %EXTRA_VM_OPTIONS% "%DEV_COMPILER%" %*
+"%DART%" "--preview-dart-2" "--packages=%DART_ROOT%\.packages" %EXTRA_VM_OPTIONS% "%DEV_COMPILER%" %*
endlocal
diff --git a/sdk/bin/dartdevk_sdk b/sdk/bin/dartdevk_sdk
index 098775a..dc790e4 100755
--- a/sdk/bin/dartdevk_sdk
+++ b/sdk/bin/dartdevk_sdk
@@ -26,4 +26,4 @@
# We are running the snapshot in the built SDK.
DART="$BIN_DIR/dart"
-exec "$DART" "$SNAPSHOT" "--packages=$SDK_DIR/../../../.packages" "$@"
+exec "$DART" "--preview-dart-2" "$SNAPSHOT" "--packages=$SDK_DIR/../../../.packages" "$@"
diff --git a/sdk/bin/dartdevk_sdk.bat b/sdk/bin/dartdevk_sdk.bat
index 8e490ef..3879afb 100644
--- a/sdk/bin/dartdevk_sdk.bat
+++ b/sdk/bin/dartdevk_sdk.bat
@@ -20,7 +20,7 @@
rem Remove trailing backslash if there is one
if %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
-"%DART%" "%SNAPSHOT%" "--packages=%SDK_DIR%\..\..\..\.packages" %*
+"%DART%" "--preview-dart-2" "%SNAPSHOT%" "--packages=%SDK_DIR%\..\..\..\.packages" %*
endlocal
diff --git a/sdk/bin/dartfmt b/sdk/bin/dartfmt
index ad54140..fb58a1e 100755
--- a/sdk/bin/dartfmt
+++ b/sdk/bin/dartfmt
@@ -28,4 +28,4 @@
DARTFMT="$DART_ROOT/third_party/pkg_tested/dart_style/bin/format.dart"
-exec "$DART" "--packages=$DART_ROOT/.packages" "$DARTFMT" "$@"
+exec "$DART" "--preview-dart-2" "--packages=$DART_ROOT/.packages" "$DARTFMT" "$@"
diff --git a/sdk/bin/dartfmt.bat b/sdk/bin/dartfmt.bat
index 7a7412b..f668f56 100644
--- a/sdk/bin/dartfmt.bat
+++ b/sdk/bin/dartfmt.bat
@@ -27,7 +27,7 @@
set DARTFMT=%DART_ROOT%\third_party\pkg_tested\dart_style\bin\format.dart
-"%DART%" "--packages=%DART_ROOT%\.packages" "%DARTFMT%" %*
+"%DART%" "--preview-dart-2" "--packages=%DART_ROOT%\.packages" "%DARTFMT%" %*
endlocal
diff --git a/sdk/bin/dartfmt_sdk b/sdk/bin/dartfmt_sdk
index 273733c..b6b98c4 100755
--- a/sdk/bin/dartfmt_sdk
+++ b/sdk/bin/dartfmt_sdk
@@ -26,4 +26,4 @@
# We are running the snapshot in the built SDK.
DART="$BIN_DIR/dart"
-exec "$DART" "$SNAPSHOT" "$@"
+exec "$DART" "--preview-dart-2" "$SNAPSHOT" "$@"
diff --git a/sdk/bin/dartfmt_sdk.bat b/sdk/bin/dartfmt_sdk.bat
index 295b977..f746a72 100644
--- a/sdk/bin/dartfmt_sdk.bat
+++ b/sdk/bin/dartfmt_sdk.bat
@@ -14,7 +14,7 @@
set DART=%BIN_DIR%\dart
set SNAPSHOT=%BIN_DIR%\snapshots\dartfmt.dart.snapshot
-"%DART%" "%SNAPSHOT%" %*
+"%DART%" "--preview-dart-2" "%SNAPSHOT%" %*
endlocal
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index 7c88473..9cfb7ef 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
@@ -17,12 +17,12 @@
}
@patch
- static _setCurrent(_Namespace namespace, path) {
+ static _setCurrent(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("Directory_SetCurrent");
}
@patch
- static _createTemp(_Namespace namespace, String path) {
+ static _createTemp(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("Directory._createTemp");
}
@@ -32,22 +32,22 @@
}
@patch
- static _exists(_Namespace namespace, String path) {
+ static _exists(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("Directory._exists");
}
@patch
- static _create(_Namespace namespace, String path) {
+ static _create(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("Directory._create");
}
@patch
- static _deleteNative(_Namespace namespace, String path, bool recursive) {
+ static _deleteNative(_Namespace namespace, Uint8List path, bool recursive) {
throw new UnsupportedError("Directory._deleteNative");
}
@patch
- static _rename(_Namespace namespace, String path, String newPath) {
+ static _rename(_Namespace namespace, Uint8List path, String newPath) {
throw new UnsupportedError("Directory._rename");
}
@@ -55,7 +55,7 @@
static void _fillWithDirectoryListing(
_Namespace namespace,
List<FileSystemEntity> list,
- String path,
+ Uint8List path,
bool recursive,
bool followLinks) {
throw new UnsupportedError("Directory._fillWithDirectoryListing");
@@ -89,7 +89,8 @@
@patch
class FileSystemEntity {
@patch
- static _getTypeNative(_Namespace namespace, String path, bool followLinks) {
+ static _getTypeNative(
+ _Namespace namespace, Uint8List path, bool followLinks) {
throw new UnsupportedError("FileSystemEntity._getType");
}
@@ -99,7 +100,7 @@
}
@patch
- static _resolveSymbolicLinks(_Namespace namespace, String path) {
+ static _resolveSymbolicLinks(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("FileSystemEntity._resolveSymbolicLinks");
}
}
@@ -107,77 +108,77 @@
@patch
class _File {
@patch
- static _exists(_Namespace namespace, String path) {
+ static _exists(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("File._exists");
}
@patch
- static _create(_Namespace namespace, String path) {
+ static _create(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("File._create");
}
@patch
- static _createLink(_Namespace namespace, String path, String target) {
+ static _createLink(_Namespace namespace, Uint8List path, String target) {
throw new UnsupportedError("File._createLink");
}
@patch
- static _linkTarget(_Namespace namespace, String path) {
+ static _linkTarget(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("File._linkTarget");
}
@patch
- static _deleteNative(_Namespace namespace, String path) {
+ static _deleteNative(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("File._deleteNative");
}
@patch
- static _deleteLinkNative(_Namespace namespace, String path) {
+ static _deleteLinkNative(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("File._deleteLinkNative");
}
@patch
- static _rename(_Namespace namespace, String oldPath, String newPath) {
+ static _rename(_Namespace namespace, Uint8List oldPath, String newPath) {
throw new UnsupportedError("File._rename");
}
@patch
- static _renameLink(_Namespace namespace, String oldPath, String newPath) {
+ static _renameLink(_Namespace namespace, Uint8List oldPath, String newPath) {
throw new UnsupportedError("File._renameLink");
}
@patch
- static _copy(_Namespace namespace, String oldPath, String newPath) {
+ static _copy(_Namespace namespace, Uint8List oldPath, String newPath) {
throw new UnsupportedError("File._copy");
}
@patch
- static _lengthFromPath(_Namespace namespace, String path) {
+ static _lengthFromPath(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("File._lengthFromPath");
}
@patch
- static _lastModified(_Namespace namespace, String path) {
+ static _lastModified(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("File._lastModified");
}
@patch
- static _lastAccessed(_Namespace namespace, String path) {
+ static _lastAccessed(_Namespace namespace, Uint8List path) {
throw new UnsupportedError("File._lastAccessed");
}
@patch
- static _setLastModified(_Namespace namespace, String path, int millis) {
+ static _setLastModified(_Namespace namespace, Uint8List path, int millis) {
throw new UnsupportedError("File._setLastModified");
}
@patch
- static _setLastAccessed(_Namespace namespace, String path, int millis) {
+ static _setLastAccessed(_Namespace namespace, Uint8List path, int millis) {
throw new UnsupportedError("File._setLastAccessed");
}
@patch
- static _open(_Namespace namespace, String path, int mode) {
+ static _open(_Namespace namespace, Uint8List path, int mode) {
throw new UnsupportedError("File._open");
}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index af67c0e..4896e9d 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -3447,10 +3447,20 @@
extractFunctionTypeObjectFrom(o) {
var interceptor = getInterceptor(o);
+ return extractFunctionTypeObjectFromInternal(interceptor);
+}
+
+extractFunctionTypeObjectFromInternal(o) {
var signatureName = JS_GET_NAME(JsGetName.SIGNATURE_NAME);
- return JS('bool', '# in #', signatureName, interceptor)
- ? JS('', '#[#]()', interceptor, signatureName)
- : null;
+ if (JS('bool', '# in #', signatureName, o)) {
+ var signature = JS('', '#[#]', o, signatureName);
+ if (JS('bool', 'typeof # == "number"', signature)) {
+ return getType(signature);
+ } else {
+ return JS('', '#[#]()', o, signatureName);
+ }
+ }
+ return null;
}
functionTypeTest(value, functionTypeRti) {
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index d6be639..09f2df3 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -859,10 +859,8 @@
if (isDartFunctionType(t)) {
// Functions are treated specially and have their type information stored
// directly in the instance.
- var targetSignatureFunction =
- getField(o, '${JS_GET_NAME(JsGetName.SIGNATURE_NAME)}');
- if (targetSignatureFunction == null) return false;
- type = invokeOn(targetSignatureFunction, o, null);
+ type = extractFunctionTypeObjectFromInternal(o);
+ if (type == null) return false;
return isFunctionSubtype(type, t);
}
return isSubtype(type, t);
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index 3e4ee6b..683e22a 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -115,7 +115,7 @@
/**
* Gets the path of this directory.
*/
- final String path;
+ String get path;
/**
* Creates a [Directory] object.
@@ -134,6 +134,11 @@
return overrides.createDirectory(path);
}
+ factory Directory.fromRawPath(Uint8List path) {
+ // TODO(bkonyi): Handle overrides.
+ return new _Directory.fromRawPath(path);
+ }
+
/**
* Create a Directory object from a URI.
*
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 8be9257..ea1aa74 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -5,28 +5,41 @@
part of dart.io;
class _Directory extends FileSystemEntity implements Directory {
- final String path;
+ String _path;
+ Uint8List _rawPath;
- _Directory(this.path) {
+ _Directory(String path) {
if (path is! String) {
- throw new ArgumentError('${Error.safeToString(path)} '
- 'is not a String');
+ throw new ArgumentError('${Error.safeToString(path)} is not a String');
}
+ _path = path;
+ _rawPath = FileSystemEntity._toUtf8Array(_path);
}
+ _Directory.fromRawPath(Uint8List rawPath) {
+ if (rawPath == null) {
+ throw new ArgumentError('rawPath cannot be null');
+ }
+ _rawPath = FileSystemEntity._toNullTerminatedUtf8Array(rawPath);
+ _path = FileSystemEntity._toStringFromUtf8Array(rawPath);
+ }
+
+ String get path => _path;
+
external static _current(_Namespace namespace);
- external static _setCurrent(_Namespace namespace, path);
- external static _createTemp(_Namespace namespace, String path);
+ external static _setCurrent(_Namespace namespace, Uint8List rawPath);
+ external static _createTemp(_Namespace namespace, Uint8List rawPath);
external static String _systemTemp(_Namespace namespace);
- external static _exists(_Namespace namespace, String path);
- external static _create(_Namespace namespace, String path);
+ external static _exists(_Namespace namespace, Uint8List rawPath);
+ external static _create(_Namespace namespace, Uint8List rawPath);
external static _deleteNative(
- _Namespace namespace, String path, bool recursive);
- external static _rename(_Namespace namespace, String path, String newPath);
+ _Namespace namespace, Uint8List rawPath, bool recursive);
+ external static _rename(
+ _Namespace namespace, Uint8List rawPath, String newPath);
external static void _fillWithDirectoryListing(
_Namespace namespace,
List<FileSystemEntity> list,
- String path,
+ Uint8List rawPath,
bool recursive,
bool followLinks);
@@ -40,12 +53,27 @@
}
static void set current(path) {
- if (path is Directory) path = path.path;
+ Uint8List _rawPath;
+ if (path is _Directory) {
+ // For our internal Directory implementation, go ahead and use the raw
+ // path.
+ _rawPath = path._rawPath;
+ } else if (path is Directory) {
+ // FIXME(bkonyi): package:file passes in instances of classes which do
+ // not have _path defined, so we will fallback to using the existing
+ // path String for now.
+ _rawPath = FileSystemEntity._toUtf8Array(path.path);
+ } else if (path is String) {
+ _rawPath = FileSystemEntity._toUtf8Array(path);
+ } else {
+ throw new ArgumentError('${Error.safeToString(path)} is not a String or'
+ ' Directory');
+ }
if (!_EmbedderConfig._mayChdir) {
throw new UnsupportedError(
"This embedder disallows setting Directory.current");
}
- var result = _setCurrent(_Namespace._namespace, path);
+ var result = _setCurrent(_Namespace._namespace, _rawPath);
if (result is ArgumentError) throw result;
if (result is OSError) {
throw new FileSystemException(
@@ -59,7 +87,7 @@
Future<bool> exists() {
return _File._dispatchWithNamespace(
- _IOService.directoryExists, [null, path]).then((response) {
+ _IOService.directoryExists, [null, _rawPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionOrErrorFromResponse(response, "Exists failed");
}
@@ -68,7 +96,7 @@
}
bool existsSync() {
- var result = _exists(_Namespace._namespace, path);
+ var result = _exists(_Namespace._namespace, _rawPath);
if (result is OSError) {
throw new FileSystemException("Exists failed", path, result);
}
@@ -91,7 +119,7 @@
});
} else {
return _File._dispatchWithNamespace(
- _IOService.directoryCreate, [null, path]).then((response) {
+ _IOService.directoryCreate, [null, _rawPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionOrErrorFromResponse(response, "Creation failed");
}
@@ -107,7 +135,7 @@
parent.createSync(recursive: true);
}
}
- var result = _create(_Namespace._namespace, path);
+ var result = _create(_Namespace._namespace, _rawPath);
if (result is OSError) {
throw new FileSystemException("Creation failed", path, result);
}
@@ -123,13 +151,15 @@
"To use the system temp directory, use Directory.systemTemp");
}
String fullPrefix;
+ // FIXME(bkonyi): here we're using `path` directly, which might cause
+ // issues if it is not UTF-8 encoded.
if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) {
fullPrefix = "$path$prefix";
} else {
fullPrefix = "$path${Platform.pathSeparator}$prefix";
}
- return _File._dispatchWithNamespace(
- _IOService.directoryCreateTemp, [null, fullPrefix]).then((response) {
+ return _File._dispatchWithNamespace(_IOService.directoryCreateTemp,
+ [null, FileSystemEntity._toUtf8Array(fullPrefix)]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionOrErrorFromResponse(
response, "Creation of temporary directory failed");
@@ -145,12 +175,15 @@
"To use the system temp directory, use Directory.systemTemp");
}
String fullPrefix;
+ // FIXME(bkonyi): here we're using `path` directly, which might cause
+ // issues if it is not UTF-8 encoded.
if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) {
fullPrefix = "$path$prefix";
} else {
fullPrefix = "$path${Platform.pathSeparator}$prefix";
}
- var result = _createTemp(_Namespace._namespace, fullPrefix);
+ var result = _createTemp(
+ _Namespace._namespace, FileSystemEntity._toUtf8Array(fullPrefix));
if (result is OSError) {
throw new FileSystemException(
"Creation of temporary directory failed", fullPrefix, result);
@@ -159,8 +192,8 @@
}
Future<Directory> _delete({bool recursive: false}) {
- return _File._dispatchWithNamespace(
- _IOService.directoryDelete, [null, path, recursive]).then((response) {
+ return _File._dispatchWithNamespace(_IOService.directoryDelete,
+ [null, _rawPath, recursive]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionOrErrorFromResponse(response, "Deletion failed");
}
@@ -169,7 +202,7 @@
}
void _deleteSync({bool recursive: false}) {
- var result = _deleteNative(_Namespace._namespace, path, recursive);
+ var result = _deleteNative(_Namespace._namespace, _rawPath, recursive);
if (result is OSError) {
throw new FileSystemException("Deletion failed", path, result);
}
@@ -177,7 +210,7 @@
Future<Directory> rename(String newPath) {
return _File._dispatchWithNamespace(
- _IOService.directoryRename, [null, path, newPath]).then((response) {
+ _IOService.directoryRename, [null, _rawPath, newPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionOrErrorFromResponse(response, "Rename failed");
}
@@ -189,7 +222,7 @@
if (newPath is! String) {
throw new ArgumentError();
}
- var result = _rename(_Namespace._namespace, path, newPath);
+ var result = _rename(_Namespace._namespace, _rawPath, newPath);
if (result is OSError) {
throw new FileSystemException("Rename failed", path, result);
}
@@ -199,7 +232,10 @@
Stream<FileSystemEntity> list(
{bool recursive: false, bool followLinks: true}) {
return new _AsyncDirectoryLister(
- FileSystemEntity._ensureTrailingPathSeparators(path),
+ // FIXME(bkonyi): here we're using `path` directly, which might cause issues
+ // if it is not UTF-8 encoded.
+ FileSystemEntity._toUtf8Array(
+ FileSystemEntity._ensureTrailingPathSeparators(path)),
recursive,
followLinks)
.stream;
@@ -214,7 +250,10 @@
_fillWithDirectoryListing(
_Namespace._namespace,
result,
- FileSystemEntity._ensureTrailingPathSeparators(path),
+ // FIXME(bkonyi): here we're using `path` directly, which might cause issues
+ // if it is not UTF-8 encoded.
+ FileSystemEntity
+ ._toUtf8Array(FileSystemEntity._ensureTrailingPathSeparators(path)),
recursive,
followLinks);
return result;
@@ -258,7 +297,7 @@
static const int responseComplete = 1;
static const int responseError = 2;
- final String path;
+ final Uint8List rawPath;
final bool recursive;
final bool followLinks;
@@ -269,7 +308,7 @@
_AsyncDirectoryListerOps _ops;
Completer closeCompleter = new Completer();
- _AsyncDirectoryLister(this.path, this.recursive, this.followLinks) {
+ _AsyncDirectoryLister(this.rawPath, this.recursive, this.followLinks) {
controller = new StreamController<FileSystemEntity>(
onListen: onListen, onResume: onResume, onCancel: onCancel, sync: true);
}
@@ -287,7 +326,7 @@
void onListen() {
_File._dispatchWithNamespace(_IOService.directoryListStart,
- [null, path, recursive, followLinks]).then((response) {
+ [null, rawPath, recursive, followLinks]).then((response) {
if (response is int) {
_ops = new _AsyncDirectoryListerOps(response);
next();
@@ -340,13 +379,13 @@
assert(i % 2 == 0);
switch (result[i++]) {
case listFile:
- controller.add(new File(result[i]));
+ controller.add(new File.fromRawPath(result[i]));
break;
case listDirectory:
- controller.add(new Directory(result[i]));
+ controller.add(new Directory.fromRawPath(result[i]));
break;
case listLink:
- controller.add(new Link(result[i]));
+ controller.add(new Link.fromRawPath(result[i]));
break;
case listError:
error(result[i]);
@@ -395,7 +434,11 @@
var err = new OSError(responseErrorInfo[_osErrorResponseMessage],
responseErrorInfo[_osErrorResponseErrorCode]);
var errorPath = message[responsePath];
- if (errorPath == null) errorPath = path;
+ if (errorPath == null) {
+ errorPath = utf8.decode(rawPath, allowMalformed: true);
+ } else if (errorPath is Uint8List) {
+ errorPath = utf8.decode(message[responsePath], allowMalformed: true);
+ }
controller.addError(
new FileSystemException("Directory listing failed", errorPath, err));
} else {
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 33ce01f..236aa2b 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -263,6 +263,15 @@
factory File.fromUri(Uri uri) => new File(uri.toFilePath());
/**
+ * Creates a File object from a raw path, that is, a sequence of bytes
+ * as represented by the OS.
+ */
+ factory File.fromRawPath(Uint8List rawPath) {
+ // TODO(bkonyi): Handle overrides.
+ return new _File.fromRawPath(rawPath);
+ }
+
+ /**
* Create the file. Returns a `Future<File>` that completes with
* the file when it has been created.
*
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 67a49b7..e8221bc 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -203,16 +203,27 @@
// Class for encapsulating the native implementation of files.
class _File extends FileSystemEntity implements File {
- final String path;
+ String _path;
+ Uint8List _rawPath;
- // Constructor for file.
- _File(this.path) {
+ _File(String path) {
if (path is! String) {
- throw new ArgumentError('${Error.safeToString(path)} '
- 'is not a String');
+ throw new ArgumentError('${Error.safeToString(path)} is not a String');
}
+ _path = path;
+ _rawPath = FileSystemEntity._toUtf8Array(path);
}
+ _File.fromRawPath(Uint8List rawPath) {
+ if (rawPath == null) {
+ throw new ArgumentError('rawPath cannot be null');
+ }
+ _rawPath = FileSystemEntity._toNullTerminatedUtf8Array(rawPath);
+ _path = FileSystemEntity._toStringFromUtf8Array(rawPath);
+ }
+
+ String get path => _path;
+
// WARNING:
// Calling this function will increase the reference count on the native
// namespace object. It should only be called to pass the pointer to the
@@ -226,7 +237,7 @@
}
Future<bool> exists() {
- return _dispatchWithNamespace(_IOService.fileExists, [null, path])
+ return _dispatchWithNamespace(_IOService.fileExists, [null, _rawPath])
.then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "Cannot check existence", path);
@@ -235,10 +246,10 @@
});
}
- external static _exists(_Namespace namespace, String path);
+ external static _exists(_Namespace namespace, Uint8List rawPath);
bool existsSync() {
- var result = _exists(_Namespace._namespace, path);
+ var result = _exists(_Namespace._namespace, _rawPath);
throwIfError(result, "Cannot check existence of file", path);
return result;
}
@@ -249,8 +260,8 @@
var result =
recursive ? parent.create(recursive: true) : new Future.value(null);
return result
- .then(
- (_) => _dispatchWithNamespace(_IOService.fileCreate, [null, path]))
+ .then((_) =>
+ _dispatchWithNamespace(_IOService.fileCreate, [null, _rawPath]))
.then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "Cannot create file", path);
@@ -259,17 +270,18 @@
});
}
- external static _create(_Namespace namespace, String path);
+ external static _create(_Namespace namespace, Uint8List rawPath);
- external static _createLink(_Namespace namespace, String path, String target);
+ external static _createLink(
+ _Namespace namespace, Uint8List rawPath, String target);
- external static _linkTarget(_Namespace namespace, String path);
+ external static _linkTarget(_Namespace namespace, Uint8List rawPath);
void createSync({bool recursive: false}) {
if (recursive) {
parent.createSync(recursive: true);
}
- var result = _create(_Namespace._namespace, path);
+ var result = _create(_Namespace._namespace, _rawPath);
throwIfError(result, "Cannot create file", path);
}
@@ -277,7 +289,7 @@
if (recursive) {
return new Directory(path).delete(recursive: true).then((_) => this);
}
- return _dispatchWithNamespace(_IOService.fileDelete, [null, path])
+ return _dispatchWithNamespace(_IOService.fileDelete, [null, _rawPath])
.then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "Cannot delete file", path);
@@ -286,21 +298,21 @@
});
}
- external static _deleteNative(_Namespace namespace, String path);
+ external static _deleteNative(_Namespace namespace, Uint8List rawPath);
- external static _deleteLinkNative(_Namespace namespace, String path);
+ external static _deleteLinkNative(_Namespace namespace, Uint8List rawPath);
void _deleteSync({bool recursive: false}) {
if (recursive) {
- return new Directory(path).deleteSync(recursive: true);
+ return new Directory.fromRawPath(_rawPath).deleteSync(recursive: true);
}
- var result = _deleteNative(_Namespace._namespace, path);
+ var result = _deleteNative(_Namespace._namespace, _rawPath);
throwIfError(result, "Cannot delete file", path);
}
Future<File> rename(String newPath) {
- return _dispatchWithNamespace(_IOService.fileRename, [null, path, newPath])
- .then((response) {
+ return _dispatchWithNamespace(
+ _IOService.fileRename, [null, _rawPath, newPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
response, "Cannot rename file to '$newPath'", path);
@@ -309,20 +321,21 @@
});
}
- external static _rename(_Namespace namespace, String oldPath, String newPath);
+ external static _rename(
+ _Namespace namespace, Uint8List oldPath, String newPath);
external static _renameLink(
- _Namespace namespace, String oldPath, String newPath);
+ _Namespace namespace, Uint8List oldPath, String newPath);
File renameSync(String newPath) {
- var result = _rename(_Namespace._namespace, path, newPath);
+ var result = _rename(_Namespace._namespace, _rawPath, newPath);
throwIfError(result, "Cannot rename file to '$newPath'", path);
return new File(newPath);
}
Future<File> copy(String newPath) {
- return _dispatchWithNamespace(_IOService.fileCopy, [null, path, newPath])
- .then((response) {
+ return _dispatchWithNamespace(
+ _IOService.fileCopy, [null, _rawPath, newPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
response, "Cannot copy file to '$newPath'", path);
@@ -331,10 +344,11 @@
});
}
- external static _copy(_Namespace namespace, String oldPath, String newPath);
+ external static _copy(
+ _Namespace namespace, Uint8List oldPath, String newPath);
File copySync(String newPath) {
- var result = _copy(_Namespace._namespace, path, newPath);
+ var result = _copy(_Namespace._namespace, _rawPath, newPath);
throwIfError(result, "Cannot copy file to '$newPath'", path);
return new File(newPath);
}
@@ -348,8 +362,8 @@
return new Future.error(
new ArgumentError('Invalid file mode for this operation'));
}
- return _dispatchWithNamespace(_IOService.fileOpen, [null, path, mode._mode])
- .then((response) {
+ return _dispatchWithNamespace(
+ _IOService.fileOpen, [null, _rawPath, mode._mode]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "Cannot open file", path);
}
@@ -358,8 +372,8 @@
}
Future<int> length() {
- return _dispatchWithNamespace(_IOService.fileLengthFromPath, [null, path])
- .then((response) {
+ return _dispatchWithNamespace(
+ _IOService.fileLengthFromPath, [null, _rawPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
response, "Cannot retrieve length of file", path);
@@ -368,16 +382,16 @@
});
}
- external static _lengthFromPath(_Namespace namespace, String path);
+ external static _lengthFromPath(_Namespace namespace, Uint8List rawPath);
int lengthSync() {
- var result = _lengthFromPath(_Namespace._namespace, path);
+ var result = _lengthFromPath(_Namespace._namespace, _rawPath);
throwIfError(result, "Cannot retrieve length of file", path);
return result;
}
Future<DateTime> lastAccessed() {
- return _dispatchWithNamespace(_IOService.fileLastAccessed, [null, path])
+ return _dispatchWithNamespace(_IOService.fileLastAccessed, [null, _rawPath])
.then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
@@ -387,10 +401,10 @@
});
}
- external static _lastAccessed(_Namespace namespace, String path);
+ external static _lastAccessed(_Namespace namespace, Uint8List rawPath);
DateTime lastAccessedSync() {
- var ms = _lastAccessed(_Namespace._namespace, path);
+ var ms = _lastAccessed(_Namespace._namespace, _rawPath);
throwIfError(ms, "Cannot retrieve access time", path);
return new DateTime.fromMillisecondsSinceEpoch(ms);
}
@@ -398,7 +412,8 @@
Future setLastAccessed(DateTime time) {
int millis = time.millisecondsSinceEpoch;
return _dispatchWithNamespace(
- _IOService.fileSetLastAccessed, [null, path, millis]).then((response) {
+ _IOService.fileSetLastAccessed, [null, _rawPath, millis])
+ .then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "Cannot set access time", path);
}
@@ -407,11 +422,11 @@
}
external static _setLastAccessed(
- _Namespace namespace, String path, int millis);
+ _Namespace namespace, Uint8List rawPath, int millis);
void setLastAccessedSync(DateTime time) {
int millis = time.millisecondsSinceEpoch;
- var result = _setLastAccessed(_Namespace._namespace, path, millis);
+ var result = _setLastAccessed(_Namespace._namespace, _rawPath, millis);
if (result is OSError) {
throw new FileSystemException(
"Failed to set file access time", path, result);
@@ -419,7 +434,7 @@
}
Future<DateTime> lastModified() {
- return _dispatchWithNamespace(_IOService.fileLastModified, [null, path])
+ return _dispatchWithNamespace(_IOService.fileLastModified, [null, _rawPath])
.then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
@@ -429,10 +444,10 @@
});
}
- external static _lastModified(_Namespace namespace, String path);
+ external static _lastModified(_Namespace namespace, Uint8List rawPath);
DateTime lastModifiedSync() {
- var ms = _lastModified(_Namespace._namespace, path);
+ var ms = _lastModified(_Namespace._namespace, _rawPath);
throwIfError(ms, "Cannot retrieve modification time", path);
return new DateTime.fromMillisecondsSinceEpoch(ms);
}
@@ -440,7 +455,8 @@
Future setLastModified(DateTime time) {
int millis = time.millisecondsSinceEpoch;
return _dispatchWithNamespace(
- _IOService.fileSetLastModified, [null, path, millis]).then((response) {
+ _IOService.fileSetLastModified, [null, _rawPath, millis])
+ .then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
response, "Cannot set modification time", path);
@@ -450,18 +466,18 @@
}
external static _setLastModified(
- _Namespace namespace, String path, int millis);
+ _Namespace namespace, Uint8List rawPath, int millis);
void setLastModifiedSync(DateTime time) {
int millis = time.millisecondsSinceEpoch;
- var result = _setLastModified(_Namespace._namespace, path, millis);
+ var result = _setLastModified(_Namespace._namespace, _rawPath, millis);
if (result is OSError) {
throw new FileSystemException(
"Failed to set file modification time", path, result);
}
}
- external static _open(_Namespace namespace, String path, int mode);
+ external static _open(_Namespace namespace, Uint8List rawPath, int mode);
RandomAccessFile openSync({FileMode mode: FileMode.read}) {
if (mode != FileMode.read &&
@@ -471,9 +487,9 @@
mode != FileMode.writeOnlyAppend) {
throw new ArgumentError('Invalid file mode for this operation');
}
- var id = _open(_Namespace._namespace, path, mode._mode);
+ var id = _open(_Namespace._namespace, _rawPath, mode._mode);
throwIfError(id, "Cannot open file", path);
- return new _RandomAccessFile(id, path);
+ return new _RandomAccessFile(id, _path);
}
external static int _openStdio(int fd);
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index a78e03f..2c995d0 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -255,6 +255,9 @@
* files and directories.
*/
abstract class FileSystemEntity {
+ String _path;
+ Uint8List _rawPath;
+
String get path;
/**
@@ -351,7 +354,7 @@
*/
Future<String> resolveSymbolicLinks() {
return _File._dispatchWithNamespace(
- _IOService.fileResolveSymbolicLinks, [null, path]).then((response) {
+ _IOService.fileResolveSymbolicLinks, [null, _rawPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
response, "Cannot resolve symbolic links", path);
@@ -390,7 +393,7 @@
* behavior.
*/
String resolveSymbolicLinksSync() {
- var result = _resolveSymbolicLinks(_Namespace._namespace, path);
+ var result = _resolveSymbolicLinks(_Namespace._namespace, _rawPath);
_throwIfError(result, "Cannot resolve symbolic links", path);
return result;
}
@@ -495,6 +498,7 @@
*/
Stream<FileSystemEvent> watch(
{int events: FileSystemEvent.all, bool recursive: false}) {
+ // FIXME(bkonyi): find a way to do this using the raw path.
final String trimmedPath = _trimTrailingPathSeparators(path);
final IOOverrides overrides = IOOverrides.current;
if (overrides == null) {
@@ -579,6 +583,22 @@
}
}
+ Uint8List get _rawAbsolutePath {
+ if (isAbsolute) return _rawPath;
+ var current = Directory.current._rawPath.toList();
+ assert(current.last == 0);
+ current.removeLast(); // Remove null terminator.
+ if ((current.last == '/'.codeUnitAt(0)) ||
+ (Platform.isWindows && (current.last == '\\'.codeUnitAt(0)))) {
+ current.addAll(_rawPath);
+ return new Uint8List.fromList(current);
+ } else {
+ current.addAll(utf8.encode(Platform.pathSeparator));
+ current.addAll(_rawPath);
+ return new Uint8List.fromList(current);
+ }
+ }
+
static bool _identicalSync(String path1, String path2) {
var result = _identicalNative(_Namespace._namespace, path1, path2);
_throwIfError(result, 'Error in FileSystemEntity.identicalSync');
@@ -618,6 +638,35 @@
return overrides.fsWatchIsSupported();
}
+ // The native methods which determine type of the FileSystemEntity require
+ // that the buffer provided is null terminated.
+ static Uint8List _toUtf8Array(String s) =>
+ _toNullTerminatedUtf8Array(utf8.encode(s));
+
+ static Uint8List _toNullTerminatedUtf8Array(Uint8List l) {
+ if (l == null) {
+ return null;
+ }
+ if (l.isNotEmpty && l.last != 0) {
+ final tmp = new Uint8List(l.length + 1);
+ tmp.setRange(0, l.length, l);
+ return tmp;
+ } else {
+ return l;
+ }
+ }
+
+ static String _toStringFromUtf8Array(Uint8List l) {
+ if (l == null) {
+ return '';
+ }
+ Uint8List nonNullTerminated = l;
+ if (l.last == 0) {
+ nonNullTerminated = new Uint8List.view(l.buffer, 0, l.length - 1);
+ }
+ return utf8.decode(nonNullTerminated, allowMalformed: true);
+ }
+
/**
* Finds the type of file system object that a path points to.
*
@@ -633,7 +682,7 @@
*/
static Future<FileSystemEntityType> type(String path,
{bool followLinks: true}) {
- return _getType(path, followLinks);
+ return _getType(_toUtf8Array(path), followLinks);
}
/**
@@ -650,53 +699,59 @@
* caused by passing the wrong type of arguments to the function.
*/
static FileSystemEntityType typeSync(String path, {bool followLinks: true}) {
- return _getTypeSync(path, followLinks);
+ return _getTypeSync(_toUtf8Array(path), followLinks);
}
/**
* Checks if type(path, followLinks: false) returns FileSystemEntityType.link.
*/
- static Future<bool> isLink(String path) =>
- _getType(path, false).then((type) => (type == FileSystemEntityType.link));
+ static Future<bool> isLink(String path) => _isLinkRaw(_toUtf8Array(path));
+
+ static Future<bool> _isLinkRaw(Uint8List rawPath) => _getType(rawPath, false)
+ .then((type) => (type == FileSystemEntityType.link));
/**
* Checks if type(path) returns FileSystemEntityType.file.
*/
- static Future<bool> isFile(String path) =>
- _getType(path, true).then((type) => (type == FileSystemEntityType.file));
+ static Future<bool> isFile(String path) => _getType(_toUtf8Array(path), true)
+ .then((type) => (type == FileSystemEntityType.file));
/**
* Checks if type(path) returns FileSystemEntityType.directory.
*/
- static Future<bool> isDirectory(String path) => _getType(path, true)
- .then((type) => (type == FileSystemEntityType.directory));
+ static Future<bool> isDirectory(String path) =>
+ _getType(_toUtf8Array(path), true)
+ .then((type) => (type == FileSystemEntityType.directory));
/**
* Synchronously checks if typeSync(path, followLinks: false) returns
* FileSystemEntityType.link.
*/
- static bool isLinkSync(String path) =>
- (_getTypeSync(path, false) == FileSystemEntityType.link);
+ static bool isLinkSync(String path) => _isLinkRawSync(_toUtf8Array(path));
+
+ static bool _isLinkRawSync(rawPath) =>
+ (_getTypeSync(rawPath, false) == FileSystemEntityType.link);
/**
* Synchronously checks if typeSync(path) returns
* FileSystemEntityType.file.
*/
static bool isFileSync(String path) =>
- (_getTypeSync(path, true) == FileSystemEntityType.file);
+ (_getTypeSync(_toUtf8Array(path), true) == FileSystemEntityType.file);
/**
* Synchronously checks if typeSync(path) returns
* FileSystemEntityType.directory.
*/
static bool isDirectorySync(String path) =>
- (_getTypeSync(path, true) == FileSystemEntityType.directory);
+ (_getTypeSync(_toUtf8Array(path), true) ==
+ FileSystemEntityType.directory);
external static _getTypeNative(
- _Namespace namespace, String path, bool followLinks);
+ _Namespace namespace, Uint8List rawPath, bool followLinks);
external static _identicalNative(
_Namespace namespace, String path1, String path2);
- external static _resolveSymbolicLinks(_Namespace namespace, String path);
+ external static _resolveSymbolicLinks(_Namespace namespace, Uint8List path);
// Finds the next-to-last component when dividing at path separators.
static final RegExp _parentRegExp = Platform.isWindows
@@ -742,37 +797,42 @@
Directory get parent => new Directory(parentOf(path));
static FileSystemEntityType _getTypeSyncHelper(
- String path, bool followLinks) {
- var result = _getTypeNative(_Namespace._namespace, path, followLinks);
+ Uint8List rawPath, bool followLinks) {
+ var result = _getTypeNative(_Namespace._namespace, rawPath, followLinks);
_throwIfError(result, 'Error getting type of FileSystemEntity');
return FileSystemEntityType._lookup(result);
}
- static FileSystemEntityType _getTypeSync(String path, bool followLinks) {
+ static FileSystemEntityType _getTypeSync(
+ Uint8List rawPath, bool followLinks) {
IOOverrides overrides = IOOverrides.current;
if (overrides == null) {
- return _getTypeSyncHelper(path, followLinks);
+ return _getTypeSyncHelper(rawPath, followLinks);
}
- return overrides.fseGetTypeSync(path, followLinks);
+ return overrides.fseGetTypeSync(
+ utf8.decode(rawPath, allowMalformed: true), followLinks);
}
static Future<FileSystemEntityType> _getTypeRequest(
- String path, bool followLinks) {
+ Uint8List rawPath, bool followLinks) {
return _File._dispatchWithNamespace(
- _IOService.fileType, [null, path, followLinks]).then((response) {
+ _IOService.fileType, [null, rawPath, followLinks]).then((response) {
if (_isErrorResponse(response)) {
- throw _exceptionFromResponse(response, "Error getting type", path);
+ throw _exceptionFromResponse(response, "Error getting type",
+ utf8.decode(rawPath, allowMalformed: true));
}
return FileSystemEntityType._lookup(response);
});
}
- static Future<FileSystemEntityType> _getType(String path, bool followLinks) {
+ static Future<FileSystemEntityType> _getType(
+ Uint8List rawPath, bool followLinks) {
IOOverrides overrides = IOOverrides.current;
if (overrides == null) {
- return _getTypeRequest(path, followLinks);
+ return _getTypeRequest(rawPath, followLinks);
}
- return overrides.fseGetType(path, followLinks);
+ return overrides.fseGetType(
+ utf8.decode(rawPath, allowMalformed: true), followLinks);
}
static _throwIfError(Object result, String msg, [String path]) {
@@ -783,6 +843,7 @@
}
}
+ // TODO(bkonyi): find a way to do this with raw paths.
static String _trimTrailingPathSeparators(String path) {
// Don't handle argument errors here.
if (path is! String) return path;
@@ -799,6 +860,7 @@
return path;
}
+ // TODO(bkonyi): find a way to do this with raw paths.
static String _ensureTrailingPathSeparators(String path) {
// Don't handle argument errors here.
if (path is! String) return path;
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 697694f..9029dcb 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -20,6 +20,11 @@
return overrides.createLink(path);
}
+ factory Link.fromRawPath(Uint8List rawPath) {
+ // TODO(bkonyi): handle overrides
+ return new _Link.fromRawPath(rawPath);
+ }
+
/**
* Creates a [Link] object.
*
@@ -150,22 +155,32 @@
}
class _Link extends FileSystemEntity implements Link {
- final String path;
+ String _path;
+ Uint8List _rawPath;
- _Link(this.path) {
+ _Link(String path) {
if (path is! String) {
throw new ArgumentError('${Error.safeToString(path)} '
'is not a String');
}
+ _path = path;
+ _rawPath = FileSystemEntity._toUtf8Array(path);
}
+ _Link.fromRawPath(Uint8List rawPath) {
+ _rawPath = FileSystemEntity._toNullTerminatedUtf8Array(rawPath);
+ _path = FileSystemEntity._toStringFromUtf8Array(rawPath);
+ }
+
+ String get path => _path;
+
String toString() => "Link: '$path'";
- Future<bool> exists() => FileSystemEntity.isLink(path);
+ Future<bool> exists() => FileSystemEntity._isLinkRaw(_rawPath);
- bool existsSync() => FileSystemEntity.isLinkSync(path);
+ bool existsSync() => FileSystemEntity._isLinkRawSync(_rawPath);
- Link get absolute => new Link(_absolutePath);
+ Link get absolute => new Link.fromRawPath(_rawAbsolutePath);
Future<Link> create(String target, {bool recursive: false}) {
if (Platform.isWindows) {
@@ -175,7 +190,7 @@
recursive ? parent.create(recursive: true) : new Future.value(null);
return result
.then((_) => _File._dispatchWithNamespace(
- _IOService.fileCreateLink, [null, path, target]))
+ _IOService.fileCreateLink, [null, _rawPath, target]))
.then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
@@ -192,7 +207,7 @@
if (Platform.isWindows) {
target = _makeWindowsLinkTarget(target);
}
- var result = _File._createLink(_Namespace._namespace, path, target);
+ var result = _File._createLink(_Namespace._namespace, _rawPath, target);
throwIfError(result, "Cannot create link", path);
}
@@ -230,10 +245,12 @@
Future<Link> _delete({bool recursive: false}) {
if (recursive) {
- return new Directory(path).delete(recursive: true).then((_) => this);
+ return new Directory.fromRawPath(_rawPath)
+ .delete(recursive: true)
+ .then((_) => this);
}
return _File._dispatchWithNamespace(
- _IOService.fileDeleteLink, [null, path]).then((response) {
+ _IOService.fileDeleteLink, [null, _rawPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "Cannot delete link", path);
}
@@ -243,15 +260,15 @@
void _deleteSync({bool recursive: false}) {
if (recursive) {
- return new Directory(path).deleteSync(recursive: true);
+ return new Directory.fromRawPath(_rawPath).deleteSync(recursive: true);
}
- var result = _File._deleteLinkNative(_Namespace._namespace, path);
+ var result = _File._deleteLinkNative(_Namespace._namespace, _rawPath);
throwIfError(result, "Cannot delete link", path);
}
Future<Link> rename(String newPath) {
return _File._dispatchWithNamespace(
- _IOService.fileRenameLink, [null, path, newPath]).then((response) {
+ _IOService.fileRenameLink, [null, _rawPath, newPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
response, "Cannot rename link to '$newPath'", path);
@@ -261,14 +278,14 @@
}
Link renameSync(String newPath) {
- var result = _File._renameLink(_Namespace._namespace, path, newPath);
+ var result = _File._renameLink(_Namespace._namespace, _rawPath, newPath);
throwIfError(result, "Cannot rename link '$path' to '$newPath'");
return new Link(newPath);
}
Future<String> target() {
return _File._dispatchWithNamespace(
- _IOService.fileLinkTarget, [null, path]).then((response) {
+ _IOService.fileLinkTarget, [null, _rawPath]).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(
response, "Cannot get target of link", path);
@@ -278,7 +295,7 @@
}
String targetSync() {
- var result = _File._linkTarget(_Namespace._namespace, path);
+ var result = _File._linkTarget(_Namespace._namespace, _rawPath);
throwIfError(result, "Cannot read link", path);
return result;
}
diff --git a/sdk/lib/io/overrides.dart b/sdk/lib/io/overrides.dart
index 4eed013..f68d417 100644
--- a/sdk/lib/io/overrides.dart
+++ b/sdk/lib/io/overrides.dart
@@ -214,7 +214,7 @@
/// When this override is installed, this function overrides the behavior of
/// `FileSystemEntity.type`.
Future<FileSystemEntityType> fseGetType(String path, bool followLinks) {
- return FileSystemEntity._getTypeRequest(path, followLinks);
+ return FileSystemEntity._getTypeRequest(utf8.encode(path), followLinks);
}
/// Returns the [FileSystemEntityType] for [path].
@@ -222,7 +222,7 @@
/// When this override is installed, this function overrides the behavior of
/// `FileSystemEntity.typeSync`.
FileSystemEntityType fseGetTypeSync(String path, bool followLinks) {
- return FileSystemEntity._getTypeSyncHelper(path, followLinks);
+ return FileSystemEntity._getTypeSyncHelper(utf8.encode(path), followLinks);
}
// _FileSystemWatcher
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 5efb0e9..7f22c73 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -7089,24 +7089,7 @@
Language/Classes/Constructors/Generative_Constructors/redirection_t03: Crash
Language/Classes/Constructors/Generative_Constructors/redirection_t07: Crash
Language/Classes/Constructors/Generative_Constructors/redirection_t08: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t02: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t05: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t07: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t08: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t09: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t10: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t11: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t12: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t13: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t14: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t15: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t16: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t17: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t18: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t19: Crash
Language/Classes/Instance_Methods/Operators/allowed_names_t20: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t21: Crash
-Language/Classes/Instance_Methods/Operators/allowed_names_t22: Crash
Language/Classes/member_definition_t04: Crash
Language/Classes/member_definition_t06: Crash
Language/Classes/member_definition_t07: Crash
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index d72657b..dfd4e39 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -1777,5 +1777,5 @@
LibTest/typed_data/Uint64List/Uint64List.view_A01_t01: CompileTimeError
LibTest/typed_data/Uint64List/Uint64List.view_A01_t02: CompileTimeError
-[ $compiler == dartk || $compiler == dartkp ]
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkp ]
*: SkipByDesign
diff --git a/tests/compiler/dart2js/closure/closure_test.dart b/tests/compiler/dart2js/closure/closure_test.dart
index 96f99de..dfc8631 100644
--- a/tests/compiler/dart2js/closure/closure_test.dart
+++ b/tests/compiler/dart2js/closure/closure_test.dart
@@ -13,10 +13,10 @@
import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
import 'package:compiler/src/js_model/locals.dart';
import 'package:compiler/src/universe/world_builder.dart';
-import 'package:compiler/src/util/util.dart';
import 'package:expect/expect.dart';
import '../equivalence/id_equivalence.dart';
import '../equivalence/id_equivalence_helper.dart';
+import 'package:front_end/src/fasta/util/link.dart' show Link;
import 'package:kernel/ast.dart' as ir;
const List<String> skipForKernel = const <String>[];
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index 50d9225..619871d 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -20,14 +20,14 @@
export 'package:compiler/src/diagnostics/messages.dart';
export 'package:compiler/src/diagnostics/source_span.dart';
export 'package:compiler/src/diagnostics/spannable.dart';
-
-import 'package:compiler/src/util/util.dart';
export 'package:compiler/src/util/util.dart';
import 'package:compiler/src/world.dart';
import 'package:compiler/src/compiler.dart' show Compiler;
+import 'package:front_end/src/fasta/util/link.dart' show Link;
+
import 'memory_compiler.dart';
import 'output_collector.dart';
diff --git a/tests/compiler/dart2js/deferred/custom_element_test.dart b/tests/compiler/dart2js/deferred/custom_element_test.dart
index 01fb615..d2e6236 100644
--- a/tests/compiler/dart2js/deferred/custom_element_test.dart
+++ b/tests/compiler/dart2js/deferred/custom_element_test.dart
@@ -23,15 +23,16 @@
await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
Compiler compiler = result.compiler;
var closedWorld = compiler.backendClosedWorldForTesting;
- var outputUnitForEntity = compiler.backend.outputUnitData.outputUnitForEntity;
+ var outputUnitForMember = compiler.backend.outputUnitData.outputUnitForMember;
+ var outputUnitForClass = compiler.backend.outputUnitData.outputUnitForClass;
var mainOutputUnit = compiler.backend.outputUnitData.mainOutputUnit;
var elementEnvironment = closedWorld.elementEnvironment;
dynamic lib = elementEnvironment.lookupLibrary(Uri.parse("memory:lib.dart"));
var customType = elementEnvironment.lookupClass(lib, "CustomType");
var foo = elementEnvironment.lookupLibraryMember(lib, "foo");
- Expect.notEquals(mainOutputUnit, outputUnitForEntity(foo));
+ Expect.notEquals(mainOutputUnit, outputUnitForMember(foo));
// Native elements are not deferred
- Expect.equals(mainOutputUnit, outputUnitForEntity(customType));
+ Expect.equals(mainOutputUnit, outputUnitForClass(customType));
}
// The main library imports a file defining a custom element.
diff --git a/tests/compiler/dart2js/deferred/dont_inline_deferred_constants_test.dart b/tests/compiler/dart2js/deferred/dont_inline_deferred_constants_test.dart
index 33da0d2..e65d0c2 100644
--- a/tests/compiler/dart2js/deferred/dont_inline_deferred_constants_test.dart
+++ b/tests/compiler/dart2js/deferred/dont_inline_deferred_constants_test.dart
@@ -25,20 +25,20 @@
return elementEnvironment.lookupLibrary(Uri.parse(name));
}
- var outputUnitForEntity =
- compiler.backend.outputUnitData.outputUnitForEntity;
+ var outputUnitForMember =
+ compiler.backend.outputUnitData.outputUnitForMember;
dynamic lib1 = lookupLibrary("memory:lib1.dart");
var foo1 = elementEnvironment.lookupLibraryMember(lib1, "foo");
- var ou_lib1 = outputUnitForEntity(foo1);
+ var ou_lib1 = outputUnitForMember(foo1);
dynamic lib2 = lookupLibrary("memory:lib2.dart");
var foo2 = elementEnvironment.lookupLibraryMember(lib2, "foo");
- var ou_lib2 = outputUnitForEntity(foo2);
+ var ou_lib2 = outputUnitForMember(foo2);
dynamic mainApp = elementEnvironment.mainLibrary;
var fooMain = elementEnvironment.lookupLibraryMember(mainApp, "foo");
- var ou_lib1_lib2 = outputUnitForEntity(fooMain);
+ var ou_lib1_lib2 = outputUnitForMember(fooMain);
String mainOutput = collector.getOutput("", OutputType.js);
String lib1Output =
diff --git a/tests/compiler/dart2js/deferred/dont_inline_deferred_globals_test.dart b/tests/compiler/dart2js/deferred/dont_inline_deferred_globals_test.dart
index 7b6db2d..25c48e3 100644
--- a/tests/compiler/dart2js/deferred/dont_inline_deferred_globals_test.dart
+++ b/tests/compiler/dart2js/deferred/dont_inline_deferred_globals_test.dart
@@ -25,12 +25,12 @@
return elementEnvironment.lookupLibrary(Uri.parse(name));
}
- var outputUnitForEntity =
- compiler.backend.outputUnitData.outputUnitForEntity;
+ var outputUnitForMember =
+ compiler.backend.outputUnitData.outputUnitForMember;
dynamic lib1 = lookupLibrary("memory:lib1.dart");
var foo1 = elementEnvironment.lookupLibraryMember(lib1, "finalVar");
- var ou_lib1 = outputUnitForEntity(foo1);
+ var ou_lib1 = outputUnitForMember(foo1);
String mainOutput = collector.getOutput("", OutputType.js);
String lib1Output =
diff --git a/tests/compiler/dart2js/deferred/follow_implicit_super_regression_test.dart b/tests/compiler/dart2js/deferred/follow_implicit_super_regression_test.dart
index f5e7858..f3aecaa 100644
--- a/tests/compiler/dart2js/deferred/follow_implicit_super_regression_test.dart
+++ b/tests/compiler/dart2js/deferred/follow_implicit_super_regression_test.dart
@@ -20,17 +20,17 @@
return elementEnvironment.lookupLibrary(Uri.parse(name));
}
- var outputUnitForEntity =
- compiler.backend.outputUnitData.outputUnitForEntity;
+ var outputUnitForMember =
+ compiler.backend.outputUnitData.outputUnitForMember;
dynamic lib = lookupLibrary("memory:lib.dart");
var a = elementEnvironment.lookupLibraryMember(lib, "a");
var b = elementEnvironment.lookupLibraryMember(lib, "b");
var c = elementEnvironment.lookupLibraryMember(lib, "c");
var d = elementEnvironment.lookupLibraryMember(lib, "d");
- Expect.equals(outputUnitForEntity(a), outputUnitForEntity(b));
- Expect.equals(outputUnitForEntity(a), outputUnitForEntity(c));
- Expect.equals(outputUnitForEntity(a), outputUnitForEntity(d));
+ Expect.equals(outputUnitForMember(a), outputUnitForMember(b));
+ Expect.equals(outputUnitForMember(a), outputUnitForMember(c));
+ Expect.equals(outputUnitForMember(a), outputUnitForMember(d));
}
asyncTest(() async {
diff --git a/tests/compiler/dart2js/deferred/inline_restrictions_test.dart b/tests/compiler/dart2js/deferred/inline_restrictions_test.dart
index a296c65e..6c53fcf 100644
--- a/tests/compiler/dart2js/deferred/inline_restrictions_test.dart
+++ b/tests/compiler/dart2js/deferred/inline_restrictions_test.dart
@@ -18,16 +18,16 @@
memorySourceFiles: MEMORY_SOURCE_FILES, outputProvider: collector);
Compiler compiler = result.compiler;
var env = compiler.backendClosedWorldForTesting.elementEnvironment;
- var outputUnitForEntity =
- compiler.backend.outputUnitData.outputUnitForEntity;
+ var outputUnitForMember =
+ compiler.backend.outputUnitData.outputUnitForMember;
lookupLibrary(name) => env.lookupLibrary(Uri.parse(name));
dynamic lib1 = lookupLibrary("memory:lib1.dart");
var inlineMeAway = env.lookupLibraryMember(lib1, "inlineMeAway");
- var ou_lib1 = outputUnitForEntity(inlineMeAway);
+ var ou_lib1 = outputUnitForMember(inlineMeAway);
dynamic lib3 = lookupLibrary("memory:lib3.dart");
var sameContextInline = env.lookupLibraryMember(lib3, "sameContextInline");
- var ou_lib3 = outputUnitForEntity(sameContextInline);
+ var ou_lib3 = outputUnitForMember(sameContextInline);
// Test that we actually got different output units.
Expect.notEquals(ou_lib1.name, ou_lib3.name);
diff --git a/tests/compiler/dart2js/deferred/load_graph_segmentation2_test.dart b/tests/compiler/dart2js/deferred/load_graph_segmentation2_test.dart
index c73eb2e..985ad2a 100644
--- a/tests/compiler/dart2js/deferred/load_graph_segmentation2_test.dart
+++ b/tests/compiler/dart2js/deferred/load_graph_segmentation2_test.dart
@@ -16,15 +16,15 @@
CompilationResult result =
await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
Compiler compiler = result.compiler;
- var outputUnitForEntity =
- compiler.backend.outputUnitData.outputUnitForEntity;
+ var outputUnitForMember =
+ compiler.backend.outputUnitData.outputUnitForMember;
var env = compiler.backendClosedWorldForTesting.elementEnvironment;
var mainOutputUnit = compiler.backend.outputUnitData.mainOutputUnit;
dynamic lib = env.lookupLibrary(Uri.parse("memory:lib.dart"));
var f1 = env.lookupLibraryMember(lib, "f1");
var f2 = env.lookupLibraryMember(lib, "f2");
- Expect.notEquals(mainOutputUnit, outputUnitForEntity(f1));
- Expect.equals(mainOutputUnit, outputUnitForEntity(f2));
+ Expect.notEquals(mainOutputUnit, outputUnitForMember(f1));
+ Expect.equals(mainOutputUnit, outputUnitForMember(f2));
});
}
diff --git a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
index 8135ce0..f20cef3 100644
--- a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
@@ -23,8 +23,9 @@
var main = env.mainFunction;
Expect.isNotNull(main, "Could not find 'main'");
- var outputUnitForEntity =
- compiler.backend.outputUnitData.outputUnitForEntity;
+ var outputUnitForMember =
+ compiler.backend.outputUnitData.outputUnitForMember;
+ var outputUnitForClass = compiler.backend.outputUnitData.outputUnitForClass;
var mainOutputUnit = compiler.backend.outputUnitData.mainOutputUnit;
var backend = compiler.backend;
@@ -40,21 +41,21 @@
var bar1 = env.lookupLibraryMember(lib4, "bar1");
var bar2 = env.lookupLibraryMember(lib4, "bar2");
- OutputUnit ou_lib1 = outputUnitForEntity(foo1);
- OutputUnit ou_lib2 = outputUnitForEntity(foo2);
- OutputUnit ou_lib1_lib2 = outputUnitForEntity(foo3);
- OutputUnit ou_lib4_1 = outputUnitForEntity(bar1);
- OutputUnit ou_lib4_2 = outputUnitForEntity(bar2);
+ OutputUnit ou_lib1 = outputUnitForMember(foo1);
+ OutputUnit ou_lib2 = outputUnitForMember(foo2);
+ OutputUnit ou_lib1_lib2 = outputUnitForMember(foo3);
+ OutputUnit ou_lib4_1 = outputUnitForMember(bar1);
+ OutputUnit ou_lib4_2 = outputUnitForMember(bar2);
- Expect.equals(mainOutputUnit, outputUnitForEntity(main));
- Expect.notEquals(mainOutputUnit, outputUnitForEntity(foo1));
+ Expect.equals(mainOutputUnit, outputUnitForMember(main));
+ Expect.notEquals(mainOutputUnit, outputUnitForMember(foo1));
Expect.notEquals(ou_lib1, ou_lib1_lib2);
Expect.notEquals(ou_lib2, ou_lib1_lib2);
Expect.notEquals(ou_lib1, ou_lib2);
Expect.notEquals(ou_lib4_1, ou_lib4_2);
Expect.notEquals(ou_lib1, ou_lib4_2);
// InputElement is native, so it should be in the mainOutputUnit.
- Expect.equals(mainOutputUnit, outputUnitForEntity(inputElement));
+ Expect.equals(mainOutputUnit, outputUnitForClass(inputElement));
var hunksToLoad = compiler.deferredLoadTask.hunksToLoad;
diff --git a/tests/compiler/dart2js/deferred/not_in_main_test.dart b/tests/compiler/dart2js/deferred/not_in_main_test.dart
index 4a13b29..a259716 100644
--- a/tests/compiler/dart2js/deferred/not_in_main_test.dart
+++ b/tests/compiler/dart2js/deferred/not_in_main_test.dart
@@ -20,8 +20,8 @@
asyncTest(() async {
CompilationResult result = await runCompiler(memorySourceFiles: TEST1);
Compiler compiler = result.compiler;
- var outputUnitForEntity =
- compiler.backend.outputUnitData.outputUnitForEntity;
+ var outputUnitForMember =
+ compiler.backend.outputUnitData.outputUnitForMember;
var mainOutputUnit = compiler.backend.outputUnitData.mainOutputUnit;
var env = compiler.backendClosedWorldForTesting.elementEnvironment;
lookupLibrary(name) => env.lookupLibrary(Uri.parse(name));
@@ -30,7 +30,7 @@
env.lookupLibraryMember(lib1, "foo1");
var foo2 = env.lookupLibraryMember(lib2, "foo2");
- Expect.notEquals(mainOutputUnit, outputUnitForEntity(foo2));
+ Expect.notEquals(mainOutputUnit, outputUnitForMember(foo2));
});
}
@@ -38,16 +38,15 @@
asyncTest(() async {
CompilationResult result = await runCompiler(memorySourceFiles: TEST2);
Compiler compiler = result.compiler;
- var outputUnitForEntity =
- compiler.backend.outputUnitData.outputUnitForEntity;
+ var outputUnitForClass = compiler.backend.outputUnitData.outputUnitForClass;
var mainOutputUnit = compiler.backend.outputUnitData.mainOutputUnit;
var env = compiler.backendClosedWorldForTesting.elementEnvironment;
lookupLibrary(name) => env.lookupLibrary(Uri.parse(name));
dynamic shared = lookupLibrary("memory:shared.dart");
- var a = env.lookupLibraryMember(shared, "A");
+ var a = env.lookupClass(shared, "A");
- Expect.equals(mainOutputUnit, outputUnitForEntity(a));
+ Expect.equals(mainOutputUnit, outputUnitForClass(a));
});
}
diff --git a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
index cef5d1b..ca8c88f 100644
--- a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
+++ b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
@@ -117,7 +117,7 @@
: super(reporter, actualMap);
String getMemberValue(MemberEntity member) {
- return outputUnitString(_data.outputUnitForEntity(member));
+ return outputUnitString(_data.outputUnitForMember(member));
}
@override
@@ -162,7 +162,7 @@
Compiler compiler, ClassEntity cls, Map<Id, ActualData> actualMap,
{bool verbose: false}) {
OutputUnitData data = compiler.backend.outputUnitData;
- String value = outputUnitString(data.outputUnitForEntity(cls));
+ String value = outputUnitString(data.outputUnitForClass(cls));
KernelBackendStrategy backendStrategy = compiler.backendStrategy;
KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
diff --git a/tests/compiler/dart2js/inference/data/field_type.dart b/tests/compiler/dart2js/inference/data/field_type.dart
index 51b672d..44168f3 100644
--- a/tests/compiler/dart2js/inference/data/field_type.dart
+++ b/tests/compiler/dart2js/inference/data/field_type.dart
@@ -202,7 +202,8 @@
/*element: A9.:[exact=A9]*/
A9(/*[exact=JSBool]*/ x) {
- if (x) {} else {
+ if (x) {
+ } else {
/*update: [exact=A9]*/ f9 = "1";
}
}
@@ -727,7 +728,8 @@
/*element: A29.:[exact=A29]*/
A29(/*[exact=JSUInt31]*/ x) {
this. /*update: [exact=A29]*/ f29a = x;
- if (x /*invoke: [exact=JSUInt31]*/ == 0) {} else {
+ if (x /*invoke: [exact=JSUInt31]*/ == 0) {
+ } else {
return;
}
this. /*update: [exact=A29]*/ f29b = x;
diff --git a/tests/compiler/dart2js/inference/data/general.dart b/tests/compiler/dart2js/inference/data/general.dart
index ea317d5..1b2d806 100644
--- a/tests/compiler/dart2js/inference/data/general.dart
+++ b/tests/compiler/dart2js/inference/data/general.dart
@@ -306,7 +306,8 @@
/*element: testIsCheck26:[subclass=JSInt]*/
testIsCheck26(/*[null|subclass=Object]*/ a) {
- if (a is int) {} else {
+ if (a is int) {
+ } else {
throw 42;
}
return a;
@@ -314,7 +315,8 @@
/*element: testIsCheck27:[subclass=JSInt]*/
testIsCheck27(/*[null|subclass=Object]*/ a) {
- if (a is int) {} else {
+ if (a is int) {
+ } else {
return 42;
}
return a;
@@ -322,7 +324,8 @@
/*element: testIsCheck28:[null|subclass=Object]*/
testIsCheck28(/*[null|subclass=Object]*/ a) {
- if (a is int) {} else {}
+ if (a is int) {
+ } else {}
return a;
}
@@ -344,7 +347,8 @@
/*element: testIf2:[null|exact=JSUInt31]*/
testIf2(/*[null|subclass=Object]*/ a) {
var c = null;
- if (a) {} else {
+ if (a) {
+ } else {
c = 10;
}
return c;
diff --git a/tests/compiler/dart2js/link_test.dart b/tests/compiler/dart2js/link_test.dart
index 841c89f..5033eea 100644
--- a/tests/compiler/dart2js/link_test.dart
+++ b/tests/compiler/dart2js/link_test.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
-import 'package:compiler/src/util/util.dart';
+import 'package:front_end/src/fasta/util/link.dart' show Link;
import 'link_helper.dart';
main() {
@@ -21,8 +21,6 @@
testFromList([0, 1, 2, 3, 4]);
testFromList([0, 1, 2, 3, 4, 5]);
testSkip();
-
- testCopyWithout();
}
testFromList(List list) {
@@ -63,14 +61,3 @@
Expect.isTrue(emptyLink.skip(0).isEmpty);
Expect.throws(() => emptyLink.skip(1), (e) => e is RangeError);
}
-
-testCopyWithout() {
- test(const Link().copyWithout(0), []);
-
- test(LinkFromList([0]).copyWithout(0), []);
- test(LinkFromList([0, 1]).copyWithout(0), [1]);
- test(LinkFromList([0, 1, 2]).copyWithout(0), [1, 2]);
- test(LinkFromList([0, 1, 2]).copyWithout(1), [0, 2]);
- test(LinkFromList([0, 1, 2]).copyWithout(2), [0, 1]);
- test(LinkFromList([0, 1, 2]).copyWithout(3), [0, 1, 2]);
-}
diff --git a/tests/compiler/dart2js/memory_source_file_helper.dart b/tests/compiler/dart2js/memory_source_file_helper.dart
index 24a93e7..b1e0be0 100644
--- a/tests/compiler/dart2js/memory_source_file_helper.dart
+++ b/tests/compiler/dart2js/memory_source_file_helper.dart
@@ -29,7 +29,8 @@
MemorySourceFileProvider(Map<String, dynamic> this.memorySourceFiles);
@override
- Future<Input> readBytesFromUri(Uri resourceUri, InputKind inputKind) {
+ Future<Input<List<int>>> readBytesFromUri(
+ Uri resourceUri, InputKind inputKind) {
if (resourceUri.scheme != 'memory') {
return super.readBytesFromUri(resourceUri, inputKind);
}
@@ -41,7 +42,7 @@
return new Future.error(new Exception(
'No such memory file $resourceUri in ${memorySourceFiles.keys}'));
}
- Input input;
+ Input<List<int>> input;
switch (inputKind) {
case InputKind.UTF8:
if (source is String) {
diff --git a/tests/compiler/dart2js/model/class_set_test.dart b/tests/compiler/dart2js/model/class_set_test.dart
index a8216b1..401c441 100644
--- a/tests/compiler/dart2js/model/class_set_test.dart
+++ b/tests/compiler/dart2js/model/class_set_test.dart
@@ -12,8 +12,8 @@
import 'package:compiler/src/elements/entities.dart' show ClassEntity;
import 'package:compiler/src/universe/class_set.dart';
import 'package:compiler/src/util/enumset.dart';
-import 'package:compiler/src/util/util.dart';
import 'package:compiler/src/world.dart';
+import 'package:front_end/src/fasta/util/link.dart' show Link;
import '../type_test_helper.dart';
void main() {
diff --git a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
index fa652b4..16a33bd 100644
--- a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
+++ b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
@@ -179,16 +179,18 @@
(ClassEntity cls) {
List<String> expectedLiveMembers =
expectedLiveMembersMap[cls.name] ?? const <String>[];
- elementEnvironment.forEachLocalClassMember(cls, (MemberEntity member) {
+ List<String> actualLiveMembers = <String>[];
+ closedWorld.processedMembers.forEach((MemberEntity member) {
if (member.enclosingClass != cls) return;
- bool expected = expectedLiveMembers.contains(member.name);
- bool live = closedWorld.processedMembers.contains(member);
- Expect.equals(
- expected,
- live,
- "Member $member ${expected ? '' : 'not '}expected to be live "
- "in ${strongMode ? 'Dart 2' : 'Dart 1'}. "
- "Expected members for ${cls.name}: $expectedLiveMembers");
+ if (member.isConstructor) return;
+ actualLiveMembers.add(member.name);
});
+ Expect.setEquals(
+ expectedLiveMembers,
+ actualLiveMembers,
+ "Unexpected live members for $cls "
+ "in ${strongMode ? 'Dart 2' : 'Dart 1'}. \n"
+ "Expected members for ${cls.name}: $expectedLiveMembers\n"
+ "Actual members for ${cls.name} : $actualLiveMembers");
});
}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types1_test.dart b/tests/compiler/dart2js_extra/deferred_function_types1_test.dart
new file mode 100644
index 0000000..91c9075
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types1_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+import 'deferred_function_types_lib1.dart' deferred as lib1;
+import 'deferred_function_types_lib2.dart' deferred as lib2;
+
+main() async {
+ await lib1.loadLibrary();
+ Expect.isTrue(lib1.method1() is int Function(int));
+ Expect.isFalse(lib1.method1() is String Function(String));
+ await lib2.loadLibrary();
+ Expect.isFalse(lib2.method2() is int Function(int));
+ Expect.isTrue(lib2.method2() is String Function(String));
+}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types2_test.dart b/tests/compiler/dart2js_extra/deferred_function_types2_test.dart
new file mode 100644
index 0000000..4336421
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types2_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+import 'deferred_function_types_lib1.dart' deferred as lib1;
+import 'deferred_function_types_lib2.dart' deferred as lib2;
+
+main() async {
+ await lib2.loadLibrary();
+ Expect.isFalse(lib2.method2() is int Function(int));
+ Expect.isTrue(lib2.method2() is String Function(String));
+ await lib1.loadLibrary();
+ Expect.isTrue(lib1.method1() is int Function(int));
+ Expect.isFalse(lib1.method1() is String Function(String));
+}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types3_test.dart b/tests/compiler/dart2js_extra/deferred_function_types3_test.dart
new file mode 100644
index 0000000..98a6de8
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types3_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+import 'deferred_function_types_lib1.dart' deferred as lib1;
+import 'deferred_function_types_lib2.dart' deferred as lib2;
+
+main() async {
+ await lib1.loadLibrary();
+ Expect.isTrue(lib1.method3() is Object Function(Null));
+ Expect.isFalse(lib1.method3() is Object Function(Null, Null));
+ await lib2.loadLibrary();
+ Expect.isFalse(lib2.method4() is Object Function(Null));
+ Expect.isTrue(lib2.method4() is Object Function(Null, Null));
+}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types4_test.dart b/tests/compiler/dart2js_extra/deferred_function_types4_test.dart
new file mode 100644
index 0000000..fc78d96
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types4_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+import 'deferred_function_types_lib1.dart' deferred as lib1;
+import 'deferred_function_types_lib2.dart' deferred as lib2;
+
+main() async {
+ await lib2.loadLibrary();
+ Expect.isFalse(lib2.method4() is Object Function(Null));
+ Expect.isTrue(lib2.method4() is Object Function(Null, Null));
+ await lib1.loadLibrary();
+ Expect.isTrue(lib1.method3() is Object Function(Null));
+ Expect.isFalse(lib1.method3() is Object Function(Null, Null));
+}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types5_test.dart b/tests/compiler/dart2js_extra/deferred_function_types5_test.dart
new file mode 100644
index 0000000..998d678
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types5_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+import 'deferred_function_types_lib1.dart' deferred as lib1;
+import 'deferred_function_types_lib2.dart' deferred as lib2;
+
+main() async {
+ await lib1.loadLibrary();
+ Expect.isTrue(lib1.test3(lib1.method3()));
+ Expect.isFalse(lib1.method3() is Object Function(String));
+ await lib2.loadLibrary();
+ Expect.isFalse(lib2.method4() is Object Function(String, String));
+ Expect.isTrue(lib2.test4(lib2.method4()));
+}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types6_test.dart b/tests/compiler/dart2js_extra/deferred_function_types6_test.dart
new file mode 100644
index 0000000..2423b52
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types6_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+import 'deferred_function_types_lib1.dart' deferred as lib1;
+import 'deferred_function_types_lib2.dart' deferred as lib2;
+
+main() async {
+ await lib2.loadLibrary();
+ Expect.isFalse(lib2.method4() is Object Function(String, String));
+ Expect.isTrue(lib2.test4(lib2.method4()));
+ await lib1.loadLibrary();
+ Expect.isTrue(lib1.test3(lib1.method3()));
+ Expect.isFalse(lib1.method3() is Object Function(String));
+}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types7_test.dart b/tests/compiler/dart2js_extra/deferred_function_types7_test.dart
new file mode 100644
index 0000000..c3e8de0
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types7_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+import 'deferred_function_types_lib1.dart' deferred as lib1;
+import 'deferred_function_types_lib2.dart' deferred as lib2;
+
+main() async {
+ await lib1.loadLibrary();
+ Expect.isTrue(lib1.method1() is int Function(int));
+ Expect.isFalse(lib1.method1() is String Function(String));
+ Expect.isTrue(lib1.method5 is Object Function(Null, String, int));
+ Expect.isFalse(lib1.method5 is Object Function(Null, int, String));
+ await lib2.loadLibrary();
+ Expect.isFalse(lib2.method2() is int Function(int));
+ Expect.isTrue(lib2.method2() is String Function(String));
+ Expect.isFalse(lib2.method6 is Object Function(Null, String, int));
+ Expect.isTrue(lib2.method6 is Object Function(Null, int, String));
+}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types8_test.dart b/tests/compiler/dart2js_extra/deferred_function_types8_test.dart
new file mode 100644
index 0000000..eaa89ca
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types8_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+import 'deferred_function_types_lib1.dart' deferred as lib1;
+import 'deferred_function_types_lib2.dart' deferred as lib2;
+
+main() async {
+ await lib2.loadLibrary();
+ Expect.isFalse(lib2.method2() is int Function(int));
+ Expect.isTrue(lib2.method2() is String Function(String));
+ Expect.isFalse(lib2.method6 is Object Function(Null, String, int));
+ Expect.isTrue(lib2.method6 is Object Function(Null, int, String));
+ await lib1.loadLibrary();
+ Expect.isTrue(lib1.method1() is int Function(int));
+ Expect.isFalse(lib1.method1() is String Function(String));
+ Expect.isTrue(lib1.method5 is Object Function(Null, String, int));
+ Expect.isFalse(lib1.method5 is Object Function(Null, int, String));
+}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types_lib1.dart b/tests/compiler/dart2js_extra/deferred_function_types_lib1.dart
new file mode 100644
index 0000000..4bacb61
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types_lib1.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+method1() {
+ return (int i) => i;
+}
+
+class Class1 {}
+
+method3() {
+ return (Class1 c) => c;
+}
+
+test3(o) => o is Class1 Function(Class1);
+
+method5(Class1 c, String s, int i) {}
diff --git a/tests/compiler/dart2js_extra/deferred_function_types_lib2.dart b/tests/compiler/dart2js_extra/deferred_function_types_lib2.dart
new file mode 100644
index 0000000..a8abb54
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_function_types_lib2.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+method2() {
+ return (String s) => s;
+}
+
+class Class2 {}
+
+method4() {
+ return (Class2 c1, Class2 c2) => c1;
+}
+
+test4(o) => o is Class2 Function(Class2, Class2);
+
+method6(Class2 c, int i, String s) {}
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index e327d40..327e76e 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -299,8 +299,8 @@
# We skip all the Dart 1.0 tests in dartk and dartkp mode as these
# modes are intended only for Dart 2.0 with strong mode enabled.
-[ $compiler == dartk || $compiler == dartkp ]
-*: Skip
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkp ]
+*: SkipByDesign
[ $runtime == dart_precompiled || $runtime == flutter || $runtime == vm ]
big_integer_arith_vm_test: CompileTimeError # Large integer literal
diff --git a/tests/corelib_2/bigint_test.dart b/tests/corelib_2/bigint_test.dart
index 290e477..030e59f 100644
--- a/tests/corelib_2/bigint_test.dart
+++ b/tests/corelib_2/bigint_test.dart
@@ -363,6 +363,9 @@
a = BigInt.parse("12345678901234567890");
b = BigInt.parse("10000000000000000");
Expect.equals(new BigInt.from(1234), a ~/ b);
+ a = BigInt.parse("9173112362840293939050000000000000000");
+ b = BigInt.parse("50000000000000000");
+ Expect.equals(BigInt.parse("183462247256805878781"), a ~/ b);
}
testBigintDiv() {
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 740c6c6..d996c09 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -4,6 +4,14 @@
iterable_where_type_test: RuntimeError # Disabled. Issue 32463
maps_test: Skip # Maps class no longer exists
+[ $compiler == app_jitk ]
+symbol_operator_test/03: RuntimeError
+symbol_reserved_word_test/06: RuntimeError
+symbol_reserved_word_test/09: RuntimeError
+symbol_reserved_word_test/12: RuntimeError
+symbol_test/none: RuntimeError
+unicode_test: RuntimeError
+
[ $compiler == dart2analyzer ]
bigint_from_test: CompileTimeError # Issue 32585
compare_to2_test: CompileTimeError # invalid test
@@ -12,11 +20,11 @@
num_sign_test: Crash, Pass # Issue 31768
[ $compiler == dart2js ]
+apply_generic_function_test: RuntimeError # Issue 32691
bigint_from_test: RuntimeError # Issue 32589
date_time11_test: RuntimeError, Pass # Fails when US is on winter time, issue 31285.
iterable_where_type_test: RuntimeError # issue 31718
list_unmodifiable_test: Pass, RuntimeError # Issue 28712
-apply_generic_function_test: RuntimeError # Issue 32691
[ $compiler != dartdevc ]
error_stack_trace_test/static: MissingCompileTimeError
@@ -93,9 +101,23 @@
[ $arch == x64 && $system == windows ]
stopwatch_test: Skip # Flaky test due to expected performance behaviour.
-[ $arch == simarm || $arch == simarm64 || $arch == simdbc64 ]
-bigint_parse_radix_test: Pass, Slow # Bigint computations are slow on simulated architectures.
-bigint_test: Pass, Slow # Bigint computations are slow on simulated architectures.
+# All static_tests have expected compile-time errors.
+[ $compiler != app_jitk && $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $compiler != fasta && $strong ]
+core_runtime_types_static_test: MissingCompileTimeError
+splay_tree_test/01: MissingCompileTimeError
+splay_tree_test/02: MissingCompileTimeError
+string_base_vm_static_test: MissingCompileTimeError
+string_replace_static_test: MissingCompileTimeError
+string_static_test: MissingCompileTimeError
+
+[ $compiler != app_jitk && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $compiler != fasta ]
+iterable_element_at_test/static: MissingCompileTimeError
+
+[ $compiler != app_jitk && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $compiler != fasta && ($compiler != dart2analyzer || !$strong) ]
+iterable_mapping_test/01: MissingCompileTimeError
+
+[ $compiler != app_jitk && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $runtime != none ]
+map_keys2_test: RuntimeError # needs Dart 2 is checks
[ $compiler == dart2analyzer && !$checked && !$strong ]
from_environment_const_type_test/02: MissingCompileTimeError
@@ -133,15 +155,6 @@
[ $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk ]
bigint_js_test: SkipByDesign # JavaScript-specific test
-# All static_tests have expected compile-time errors.
-[ $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $compiler != fasta && $strong ]
-core_runtime_types_static_test: MissingCompileTimeError
-splay_tree_test/01: MissingCompileTimeError
-splay_tree_test/02: MissingCompileTimeError
-string_base_vm_static_test: MissingCompileTimeError
-string_replace_static_test: MissingCompileTimeError
-string_static_test: MissingCompileTimeError
-
[ $compiler == dart2js && $runtime == chromeOnAndroid ]
list_as_map_test: Pass, Slow # TODO(kasperl): Please triage.
string_trimlr_test/unicode63: RuntimeError # Uses Unicode 6.2.0 or earlier.
@@ -196,10 +209,6 @@
map_test: Crash # tests/corelib_2/map_test.dart:903:7: Internal problem: Unhandled Null in installDefaultConstructor.
symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
-[ $compiler == dart2js && $fast_startup ]
-apply3_test: RuntimeError
-dynamic_nosuchmethod_test: RuntimeError
-
[ $compiler == dart2js && $fast_startup && $fasta && $strong ]
cast_test: RuntimeError
error_stack_trace1_test: RuntimeError
@@ -279,15 +288,6 @@
[ $compiler == dart2js && !$fasta ]
*: SkipByDesign
-[ $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $compiler != fasta ]
-iterable_element_at_test/static: MissingCompileTimeError
-
-[ $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $compiler != fasta && ($compiler != dart2analyzer || !$strong) ]
-iterable_mapping_test/01: MissingCompileTimeError
-
-[ $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkp && $runtime != none ]
-map_keys2_test: RuntimeError # needs Dart 2 is checks
-
[ $compiler != dart2js && $fasta ]
bool_from_environment2_test/03: MissingCompileTimeError
string_from_environment3_test/03: MissingCompileTimeError
@@ -539,6 +539,10 @@
[ !$strong && ($runtime == dart_precompiled || $runtime == vm) ]
list_test/*: RuntimeError # VM doesn't implement strong mode covariance checks
+[ $arch == simarm || $arch == simarm64 || $arch == simdbc64 ]
+bigint_parse_radix_test: Pass, Slow # Bigint computations are slow on simulated architectures.
+bigint_test: Pass, Slow # Bigint computations are slow on simulated architectures.
+
[ $arch == simdbc || $arch == simdbc64 ]
regexp/stack-overflow_test: RuntimeError, OK # Smaller limit with irregex interpreter
diff --git a/tests/kernel/kernel.status b/tests/kernel/kernel.status
index 37322af..7d79601 100644
--- a/tests/kernel/kernel.status
+++ b/tests/kernel/kernel.status
@@ -11,6 +11,9 @@
[ !$fasta ]
unsorted/loop_test: Skip # This test uses optional new/const.
+[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkp && $runtime != none ]
+unsorted/types_test: RuntimeError
+
[ $compiler == dart2analyzer && $runtime == none ]
unsorted/super_mixin_test: CompileTimeError
@@ -27,9 +30,6 @@
[ $compiler == dart2js && !$fasta ]
unsorted/super_mixin_test: CompileTimeError
-[ $compiler != dartk && $compiler != dartkp && $runtime != none ]
-unsorted/types_test: RuntimeError
-
[ $compiler != dartk && $compiler != dartkp && !$strong ]
unsorted/invocation_errors_test/00: MissingCompileTimeError # This test has been tuned for dart 2.
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index e634a35..76720a4 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -559,31 +559,10 @@
generic_methods_type_expression_test/03: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 1728 pos 16: 'type is MethodTypeVariableType': is not true.
generic_methods_type_expression_test/none: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 1728 pos 16: 'type is MethodTypeVariableType': is not true.
invocation_mirror_test: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 3014 pos 14: 'arguments.named.isEmpty': is not true.
-operator2_negative_test: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
sync_generator2_test/41: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
sync_generator2_test/52: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
-syntax_test/04: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/05: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/06: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/07: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/08: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/09: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/10: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/11: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/13: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/14: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/15: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/16: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/17: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/18: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/19: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/20: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
syntax_test/21: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
syntax_test/22: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/23: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/24: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/25: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-syntax_test/26: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
[ $compiler == dart2js && $fasta && $minified ]
deferred_load_library_wrong_args_test/01: Crash # NoSuchMethodError: The getter 'closureClassEntity' was called on null.
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
index c9903f0..7b7cd78 100644
--- a/tests/language/language_kernel.status
+++ b/tests/language/language_kernel.status
@@ -195,5 +195,5 @@
# We skip all the Dart 1.0 tests in dartk and dartkp mode as these
# modes are intended only for Dart 2.0 with strong mode enabled.
-[ $compiler == dartk || $compiler == dartkp ]
-*: Skip
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkp ]
+*: SkipByDesign
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 23cf368..ba20d61 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -46,6 +46,9 @@
initializer_super_last_test/cc31: MissingCompileTimeError
initializer_super_last_test/cc32: MissingCompileTimeError
+[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkp && $mode == debug && $runtime == vm ]
+built_in_identifier_type_annotation_test/set: Crash # Not supported by legacy VM front-end.
+
[ $compiler != dart2js && $compiler != dartdevc && !$fasta && $strong ]
type_promotion_functions_test: CompileTimeError # Issue 30895: This test requires a complete rewrite for 2.0.
@@ -117,9 +120,6 @@
[ $compiler != dartdevc && !$checked ]
function_type/*: Skip # Needs checked mode.
-[ $compiler != dartk && $compiler != dartkp && $mode == debug && $runtime == vm ]
-built_in_identifier_type_annotation_test/set: Crash # Not supported by legacy VM front-end.
-
[ $compiler == none && $runtime == drt && !$checked ]
assertion_initializer_const_error_test/01: Fail
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 74be6be..fdfc105 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -399,7 +399,6 @@
generic_methods_bounds_test/01: MissingCompileTimeError
generic_methods_dynamic_test/01: MissingCompileTimeError
generic_methods_dynamic_test/03: MissingCompileTimeError
-generic_methods_overriding_test/01: MissingCompileTimeError
generic_methods_overriding_test/03: MissingCompileTimeError
generic_methods_overriding_test/06: StaticWarning
generic_methods_recursive_bound_test/02: MissingCompileTimeError
@@ -1107,8 +1106,6 @@
field3a_negative_test: StaticWarning # Issue 28823
forwarding_stub_tearoff_test: CompileTimeError
generic_methods_generic_function_result_test/none: CompileTimeError # Issue #30207
-generic_methods_overriding_test/01: MissingCompileTimeError # Issue 29070
-generic_methods_overriding_test/03: MissingCompileTimeError # Issue 29070
generic_no_such_method_dispatcher_test: CompileTimeError
generic_tearoff_test: CompileTimeError
import_core_prefix_test: CompileTimeError # "dynamic" should be defined in core.
@@ -1353,6 +1350,7 @@
generic_field_mixin6_test/01: MissingCompileTimeError
generic_function_typedef2_test/04: MissingCompileTimeError
generic_methods_generic_function_result_test/01: MissingCompileTimeError # Issue #30207
+generic_methods_overriding_test/01: MissingCompileTimeError
generic_test/01: MissingCompileTimeError
identical_const_test/01: MissingCompileTimeError
identical_const_test/02: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 953e7a2..830d006 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -486,7 +486,6 @@
stacktrace_rethrow_error_test/withtraceparameter: RuntimeError # Issue 12698
stacktrace_rethrow_nonerror_test: RuntimeError # Issue 12698
stacktrace_test: RuntimeError # Issue 12698
-super_call4_test: Crash # NoSuchMethodError: The getter 'thisLocal' was called on null.
switch_bad_case_test/01: MissingCompileTimeError
switch_bad_case_test/02: MissingCompileTimeError
switch_case_test/00: MissingCompileTimeError
@@ -808,7 +807,6 @@
string_split_test: CompileTimeError
string_supertype_checked_test: CompileTimeError
super_bound_closure_test/none: CompileTimeError
-super_call4_test: Crash # NoSuchMethodError: The getter 'thisLocal' was called on null.
super_no_such_method1_test: CompileTimeError
super_no_such_method2_test: CompileTimeError
super_no_such_method3_test: CompileTimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 2bfb404..11456f2 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -63,7 +63,6 @@
generic_local_functions_test: CompileTimeError
generic_methods_generic_function_parameter_test: CompileTimeError
generic_methods_generic_function_result_test/none: CompileTimeError # Issue #30208
-generic_methods_overriding_test/03: MissingCompileTimeError # Issue 29920
generic_no_such_method_dispatcher_simple_test: Skip # This test is just for kernel.
generic_no_such_method_dispatcher_test: CompileTimeError
getter_closure_execution_order_test: RuntimeError # Issue 29920
@@ -391,6 +390,7 @@
function_type_parameter_negative_test: Fail
generic_function_bounds_test: RuntimeError
generic_methods_generic_function_result_test/01: MissingCompileTimeError
+generic_methods_overriding_test/01: MissingCompileTimeError # Issue 29920
generic_methods_recursive_bound_test/02: MissingCompileTimeError
generic_no_such_method_dispatcher_simple_test: CompileTimeError # Warning: Superclass has no method named 'foo'.
generic_no_such_method_dispatcher_test: CompileTimeError # Issue 31533
@@ -685,7 +685,6 @@
generic_function_type_as_type_argument_test/02: MissingCompileTimeError # Issue 29920
generic_instanceof2_test: RuntimeError # Issue 29920; ReferenceError: FooOfK$String is not defined
generic_is_check_test: RuntimeError # Issue 29920; Expect.isTrue(false) fails.
-generic_methods_overriding_test/01: MissingCompileTimeError # Issue 29920
generic_tearoff_test: CompileTimeError
identical_closure2_test: RuntimeError # Issue 29920; Expect.isFalse(true) fails.
infinite_switch_label_test: RuntimeError # Issue 29920; NoSuchMethodError: method not found: '<Unexpected Null Value>'
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 4a738cc..e923ac4 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -10,6 +10,175 @@
# missing a section you need, please reach out to sigmund@ to see the best way
# to add them.
+[ $compiler == app_jitk ]
+assertion_initializer_const_error2_test/cc01: MissingCompileTimeError
+assertion_initializer_const_error2_test/cc02: MissingCompileTimeError
+assertion_initializer_const_error2_test/cc03: MissingCompileTimeError
+assertion_initializer_const_error2_test/cc04: MissingCompileTimeError
+assertion_initializer_const_error2_test/cc05: MissingCompileTimeError
+assertion_initializer_const_error2_test/cc06: MissingCompileTimeError
+assertion_initializer_const_error2_test/cc07: MissingCompileTimeError
+assertion_initializer_const_error2_test/cc08: MissingCompileTimeError
+assertion_initializer_const_error2_test/cc09: MissingCompileTimeError
+assertion_initializer_const_error2_test/cc10: MissingCompileTimeError
+async_star_cancel_while_paused_test: RuntimeError
+async_star_pause_test: RuntimeError
+async_star_test/02: RuntimeError
+call_method_implicit_tear_off_implements_function_test/05: RuntimeError
+call_method_implicit_tear_off_implements_function_test/06: RuntimeError
+call_method_must_not_be_field_test/03: RuntimeError
+call_method_must_not_be_getter_test/03: RuntimeError
+compile_time_constant_static5_test/11: CompileTimeError
+compile_time_constant_static5_test/16: CompileTimeError
+compile_time_constant_static5_test/21: CompileTimeError
+compile_time_constant_static5_test/23: CompileTimeError
+conditional_import_string_test: CompileTimeError
+conditional_import_test: CompileTimeError
+conditional_rewrite_test: RuntimeError
+config_import_corelib_test: CompileTimeError
+config_import_test: RuntimeError
+const_list_test: RuntimeError
+const_locals_test: RuntimeError
+const_map4_test: RuntimeError
+const_nested_test: RuntimeError
+const_string_test: RuntimeError
+constructor12_test: RuntimeError
+covariant_subtyping_test: RuntimeError
+ct_const_test: RuntimeError
+cyclic_type2_test: CompileTimeError
+cyclic_type_test/02: CompileTimeError
+cyclic_type_test/04: CompileTimeError
+cyclic_typedef_test/10: DartkCrash
+cyclic_typedef_test/11: DartkCrash
+deferred_call_empty_before_load_test: RuntimeError
+deferred_load_constants_test/none: RuntimeError
+deferred_not_loaded_check_test: RuntimeError
+deferred_redirecting_factory_test: RuntimeError
+deferred_static_seperate_test: RuntimeError
+dynamic_prefix_core_test/none: CompileTimeError
+emit_const_fields_test: CompileTimeError
+example_constructor_test: RuntimeError
+export_ambiguous_main_test: Crash
+external_test/10: MissingRuntimeError
+external_test/13: MissingRuntimeError
+external_test/20: MissingRuntimeError
+field_initialization_order_test/01: MissingCompileTimeError
+field_initialization_order_test/none: RuntimeError
+flatten_test/05: MissingRuntimeError
+flatten_test/08: MissingRuntimeError
+flatten_test/09: MissingRuntimeError
+flatten_test/12: MissingRuntimeError
+function_propagation_test: RuntimeError
+function_subtype_inline2_test: RuntimeError
+generic_function_bounds_test: RuntimeError
+generic_function_dcall_test: RuntimeError
+generic_instanceof2_test: RuntimeError
+generic_is_check_test: RuntimeError
+generic_no_such_method_dispatcher_simple_test: CompileTimeError
+generic_no_such_method_dispatcher_test: CompileTimeError
+generic_tearoff_test: CompileTimeError
+generic_test/01: MissingCompileTimeError
+instantiate_tearoff_of_call_test: CompileTimeError
+issue31596_super_test/01: CompileTimeError
+issue31596_super_test/03: CompileTimeError
+issue31596_super_test/05: RuntimeError
+least_upper_bound_expansive_test/none: CompileTimeError
+library_env_test/has_html_support: RuntimeError
+library_env_test/has_no_io_support: RuntimeError
+library_env_test/has_no_mirror_support: RuntimeError
+local_function2_test/none: RuntimeError
+local_function3_test/none: RuntimeError
+local_function_test/none: RuntimeError
+main_test/03: RuntimeError
+method_override_test: CompileTimeError
+mixin_illegal_super_use_test/01: MissingCompileTimeError
+mixin_illegal_super_use_test/04: MissingCompileTimeError
+mixin_illegal_super_use_test/07: MissingCompileTimeError
+mixin_illegal_super_use_test/10: MissingCompileTimeError
+mixin_illegal_super_use_test/11: MissingCompileTimeError
+mixin_illegal_superclass_test/01: MissingCompileTimeError
+mixin_illegal_superclass_test/02: MissingCompileTimeError
+mixin_illegal_superclass_test/03: MissingCompileTimeError
+mixin_illegal_superclass_test/04: MissingCompileTimeError
+mixin_illegal_superclass_test/05: MissingCompileTimeError
+mixin_illegal_superclass_test/06: MissingCompileTimeError
+mixin_illegal_superclass_test/07: MissingCompileTimeError
+mixin_illegal_superclass_test/08: MissingCompileTimeError
+mixin_illegal_superclass_test/09: MissingCompileTimeError
+mixin_illegal_superclass_test/10: MissingCompileTimeError
+mixin_illegal_superclass_test/11: MissingCompileTimeError
+mixin_illegal_superclass_test/12: MissingCompileTimeError
+mixin_illegal_superclass_test/13: MissingCompileTimeError
+mixin_illegal_superclass_test/14: MissingCompileTimeError
+mixin_illegal_superclass_test/15: MissingCompileTimeError
+mixin_illegal_superclass_test/16: MissingCompileTimeError
+mixin_illegal_superclass_test/17: MissingCompileTimeError
+mixin_illegal_superclass_test/18: MissingCompileTimeError
+mixin_illegal_superclass_test/19: MissingCompileTimeError
+mixin_illegal_superclass_test/20: MissingCompileTimeError
+mixin_illegal_superclass_test/21: MissingCompileTimeError
+mixin_illegal_superclass_test/22: MissingCompileTimeError
+mixin_illegal_superclass_test/23: MissingCompileTimeError
+mixin_illegal_superclass_test/24: MissingCompileTimeError
+mixin_illegal_superclass_test/25: MissingCompileTimeError
+mixin_illegal_superclass_test/26: MissingCompileTimeError
+mixin_illegal_superclass_test/27: MissingCompileTimeError
+mixin_illegal_superclass_test/28: MissingCompileTimeError
+mixin_illegal_superclass_test/29: MissingCompileTimeError
+mixin_illegal_superclass_test/30: MissingCompileTimeError
+mock_writable_final_private_field_test: RuntimeError
+named_parameters_default_eq_test/none: RuntimeError
+nested_generic_closure_test: RuntimeError
+no_main_test/01: Crash
+no_such_method_mock_test: RuntimeError
+null_no_such_method_test: CompileTimeError
+override_inheritance_field_test/04: CompileTimeError
+override_inheritance_field_test/06: CompileTimeError
+override_inheritance_field_test/26: CompileTimeError
+override_inheritance_field_test/29: CompileTimeError
+override_inheritance_generic_test/02: CompileTimeError
+override_inheritance_method_test/28: CompileTimeError
+override_inheritance_method_test/29: CompileTimeError
+parser_quirks_test: CompileTimeError
+regress_22443_test: RuntimeError
+regress_23089_test: DartkCrash
+regress_23408_test: CompileTimeError
+regress_29025_test: CompileTimeError
+regress_29405_test: CompileTimeError
+regress_30339_test: CompileTimeError
+string_interpolate_test: CompileTimeError
+string_interpolation_and_buffer_test: RuntimeError
+string_split_test: CompileTimeError
+string_supertype_checked_test: CompileTimeError
+super_bound_closure_test/none: CompileTimeError
+super_no_such_method1_test: CompileTimeError
+super_no_such_method2_test: CompileTimeError
+super_no_such_method3_test: CompileTimeError
+super_no_such_method4_test: CompileTimeError
+super_no_such_method5_test: CompileTimeError
+super_operator_index5_test: CompileTimeError
+super_operator_index6_test: CompileTimeError
+super_operator_index7_test: CompileTimeError
+super_operator_index8_test: CompileTimeError
+super_test: RuntimeError
+type_alias_equality_test/02: RuntimeError
+type_alias_equality_test/03: RuntimeError
+type_alias_equality_test/04: RuntimeError
+type_error_test: RuntimeError
+type_literal_test: RuntimeError
+type_promotion_functions_test/02: CompileTimeError
+type_promotion_functions_test/03: CompileTimeError
+type_promotion_functions_test/04: CompileTimeError
+type_promotion_functions_test/09: CompileTimeError
+type_promotion_functions_test/11: CompileTimeError
+type_promotion_functions_test/12: CompileTimeError
+type_promotion_functions_test/13: CompileTimeError
+type_promotion_functions_test/14: CompileTimeError
+type_promotion_functions_test/none: CompileTimeError
+type_promotion_more_specific_test/04: CompileTimeError
+vm/optimized_guarded_field_isolates_test: RuntimeError
+vm/type_cast_vm_test: RuntimeError
+
[ $compiler == dartkp ]
class_cycle_test/02: MissingCompileTimeError
class_cycle_test/03: MissingCompileTimeError
@@ -437,7 +606,15 @@
[ $arch != simarm && $arch != simarm64 && $arch != simdbc64 && $compiler == dartk && $runtime == vm && $strong ]
export_ambiguous_main_test: Crash # Issue 32618
-[ $compiler != dart2js && $compiler != dartk && $compiler != dartkp && $fasta ]
+[ $compiler == app_jitk && $mode == product ]
+type_variable_promotion_test: RuntimeError
+vm/causal_async_exception_stack2_test: RuntimeError
+vm/causal_async_exception_stack_test: RuntimeError
+
+[ $compiler == app_jitk && ($mode == debug || $mode == release) ]
+assertion_test: RuntimeError
+
+[ $compiler != app_jitk && $compiler != dart2js && $compiler != dartk && $compiler != dartkp && $fasta ]
const_optional_args_test/01: MissingCompileTimeError
# The precomilation configuration uses a kernel2kernel constants evaluator
@@ -454,10 +631,6 @@
mixin_supertype_subclass_test/02: MissingCompileTimeError
mixin_supertype_subclass_test/05: MissingCompileTimeError
-[ $compiler == dartk && $mode == debug && $runtime == vm && $strong ]
-const_instance_field_test/01: Crash # Issue 32326.
-deopt_inlined_function_lazy_test: Skip
-
[ $compiler == dartk && $mode == product && $runtime == vm ]
deferred_load_constants_test/02: Fail
deferred_load_constants_test/03: Fail
@@ -1305,6 +1478,10 @@
setter_override2_test/02: MissingCompileTimeError
variable_shadow_class_test/01: MissingCompileTimeError
+[ $mode == debug && $runtime == vm && $strong && ($compiler == app_jitk || $compiler == dartk) ]
+const_instance_field_test/01: Crash # Issue 32326.
+deopt_inlined_function_lazy_test: Skip
+
[ $fasta && $strong ]
compile_time_constant_static2_test/04: MissingCompileTimeError
compile_time_constant_static3_test/04: MissingCompileTimeError
diff --git a/tests/language_2/partial_tearoff_instantiation_test.dart b/tests/language_2/partial_tearoff_instantiation_test.dart
index 72bd744..b534a96 100644
--- a/tests/language_2/partial_tearoff_instantiation_test.dart
+++ b/tests/language_2/partial_tearoff_instantiation_test.dart
@@ -112,5 +112,10 @@
// Not OK with a type argument.
y.f<String>("hello6"); //# 08: compile-time error
+
+ // Correct runtime type of x.f.
+ void instantiatedFType(dynamic _) {}
+ Expect.equals(x.f.runtimeType.toString(),
+ instantiatedFType.runtimeType.toString()); // #09: ok
}
}
diff --git a/tests/language_2/vm/regress_b80154489_test.dart b/tests/language_2/vm/regress_b80154489_test.dart
new file mode 100644
index 0000000..a93b384
--- /dev/null
+++ b/tests/language_2/vm/regress_b80154489_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that class finalizer correctly marks supertypes of superinterfaces
+// as implemented.
+
+import 'package:expect/expect.dart';
+
+abstract class A {
+ String method();
+}
+
+abstract class B extends A {}
+
+class D extends A {
+ String method() => "D";
+}
+
+class C implements B {
+ String method() => "C";
+}
+
+String invoke(A a) {
+ return a.method();
+}
+
+void main(List<String> args) {
+ Expect.equals("C", invoke(args.contains('--use-d') ? new D() : new C()));
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index a376ae2..d316685 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -374,7 +374,7 @@
# All these tests have been migrated as strong mode compatible tests to
# lib_2, so skipping these tests for dartk and dartkp
-[ $compiler == dartk || $compiler == dartkp ]
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkp ]
*: SkipByDesign
[ $runtime == chrome || $runtime == ff ]
diff --git a/tests/lib_2/convert/json_test.dart b/tests/lib_2/convert/json_test.dart
index d7be8a0..22e5f24 100644
--- a/tests/lib_2/convert/json_test.dart
+++ b/tests/lib_2/convert/json_test.dart
@@ -104,10 +104,16 @@
}
void testThrows(jsonText) {
+ var message = "json = '${escape(jsonText)}'";
Expect.throwsFormatException(() => json.decode(jsonText),
- "json = '${escape(jsonText)}'");
+ "json.decode, $message");
Expect.throwsFormatException(() => jsonDecode(jsonText),
- "json = '${escape(jsonText)}'");
+ "jsonDecode, $message");
+ Expect.throwsFormatException(() => json.decoder.convert(jsonText),
+ "json.decoder.convert, $message");
+ Expect.throwsFormatException(() =>
+ utf8.decoder.fuse(json.decoder).convert(utf8.encode(jsonText)),
+ "utf8.decoder.fuse(json.decoder) o utf.encode, $message");
}
testNumbers() {
@@ -187,6 +193,10 @@
testThrows("-2.2 e+2");
testThrows("-2.2e +2");
testThrows("-2.2e+ 2");
+ testThrows("01");
+ testThrows("0.");
+ testThrows(".0");
+ testThrows("0.e1");
testThrows("[2.,2]");
testThrows("{2.:2}");
diff --git a/tests/lib_2/convert/json_utf8_test.dart b/tests/lib_2/convert/json_utf8_test.dart
new file mode 100644
index 0000000..6afae4d
--- /dev/null
+++ b/tests/lib_2/convert/json_utf8_test.dart
@@ -0,0 +1,77 @@
+// 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.
+
+// Test that the fused UTF-8/JSON decoder accepts a leading BOM.
+library test;
+
+import "package:expect/expect.dart";
+import "dart:convert";
+
+void main() {
+ for (var parse in [parseFuse, parseSequence, parseChunked]) {
+ // Sanity checks.
+ Expect.isTrue(parse('true'.codeUnits.toList()));
+ Expect.isFalse(parse('false'.codeUnits.toList()));
+ Expect.equals(123, parse('123'.codeUnits.toList()));
+ Expect.listEquals([42], parse('[42]'.codeUnits.toList()));
+ Expect.mapEquals({"x": 42}, parse('{"x":42}'.codeUnits.toList()));
+
+ // String (0x22 = ") with UTF-8 encoded Unicode characters.
+ Expect.equals(
+ "A\xff\u1234\u{65555}",
+ parse([
+ 0x22,
+ 0x41,
+ 0xc3,
+ 0xbf,
+ 0xe1,
+ 0x88,
+ 0xb4,
+ 0xf1,
+ 0xa5,
+ 0x95,
+ 0x95,
+ 0x22
+ ]));
+
+ // BOM followed by true.
+ Expect.isTrue(parse([0xEF, 0xBB, 0xBF, 0x74, 0x72, 0x75, 0x65]));
+ }
+
+ // Do not accept BOM in non-UTF-8 decoder.
+ Expect.throws<FormatException>(
+ () => new JsonDecoder().convert("\xEF\xBB\xBFtrue"));
+ Expect.throws<FormatException>(() => new JsonDecoder().convert("\uFEFFtrue"));
+
+ // Only accept BOM first.
+ Expect.throws<FormatException>(
+ () => parseFuse(" \xEF\xBB\xBFtrue".codeUnits.toList()));
+ // Only accept BOM first.
+ Expect.throws<FormatException>(
+ () => parseFuse(" true\xEF\xBB\xBF".codeUnits.toList()));
+
+ Expect.throws<FormatException>(
+ () => parseFuse(" [\xEF\xBB\xBF]".codeUnits.toList()));
+}
+
+Object parseFuse(List<int> text) {
+ return new Utf8Decoder().fuse(new JsonDecoder()).convert(text);
+}
+
+Object parseSequence(List<int> text) {
+ return new JsonDecoder().convert(new Utf8Decoder().convert(text));
+}
+
+Object parseChunked(List<int> text) {
+ var result;
+ var sink = new Utf8Decoder().fuse(new JsonDecoder()).startChunkedConversion(
+ new ChunkedConversionSink.withCallback((List<Object> values) {
+ result = values[0];
+ }));
+ for (var i = 0; i < text.length; i++) {
+ sink.add([text[i]]);
+ }
+ sink.close();
+ return result;
+}
diff --git a/tests/lib_2/html/interactive_media_test.dart b/tests/lib_2/html/interactive_media_test.dart
index d7060ac..4fbc597 100644
--- a/tests/lib_2/html/interactive_media_test.dart
+++ b/tests/lib_2/html/interactive_media_test.dart
@@ -32,72 +32,68 @@
}
} catch (e) {
// Could fail if bot machine doesn't support audio or video.
- expect(e.name, DomException.NOT_FOUND);
+ expect(e.name == DomException.NOT_FOUND, true);
}
});
test('getUserMedia', () {
- try {
- return window.navigator.getUserMedia(video: true).then((stream) {
- expect(stream, isNotNull);
+ return window.navigator.getUserMedia(video: true).then((stream) {
+ expect(stream, isNotNull);
- var url = Url.createObjectUrlFromStream(stream);
- expect(url, isNotNull);
+ var url = Url.createObjectUrlFromStream(stream);
+ expect(url, isNotNull);
- var video = new VideoElement()..autoplay = true;
+ var video = new VideoElement()..autoplay = true;
- var completer = new Completer();
- video.onError.listen((e) {
- completer.completeError(e);
- });
- video.onPlaying.first.then((e) {
- completer.complete(video);
- });
-
- document.body.append(video);
- video.src = url;
-
- return completer.future;
+ var completer = new Completer();
+ video.onError.listen((e) {
+ completer.completeError(e);
});
- } catch (e) {
+ video.onPlaying.first.then((e) {
+ completer.complete(video);
+ });
+
+ document.body.append(video);
+ video.src = url;
+
+ return completer.future;
+ }).catchError((e) {
// Could fail if bot machine doesn't support audio or video.
- expect(e.name, DomException.NOT_FOUND);
- }
+ expect(e.name == DomException.NOT_FOUND, true);
+ });
});
test('getUserMediaComplexConstructor', () {
- try {
- return window.navigator.getUserMedia(video: {
- 'mandatory': {'minAspectRatio': 1.333, 'maxAspectRatio': 1.334},
- 'optional': [
- {'minFrameRate': 60},
- {'maxWidth': 640}
- ]
- }).then((stream) {
- expect(stream, isNotNull);
+ return window.navigator.getUserMedia(video: {
+ 'mandatory': {'minAspectRatio': 1.333, 'maxAspectRatio': 1.334},
+ 'optional': [
+ {'minFrameRate': 60},
+ {'maxWidth': 640}
+ ]
+ }).then((stream) {
+ expect(stream, isNotNull);
- var url = Url.createObjectUrlFromStream(stream);
- expect(url, isNotNull);
+ var url = Url.createObjectUrlFromStream(stream);
+ expect(url, isNotNull);
- var video = new VideoElement()..autoplay = true;
+ var video = new VideoElement()..autoplay = true;
- var completer = new Completer();
- video.onError.listen((e) {
- completer.completeError(e);
- });
- video.onPlaying.first.then((e) {
- completer.complete(video);
- });
-
- document.body.append(video);
- video.src = url;
-
- return completer.future;
+ var completer = new Completer();
+ video.onError.listen((e) {
+ completer.completeError(e);
});
- } catch (e) {
+ video.onPlaying.first.then((e) {
+ completer.complete(video);
+ });
+
+ document.body.append(video);
+ video.src = url;
+
+ return completer.future;
+ }).catchError((e) {
// Could fail if bot machine doesn't support audio or video.
- expect(e.name, DomException.NOT_FOUND);
- }
+ expect(e.name == DomException.NOT_FOUND, true);
+ });
});
}
}
diff --git a/tests/lib_2/lib_2_app_jit.status b/tests/lib_2/lib_2_app_jit.status
index a2a86f3..d219200 100644
--- a/tests/lib_2/lib_2_app_jit.status
+++ b/tests/lib_2/lib_2_app_jit.status
@@ -2,5 +2,5 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-[ $compiler == app_jit ]
+[ $compiler == app_jit || $compiler == app_jitk ]
mirrors/*: Skip # Issue 27929: Triage
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index 72d9070..785d1a3 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -371,6 +371,7 @@
html/input_element_datetime_test: Fail
html/input_element_month_test: Fail
html/input_element_week_test: Fail
+html/interactive_media_test: RuntimeError # Not supported in FF
html/media_stream_test: Fail
html/messageevent_test: Pass, RuntimeError # Issue 28983
html/request_animation_frame_test: Skip # Async test hangs.
@@ -468,9 +469,6 @@
[ $compiler == dart2js && $system == linux ]
html/interactive_geolocation_test: Skip # Requires allowing geo location.
-[ $compiler == dart2js && $system != macos && ($runtime != chrome || $runtime != safari) ]
-html/interactive_media_test: RuntimeError # # See NOTE in test on how to run.
-
[ $compiler == dart2js && $system == windows ]
html/xhr_test: RuntimeError
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index e2910bb..d1abdeb 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -26,7 +26,6 @@
[ $system == linux && ($compiler == dartdevc || $compiler == dartdevk) ]
html/interactive_geolocation_test: Skip # Requires allowing geo location.
-html/interactive_media_test: RuntimeError # # See NOTE in test on how to run.
[ $system == macos && ($compiler == dartdevc || $compiler == dartdevk) ]
html/client_rect_test: Pass, RuntimeError # Issue 31019
@@ -85,7 +84,6 @@
html/element_classes_svg_test: RuntimeError # Issue 29922
html/element_classes_test: RuntimeError # Issue 29922
html/fontface_loaded_test: RuntimeError
-html/interactive_media_test: RuntimeError # See NOTE in test on how to run and interactive permissions (camera, geolocation)
html/isolates_test: RuntimeError # Issue 29922
html/js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue 29922
html/js_typed_interop_side_cast_exp_test/01: RuntimeError # Requires --experimental-trust-js-interop-type-annotations flag.
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index 14b7bf9..da72614 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -10,6 +10,24 @@
# missing a section you need, please reach out to sigmund@ to see the best way
# to add them.
+[ $compiler == app_jitk ]
+async/async_await_sync_completer_test: RuntimeError
+async/future_test/01: RuntimeError
+async/future_test/none: RuntimeError
+async/slow_consumer2_test: RuntimeError
+async/stream_controller_async_test: RuntimeError
+async/stream_distinct_test: RuntimeError
+async/stream_join_test: RuntimeError
+async/stream_subscription_as_future_test: RuntimeError
+async/timer_not_available_test: RuntimeError
+isolate/issue_21398_parent_isolate1_test: RuntimeError
+isolate/issue_22778_test: Crash
+isolate/kill_self_synchronously_test: RuntimeError
+isolate/message_test: RuntimeError
+isolate/mint_maker_test: RuntimeError
+isolate/ping_pause_test: Skip # Timeout
+isolate/static_function_test: RuntimeError
+
[ $compiler == fasta ]
html/*: Skip # TODO(ahe): Make dart:html available.
isolate/browser/*: Skip # TODO(ahe): Make dart:html available.
@@ -45,6 +63,10 @@
mirrors/invocation_fuzz_test/smi: Crash, RuntimeError, Fail, Pass # Crashes on opt counter builder (#31838)
mirrors/invocation_fuzz_test/string: Pass, Crash, RuntimeError # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
+[ $compiler == app_jitk && $mode == product ]
+isolate/spawn_function_custom_class_test: Skip # Timeout
+isolate/spawn_uri_nested_vm_test: Skip # Timeout
+
[ $compiler != dart2js && $fasta && !$strong ]
isolate/browser/compute_this_script_browser_test: CompileTimeError
isolate/browser/package_resolve_browser_hook2_test: CompileTimeError
@@ -111,12 +133,9 @@
mirrors/generic_f_bounded_mixin_application_test: RuntimeError
mirrors/generic_function_typedef_test: RuntimeError
mirrors/generic_interface_test/01: RuntimeError
-mirrors/generic_interface_test/none: RuntimeError
mirrors/generic_mixin_applications_test: RuntimeError
-mirrors/generic_mixin_test: RuntimeError
mirrors/hot_get_field_test: RuntimeError
mirrors/hot_set_field_test: RuntimeError
-mirrors/intercepted_object_test: RuntimeError # Issue 31402 (Invocation arguments)
mirrors/invocation_fuzz_test: RuntimeError, Crash
mirrors/invoke_private_test: RuntimeError
mirrors/invoke_private_wrong_library_test: RuntimeError
@@ -149,8 +168,6 @@
mirrors/mirrors_used_typedef_declaration_test/none: RuntimeError
mirrors/mixin_application_test: RuntimeError # Issue 31402 (Invocation arguments)
mirrors/mixin_members_test: CompileTimeError # Issue 31402 (Invocation arguments)
-mirrors/mixin_simple_test: RuntimeError
-mirrors/mixin_test: RuntimeError
mirrors/native_class_test: SkipByDesign # Imports dart:html
mirrors/operator_test: CompileTimeError # Issue 31402 (Invocation arguments)
mirrors/other_declarations_location_test: RuntimeError
@@ -322,7 +339,7 @@
typed_data/int32x4_static_test/01: MissingCompileTimeError
typed_data/int32x4_static_test/02: MissingCompileTimeError
-[ $compiler == dartk || $compiler == dartkp ]
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkp ]
html/*: SkipByDesign
isolate/browser/*: SkipByDesign
js/*: SkipByDesign
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index cd5c32c..16463be 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -14,7 +14,7 @@
[ $arch == simarm64 && $runtime == vm ]
convert/utf85_test: Skip # Pass, Slow Issue 20111.
-[ $compiler != dartk && $runtime == vm ]
+[ $compiler != app_jitk && $compiler != dartk && $runtime == vm ]
convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
html/*: SkipByDesign # dart:html not supported on VM.
js/datetime_roundtrip_test: CompileTimeError
@@ -32,10 +32,10 @@
mirrors/native_class_test: SkipByDesign # Imports dart:html
mirrors/redirecting_factory_different_type_test/01: MissingCompileTimeError
-[ $compiler != dartk && $runtime == vm && !$checked ]
+[ $compiler != app_jitk && $compiler != dartk && $runtime == vm && !$checked ]
mirrors/inference_and_no_such_method_test: RuntimeError
-[ $compiler != dartk && $runtime == vm && $strong ]
+[ $compiler != app_jitk && $compiler != dartk && $runtime == vm && $strong ]
async/future_or_only_in_async_test/00: MissingCompileTimeError
[ $compiler != dartk && $runtime == vm && !$strong ]
diff --git a/tests/standalone/io/file_invalid_arguments_test.dart b/tests/standalone/io/file_invalid_arguments_test.dart
deleted file mode 100644
index 94e3a22..0000000
--- a/tests/standalone/io/file_invalid_arguments_test.dart
+++ /dev/null
@@ -1,112 +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.
-
-// OtherResources=fixed_length_file_invalid_arguments
-
-import "dart:async";
-import "dart:io";
-
-import "package:async_helper/async_helper.dart";
-import "package:expect/expect.dart";
-
-void testReadInvalidArgs(arg) {
- String filename = getFilename("fixed_length_file_invalid_arguments");
- var file = (new File(filename)).openSync();
- Expect.throws(() => file.readSync(arg), (e) => e is ArgumentError);
-
- Expect.throws(() => file.read(arg), (e) => e is ArgumentError);
- file.closeSync();
-}
-
-void testReadIntoInvalidArgs(buffer, start, end) {
- String filename = getFilename("fixed_length_file_invalid_arguments");
- var file = (new File(filename)).openSync();
- Expect.throws(
- () => file.readIntoSync(buffer, start, end), (e) => e is ArgumentError);
-
- Expect.throws(
- () => file.readInto(buffer, start, end), (e) => e is ArgumentError);
- file.closeSync();
-}
-
-void testWriteByteInvalidArgs(value) {
- String filename = getFilename("fixed_length_file_invalid_arguments");
- var file = (new File("${filename}_out")).openSync(mode: FileMode.write);
- Expect.throws(() => file.writeByteSync(value), (e) => e is ArgumentError);
-
- Expect.throws(() => file.writeByte(value), (e) => e is ArgumentError);
- file.closeSync();
-}
-
-void testWriteFromInvalidArgs(buffer, start, end) {
- String filename = getFilename("fixed_length_file_invalid_arguments");
- var file = (new File("${filename}_out")).openSync(mode: FileMode.write);
- Expect.throws(
- () => file.writeFromSync(buffer, start, end), (e) => e is ArgumentError);
-
- Expect.throws(
- () => file.writeFrom(buffer, start, end), (e) => e is ArgumentError);
- file.closeSync();
-}
-
-void testWriteStringInvalidArgs(string, encoding) {
- String filename = getFilename("fixed_length_file_invalid_arguments");
- var file = new File("${filename}_out").openSync(mode: FileMode.write);
- Expect.throws(() => file.writeStringSync(string, encoding: encoding),
- (e) => e is ArgumentError);
-
- Expect.throws(() => file.writeString(string, encoding: encoding),
- (e) => e is ArgumentError);
- file.closeSync();
-}
-
-Future futureThrows(Future result) {
- return result.then((value) {
- throw new ExpectException(
- "futureThrows received $value instead of an exception");
- }, onError: (_) => null);
-}
-
-void testFileSystemEntity() {
- Expect.throws(() => ((x) => FileSystemEntity.typeSync(x))([1, 2, 3]));
- Expect.throws(() => ((x, y) =>
- FileSystemEntity.typeSync(x, followLinks: y))(".", "why not?"));
- Expect.throws(
- () => ((x, y) => FileSystemEntity.identicalSync(x, y))([1, 2, 3], "."));
- Expect
- .throws(() => ((x, y) => FileSystemEntity.identicalSync(x, y))(".", 52));
- Expect.throws(() => ((x) => FileSystemEntity.isLinkSync(x))(52));
- Expect.throws(() => ((x) => FileSystemEntity.isFileSync(x))(52));
- Expect.throws(() => ((x) => FileSystemEntity.isDirectorySync(x))(52));
-
- asyncStart();
- futureThrows(((x) => FileSystemEntity.type(x))([1, 2, 3]))
- .then((_) => futureThrows(((x, y) =>
- FileSystemEntity.type(x, followLinks: y))(".", "why not?")))
- .then((_) => futureThrows(
- ((x, y) => FileSystemEntity.identical(x, y))([1, 2, 3], ".")))
- .then((_) =>
- futureThrows(((x, y) => FileSystemEntity.identical(x, y))(".", 52)))
- .then((_) => futureThrows(((x) => FileSystemEntity.isLink(x))(52)))
- .then((_) => futureThrows(((x) => FileSystemEntity.isFile(x))(52)))
- .then((_) => futureThrows(((x) => FileSystemEntity.isDirectory(x))(52)))
- .then((_) => asyncEnd());
-}
-
-String getFilename(String path) {
- return Platform.script.resolve(path).toFilePath();
-}
-
-main() {
- testReadInvalidArgs('asdf');
- testReadIntoInvalidArgs(12, 0, 1);
- testReadIntoInvalidArgs(new List(10), '0', 1);
- testReadIntoInvalidArgs(new List(10), 0, '1');
- testWriteByteInvalidArgs('asdf');
- testWriteFromInvalidArgs(12, 0, 1);
- testWriteFromInvalidArgs(new List(10), '0', 1);
- testWriteFromInvalidArgs(new List(10), 0, '1');
- testWriteStringInvalidArgs("Hello, world", 42);
- testFileSystemEntity();
-}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 22bb3c2..beb2ac3 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -26,9 +26,6 @@
[ $builder_tag == swarming && $system == macos ]
io/*: Skip # Issue 30618
-[ $compiler == dartk && $strong ]
-*: SkipByDesign
-
[ $compiler == fasta && $strong ]
io/directory_invalid_arguments_test: CompileTimeError
io/io_override_test: CompileTimeError
@@ -63,25 +60,21 @@
io/directory_fuzz_test: Skip # These test have type errors on purpose and take very long to run in checked mode with no benefit. Skip.
io/directory_invalid_arguments_test: Fail, OK # These tests have type errors on purpose.
io/file_fuzz_test: Skip # These test have type errors on purpose and take very long to run in checked mode with no benefit. Skip.
-io/file_invalid_arguments_test: Fail, OK # These tests have type errors on purpose.
io/internet_address_invalid_arguments_test: Fail, OK # These tests have type errors on purpose.
io/process_invalid_arguments_test: Fail, OK # These tests have type errors on purpose.
io/socket_invalid_arguments_test: Fail, OK # These tests have type errors on purpose.
io/stdout_bad_argument_test: Fail, OK # These tests have type errors on purpose.
-[ !$strong && ($compiler == dartk || $compiler == dartkp) ]
-*: Skip
-
[ $compiler == app_jit || $compiler == precompiler ]
io/compile_all_test: Skip # Incompatible flag --compile_all
-[ $compiler == dart2js || $compiler == dartdevc ]
-*: SkipByDesign
-
# We skip all the Dart 1.0 tests in dartk and dartkp mode as these
# modes are intended only for Dart 2.0 with strong mode enabled.
-[ $compiler == dartk || $compiler == dartkp ]
-*: Skip
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkp ]
+*: SkipByDesign
+
+[ $compiler == dart2js || $compiler == dartdevc ]
+*: SkipByDesign
[ $compiler != none || $runtime != vm ]
script_snapshot_depfile_test: SkipByDesign # Only makes sense running from source.
diff --git a/tests/standalone_2/io/non_utf8_directory_test.dart b/tests/standalone_2/io/non_utf8_directory_test.dart
new file mode 100644
index 0000000..1ebe6b9
--- /dev/null
+++ b/tests/standalone_2/io/non_utf8_directory_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:test/test.dart';
+
+Future main() async {
+ var asyncDir;
+ var syncDir;
+
+ test('Non-UTF8 Directory Listing', () async {
+ Directory.current = await Directory.systemTemp.createTemp();
+ final rawPath = new Uint8List.fromList([182]);
+ asyncDir = new Directory.fromRawPath(rawPath);
+ if (Platform.isMacOS || Platform.isIOS) {
+ try {
+ await asyncDir.create();
+ } on FileSystemException catch (e) {
+ // Macos doesn't support non-UTF-8 paths.
+ return;
+ }
+ } else {
+ await asyncDir.create();
+ }
+ expect(await asyncDir.exists(), isTrue);
+
+ await for (final e in Directory.current.list()) {
+ // FIXME(bkonyi): reenable when rawPath is exposed.
+ /*
+ if (Platform.isWindows) {
+ // Windows replaces invalid characters with � when creating file system
+ // entities.
+ final raw = e.rawPath;
+ expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+ } else {
+ expect(e.rawPath.last, 182);
+ }
+ */
+ }
+ await asyncDir.delete(recursive: true);
+ });
+
+ test('Non-UTF8 Directory Sync Listing', () {
+ Directory.current = Directory.systemTemp.createTempSync();
+ final rawPath = new Uint8List.fromList([182]);
+ syncDir = new Directory.fromRawPath(rawPath);
+
+ if (Platform.isMacOS || Platform.isIOS) {
+ try {
+ syncDir.createSync();
+ } on FileSystemException catch (e) {
+ // Macos doesn't support non-UTF-8 paths.
+ return;
+ }
+ } else {
+ syncDir.createSync();
+ }
+ expect(syncDir.existsSync(), isTrue);
+
+ for (final e in Directory.current.listSync()) {
+ // FIXME(bkonyi): reenable when rawPath is exposed.
+ /*
+ if (Platform.isWindows) {
+ // Windows replaces invalid characters with � when creating file system
+ // entities.
+ final raw = e.rawPath;
+ expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+ } else {
+ expect(e.rawPath.last, 182);
+ }
+ */
+ }
+ syncDir.deleteSync(recursive: true);
+ });
+
+ tearDown(() {
+ if ((asyncDir != null) && asyncDir.existsSync()) {
+ asyncDir.deleteSync(recursive: true);
+ }
+ if ((syncDir != null) && syncDir.existsSync()) {
+ syncDir.deleteSync(recursive: true);
+ }
+ });
+}
diff --git a/tests/standalone_2/io/non_utf8_file_test.dart b/tests/standalone_2/io/non_utf8_file_test.dart
new file mode 100644
index 0000000..df35c06
--- /dev/null
+++ b/tests/standalone_2/io/non_utf8_file_test.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:test/test.dart';
+
+Future main() async {
+ var asyncFile;
+ var syncFile;
+
+ test('Non-UTF8 Filename', () async {
+ Directory.current = await Directory.systemTemp.createTemp();
+ final rawPath = new Uint8List.fromList([182]);
+ asyncFile = new File.fromRawPath(rawPath);
+ if (Platform.isMacOS || Platform.isIOS) {
+ try {
+ await asyncFile.create();
+ } on FileSystemException catch (e) {
+ // Macos doesn't support non-UTF-8 paths.
+ return;
+ }
+ } else {
+ await asyncFile.create();
+ }
+ expect(await asyncFile.exists(), isTrue);
+
+ for (final file in Directory.current.listSync()) {
+ // FIXME(bkonyi): reenable when rawPath is exposed.
+ /*
+ if (Platform.isWindows) {
+ // Windows replaces invalid characters with � when creating file system
+ // entities.
+ final raw = file.rawPath;
+ expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+ } else {
+ expect(file.rawPath.last, 182);
+ }
+ */
+ // FIXME(bkonyi): this isn't true on some versions of MacOS. Why?
+ if (!Platform.isMacOS && !Platform.isIOS) {
+ expect(file.path.endsWith('�'), isTrue);
+ }
+ }
+ await asyncFile.delete();
+ });
+
+ test('Non-UTF8 Filename Sync', () {
+ Directory.current = Directory.systemTemp.createTempSync();
+ final rawPath = new Uint8List.fromList([182]);
+ syncFile = new File.fromRawPath(rawPath);
+
+ if (Platform.isMacOS || Platform.isIOS) {
+ try {
+ syncFile.createSync();
+ } on FileSystemException catch (e) {
+ // Macos doesn't support non-UTF-8 paths.
+ return;
+ }
+ } else {
+ syncFile.createSync();
+ }
+ expect(syncFile.existsSync(), isTrue);
+
+ for (final file in Directory.current.listSync()) {
+ // FIXME(bkonyi): reenable when rawPath is exposed.
+ /*
+ if (Platform.isWindows) {
+ // Windows replaces invalid characters with � when creating file system
+ // entities.
+ final raw = file.rawPath;
+ expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+ } else {
+ expect(file.rawPath.last, 182);
+ }
+ */
+ // FIXME(bkonyi): this isn't true on some versions of MacOS. Why?
+ if (!Platform.isMacOS && !Platform.isIOS) {
+ expect(file.path.endsWith('�'), isTrue);
+ }
+ }
+ syncFile.deleteSync();
+ });
+
+ tearDown(() {
+ if ((asyncFile != null) && asyncFile.existsSync()) {
+ asyncFile.deleteSync();
+ }
+ if ((syncFile != null) && syncFile.existsSync()) {
+ syncFile.deleteSync();
+ }
+ });
+}
diff --git a/tests/standalone_2/io/non_utf8_link_test.dart b/tests/standalone_2/io/non_utf8_link_test.dart
new file mode 100644
index 0000000..4527412
--- /dev/null
+++ b/tests/standalone_2/io/non_utf8_link_test.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:path/path.dart';
+import 'package:test/test.dart';
+
+Future main() async {
+ var asyncLink;
+ var syncLink;
+ const dirName = 'foobar';
+
+ test('Non-UTF8 Link', () async {
+ Directory tmp = await Directory.systemTemp.createTemp();
+ Directory.current = await tmp.resolveSymbolicLinks();
+ final path = join(Directory.current.path, dirName);
+ final rawPath =
+ utf8.encode(path).sublist(0, path.length - dirName.length).toList();
+ rawPath.add(47);
+ rawPath.add(182);
+
+ final f = new Directory(path);
+ await f.create();
+ expect(await f.exists(), isTrue);
+
+ final rawName = new Uint8List.fromList(rawPath);
+ asyncLink = new Link.fromRawPath(rawName);
+
+ if (Platform.isMacOS || Platform.isIOS) {
+ try {
+ asyncLink = await asyncLink.create(path);
+ } on FileSystemException catch (e) {
+ // Macos doesn't support non-UTF-8 paths.
+ return;
+ }
+ } else {
+ asyncLink = await asyncLink.create(path);
+ }
+ expect(await asyncLink.exists(), isTrue);
+
+ await for (final e in Directory.current.list()) {
+ if (e is Link) {
+ // FIXME(bkonyi): reenable when rawPath is exposed.
+ /*
+ if (Platform.isWindows) {
+ // Windows replaces invalid characters with � when creating file system
+ // entities.
+ final raw = e.rawPath;
+ expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+ } else {
+ expect(e.rawPath.last, 182);
+ }
+ */
+ expect(e.path, path);
+ }
+ }
+
+ // FIXME(bkonyi): reenable when rawPath is exposed.
+ // expect(asyncLink.absolute.rawPath, rawPath);
+ expect(await asyncLink.resolveSymbolicLinks(), path);
+ expect(await asyncLink.target(), path);
+ await asyncLink.delete();
+ });
+
+ test('Non-UTF8 Link Sync', () {
+ Directory tmp = Directory.systemTemp.createTempSync();
+ Directory.current = tmp.resolveSymbolicLinksSync();
+ final path = join(Directory.current.path, dirName);
+ final rawPath =
+ utf8.encode(path).sublist(0, path.length - dirName.length).toList();
+ rawPath.add(47); // '/'
+ rawPath.add(182); // invalid UTF-8 character.
+
+ final f = new Directory(path);
+ f.createSync();
+ expect(f.existsSync(), isTrue);
+
+ final rawName = new Uint8List.fromList(rawPath);
+ syncLink = new Link.fromRawPath(rawName);
+
+ if (Platform.isMacOS || Platform.isIOS) {
+ try {
+ syncLink.createSync(path);
+ } on FileSystemException catch (e) {
+ // Macos doesn't support non-UTF-8 paths.
+ return;
+ }
+ } else {
+ syncLink.createSync(path);
+ }
+ expect(syncLink.existsSync(), isTrue);
+
+ for (final e in Directory.current.listSync()) {
+ if (e is Link) {
+ // FIXME(bkonyi): reenable when rawPath is exposed.
+ /*
+ if (Platform.isWindows) {
+ // Windows replaces invalid characters with � when creating file system
+ // entities.
+ final raw = e.rawPath;
+ expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+ } else {
+ expect(e.rawPath.last, 182);
+ }
+ */
+ expect(e.path, path);
+ }
+ }
+ // FIXME(bkonyi): reenable when rawPath is exposed.
+ // expect(syncLink.absolute.rawPath, rawPath);
+ expect(syncLink.resolveSymbolicLinksSync(), path);
+ expect(syncLink.targetSync(), path);
+ syncLink.deleteSync();
+ });
+
+ tearDown(() {
+ if ((asyncLink != null) && asyncLink.existsSync()) {
+ asyncLink.deleteSync();
+ }
+ if ((syncLink != null) && syncLink.existsSync()) {
+ syncLink.deleteSync();
+ }
+ });
+}
diff --git a/tests/standalone_2/standalone_2.status b/tests/standalone_2/standalone_2.status
index eb1b3b2..90a5707 100644
--- a/tests/standalone_2/standalone_2.status
+++ b/tests/standalone_2/standalone_2.status
@@ -69,7 +69,7 @@
io/*: Skip # Issue 30618
# All static_tests have expected compile-time errors.
-[ $compiler != dart2analyzer && $compiler != dartdevc && $compiler != dartk && $compiler != dartkp && $runtime != none && $strong ]
+[ $compiler != app_jitk && $compiler != dart2analyzer && $compiler != dartdevc && $compiler != dartk && $compiler != dartkp && $runtime != none && $strong ]
float_array_static_test: MissingCompileTimeError
[ $compiler == none && $runtime == vm && $system == fuchsia ]
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index dcf6699..66193af 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -10,6 +10,42 @@
# missing a section you need, please reach out to sigmund@ to see the best way
# to add them.
+[ $compiler == app_jitk ]
+io/dependency_graph_test: CompileTimeError
+io/directory_test: RuntimeError
+io/file_error_test: RuntimeError
+io/file_test: RuntimeError
+io/http_auth_digest_test: RuntimeError
+io/http_auth_test: RuntimeError
+io/http_compression_test: RuntimeError
+io/http_cookie_date_test: CompileTimeError
+io/http_headers_test: CompileTimeError
+io/http_parser_test: CompileTimeError
+io/http_redirect_test: RuntimeError
+io/http_reuse_server_port_test: RuntimeError
+io/http_server_response_test: RuntimeError
+io/namespace_test: RuntimeError
+io/platform_resolved_executable_test/00: RuntimeError
+io/platform_resolved_executable_test/01: RuntimeError
+io/platform_resolved_executable_test/02: RuntimeError
+io/platform_resolved_executable_test/03: RuntimeError
+io/platform_resolved_executable_test/04: RuntimeError
+io/platform_resolved_executable_test/05: RuntimeError
+io/platform_test: RuntimeError
+io/regress_10026_test: RuntimeError
+io/secure_socket_argument_test: CompileTimeError
+io/skipping_dart2js_compilations_test: CompileTimeError
+io/socket_upgrade_to_secure_test: RuntimeError
+io/test_extension_fail_test: RuntimeError
+io/test_extension_test: RuntimeError
+io/test_harness_analyzer_test: CompileTimeError
+io/test_runner_test: CompileTimeError
+io/web_socket_pipe_test: RuntimeError
+io/web_socket_protocol_processor_test: CompileTimeError
+io/zlib_test: RuntimeError
+oom_error_stacktrace_test: RuntimeError
+out_of_memory_test: RuntimeError
+
[ $fasta ]
deferred_transitive_import_error_test: CompileTimeError
package/package1_test: CompileTimeError
@@ -24,6 +60,10 @@
[ $builder_tag == optimization_counter_threshold && $compiler == dartk ]
map_insert_remove_oom_test: Skip # Heap limit too low.
+[ $compiler == app_jitk && ($mode == debug || $mode == release) ]
+dart_developer_disabled_env_test: RuntimeError
+io/code_collection_test: RuntimeError
+
[ $compiler == dartk && $mode == debug && $runtime == vm && $strong ]
io/file_lock_test: Slow, Pass
io/raw_socket_test: Crash
diff --git a/tools/VERSION b/tools/VERSION
index 18e0327..1d4965d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 0
PATCH 0
-PRERELEASE 58
+PRERELEASE 59
PRERELEASE_PATCH 0
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 0f5f4a7..ce55a8e 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -436,6 +436,29 @@
},
{
"builders": [
+ "app-kernel-linux-debug-x64",
+ "app-kernel-linux-product-x64",
+ "app-kernel-linux-release-x64"
+ ],
+ "meta": {
+ "description": "This configuration is used by the vm kernel app builder group."
+ },
+ "steps": [
+ {
+ "name": "build dart",
+ "script": "tools/build.py",
+ "arguments": [
+ "runtime_kernel"
+ ]
+ },
+ {
+ "name": "vm tests",
+ "arguments": ["--compiler=app_jitk", "--strong"]
+ }
+ ]
+ },
+ {
+ "builders": [
"ddc-linux-release-chrome",
"ddc-win-release-chrome"
],
diff --git a/tools/build.py b/tools/build.py
index f22d32d..faab699 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -228,6 +228,8 @@
build_config = utils.GetBuildConf(mode, arch, target_os)
out_dir = utils.GetBuildRoot(HOST_OS, mode, arch, target_os)
using_goma = False
+ # TODO(zra): Remove auto-run of gn, replace with prompt for user to run
+ # gn.py manually.
if ShouldRunGN(out_dir):
RunGN(target_os, mode, arch)
command = ['ninja', '-C', out_dir]
diff --git a/tools/gn.py b/tools/gn.py
index d348a21..1a19afd 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -221,6 +221,8 @@
else:
gn_args['dart_runtime_mode'] = 'develop'
+ gn_args['exclude_kernel_service'] = args.exclude_kernel_service
+
dont_use_clang = DontUseClang(args, gn_args['target_os'],
gn_args['host_cpu'],
gn_args['target_cpu'])
@@ -392,6 +394,11 @@
help='Generate an IDE file.',
default=os_has_ide(HOST_OS),
action='store_true')
+ other_group.add_argument('--exclude-kernel-service',
+ help='Exclude the kernel service.',
+ default=False,
+ dest='exclude_kernel_service',
+ action='store_true')
other_group.add_argument('--msan',
help='Build with MSAN',
default=UseMSAN(),
diff --git a/tools/patch_sdk.dart b/tools/patch_sdk.dart
index 53f4002..411442c 100644
--- a/tools/patch_sdk.dart
+++ b/tools/patch_sdk.dart
@@ -200,19 +200,11 @@
..compileSdk = true
..sdkRoot = patchedSdk
..packagesFileUri = packages
- ..chaseDependencies = true
..target = target;
var inputs = [Uri.parse('dart:core')];
- var result = await generateKernel(
- new ProcessedOptions(
- options,
- // TODO(sigmund): pass all sdk libraries needed here, and make this
- // hermetic.
- false,
- inputs),
- buildSummary: true,
- buildComponent: true);
+ var result = await generateKernel(new ProcessedOptions(options, inputs),
+ buildSummary: true, buildComponent: true);
await writeComponentToFile(result.component, output);
return result.deps;
}
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 5f930c6..2206a5c 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -68,6 +68,9 @@
case Compiler.appJit:
return new AppJitCompilerConfiguration(configuration);
+ case Compiler.appJitk:
+ return new AppJitCompilerConfiguration(configuration, useDfe: true);
+
case Compiler.precompiler:
return new PrecompilerCompilerConfiguration(configuration);
@@ -910,7 +913,11 @@
}
class AppJitCompilerConfiguration extends CompilerConfiguration {
- AppJitCompilerConfiguration(Configuration configuration)
+ // This boolean is used by the [VMTestSuite] for running cc tests via
+ // run_vm_tests.
+ final bool useDfe;
+
+ AppJitCompilerConfiguration(Configuration configuration, {this.useDfe: false})
: super._subclass(configuration);
int get timeoutMultiplier {
@@ -934,6 +941,9 @@
var exec = "${_configuration.buildDirectory}/dart";
var snapshot = "$tempDir/out.jitsnapshot";
var args = ["--snapshot=$snapshot", "--snapshot-kind=app-jit"];
+ if (useDfe) {
+ args.add("--preview-dart-2");
+ }
args.addAll(arguments);
return Command.compilation('app_jit', tempDir, bootstrapDependencies(),
@@ -966,6 +976,9 @@
args.add('--enable_asserts');
args.add('--enable_type_checks');
}
+ if (useDfe) {
+ args.add('--preview-dart-2');
+ }
args
..addAll(vmOptions)
..addAll(sharedOptions)
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index 9071636..a6ad1fd 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -187,6 +187,7 @@
/// as the first stage of compilation.
bool get usesFasta {
var fastaCompilers = const [
+ Compiler.appJitk,
Compiler.dartdevk,
Compiler.dartk,
Compiler.dartkp,
@@ -546,6 +547,7 @@
static const dartdevc = const Compiler._('dartdevc');
static const dartdevk = const Compiler._('dartdevk');
static const appJit = const Compiler._('app_jit');
+ static const appJitk = const Compiler._('app_jitk');
static const dartk = const Compiler._('dartk');
static const dartkp = const Compiler._('dartkp');
static const specParser = const Compiler._('spec_parser');
@@ -561,6 +563,7 @@
dartdevc,
dartdevk,
appJit,
+ appJitk,
dartk,
dartkp,
specParser,
@@ -614,6 +617,7 @@
case Compiler.dart2analyzer:
return const [Runtime.none];
case Compiler.appJit:
+ case Compiler.appJitk:
case Compiler.dartk:
return const [Runtime.vm, Runtime.selfCheck];
case Compiler.precompiler:
@@ -647,6 +651,7 @@
case Compiler.dart2analyzer:
return Runtime.none;
case Compiler.appJit:
+ case Compiler.appJitk:
case Compiler.dartk:
return Runtime.vm;
case Compiler.precompiler:
@@ -805,6 +810,7 @@
].contains(this);
bool get isIE => name.startsWith("ie");
+
bool get isSafari => name.startsWith("safari");
/// Whether this runtime is a command-line JavaScript environment.
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index f20dbfd..e52f9cb 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -96,6 +96,7 @@
dart2js: Compile to JavaScript using dart2js.
dart2analyzer: Perform static analysis on Dart code using the analyzer.
app_jit: Compile the Dart code into an app snapshot.
+app_jitk: Compile the Dart code into Kernel and then into an app snapshot.
dartk: Compile the Dart code into Kernel before running test.
dartkp: Compile the Dart code into Kernel and then Kernel into AOT
snapshot before running the test.
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index 6165c85..888f89d 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -35,6 +35,8 @@
}
application_snapshot("dartdevk") {
+ dart_version = 2
+
main_dart = "../../pkg/dev_compiler/bin/dartdevk.dart"
training_args = [
diff --git a/utils/dartfmt/BUILD.gn b/utils/dartfmt/BUILD.gn
index 566475f..99ae1ed 100644
--- a/utils/dartfmt/BUILD.gn
+++ b/utils/dartfmt/BUILD.gn
@@ -5,6 +5,9 @@
import("../application_snapshot.gni")
application_snapshot("dartfmt") {
+ dart_version = 2
main_dart = "../../third_party/pkg_tested/dart_style/bin/format.dart"
- training_args = [ "--help" ]
+
+ # Train it on formatting its own source.
+ training_args = [ "../../third_party/pkg_tested/dart_style" ]
}