Version 0.8.8.0 .
svn merge -r 29340:29512 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@29513 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 518e52e..04d6d01 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -3400,7 +3400,7 @@
statistics.putCacheItem(dartEntry, DartEntry.PARSE_ERRORS);
statistics.putCacheItem(dartEntry, DartEntry.PARSED_UNIT);
statistics.putCacheItem(dartEntry, DartEntry.SOURCE_KIND);
- statistics.putCacheItem(dartEntry, DartEntry.LINE_INFO);
+ statistics.putCacheItem(dartEntry, SourceEntry.LINE_INFO);
if (identical(kind, SourceKind.LIBRARY)) {
statistics.putCacheItem(dartEntry, DartEntry.ELEMENT);
statistics.putCacheItem(dartEntry, DartEntry.EXPORTED_LIBRARIES);
@@ -4054,6 +4054,10 @@
AnalysisTask get nextTaskAnalysisTask {
{
bool hintsEnabled = _options.hint;
+ if (_incrementalAnalysisCache != null) {
+ AnalysisTask task = new IncrementalAnalysisTask(this, _incrementalAnalysisCache);
+ _incrementalAnalysisCache = null;
+ }
for (Source source in _priorityOrder) {
AnalysisTask task = getNextTaskAnalysisTask2(source, _cache.get(source), true, hintsEnabled);
if (task != null) {
@@ -4580,6 +4584,24 @@
}
/**
+ * Record the results produced by performing a [IncrementalAnalysisTask].
+ *
+ * @param task the task that was performed
+ * @return an entry containing the computed results
+ * @throws AnalysisException if the results could not be recorded
+ */
+ DartEntry recordIncrementalAnalysisTaskResults(IncrementalAnalysisTask task) {
+ {
+ CompilationUnit unit = task.compilationUnit;
+ if (unit != null) {
+ ChangeNoticeImpl notice = getNotice(task.source);
+ notice.compilationUnit = unit;
+ }
+ }
+ return null;
+ }
+
+ /**
* Record the results produced by performing a [ParseDartTask]. If the results were computed
* from data that is now out-of-date, then the results will not be recorded.
*
@@ -5033,6 +5055,7 @@
AnalysisContextImpl_AnalysisTaskResultRecorder(this.AnalysisContextImpl_this);
SourceEntry visitGenerateDartErrorsTask(GenerateDartErrorsTask task) => AnalysisContextImpl_this.recordGenerateDartErrorsTask(task);
SourceEntry visitGenerateDartHintsTask(GenerateDartHintsTask task) => AnalysisContextImpl_this.recordGenerateDartHintsTask(task);
+ SourceEntry visitIncrementalAnalysisTask(IncrementalAnalysisTask task) => AnalysisContextImpl_this.recordIncrementalAnalysisTaskResults(task);
DartEntry visitParseDartTask(ParseDartTask task) => AnalysisContextImpl_this.recordParseDartTaskResults(task);
HtmlEntry visitParseHtmlTask(ParseHtmlTask task) => AnalysisContextImpl_this.recordParseHtmlTaskResults(task);
DartEntry visitResolveDartLibraryTask(ResolveDartLibraryTask task) => AnalysisContextImpl_this.recordResolveDartLibraryTaskResults(task);
@@ -6619,6 +6642,15 @@
E visitGenerateDartHintsTask(GenerateDartHintsTask task);
/**
+ * Visit an [IncrementalAnalysisTask].
+ *
+ * @param task the task to be visited
+ * @return the result of visiting the task
+ * @throws AnalysisException if the visitor throws an exception for some reason
+ */
+ E visitIncrementalAnalysisTask(IncrementalAnalysisTask incrementalAnalysisTask);
+
+ /**
* Visit a [ParseDartTask].
*
* @param task the task to be visited
@@ -6802,6 +6834,46 @@
TimestampedData<CompilationUnit> getCompilationUnit(Source unitSource) => context.internalResolveCompilationUnit(unitSource, libraryElement);
}
/**
+ * Instances of the class `IncrementalAnalysisTask` incrementally update existing analysis.
+ */
+class IncrementalAnalysisTask extends AnalysisTask {
+
+ /**
+ * The information used to perform incremental analysis.
+ */
+ IncrementalAnalysisCache _cache;
+
+ /**
+ * The compilation unit that was produced by incrementally updating the existing unit.
+ */
+ CompilationUnit compilationUnit;
+
+ /**
+ * Initialize a newly created task to perform analysis within the given context.
+ *
+ * @param context the context in which the task is to be performed
+ * @param cache the incremental analysis cache used to perform the analysis
+ */
+ IncrementalAnalysisTask(InternalAnalysisContext context, IncrementalAnalysisCache cache) : super(context) {
+ this._cache = cache;
+ }
+ accept(AnalysisTaskVisitor visitor) => visitor.visitIncrementalAnalysisTask(this);
+
+ /**
+ * Return the source that is to be incrementally analyzed.
+ *
+ * @return the source
+ */
+ Source get source => _cache != null ? _cache.source : null;
+ String get taskDescription => "incremental analysis ${(_cache != null ? _cache.source : "null")}";
+ void internalPerform() {
+ if (_cache == null) {
+ return;
+ }
+ compilationUnit = _cache.resolvedUnit;
+ }
+}
+/**
* Instances of the class `ParseDartTask` parse a specific source as a Dart file.
*/
class ParseDartTask extends AnalysisTask {
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 6fc95e0..c1c580a 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -1734,31 +1734,43 @@
* 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with the const modifier but
* <i>k'</i> is not a constant constructor.
*/
- static final CompileTimeErrorCode REDIRECT_TO_NON_CONST_CONSTRUCTOR = new CompileTimeErrorCode.con1('REDIRECT_TO_NON_CONST_CONSTRUCTOR', 119, "Constant factory constructor cannot delegate to a non-constant constructor");
+ static final CompileTimeErrorCode REDIRECT_TO_MISSING_CONSTRUCTOR = new CompileTimeErrorCode.con1('REDIRECT_TO_MISSING_CONSTRUCTOR', 119, "The constructor '%s' could not be found in '%s'");
+
+ /**
+ * 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with the const modifier but
+ * <i>k'</i> is not a constant constructor.
+ */
+ static final CompileTimeErrorCode REDIRECT_TO_NON_CLASS = new CompileTimeErrorCode.con1('REDIRECT_TO_NON_CLASS', 120, "The name '%s' is not a type and cannot be used in a redirected constructor");
+
+ /**
+ * 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with the const modifier but
+ * <i>k'</i> is not a constant constructor.
+ */
+ static final CompileTimeErrorCode REDIRECT_TO_NON_CONST_CONSTRUCTOR = new CompileTimeErrorCode.con1('REDIRECT_TO_NON_CONST_CONSTRUCTOR', 121, "Constant factory constructor cannot delegate to a non-constant constructor");
/**
* 13.3 Local Variable Declaration: It is a compile-time error if <i>e</i> refers to the name
* <i>v</i> or the name <i>v=</i>.
*/
- static final CompileTimeErrorCode REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER = new CompileTimeErrorCode.con1('REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER', 120, "The name '%s' cannot be referenced in the initializer of a variable with the same name");
+ static final CompileTimeErrorCode REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER = new CompileTimeErrorCode.con1('REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER', 122, "The name '%s' cannot be referenced in the initializer of a variable with the same name");
/**
* 5 Variables: A local variable may only be referenced at a source code location that is after
* its initializer, if any, is complete, or a compile-time error occurs.
*/
- static final CompileTimeErrorCode REFERENCED_BEFORE_DECLARATION = new CompileTimeErrorCode.con1('REFERENCED_BEFORE_DECLARATION', 121, "Local variables cannot be referenced before they are declared");
+ static final CompileTimeErrorCode REFERENCED_BEFORE_DECLARATION = new CompileTimeErrorCode.con1('REFERENCED_BEFORE_DECLARATION', 123, "Local variables cannot be referenced before they are declared");
/**
* 12.8.1 Rethrow: It is a compile-time error if an expression of the form <i>rethrow;</i> is not
* enclosed within a on-catch clause.
*/
- static final CompileTimeErrorCode RETHROW_OUTSIDE_CATCH = new CompileTimeErrorCode.con1('RETHROW_OUTSIDE_CATCH', 122, "rethrow must be inside of a catch clause");
+ static final CompileTimeErrorCode RETHROW_OUTSIDE_CATCH = new CompileTimeErrorCode.con1('RETHROW_OUTSIDE_CATCH', 124, "rethrow must be inside of a catch clause");
/**
* 13.11 Return: It is a compile-time error if a return statement of the form <i>return e;</i>
* appears in a generative constructor.
*/
- static final CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR = new CompileTimeErrorCode.con1('RETURN_IN_GENERATIVE_CONSTRUCTOR', 123, "Constructors cannot return a value");
+ static final CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR = new CompileTimeErrorCode.con1('RETURN_IN_GENERATIVE_CONSTRUCTOR', 125, "Constructors cannot return a value");
/**
* 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
@@ -1768,19 +1780,19 @@
* initializer list, in class Object, in a factory constructor, or in a static method or variable
* initializer.
*/
- static final CompileTimeErrorCode SUPER_IN_INVALID_CONTEXT = new CompileTimeErrorCode.con1('SUPER_IN_INVALID_CONTEXT', 124, "Invalid context for 'super' invocation");
+ static final CompileTimeErrorCode SUPER_IN_INVALID_CONTEXT = new CompileTimeErrorCode.con1('SUPER_IN_INVALID_CONTEXT', 126, "Invalid context for 'super' invocation");
/**
* 7.6.1 Generative Constructors: A generative constructor may be redirecting, in which case its
* only action is to invoke another generative constructor.
*/
- static final CompileTimeErrorCode SUPER_IN_REDIRECTING_CONSTRUCTOR = new CompileTimeErrorCode.con1('SUPER_IN_REDIRECTING_CONSTRUCTOR', 125, "The redirecting constructor cannot have a 'super' initializer");
+ static final CompileTimeErrorCode SUPER_IN_REDIRECTING_CONSTRUCTOR = new CompileTimeErrorCode.con1('SUPER_IN_REDIRECTING_CONSTRUCTOR', 127, "The redirecting constructor cannot have a 'super' initializer");
/**
* 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile-time
* error if a generative constructor of class Object includes a superinitializer.
*/
- static final CompileTimeErrorCode SUPER_INITIALIZER_IN_OBJECT = new CompileTimeErrorCode.con1('SUPER_INITIALIZER_IN_OBJECT', 126, "");
+ static final CompileTimeErrorCode SUPER_INITIALIZER_IN_OBJECT = new CompileTimeErrorCode.con1('SUPER_INITIALIZER_IN_OBJECT', 128, "");
/**
* 12.11 Instance Creation: It is a static type warning if any of the type arguments to a
@@ -1799,19 +1811,19 @@
* @param boundingTypeName the name of the bounding type
* @see StaticTypeWarningCode#TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
*/
- static final CompileTimeErrorCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new CompileTimeErrorCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 127, "'%s' does not extend '%s'");
+ static final CompileTimeErrorCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new CompileTimeErrorCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 129, "'%s' does not extend '%s'");
/**
* 15.3.1 Typedef: Any self reference, either directly, or recursively via another typedef, is a
* compile time error.
*/
- static final CompileTimeErrorCode TYPE_ALIAS_CANNOT_REFERENCE_ITSELF = new CompileTimeErrorCode.con1('TYPE_ALIAS_CANNOT_REFERENCE_ITSELF', 128, "Type alias cannot reference itself directly or recursively via another typedef");
+ static final CompileTimeErrorCode TYPE_ALIAS_CANNOT_REFERENCE_ITSELF = new CompileTimeErrorCode.con1('TYPE_ALIAS_CANNOT_REFERENCE_ITSELF', 130, "Type alias cannot reference itself directly or recursively via another typedef");
/**
* 12.11.2 Const: It is a compile-time error if <i>T</i> is not a class accessible in the current
* scope, optionally followed by type arguments.
*/
- static final CompileTimeErrorCode UNDEFINED_CLASS = new CompileTimeErrorCode.con1('UNDEFINED_CLASS', 129, "Undefined class '%s'");
+ static final CompileTimeErrorCode UNDEFINED_CLASS = new CompileTimeErrorCode.con1('UNDEFINED_CLASS', 131, "Undefined class '%s'");
/**
* 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the superinitializer appears
@@ -1819,7 +1831,7 @@
* a compile-time error if class <i>S</i> does not declare a generative constructor named <i>S</i>
* (respectively <i>S.id</i>)
*/
- static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER = new CompileTimeErrorCode.con1('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER', 130, "The class '%s' does not have a generative constructor '%s'");
+ static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER = new CompileTimeErrorCode.con1('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER', 132, "The class '%s' does not have a generative constructor '%s'");
/**
* 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the superinitializer appears
@@ -1827,7 +1839,7 @@
* a compile-time error if class <i>S</i> does not declare a generative constructor named <i>S</i>
* (respectively <i>S.id</i>)
*/
- static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT = new CompileTimeErrorCode.con1('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT', 131, "The class '%s' does not have a default generative constructor");
+ static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT = new CompileTimeErrorCode.con1('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT', 133, "The class '%s' does not have a default generative constructor");
/**
* 12.14.3 Unqualified Invocation: If there exists a lexically visible declaration named
@@ -1837,7 +1849,7 @@
*
* @param methodName the name of the method that is undefined
*/
- static final CompileTimeErrorCode UNDEFINED_FUNCTION = new CompileTimeErrorCode.con1('UNDEFINED_FUNCTION', 132, "The function '%s' is not defined");
+ static final CompileTimeErrorCode UNDEFINED_FUNCTION = new CompileTimeErrorCode.con1('UNDEFINED_FUNCTION', 134, "The function '%s' is not defined");
/**
* 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub></i>, <i>1<=i<=l</i>,
@@ -1849,7 +1861,7 @@
*
* @param name the name of the requested named parameter
*/
- static final CompileTimeErrorCode UNDEFINED_NAMED_PARAMETER = new CompileTimeErrorCode.con1('UNDEFINED_NAMED_PARAMETER', 133, "The named parameter '%s' is not defined");
+ static final CompileTimeErrorCode UNDEFINED_NAMED_PARAMETER = new CompileTimeErrorCode.con1('UNDEFINED_NAMED_PARAMETER', 135, "The named parameter '%s' is not defined");
/**
* 14.2 Exports: It is a compile-time error if the compilation unit found at the specified URI is
@@ -1864,7 +1876,7 @@
* @param uri the URI pointing to a non-existent file
* @see #INVALID_URI
*/
- static final CompileTimeErrorCode URI_DOES_NOT_EXIST = new CompileTimeErrorCode.con1('URI_DOES_NOT_EXIST', 134, "Target of URI does not exist: '%s'");
+ static final CompileTimeErrorCode URI_DOES_NOT_EXIST = new CompileTimeErrorCode.con1('URI_DOES_NOT_EXIST', 136, "Target of URI does not exist: '%s'");
/**
* 14.1 Imports: It is a compile-time error if <i>x</i> is not a compile-time constant, or if
@@ -1876,7 +1888,7 @@
* 14.5 URIs: It is a compile-time error if the string literal <i>x</i> that describes a URI is
* not a compile-time constant, or if <i>x</i> involves string interpolation.
*/
- static final CompileTimeErrorCode URI_WITH_INTERPOLATION = new CompileTimeErrorCode.con1('URI_WITH_INTERPOLATION', 135, "URIs cannot use string interpolation");
+ static final CompileTimeErrorCode URI_WITH_INTERPOLATION = new CompileTimeErrorCode.con1('URI_WITH_INTERPOLATION', 137, "URIs cannot use string interpolation");
/**
* 7.1.1 Operators: It is a compile-time error if the arity of the user-declared operator []= is
@@ -1889,7 +1901,7 @@
* @param expectedNumberOfParameters the number of parameters expected
* @param actualNumberOfParameters the number of parameters found in the operator declaration
*/
- static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR', 136, "Operator '%s' should declare exactly %d parameter(s), but %d found");
+ static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR', 138, "Operator '%s' should declare exactly %d parameter(s), but %d found");
/**
* 7.1.1 Operators: It is a compile time error if the arity of the user-declared operator - is not
@@ -1897,13 +1909,13 @@
*
* @param actualNumberOfParameters the number of parameters found in the operator declaration
*/
- static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS', 137, "Operator '-' should declare 0 or 1 parameter, but %d found");
+ static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS', 139, "Operator '-' should declare 0 or 1 parameter, but %d found");
/**
* 7.3 Setters: It is a compile-time error if a setter's formal parameter list does not include
* exactly one required formal parameter <i>p</i>.
*/
- static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER', 138, "Setters should declare exactly one required parameter");
+ static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER = new CompileTimeErrorCode.con1('WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER', 140, "Setters should declare exactly one required parameter");
static final List<CompileTimeErrorCode> values = [
AMBIGUOUS_EXPORT,
ARGUMENT_DEFINITION_TEST_NON_PARAMETER,
@@ -2024,6 +2036,8 @@
RECURSIVE_INTERFACE_INHERITANCE,
RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS,
RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS,
+ REDIRECT_TO_MISSING_CONSTRUCTOR,
+ REDIRECT_TO_NON_CLASS,
REDIRECT_TO_NON_CONST_CONSTRUCTOR,
REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER,
REFERENCED_BEFORE_DECLARATION,
@@ -3234,7 +3248,7 @@
static final StaticTypeWarningCode INVOCATION_OF_NON_FUNCTION_EXPRESSION = new StaticTypeWarningCode.con1('INVOCATION_OF_NON_FUNCTION_EXPRESSION', 7, "Cannot invoke a non-function");
/**
- * 12.19 Conditional: It is a static type warning if the type of <i>e<sub>1</sub></i> may not be
+ * 12.20 Conditional: It is a static type warning if the type of <i>e<sub>1</sub></i> may not be
* assigned to bool.
*
* 13.5 If: It is a static type warning if the type of the expression <i>b</i> may not be assigned
@@ -3253,10 +3267,19 @@
static final StaticTypeWarningCode NON_BOOL_EXPRESSION = new StaticTypeWarningCode.con1('NON_BOOL_EXPRESSION', 9, "Assertions must be on either a 'bool' or '() -> bool'");
/**
+ * 12.28 Unary Expressions: The expression !<i>e</i> is equivalent to the expression
+ * <i>e</i>?<b>false<b> : <b>true</b>.
+ *
+ * 12.20 Conditional: It is a static type warning if the type of <i>e<sub>1</sub></i> may not be
+ * assigned to bool.
+ */
+ static final StaticTypeWarningCode NON_BOOL_NEGATION_EXPRESSION = new StaticTypeWarningCode.con1('NON_BOOL_NEGATION_EXPRESSION', 10, "Negation argument must have a static type of 'bool'");
+
+ /**
* 15.8 Parameterized Types: It is a static type warning if <i>A<sub>i</sub>, 1 <= i <=
* n</i> does not denote a type in the enclosing lexical scope.
*/
- static final StaticTypeWarningCode NON_TYPE_AS_TYPE_ARGUMENT = new StaticTypeWarningCode.con1('NON_TYPE_AS_TYPE_ARGUMENT', 10, "The name '%s' is not a type and cannot be used as a parameterized type");
+ static final StaticTypeWarningCode NON_TYPE_AS_TYPE_ARGUMENT = new StaticTypeWarningCode.con1('NON_TYPE_AS_TYPE_ARGUMENT', 11, "The name '%s' is not a type and cannot be used as a parameterized type");
/**
* 13.11 Return: It is a static type warning if the type of <i>e</i> may not be assigned to the
@@ -3266,7 +3289,7 @@
* @param expectedReturnType the expected return type as defined by the method
* @param methodName the name of the method
*/
- static final StaticTypeWarningCode RETURN_OF_INVALID_TYPE = new StaticTypeWarningCode.con1('RETURN_OF_INVALID_TYPE', 11, "The return type '%s' is not a '%s', as defined by the method '%s'");
+ static final StaticTypeWarningCode RETURN_OF_INVALID_TYPE = new StaticTypeWarningCode.con1('RETURN_OF_INVALID_TYPE', 12, "The return type '%s' is not a '%s', as defined by the method '%s'");
/**
* 12.11 Instance Creation: It is a static type warning if any of the type arguments to a
@@ -3290,7 +3313,7 @@
* @param boundingTypeName the name of the bounding type
* @see #TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND
*/
- static final StaticTypeWarningCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new StaticTypeWarningCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 12, "'%s' does not extend '%s'");
+ static final StaticTypeWarningCode TYPE_ARGUMENT_NOT_MATCHING_BOUNDS = new StaticTypeWarningCode.con1('TYPE_ARGUMENT_NOT_MATCHING_BOUNDS', 13, "'%s' does not extend '%s'");
/**
* 10 Generics: It is a static type warning if a type parameter is a supertype of its upper bound.
@@ -3298,7 +3321,7 @@
* @param typeParameterName the name of the type parameter
* @see #TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
*/
- static final StaticTypeWarningCode TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND = new StaticTypeWarningCode.con1('TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND', 13, "'%s' cannot be a supertype of its upper bound");
+ static final StaticTypeWarningCode TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND = new StaticTypeWarningCode.con1('TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND', 14, "'%s' cannot be a supertype of its upper bound");
/**
* 12.17 Getter Invocation: Let <i>T</i> be the static type of <i>e</i>. It is a static type
@@ -3307,7 +3330,7 @@
* @param getterName the name of the getter
* @param enclosingType the name of the enclosing type where the getter is being looked for
*/
- static final StaticTypeWarningCode UNDEFINED_GETTER = new StaticTypeWarningCode.con1('UNDEFINED_GETTER', 14, "There is no such getter '%s' in '%s'");
+ static final StaticTypeWarningCode UNDEFINED_GETTER = new StaticTypeWarningCode.con1('UNDEFINED_GETTER', 15, "There is no such getter '%s' in '%s'");
/**
* 12.15.1 Ordinary Invocation: Let <i>T</i> be the static type of <i>o</i>. It is a static type
@@ -3316,7 +3339,7 @@
* @param methodName the name of the method that is undefined
* @param typeName the resolved type name that the method lookup is happening on
*/
- static final StaticTypeWarningCode UNDEFINED_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_METHOD', 15, "The method '%s' is not defined for the class '%s'");
+ static final StaticTypeWarningCode UNDEFINED_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_METHOD', 16, "The method '%s' is not defined for the class '%s'");
/**
* 12.18 Assignment: Evaluation of an assignment of the form
@@ -3334,7 +3357,7 @@
* @param operator the name of the operator
* @param enclosingType the name of the enclosing type where the operator is being looked for
*/
- static final StaticTypeWarningCode UNDEFINED_OPERATOR = new StaticTypeWarningCode.con1('UNDEFINED_OPERATOR', 16, "There is no such operator '%s' in '%s'");
+ static final StaticTypeWarningCode UNDEFINED_OPERATOR = new StaticTypeWarningCode.con1('UNDEFINED_OPERATOR', 17, "There is no such operator '%s' in '%s'");
/**
* 12.18 Assignment: Let <i>T</i> be the static type of <i>e<sub>1</sub></i>. It is a static type
@@ -3344,7 +3367,7 @@
* @param enclosingType the name of the enclosing type where the setter is being looked for
* @see #INACCESSIBLE_SETTER
*/
- static final StaticTypeWarningCode UNDEFINED_SETTER = new StaticTypeWarningCode.con1('UNDEFINED_SETTER', 17, "There is no such setter '%s' in '%s'");
+ static final StaticTypeWarningCode UNDEFINED_SETTER = new StaticTypeWarningCode.con1('UNDEFINED_SETTER', 18, "There is no such setter '%s' in '%s'");
/**
* 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
@@ -3355,7 +3378,7 @@
* @param methodName the name of the method that is undefined
* @param typeName the resolved type name that the method lookup is happening on
*/
- static final StaticTypeWarningCode UNDEFINED_SUPER_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_SUPER_METHOD', 18, "There is no such method '%s' in '%s'");
+ static final StaticTypeWarningCode UNDEFINED_SUPER_METHOD = new StaticTypeWarningCode.con1('UNDEFINED_SUPER_METHOD', 19, "There is no such method '%s' in '%s'");
/**
* 12.15.1 Ordinary Invocation: It is a static type warning if <i>T</i> does not have an
@@ -3365,7 +3388,7 @@
* able to find the name defined in a supertype. It exists to provide a more informative error
* message.
*/
- static final StaticTypeWarningCode UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER = new StaticTypeWarningCode.con1('UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER', 19, "Static members from supertypes must be qualified by the name of the defining type");
+ static final StaticTypeWarningCode UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER = new StaticTypeWarningCode.con1('UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER', 20, "Static members from supertypes must be qualified by the name of the defining type");
/**
* 15.8 Parameterized Types: It is a static type warning if <i>G</i> is not a generic type with
@@ -3377,7 +3400,7 @@
* @see CompileTimeErrorCode#CONST_WITH_INVALID_TYPE_PARAMETERS
* @see CompileTimeErrorCode#NEW_WITH_INVALID_TYPE_PARAMETERS
*/
- static final StaticTypeWarningCode WRONG_NUMBER_OF_TYPE_ARGUMENTS = new StaticTypeWarningCode.con1('WRONG_NUMBER_OF_TYPE_ARGUMENTS', 20, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
+ static final StaticTypeWarningCode WRONG_NUMBER_OF_TYPE_ARGUMENTS = new StaticTypeWarningCode.con1('WRONG_NUMBER_OF_TYPE_ARGUMENTS', 21, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
static final List<StaticTypeWarningCode> values = [
EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
EXPECTED_TWO_MAP_TYPE_ARGUMENTS,
@@ -3389,6 +3412,7 @@
INVOCATION_OF_NON_FUNCTION_EXPRESSION,
NON_BOOL_CONDITION,
NON_BOOL_EXPRESSION,
+ NON_BOOL_NEGATION_EXPRESSION,
NON_TYPE_AS_TYPE_ARGUMENT,
RETURN_OF_INVALID_TYPE,
TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index a0fedd3..bf066f2 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2939,6 +2939,11 @@
ResolverVisitor _resolver;
/**
+ * The element for the library containing the compilation unit being visited.
+ */
+ LibraryElement _definingLibrary;
+
+ /**
* A flag indicating whether we are running in strict mode. In strict mode, error reporting is
* based exclusively on the static type information.
*/
@@ -2988,7 +2993,8 @@
*/
ElementResolver(ResolverVisitor resolver) {
this._resolver = resolver;
- AnalysisOptions options = resolver.definingLibrary.context.analysisOptions;
+ this._definingLibrary = resolver.definingLibrary;
+ AnalysisOptions options = _definingLibrary.context.analysisOptions;
_strictMode = options.strictMode;
_enableHints = options.hint;
_dynamicType = resolver.typeProvider.dynamicType;
@@ -3085,7 +3091,7 @@
}
if (element == null) {
} else {
- if (element.library == null || element.library != _resolver.definingLibrary) {
+ if (element.library == null || element.library != _definingLibrary) {
}
simpleIdentifier.staticElement = element;
if (node.newKeyword != null) {
@@ -3108,14 +3114,14 @@
} else {
if (element is PrefixElement) {
prefix.staticElement = element;
- element = _resolver.nameScope.lookup(identifier, _resolver.definingLibrary);
+ element = _resolver.nameScope.lookup(identifier, _definingLibrary);
name.staticElement = element;
return null;
}
LibraryElement library = element.library;
if (library == null) {
AnalysisEngine.instance.logger.logError("Found element with null library: ${element.name}");
- } else if (library != _resolver.definingLibrary) {
+ } else if (library != _definingLibrary) {
}
name.staticElement = element;
if (node.newKeyword == null) {
@@ -3196,11 +3202,10 @@
ConstructorElement constructor;
SimpleIdentifier name = node.name;
InterfaceType interfaceType = type as InterfaceType;
- LibraryElement definingLibrary = _resolver.definingLibrary;
if (name == null) {
- constructor = interfaceType.lookUpConstructor(null, definingLibrary);
+ constructor = interfaceType.lookUpConstructor(null, _definingLibrary);
} else {
- constructor = interfaceType.lookUpConstructor(name.name, definingLibrary);
+ constructor = interfaceType.lookUpConstructor(name.name, _definingLibrary);
name.staticElement = constructor;
}
node.staticElement = constructor;
@@ -3274,7 +3279,7 @@
SimpleIdentifier prefixNode = node.prefix;
if (prefixNode != null) {
String prefixName = prefixNode.name;
- for (PrefixElement prefixElement in _resolver.definingLibrary.prefixes) {
+ for (PrefixElement prefixElement in _definingLibrary.prefixes) {
if (prefixElement.displayName == prefixName) {
prefixNode.staticElement = prefixElement;
break;
@@ -3393,7 +3398,7 @@
}
}
if (classElementContext != null) {
- _subtypeManager.ensureLibraryVisited(_resolver.definingLibrary);
+ _subtypeManager.ensureLibraryVisited(_definingLibrary);
Set<ClassElement> subtypeElements = _subtypeManager.computeAllSubtypes(classElementContext);
for (ClassElement subtypeElement in subtypeElements) {
if (subtypeElement.getMethod(methodName.name) != null) {
@@ -3479,9 +3484,9 @@
SimpleIdentifier identifier = node.identifier;
Element prefixElement = prefix.staticElement;
if (prefixElement is PrefixElement) {
- Element element = _resolver.nameScope.lookup(node, _resolver.definingLibrary);
+ Element element = _resolver.nameScope.lookup(node, _definingLibrary);
if (element == null && identifier.inSetterContext()) {
- element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdentifier("${node.name}="), _resolver.definingLibrary);
+ element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdentifier("${node.name}="), _definingLibrary);
}
if (element == null) {
if (identifier.inSetterContext()) {
@@ -3624,7 +3629,7 @@
}
SimpleIdentifier name = node.constructorName;
String superName = name != null ? name.name : null;
- ConstructorElement element = superType.lookUpConstructor(superName, _resolver.definingLibrary);
+ ConstructorElement element = superType.lookUpConstructor(superName, _definingLibrary);
if (element == null) {
if (name != null) {
_resolver.reportError5(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, node, [superType.displayName, name]);
@@ -3807,7 +3812,7 @@
if (getterType != null) {
Type2 getterReturnType = getterType.returnType;
if (getterReturnType is InterfaceType) {
- MethodElement callMethod = ((getterReturnType as InterfaceType)).lookUpMethod(CALL_METHOD_NAME, _resolver.definingLibrary);
+ MethodElement callMethod = ((getterReturnType as InterfaceType)).lookUpMethod(CALL_METHOD_NAME, _definingLibrary);
if (callMethod != null) {
return resolveArgumentsToParameters(false, argumentList, callMethod);
}
@@ -3828,7 +3833,7 @@
List<ParameterElement> parameters = functionType.parameters;
return resolveArgumentsToParameters2(false, argumentList, parameters);
} else if (type is InterfaceType) {
- MethodElement callMethod = ((type as InterfaceType)).lookUpMethod(CALL_METHOD_NAME, _resolver.definingLibrary);
+ MethodElement callMethod = ((type as InterfaceType)).lookUpMethod(CALL_METHOD_NAME, _definingLibrary);
if (callMethod != null) {
List<ParameterElement> parameters = callMethod.parameters;
return resolveArgumentsToParameters2(false, argumentList, parameters);
@@ -3862,17 +3867,16 @@
Element findImportWithoutPrefix(SimpleIdentifier identifier) {
Element element = null;
Scope nameScope = _resolver.nameScope;
- LibraryElement definingLibrary = _resolver.definingLibrary;
- for (ImportElement importElement in definingLibrary.imports) {
+ for (ImportElement importElement in _definingLibrary.imports) {
PrefixElement prefixElement = importElement.prefix;
if (prefixElement != null) {
Identifier prefixedIdentifier = new ElementResolver_SyntheticIdentifier("${prefixElement.name}.${identifier.name}");
- Element importedElement = nameScope.lookup(prefixedIdentifier, definingLibrary);
+ Element importedElement = nameScope.lookup(prefixedIdentifier, _definingLibrary);
if (importedElement != null) {
if (element == null) {
element = importedElement;
} else {
- element = MultiplyDefinedElementImpl.fromElements(definingLibrary.context, element, importedElement);
+ element = MultiplyDefinedElementImpl.fromElements(_definingLibrary.context, element, importedElement);
}
}
}
@@ -3951,7 +3955,7 @@
return true;
} else if (type is InterfaceType) {
ClassElement classElement = ((type as InterfaceType)).element;
- MethodElement methodElement = classElement.lookUpMethod(CALL_METHOD_NAME, _resolver.definingLibrary);
+ MethodElement methodElement = classElement.lookUpMethod(CALL_METHOD_NAME, _definingLibrary);
return methodElement != null;
}
return false;
@@ -4020,9 +4024,9 @@
InterfaceType interfaceType = type as InterfaceType;
PropertyAccessorElement accessor;
if (target is SuperExpression) {
- accessor = interfaceType.lookUpGetterInSuperclass(getterName, _resolver.definingLibrary);
+ accessor = interfaceType.lookUpGetterInSuperclass(getterName, _definingLibrary);
} else {
- accessor = interfaceType.lookUpGetter(getterName, _resolver.definingLibrary);
+ accessor = interfaceType.lookUpGetter(getterName, _definingLibrary);
}
if (accessor != null) {
return accessor;
@@ -4052,7 +4056,7 @@
javaSetAdd(visitedInterfaces, targetClass);
if (includeTargetType) {
PropertyAccessorElement getter = targetType.getGetter(getterName);
- if (getter != null && getter.isAccessibleIn(_resolver.definingLibrary)) {
+ if (getter != null && getter.isAccessibleIn(_definingLibrary)) {
return getter;
}
}
@@ -4088,11 +4092,11 @@
type = resolveTypeParameter(type);
if (type is InterfaceType) {
InterfaceType interfaceType = type as InterfaceType;
- ExecutableElement member = interfaceType.lookUpMethod(memberName, _resolver.definingLibrary);
+ ExecutableElement member = interfaceType.lookUpMethod(memberName, _definingLibrary);
if (member != null) {
return member;
}
- member = interfaceType.lookUpGetter(memberName, _resolver.definingLibrary);
+ member = interfaceType.lookUpGetter(memberName, _definingLibrary);
if (member != null) {
return member;
}
@@ -4203,9 +4207,9 @@
InterfaceType interfaceType = type as InterfaceType;
MethodElement method;
if (target is SuperExpression) {
- method = interfaceType.lookUpMethodInSuperclass(methodName, _resolver.definingLibrary);
+ method = interfaceType.lookUpMethodInSuperclass(methodName, _definingLibrary);
} else {
- method = interfaceType.lookUpMethod(methodName, _resolver.definingLibrary);
+ method = interfaceType.lookUpMethod(methodName, _definingLibrary);
}
if (method != null) {
return method;
@@ -4235,7 +4239,7 @@
javaSetAdd(visitedInterfaces, targetClass);
if (includeTargetType) {
MethodElement method = targetType.getMethod(methodName);
- if (method != null && method.isAccessibleIn(_resolver.definingLibrary)) {
+ if (method != null && method.isAccessibleIn(_definingLibrary)) {
return method;
}
}
@@ -4273,9 +4277,9 @@
InterfaceType interfaceType = type as InterfaceType;
PropertyAccessorElement accessor;
if (target is SuperExpression) {
- accessor = interfaceType.lookUpSetterInSuperclass(setterName, _resolver.definingLibrary);
+ accessor = interfaceType.lookUpSetterInSuperclass(setterName, _definingLibrary);
} else {
- accessor = interfaceType.lookUpSetter(setterName, _resolver.definingLibrary);
+ accessor = interfaceType.lookUpSetter(setterName, _definingLibrary);
}
if (accessor != null) {
return accessor;
@@ -4305,7 +4309,7 @@
javaSetAdd(visitedInterfaces, targetClass);
if (includeTargetType) {
PropertyAccessorElement setter = targetType.getSetter(setterName);
- if (setter != null && setter.isAccessibleIn(_resolver.definingLibrary)) {
+ if (setter != null && setter.isAccessibleIn(_definingLibrary)) {
return setter;
}
}
@@ -4343,7 +4347,7 @@
*/
bool memberFoundInSubclass(Element element, String memberName, bool asMethod, bool asAccessor) {
if (element is ClassElement) {
- _subtypeManager.ensureLibraryVisited(_resolver.definingLibrary);
+ _subtypeManager.ensureLibraryVisited(_definingLibrary);
Set<ClassElement> subtypeElements = _subtypeManager.computeAllSubtypes(element as ClassElement);
for (ClassElement subtypeElement in subtypeElements) {
if (asMethod && subtypeElement.getMethod(memberName) != null) {
@@ -4433,8 +4437,7 @@
ConstructorElement constructor;
{
InterfaceType interfaceType = new InterfaceTypeImpl.con1(element as ClassElement);
- LibraryElement definingLibrary = _resolver.definingLibrary;
- constructor = interfaceType.lookUpConstructor(name, definingLibrary);
+ constructor = interfaceType.lookUpConstructor(name, _definingLibrary);
}
if (constructor == null) {
_resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotation, []);
@@ -4589,7 +4592,7 @@
if (targetElement is PrefixElement) {
String name = "${((target as SimpleIdentifier)).name}.${methodName}";
Identifier functionName = new ElementResolver_SyntheticIdentifier(name);
- Element element = _resolver.nameScope.lookup(functionName, _resolver.definingLibrary);
+ Element element = _resolver.nameScope.lookup(functionName, _definingLibrary);
if (element != null) {
return element;
}
@@ -4608,7 +4611,7 @@
* @return the element being invoked
*/
Element resolveInvokedElement2(SimpleIdentifier methodName) {
- Element element = _resolver.nameScope.lookup(methodName, _resolver.definingLibrary);
+ Element element = _resolver.nameScope.lookup(methodName, _definingLibrary);
if (element == null) {
ClassElement enclosingClass = _resolver.enclosingClass;
if (enclosingClass != null) {
@@ -4706,7 +4709,7 @@
* @return the element to which the identifier could be resolved
*/
Element resolveSimpleIdentifier(SimpleIdentifier node) {
- Element element = _resolver.nameScope.lookup(node, _resolver.definingLibrary);
+ Element element = _resolver.nameScope.lookup(node, _definingLibrary);
if (element is PropertyAccessorElement && node.inSetterContext()) {
PropertyInducingElement variable = ((element as PropertyAccessorElement)).variable;
if (variable != null) {
@@ -4722,7 +4725,7 @@
}
}
} else if (element == null && node.inSetterContext()) {
- element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdentifier("${node.name}="), _resolver.definingLibrary);
+ element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdentifier("${node.name}="), _definingLibrary);
}
ClassElement enclosingClass = _resolver.enclosingClass;
if (element == null && enclosingClass != null) {
@@ -5341,14 +5344,13 @@
*/
void substituteTypeParametersDownHierarchy(InterfaceType superType, MemberMap map) {
for (int i = 0; i < map.size; i++) {
- String key = map.getKey(i);
ExecutableElement executableElement = map.getValue(i);
if (executableElement is MethodMember) {
executableElement = MethodMember.from(executableElement as MethodMember, superType);
- map.put(key, executableElement);
+ map.setValue(i, executableElement);
} else if (executableElement is PropertyAccessorMember) {
executableElement = PropertyAccessorMember.from(executableElement as PropertyAccessorMember, superType);
- map.put(key, executableElement);
+ map.setValue(i, executableElement);
}
}
}
@@ -6608,6 +6610,16 @@
}
/**
+ * Sets the ExecutableElement at the specified location.
+ *
+ * @param i some non-zero value less than size
+ * @param value the ExecutableElement value to store in the map
+ */
+ void setValue(int i, ExecutableElement value) {
+ _values[i] = value;
+ }
+
+ /**
* Initializes [keys] and [values].
*/
void initArrays(int initialCapacity) {
@@ -10823,6 +10835,7 @@
}
if (elementValid && element == null) {
SimpleIdentifier typeNameSimple = getTypeSimpleIdentifier(typeName);
+ RedirectingConstructorKind redirectingConstructorKind;
if (isBuiltInIdentifier(node) && isTypeAnnotation(node)) {
reportError5(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, typeName, [typeName.name]);
} else if (typeNameSimple.name == "boolean") {
@@ -10833,8 +10846,9 @@
reportError5(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.name]);
} else if (isTypeNameInIsExpression(node)) {
reportError5(StaticWarningCode.TYPE_TEST_NON_TYPE, typeName, [typeName.name]);
- } else if (isTypeNameTargetInRedirectedConstructor(node)) {
- reportError5(StaticWarningCode.REDIRECT_TO_NON_CLASS, typeName, [typeName.name]);
+ } else if ((redirectingConstructorKind = getRedirectingConstructorKind(node)) != null) {
+ ErrorCode errorCode = (identical(redirectingConstructorKind, RedirectingConstructorKind.CONST) ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS : StaticWarningCode.REDIRECT_TO_NON_CLASS) as ErrorCode;
+ reportError5(errorCode, typeName, [typeName.name]);
} else if (isTypeNameInTypeArgumentList(node)) {
reportError5(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, typeName, [typeName.name]);
} else {
@@ -10871,14 +10885,16 @@
node.type = type;
}
} else {
+ RedirectingConstructorKind redirectingConstructorKind;
if (isTypeNameInCatchClause(node)) {
reportError5(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName, [typeName.name]);
} else if (isTypeNameInAsExpression(node)) {
reportError5(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.name]);
} else if (isTypeNameInIsExpression(node)) {
reportError5(StaticWarningCode.TYPE_TEST_NON_TYPE, typeName, [typeName.name]);
- } else if (isTypeNameTargetInRedirectedConstructor(node)) {
- reportError5(StaticWarningCode.REDIRECT_TO_NON_CLASS, typeName, [typeName.name]);
+ } else if ((redirectingConstructorKind = getRedirectingConstructorKind(node)) != null) {
+ ErrorCode errorCode = (identical(redirectingConstructorKind, RedirectingConstructorKind.CONST) ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS : StaticWarningCode.REDIRECT_TO_NON_CLASS) as ErrorCode;
+ reportError5(errorCode, typeName, [typeName.name]);
} else if (isTypeNameInTypeArgumentList(node)) {
reportError5(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, typeName, [typeName.name]);
} else {
@@ -11058,6 +11074,31 @@
}
/**
+ * Checks if the given type name is the target in a redirected constructor.
+ *
+ * @param typeName the type name to analyze
+ * @return some [RedirectingConstructorKind] if the given type name is used as the type in a
+ * redirected constructor, or `null` otherwise
+ */
+ RedirectingConstructorKind getRedirectingConstructorKind(TypeName typeName) {
+ ASTNode parent = typeName.parent;
+ if (parent is ConstructorName) {
+ ConstructorName constructorName = parent as ConstructorName;
+ parent = constructorName.parent;
+ if (parent is ConstructorDeclaration) {
+ ConstructorDeclaration constructorDeclaration = parent as ConstructorDeclaration;
+ if (identical(constructorDeclaration.redirectedConstructor, constructorName)) {
+ if (constructorDeclaration.constKeyword != null) {
+ return RedirectingConstructorKind.CONST;
+ }
+ return RedirectingConstructorKind.NORMAL;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
* Given the multiple elements to which a single name could potentially be resolved, return the
* single interface type that should be used, or `null` if there is no clear choice.
*
@@ -11190,25 +11231,6 @@
bool isTypeNameInTypeArgumentList(TypeName typeName) => typeName.parent is TypeArgumentList;
/**
- * Checks if the given type name is the target in a redirected constructor.
- *
- * @param typeName the type name to analyzer
- * @return `true` if the given type name is used as the type in a redirected constructor
- */
- bool isTypeNameTargetInRedirectedConstructor(TypeName typeName) {
- ASTNode parent = typeName.parent;
- if (parent is ConstructorName) {
- ConstructorName constructorName = parent as ConstructorName;
- parent = constructorName.parent;
- if (parent is ConstructorDeclaration) {
- ConstructorDeclaration constructorDeclaration = parent as ConstructorDeclaration;
- return constructorName == constructorDeclaration.redirectedConstructor;
- }
- }
- return false;
- }
-
- /**
* Record that the static type of the given node is the given type.
*
* @param expression the node whose type is to be recorded
@@ -11362,6 +11384,15 @@
}
}
/**
+ * Kind of the redirecting constructor.
+ */
+class RedirectingConstructorKind extends Enum<RedirectingConstructorKind> {
+ static final RedirectingConstructorKind CONST = new RedirectingConstructorKind('CONST', 0);
+ static final RedirectingConstructorKind NORMAL = new RedirectingConstructorKind('NORMAL', 1);
+ static final List<RedirectingConstructorKind> values = [CONST, NORMAL];
+ RedirectingConstructorKind(String name, int ordinal) : super(name, ordinal);
+}
+/**
* Instances of the class `VariableResolverVisitor` are used to resolve
* [SimpleIdentifier]s to local variables and formal parameters.
*
@@ -12739,6 +12770,11 @@
Type2 _dynamicType;
/**
+ * The type representing the type 'bool'.
+ */
+ InterfaceType _boolType;
+
+ /**
* The object providing access to the types defined by the language.
*/
TypeProvider _typeProvider;
@@ -12909,13 +12945,14 @@
_isInInstanceVariableInitializer = false;
_isInConstructorInitializer = false;
_isInStaticMethod = false;
+ _boolType = typeProvider.boolType;
_dynamicType = typeProvider.dynamicType;
_DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = <InterfaceType> [
typeProvider.nullType,
typeProvider.numType,
typeProvider.intType,
typeProvider.doubleType,
- typeProvider.boolType,
+ _boolType,
typeProvider.stringType];
}
Object visitArgumentDefinitionTest(ArgumentDefinitionTest node) {
@@ -13305,10 +13342,14 @@
return super.visitPrefixedIdentifier(node);
}
Object visitPrefixExpression(PrefixExpression node) {
- if (node.operator.type.isIncrementOperator) {
- checkForAssignmentToFinal2(node.operand);
+ sc.TokenType operatorType = node.operator.type;
+ Expression operand = node.operand;
+ if (identical(operatorType, sc.TokenType.BANG)) {
+ checkForNonBoolNegationExpression(operand);
+ } else if (operatorType.isIncrementOperator) {
+ checkForAssignmentToFinal2(operand);
}
- checkForIntNotAssignable(node.operand);
+ checkForIntNotAssignable(operand);
return super.visitPrefixExpression(node);
}
Object visitPropertyAccess(PropertyAccess node) {
@@ -13872,7 +13913,8 @@
if (redirectedConstructor.name != null) {
constructorStrName += ".${redirectedConstructor.name.name}";
}
- _errorReporter.reportError2(StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR, redirectedConstructor, [constructorStrName, redirectedType.displayName]);
+ ErrorCode errorCode = (node.constKeyword != null ? CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR : StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR) as ErrorCode;
+ _errorReporter.reportError2(errorCode, redirectedConstructor, [constructorStrName, redirectedType.displayName]);
return true;
}
return false;
@@ -15879,7 +15921,7 @@
*/
bool checkForNonBoolCondition(Expression condition) {
Type2 conditionType = getStaticType(condition);
- if (conditionType != null && !conditionType.isAssignableTo(_typeProvider.boolType)) {
+ if (conditionType != null && !conditionType.isAssignableTo(_boolType)) {
_errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_CONDITION, condition, []);
return true;
}
@@ -15897,13 +15939,13 @@
Expression expression = node.condition;
Type2 type = getStaticType(expression);
if (type is InterfaceType) {
- if (!type.isAssignableTo(_typeProvider.boolType)) {
+ if (!type.isAssignableTo(_boolType)) {
_errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression, []);
return true;
}
} else if (type is FunctionType) {
FunctionType functionType = type as FunctionType;
- if (functionType.typeArguments.length == 0 && !functionType.returnType.isAssignableTo(_typeProvider.boolType)) {
+ if (functionType.typeArguments.length == 0 && !functionType.returnType.isAssignableTo(_boolType)) {
_errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression, []);
return true;
}
@@ -15912,6 +15954,22 @@
}
/**
+ * Checks to ensure that the given expression is assignable to bool.
+ *
+ * @param expression the expression expression to test
+ * @return `true` if and only if an error code is generated on the passed node
+ * @see StaticTypeWarningCode#NON_BOOL_NEGATION_EXPRESSION
+ */
+ bool checkForNonBoolNegationExpression(Expression expression) {
+ Type2 conditionType = getStaticType(expression);
+ if (conditionType != null && !conditionType.isAssignableTo(_boolType)) {
+ _errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, expression, []);
+ return true;
+ }
+ return false;
+ }
+
+ /**
* This verifies the passed map literal either:
*
* * has `const modifier`
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index a9cfe4d..1df9ef8 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.9.0
+version: 0.9.1
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 4a0fb46b..ec6d987 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -2557,6 +2557,18 @@
assertNoErrors(source);
verify([source]);
}
+ void test_nonBoolNegationExpression() {
+ Source source = addSource(EngineTestCase.createSource([
+ "f(bool pb, pd) {",
+ " !true;",
+ " !false;",
+ " !pb;",
+ " !pd;",
+ "}"]));
+ resolve(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
void test_nonConstantDefaultValue_function_named() {
Source source = addSource(EngineTestCase.createSource(["f({x : 2 + 3}) {}"]));
resolve(source);
@@ -4367,6 +4379,10 @@
final __test = new NonErrorResolverTest();
runJUnitTest(__test, __test.test_nonBoolExpression_interfaceType);
});
+ _ut.test('test_nonBoolNegationExpression', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_nonBoolNegationExpression);
+ });
_ut.test('test_nonConstCaseExpression', () {
final __test = new NonErrorResolverTest();
runJUnitTest(__test, __test.test_nonConstCaseExpression);
@@ -5201,6 +5217,12 @@
assertErrors(source, [StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
verify([source]);
}
+ void test_nonBoolNegationExpression() {
+ Source source = addSource(EngineTestCase.createSource(["f() {", " !42;", "}"]));
+ resolve(source);
+ assertErrors(source, [StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION]);
+ verify([source]);
+ }
void test_nonTypeAsTypeArgument_notAType() {
Source source = addSource(EngineTestCase.createSource(["int A;", "class B<E> {}", "f(B<A> b) {}"]));
resolve(source);
@@ -5875,6 +5897,10 @@
final __test = new StaticTypeWarningCodeTest();
runJUnitTest(__test, __test.test_nonBoolExpression_interfaceType);
});
+ _ut.test('test_nonBoolNegationExpression', () {
+ final __test = new StaticTypeWarningCodeTest();
+ runJUnitTest(__test, __test.test_nonBoolNegationExpression);
+ });
_ut.test('test_nonTypeAsTypeArgument_notAType', () {
final __test = new StaticTypeWarningCodeTest();
runJUnitTest(__test, __test.test_nonTypeAsTypeArgument_notAType);
@@ -10493,6 +10519,40 @@
assertErrors(source, [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS]);
verify([source]);
}
+ void test_redirectToMissingConstructor_named() {
+ Source source = addSource(EngineTestCase.createSource([
+ "class A implements B{",
+ " A() {}",
+ "}",
+ "class B {",
+ " const factory B() = A.name;",
+ "}"]));
+ resolve(source);
+ assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
+ }
+ void test_redirectToMissingConstructor_unnamed() {
+ Source source = addSource(EngineTestCase.createSource([
+ "class A implements B{",
+ " A.name() {}",
+ "}",
+ "class B {",
+ " const factory B() = A;",
+ "}"]));
+ resolve(source);
+ assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
+ }
+ void test_redirectToNonClass_notAType() {
+ Source source = addSource(EngineTestCase.createSource(["int A;", "class B {", " const factory B() = A;", "}"]));
+ resolve(source);
+ assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_NON_CLASS]);
+ verify([source]);
+ }
+ void test_redirectToNonClass_undefinedIdentifier() {
+ Source source = addSource(EngineTestCase.createSource(["class B {", " const factory B() = A;", "}"]));
+ resolve(source);
+ assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_NON_CLASS]);
+ verify([source]);
+ }
void test_redirectToNonConstConstructor() {
Source source = addSource(EngineTestCase.createSource([
"class A {",
@@ -12038,6 +12098,22 @@
final __test = new CompileTimeErrorCodeTest();
runJUnitTest(__test, __test.test_recursiveInterfaceInheritance_tail3);
});
+ _ut.test('test_redirectToMissingConstructor_named', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_redirectToMissingConstructor_named);
+ });
+ _ut.test('test_redirectToMissingConstructor_unnamed', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_redirectToMissingConstructor_unnamed);
+ });
+ _ut.test('test_redirectToNonClass_notAType', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_redirectToNonClass_notAType);
+ });
+ _ut.test('test_redirectToNonClass_undefinedIdentifier', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_redirectToNonClass_undefinedIdentifier);
+ });
_ut.test('test_redirectToNonConstConstructor', () {
final __test = new CompileTimeErrorCodeTest();
runJUnitTest(__test, __test.test_redirectToNonConstConstructor);
diff --git a/pkg/barback/lib/barback.dart b/pkg/barback/lib/barback.dart
index d6dfccf..37c1506 100644
--- a/pkg/barback/lib/barback.dart
+++ b/pkg/barback/lib/barback.dart
@@ -8,9 +8,9 @@
export 'src/asset_id.dart';
export 'src/asset_set.dart';
export 'src/barback.dart';
-export 'src/barback_logger.dart';
export 'src/build_result.dart';
export 'src/errors.dart' hide flattenAggregateExceptions;
+export 'src/log.dart';
export 'src/package_provider.dart';
export 'src/transform.dart' show Transform;
export 'src/transform_logger.dart';
diff --git a/pkg/barback/lib/src/asset_cascade.dart b/pkg/barback/lib/src/asset_cascade.dart
index 9857c80..cc90560 100644
--- a/pkg/barback/lib/src/asset_cascade.dart
+++ b/pkg/barback/lib/src/asset_cascade.dart
@@ -11,7 +11,7 @@
import 'asset_id.dart';
import 'asset_node.dart';
import 'asset_set.dart';
-import 'barback_logger.dart';
+import 'log.dart';
import 'build_result.dart';
import 'cancelable_future.dart';
import 'errors.dart';
@@ -85,7 +85,7 @@
/// A controller whose stream feeds into [_onDirtyPool].
final _onDirtyController = new StreamController.broadcast(sync: true);
- /// A stream that emits an event whenever any transforms in this cascade log
+ /// A stream that emits an event whenever any transforms in this cascade logs
/// an entry.
Stream<LogEntry> get onLog => _onLogPool.stream;
final _onLogPool = new StreamPool<LogEntry>.broadcast();
diff --git a/pkg/barback/lib/src/barback.dart b/pkg/barback/lib/src/barback.dart
index 932077e..1027369 100644
--- a/pkg/barback/lib/src/barback.dart
+++ b/pkg/barback/lib/src/barback.dart
@@ -9,7 +9,7 @@
import 'asset.dart';
import 'asset_id.dart';
import 'asset_set.dart';
-import 'barback_logger.dart';
+import 'log.dart';
import 'build_result.dart';
import 'errors.dart';
import 'package_graph.dart';
@@ -65,8 +65,14 @@
/// emitted through the [results] stream's error channel.
Stream get errors => _graph.errors;
- Barback(PackageProvider provider, {BarbackLogger logger})
- : _graph = new PackageGraph(provider, logger: logger);
+ /// The stream of [LogEntry] objects used to report transformer log entries.
+ ///
+ /// If this stream has listeners, then log entries will go to that.
+ /// Otherwise, a default logger will display them.
+ Stream<LogEntry> get log => _graph.log;
+
+ Barback(PackageProvider provider)
+ : _graph = new PackageGraph(provider);
/// Gets the asset identified by [id].
///
diff --git a/pkg/barback/lib/src/build_result.dart b/pkg/barback/lib/src/build_result.dart
index 00c702c..65e8269 100644
--- a/pkg/barback/lib/src/build_result.dart
+++ b/pkg/barback/lib/src/build_result.dart
@@ -8,7 +8,6 @@
import 'package:stack_trace/stack_trace.dart';
-import 'barback_logger.dart';
import 'errors.dart';
import 'utils.dart';
diff --git a/pkg/barback/lib/src/file_pool.dart b/pkg/barback/lib/src/file_pool.dart
index 7e95c68..ace7ae4 100644
--- a/pkg/barback/lib/src/file_pool.dart
+++ b/pkg/barback/lib/src/file_pool.dart
@@ -5,7 +5,6 @@
library barback.file_pool;
import 'dart:async';
-import 'dart:collection';
import 'dart:convert';
import 'dart:io';
diff --git a/pkg/barback/lib/src/group_runner.dart b/pkg/barback/lib/src/group_runner.dart
index dc7b4b4..4718d18 100644
--- a/pkg/barback/lib/src/group_runner.dart
+++ b/pkg/barback/lib/src/group_runner.dart
@@ -8,7 +8,7 @@
import 'asset_cascade.dart';
import 'asset_node.dart';
-import 'barback_logger.dart';
+import 'log.dart';
import 'phase.dart';
import 'stream_pool.dart';
import 'transformer_group.dart';
@@ -32,8 +32,8 @@
/// Whether this group is dirty and needs to be run.
bool get isDirty => _phases.any((phase) => phase.isDirty);
- /// A stream that emits an event whenever any transforms in this group log an
- /// entry.
+ /// A stream that emits an event whenever any transforms in this group logs
+ /// an entry.
Stream<LogEntry> get onLog => _onLogPool.stream;
final _onLogPool = new StreamPool<LogEntry>.broadcast();
diff --git a/pkg/barback/lib/src/barback_logger.dart b/pkg/barback/lib/src/log.dart
similarity index 61%
rename from pkg/barback/lib/src/barback_logger.dart
rename to pkg/barback/lib/src/log.dart
index c343c59..809d8a9 100644
--- a/pkg/barback/lib/src/barback_logger.dart
+++ b/pkg/barback/lib/src/log.dart
@@ -2,32 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library barback.barback_logger;
+library barback.log;
import 'package:source_maps/span.dart';
import 'asset_id.dart';
import 'errors.dart';
-/// Object used to report warnings and errors encountered while running a
-/// transformer.
-class BarbackLogger {
- /// Logs [entry].
- void logEntry(LogEntry entry) {
- var buffer = new StringBuffer();
- buffer.write("[${entry.level} ${entry.transform}] ");
-
- var message = entry.message;
- if (entry.span == null) {
- buffer.write(entry.span.getLocationMessage(entry.message));
- } else {
- buffer.write(message);
- }
-
- print(buffer);
- }
-}
-
/// The severity of a logged message.
class LogLevel {
static const INFO = const LogLevel("Info");
@@ -46,7 +27,7 @@
final TransformInfo transform;
/// The asset that the message is associated with.
- final AssetId asset;
+ final AssetId assetId;
final LogLevel level;
final String message;
@@ -55,5 +36,5 @@
/// a source [Span].
final Span span;
- LogEntry(this.transform, this.asset, this.level, this.message, this.span);
+ LogEntry(this.transform, this.assetId, this.level, this.message, this.span);
}
diff --git a/pkg/barback/lib/src/package_graph.dart b/pkg/barback/lib/src/package_graph.dart
index dcc3d7f..95ecbb1 100644
--- a/pkg/barback/lib/src/package_graph.dart
+++ b/pkg/barback/lib/src/package_graph.dart
@@ -10,9 +10,9 @@
import 'asset_id.dart';
import 'asset_node.dart';
import 'asset_set.dart';
-import 'barback_logger.dart';
import 'build_result.dart';
import 'errors.dart';
+import 'log.dart';
import 'package_provider.dart';
import 'pool.dart';
import 'transformer.dart';
@@ -26,10 +26,6 @@
/// The provider that exposes asset and package information.
final PackageProvider provider;
- /// The logger used to report transformer log entries. If this is null, then
- /// [_defaultLogger] will be used instead.
- final BarbackLogger _logger;
-
/// The [AssetCascade] for each package.
final _cascades = <String, AssetCascade>{};
@@ -60,6 +56,10 @@
Stream<BarbackException> get errors => _errors;
Stream<BarbackException> _errors;
+ /// The stream of [LogEntry] objects used to report transformer log entries.
+ Stream<LogEntry> get log => _logController.stream;
+ final _logController = new StreamController<LogEntry>.broadcast();
+
/// The most recent error emitted from a cascade's result stream.
///
/// This is used to pipe an unexpected error from a build to the resulting
@@ -75,8 +75,7 @@
/// Creates a new [PackageGraph] that will transform assets in all packages
/// made available by [provider].
- PackageGraph(this.provider, {BarbackLogger logger})
- : _logger = logger != null ? logger : new BarbackLogger() {
+ PackageGraph(this.provider) {
for (var package in provider.packages) {
var cascade = new AssetCascade(this, package);
// The initial result for each cascade is "success" since the cascade
@@ -87,7 +86,23 @@
_cascadeResults[package] = null;
});
- cascade.onLog.listen(_logger.logEntry);
+ cascade.onLog.listen((entry) {
+ if (_logController.hasListener) {
+ _logController.add(entry);
+ } else {
+ // No listeners, so just print entry.
+ var buffer = new StringBuffer();
+ buffer.write("[${entry.level} ${entry.transform}] ");
+
+ if (entry.span != null) {
+ buffer.write(entry.span.getLocationMessage(entry.message));
+ } else {
+ buffer.write(entry.message);
+ }
+
+ print(buffer);
+ }
+ });
cascade.results.listen((result) {
_cascadeResults[cascade.package] = result;
diff --git a/pkg/barback/lib/src/phase.dart b/pkg/barback/lib/src/phase.dart
index 8680e60..d712354 100644
--- a/pkg/barback/lib/src/phase.dart
+++ b/pkg/barback/lib/src/phase.dart
@@ -5,15 +5,12 @@
library barback.phase;
import 'dart:async';
-import 'dart:collection';
import 'asset_cascade.dart';
import 'asset_id.dart';
import 'asset_node.dart';
-import 'asset_set.dart';
-import 'barback_logger.dart';
import 'group_runner.dart';
-import 'errors.dart';
+import 'log.dart';
import 'multiset.dart';
import 'phase_forwarder.dart';
import 'phase_input.dart';
@@ -92,8 +89,8 @@
bool get isDirty => _inputs.values.any((input) => input.isDirty) ||
_groups.values.any((group) => group.isDirty);
- /// A stream that emits an event whenever any transforms in this phase log an
- /// entry.
+ /// A stream that emits an event whenever any transforms in this phase logs
+ /// an entry.
Stream<LogEntry> get onLog => _onLogPool.stream;
final _onLogPool = new StreamPool<LogEntry>.broadcast();
diff --git a/pkg/barback/lib/src/phase_forwarder.dart b/pkg/barback/lib/src/phase_forwarder.dart
index 90831f7e..c1f7abd 100644
--- a/pkg/barback/lib/src/phase_forwarder.dart
+++ b/pkg/barback/lib/src/phase_forwarder.dart
@@ -7,8 +7,6 @@
import 'dart:async';
import 'asset_node.dart';
-import 'asset_forwarder.dart';
-import 'phase_output.dart';
/// A class that takes care of forwarding assets within a phase.
///
diff --git a/pkg/barback/lib/src/phase_input.dart b/pkg/barback/lib/src/phase_input.dart
index 1b96ee0..240fb03 100644
--- a/pkg/barback/lib/src/phase_input.dart
+++ b/pkg/barback/lib/src/phase_input.dart
@@ -10,8 +10,8 @@
import 'asset.dart';
import 'asset_forwarder.dart';
import 'asset_node.dart';
-import 'barback_logger.dart';
import 'errors.dart';
+import 'log.dart';
import 'phase.dart';
import 'stream_pool.dart';
import 'transform_node.dart';
diff --git a/pkg/barback/lib/src/pool.dart b/pkg/barback/lib/src/pool.dart
index 8da8434..3224fbe 100644
--- a/pkg/barback/lib/src/pool.dart
+++ b/pkg/barback/lib/src/pool.dart
@@ -1,3 +1,9 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library barback.pool;
+
import 'dart:async';
import 'dart:collection';
diff --git a/pkg/barback/lib/src/stream_replayer.dart b/pkg/barback/lib/src/stream_replayer.dart
index bb04007..705f97a 100644
--- a/pkg/barback/lib/src/stream_replayer.dart
+++ b/pkg/barback/lib/src/stream_replayer.dart
@@ -11,10 +11,16 @@
/// Records the values and errors that are sent through a stream and allows them
/// to be replayed arbitrarily many times.
+///
+/// This only listens to the wrapped stream when a replayed stream gets a
+/// listener.
class StreamReplayer<T> {
/// The wrapped stream.
final Stream<T> _stream;
+ /// Whether or not [this] has started listening to [_stream].
+ bool _isSubscribed = false;
+
/// Whether or not [_stream] has been closed.
bool _isClosed = false;
@@ -28,7 +34,32 @@
/// The controllers that are listening for future events from [_stream].
final _controllers = new Set<StreamController<T>>();
- StreamReplayer(this._stream) {
+ StreamReplayer(this._stream);
+
+ /// Returns a stream that replays the values and errors of the input stream.
+ ///
+ /// This stream is a buffered stream.
+ Stream<T> getReplay() {
+ var controller = new StreamController<T>(onListen: _subscribe);
+
+ for (var eventOrError in _buffer) {
+ eventOrError.match(controller.add, (pair) {
+ controller.addError(pair.first, pair.second);
+ });
+ }
+ if (_isClosed) {
+ controller.close();
+ } else {
+ _controllers.add(controller);
+ }
+ return controller.stream;
+ }
+
+ /// Subscribe to [_stream] if we haven't yet done so.
+ void _subscribe() {
+ if (_isSubscribed || _isClosed) return;
+ _isSubscribed = true;
+
_stream.listen((data) {
_buffer.add(new Either<T, dynamic>.withFirst(data));
for (var controller in _controllers) {
@@ -48,23 +79,4 @@
_controllers.clear();
});
}
-
- /// Returns a stream that replays the values and errors of the input stream.
- ///
- /// This stream is a buffered stream regardless of whether the input stream
- /// was broadcast or buffered.
- Stream<T> getReplay() {
- var controller = new StreamController<T>();
- for (var eventOrError in _buffer) {
- eventOrError.match(controller.add, (pair) {
- controller.addError(pair.first, pair.second);
- });
- }
- if (_isClosed) {
- controller.close();
- } else {
- _controllers.add(controller);
- }
- return controller.stream;
- }
}
diff --git a/pkg/barback/lib/src/transform.dart b/pkg/barback/lib/src/transform.dart
index fa1df82..7f0d217 100644
--- a/pkg/barback/lib/src/transform.dart
+++ b/pkg/barback/lib/src/transform.dart
@@ -13,8 +13,8 @@
import 'asset_id.dart';
import 'asset_node.dart';
import 'asset_set.dart';
-import 'barback_logger.dart';
import 'errors.dart';
+import 'log.dart';
import 'transform_logger.dart';
import 'transform_node.dart';
import 'utils.dart';
diff --git a/pkg/barback/lib/src/transform_logger.dart b/pkg/barback/lib/src/transform_logger.dart
index d046460..6067b36 100644
--- a/pkg/barback/lib/src/transform_logger.dart
+++ b/pkg/barback/lib/src/transform_logger.dart
@@ -7,7 +7,7 @@
import 'package:source_maps/span.dart';
import 'asset_id.dart';
-import 'barback_logger.dart';
+import 'log.dart';
import 'transform.dart';
/// Object used to report warnings and errors encountered while running a
@@ -19,8 +19,8 @@
/// Logs an informative message.
///
- /// If [asset] is provided, the log entry is associated with that asset,
- /// otherwise it's associated with the primary input of [transformer].
+ /// If [asset] is provided, the log entry is associated with that asset.
+ /// Otherwise it's associated with the primary input of [transformer].
/// If [span] is provided, indicates the location in the input asset that
/// caused the message.
void info(String message, {AssetId asset, Span span}) {
@@ -29,8 +29,8 @@
/// Logs a warning message.
///
- /// If [asset] is provided, the log entry is associated with that asset,
- /// otherwise it's associated with the primary input of [transformer].
+ /// If [asset] is provided, the log entry is associated with that asset.
+ /// Otherwise it's associated with the primary input of [transformer].
/// If present, [span] indicates the location in the input asset that caused
/// the warning.
void warning(String message, {AssetId asset, Span span}) {
@@ -39,8 +39,8 @@
/// Logs an error message.
///
- /// If [asset] is provided, the log entry is associated with that asset,
- /// otherwise it's associated with the primary input of [transformer].
+ /// If [asset] is provided, the log entry is associated with that asset.
+ /// Otherwise it's associated with the primary input of [transformer].
/// If present, [span] indicates the location in the input asset that caused
/// the error.
// TODO(sigmund,nweiz): clarify when an error should be logged or thrown.
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index aa77d72..1ef1919 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -12,8 +12,8 @@
import 'asset_id.dart';
import 'asset_node.dart';
import 'asset_set.dart';
-import 'barback_logger.dart';
import 'errors.dart';
+import 'log.dart';
import 'phase.dart';
import 'transform.dart';
import 'transformer.dart';
@@ -218,7 +218,6 @@
void _log(AssetId asset, LogLevel level, String message, Span span) {
// If the log isn't already associated with an asset, use the primary.
if (asset == null) asset = primary.id;
- var info = new TransformInfo(transformer, primary.id);
var entry = new LogEntry(info, asset, level, message, span);
_onLogController.add(entry);
}
diff --git a/pkg/barback/lib/src/transformer_group.dart b/pkg/barback/lib/src/transformer_group.dart
index f6bf2b8..49359c9 100644
--- a/pkg/barback/lib/src/transformer_group.dart
+++ b/pkg/barback/lib/src/transformer_group.dart
@@ -4,8 +4,6 @@
library barback.transformer_group;
-import 'dart:async';
-
/// A [TransformerGroup] encapsulates a phased collection of transformers.
///
/// A transformer group is defined like a collection of phases, such as you
diff --git a/pkg/barback/lib/src/utils.dart b/pkg/barback/lib/src/utils.dart
index a925bec..22203b4 100644
--- a/pkg/barback/lib/src/utils.dart
+++ b/pkg/barback/lib/src/utils.dart
@@ -5,7 +5,6 @@
library barback.utils;
import 'dart:async';
-import 'dart:io';
/// A pair of values.
class Pair<E, F> {
diff --git a/pkg/barback/test/stream_replayer_test.dart b/pkg/barback/test/stream_replayer_test.dart
index f341a29..9bc8224 100644
--- a/pkg/barback/test/stream_replayer_test.dart
+++ b/pkg/barback/test/stream_replayer_test.dart
@@ -76,4 +76,26 @@
expect(isClosed, isTrue);
}), completes);
});
+
+ test("the wrapped stream isn't opened if there are no replays", () {
+ var isOpened = false;
+ var controller = new StreamController<int>(onListen: () {
+ isOpened = true;
+ });
+ var replayer = new StreamReplayer<int>(controller.stream);
+
+ expect(pumpEventQueue().then((_) => isOpened), completion(isFalse));
+ });
+
+ test("the wrapped stream isn't opened if no replays are opened", () {
+ var isOpened = false;
+ var controller = new StreamController<int>(onListen: () {
+ isOpened = true;
+ });
+ var replayer = new StreamReplayer<int>(controller.stream);
+ replayer.getReplay();
+ replayer.getReplay();
+
+ expect(pumpEventQueue().then((_) => isOpened), completion(isFalse));
+ });
}
diff --git a/pkg/custom_element/test/analyzer_test.dart b/pkg/custom_element/test/analyzer_test.dart
index 1ac251b..0cbe620 100644
--- a/pkg/custom_element/test/analyzer_test.dart
+++ b/pkg/custom_element/test/analyzer_test.dart
@@ -6,8 +6,6 @@
import 'package:custom_element/custom_element.dart';
-// @static-clean
-
// This test ensures CustomElement compiles without errors.
void main() {
}
diff --git a/pkg/docgen/README.md b/pkg/docgen/README.md
index 66d0a46..343d9c0 100644
--- a/pkg/docgen/README.md
+++ b/pkg/docgen/README.md
@@ -8,7 +8,7 @@
about all classes, variables, functions, and methods defined in the library and
its imported libraries.
-### Generating Files & Uploading to Cloud Storage
+### Generating files & uploading to Cloud Storage
The viewer uses YAML files generated by the docgen package as the data
being displayed. These files are stored in Google Cloud Storage.
@@ -20,7 +20,7 @@
#####
-#### Generating YAML Files
+#### Generating YAML files
YAML files can be generated using the docgen package in the dart repository.
@@ -44,7 +44,7 @@
for the outputted documentation.
-###### Output Directory
+###### Output directory
Documented libraries will be located at bin/docs in either YAML or JSON format
depending on options specified. There will also be a library_list.json,
containing a list of all the libraries inside the docs folder.
@@ -68,7 +68,7 @@
a new version of documentation. You can see the format of the VERSION file
by running `python gsutil cat gs://dartlang-docgen/VERSION`.
-### Viewing Generated Documentation
+### Viewing generated documentation
Docgen's generated YAML files can be used by the
[Dart Documentation Viewer][dartdoc-viewer] for easy viewing and navigation
diff --git a/pkg/docgen/bin/dartdoc.py b/pkg/docgen/bin/dartdoc.py
index 15f0de1..7fa875b 100644
--- a/pkg/docgen/bin/dartdoc.py
+++ b/pkg/docgen/bin/dartdoc.py
@@ -51,7 +51,7 @@
def main():
options = GetOptions()
docgen = [DART, '--checked', '--package-root=' + PACKAGE_ROOT,
- join(DIRECTORY, 'docgen.dart')]
+ join(DIRECTORY, 'docgen.dart'), '--json', '--package-root=' + PACKAGE_ROOT]
docgen.extend(options.options.split())
ExecuteCommand(docgen)
ExecuteCommand(['git', 'clone', '-b', 'master',
@@ -59,9 +59,7 @@
ExecuteCommand(['mv', 'docs', 'dartdoc-viewer/client/local'])
os.chdir('dartdoc-viewer/client/')
subprocess.call([PUB, 'install'])
- subprocess.call([DART, 'build.dart'])
- subprocess.call([DART2JS, '-o', 'web/out/index.html_bootstrap.dart.js',
- './web/out/index.html_bootstrap.dart'])
+ subprocess.call([DART, 'deploy.dart'])
server = subprocess.Popen(['python',
join(abspath(join(dirname(__file__), options.gae_sdk)), 'dev_appserver.py'),
'..'])
diff --git a/pkg/docgen/bin/docgen.dart b/pkg/docgen/bin/docgen.dart
index 293f3cf..82140a9 100644
--- a/pkg/docgen/bin/docgen.dart
+++ b/pkg/docgen/bin/docgen.dart
@@ -8,34 +8,35 @@
import 'package:logging/logging.dart';
import '../lib/docgen.dart';
+import 'package:path/path.dart' as path;
/**
- * Analyzes Dart files and generates a representation of included libraries,
- * classes, and members.
+ * Analyzes Dart files and generates a representation of included libraries,
+ * classes, and members.
*/
void main() {
logger.onRecord.listen((record) => print(record.message));
var results = _initArgParser().parse(new Options().arguments);
-
- docgen(results.rest,
- packageRoot: results['package-root'],
- outputToYaml: !results['json'],
- includePrivate: results['include-private'],
- includeSdk: results['parse-sdk'] || results['include-sdk'],
+
+ docgen(results.rest.map(path.normalize).toList(),
+ packageRoot: results['package-root'],
+ outputToYaml: !results['json'],
+ includePrivate: results['include-private'],
+ includeSdk: results['parse-sdk'] || results['include-sdk'],
parseSdk: results['parse-sdk'],
append: results['append'] && new Directory('docs').existsSync(),
- introduction: results['parse-sdk'] ?
+ introduction: results['parse-sdk'] ?
'sdk-introduction.md' : results['introduction']);
}
/**
- * Creates parser for docgen command line arguments.
+ * Creates parser for docgen command line arguments.
*/
ArgParser _initArgParser() {
var parser = new ArgParser();
- parser.addFlag('help', abbr: 'h',
- help: 'Prints help and usage information.',
- negatable: false,
+ parser.addFlag('help', abbr: 'h',
+ help: 'Prints help and usage information.',
+ negatable: false,
callback: (help) {
if (help) {
logger.info(parser.getUsage());
@@ -43,31 +44,31 @@
exit(0);
}
});
- parser.addFlag('verbose', abbr: 'v',
- help: 'Output more logging information.', negatable: false,
+ parser.addFlag('verbose', abbr: 'v',
+ help: 'Output more logging information.', negatable: false,
callback: (verbose) {
if (verbose) Logger.root.level = Level.FINEST;
});
- parser.addFlag('json', abbr: 'j',
- help: 'Outputs to JSON. Files are outputted to YAML by default. '
+ parser.addFlag('json', abbr: 'j',
+ help: 'Outputs to JSON. Files are outputted to YAML by default. '
'If --append is used, it takes the file-format of the previous '
- 'run stated in library_list.json ignoring the flag.',
+ 'run stated in library_list.json ignoring the flag.',
negatable: true);
- parser.addFlag('include-private',
+ parser.addFlag('include-private',
help: 'Flag to include private declarations.', negatable: false);
- parser.addFlag('include-sdk',
+ parser.addFlag('include-sdk',
help: 'Flag to parse SDK Library files.', negatable: false);
- parser.addFlag('parse-sdk',
- help: 'Parses the SDK libraries only.',
+ parser.addFlag('parse-sdk',
+ help: 'Parses the SDK libraries only.',
defaultsTo: false, negatable: false);
- parser.addOption('package-root',
+ parser.addOption('package-root',
help: 'Sets the package root of the library being analyzed.');
- parser.addFlag('append',
- help: 'Append to the docs folder, library_list.json and index.txt',
+ parser.addFlag('append',
+ help: 'Append to the docs folder, library_list.json and index.txt',
defaultsTo: false, negatable: false);
- parser.addOption('introduction',
- help: 'Adds the provided markdown text file as the introduction'
+ parser.addOption('introduction',
+ help: 'Adds the provided markdown text file as the introduction'
' for the outputted documentation.', defaultsTo: '');
-
+
return parser;
}
diff --git a/pkg/docgen/bin/generate_all_docs.sh b/pkg/docgen/bin/generate_all_docs.sh
new file mode 100755
index 0000000..8d5d82c
--- /dev/null
+++ b/pkg/docgen/bin/generate_all_docs.sh
@@ -0,0 +1,6 @@
+# A simple shell script to generate all docs for the sdk and pkg directories
+# into the docs folder in this directory.
+# TODO(alanknight): This should get subsumed into the python scripts
+dart --package-root=$DART_SDK/../packages/ docgen.dart --parse-sdk --json
+dart --old_gen_heap_size=1024 --package-root=$DART_SDK/../packages/ docgen.dart \
+ --package-root=$DART_SDK/../packages/ --append --json $DART_SDK/../../../pkg
diff --git a/pkg/docgen/bin/upload_docgen.py b/pkg/docgen/bin/upload_docgen.py
index 22903e1..9e2d335 100644
--- a/pkg/docgen/bin/upload_docgen.py
+++ b/pkg/docgen/bin/upload_docgen.py
@@ -69,7 +69,7 @@
# Execute Docgen.dart on the SDK.
ExecuteCommand([DART, '--checked', '--package-root=' + PACKAGE_ROOT,
abspath(join(dirname(__file__), 'docgen.dart')),
- '--parse-sdk'])
+ '--parse-sdk', '--json'])
# Use SVN Revision to get the revision number.
revision = utils.GetSVNRevision()
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index 7ec72ec..a31cf70 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -22,6 +22,7 @@
import 'package:logging/logging.dart';
import 'package:markdown/markdown.dart' as markdown;
import 'package:path/path.dart' as path;
+import 'package:yaml/yaml.dart';
import 'dart2yaml.dart';
import 'src/io.dart';
@@ -38,8 +39,8 @@
const String USAGE = 'Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]';
-List<String> validAnnotations = const ['metadata.Experimental',
- 'metadata.DomName', 'metadata.Deprecated', 'metadata.Unstable',
+List<String> validAnnotations = const ['metadata.Experimental',
+ 'metadata.DomName', 'metadata.Deprecated', 'metadata.Unstable',
'meta.deprecated', 'metadata.SupportedBrowser'];
/// Current library being documented to be used for comment links.
@@ -65,9 +66,9 @@
/// This is set from the command line arguments flag --include-private
bool _includePrivate = false;
-// TODO(janicejl): Make MDN content generic or pluggable. Maybe move
+// TODO(janicejl): Make MDN content generic or pluggable. Maybe move
// MDN-specific code to its own library that is imported into the default impl?
-/// Map of all the comments for dom elements from MDN.
+/// Map of all the comments for dom elements from MDN.
Map _mdn;
/**
@@ -109,26 +110,50 @@
if (mirrorSystem.libraries.isEmpty) {
throw new StateError('No library mirrors were created.');
}
- _documentLibraries(mirrorSystem.libraries.values,includeSdk: includeSdk,
- outputToYaml: outputToYaml, append: append, parseSdk: parseSdk,
+ var librariesWeAskedFor = _listLibraries(files);
+ var librariesWeGot = mirrorSystem.libraries.values.where((each)
+ => each.uri.scheme == 'file');
+ var sdkLibraries = mirrorSystem.libraries.values.where(
+ (each) => each.uri.scheme == 'dart');
+ var librariesWeGotByPath = new Map.fromIterables(
+ librariesWeGot.map((each) => each.uri.toFilePath()),
+ librariesWeGot);
+ var librariesToDocument = librariesWeAskedFor.map((each) =>
+ librariesWeGotByPath
+ .putIfAbsent(each, () => throw "Missing library $each")).toList();
+ librariesToDocument.addAll((includeSdk || parseSdk) ? sdkLibraries : []);
+ _documentLibraries(librariesToDocument, includeSdk: includeSdk,
+ outputToYaml: outputToYaml, append: append, parseSdk: parseSdk,
introduction: introduction);
-
return true;
});
}
-List<String> _listLibraries(List<String> args) {
- if (args.length != 1) throw new UnsupportedError(USAGE);
- var libraries = new List<String>();
- var type = FileSystemEntity.typeSync(args[0]);
+/// For a [library] and its corresponding [mirror] that we believe come
+/// from a package (because it has a file
+/// URI) look for the package name and set it on [library].
+_findPackage(Library library, LibraryMirror mirror) {
+ if (mirror.uri.scheme != 'file') return;
+ var filePath = mirror.uri.toFilePath();
+ // We assume that we are documenting only libraries under package/lib
+ var rootdir = path.dirname((path.dirname(filePath)));
+ var pubspec = path.join(rootdir, 'pubspec.yaml');
+ library.packageName = _packageName(pubspec);
+}
- if (type == FileSystemEntityType.FILE) {
- if (args[0].endsWith('.dart')) {
- libraries.add(path.absolute(args[0]));
- logger.info('Added to libraries: ${libraries.last}');
+List<String> _listLibraries(List<String> args) {
+ var libraries = new List<String>();
+ for (var arg in args) {
+ var type = FileSystemEntity.typeSync(arg);
+
+ if (type == FileSystemEntityType.FILE) {
+ if (arg.endsWith('.dart')) {
+ libraries.add(path.absolute(arg));
+ logger.info('Added to libraries: ${libraries.last}');
+ }
+ } else {
+ libraries.addAll(_listDartFromDir(arg));
}
- } else {
- libraries.addAll(_listDartFromDir(args[0]));
}
return libraries;
}
@@ -141,15 +166,18 @@
var files = listDir(args, recursive: true).where((f) => f.endsWith('.dart') &&
(!f.contains('${path.separator}packages') ||
args.contains('${path.separator}packages'))).toList();
-
- files.forEach((f) {
- // Only add the file if it does not contain 'part of'
- // TODO(janicejl): Remove when Issue(12406) is resolved.
- var contents = new File(f).readAsStringSync();
- if (!(contents.contains(new RegExp('\npart of ')) ||
- contents.startsWith(new RegExp('part of ')))) {
- libraries.add(f);
- logger.info('Added to libraries: $f');
+
+ files.forEach((String f) {
+ // Only include libraries at the top level of "lib"
+ if (path.basename(path.dirname(f)) == 'lib') {
+ // Only add the file if it does not contain 'part of'
+ // TODO(janicejl): Remove when Issue(12406) is resolved.
+ var contents = new File(f).readAsStringSync();
+ if (!(contents.contains(new RegExp('\npart of ')) ||
+ contents.startsWith(new RegExp('part of ')))) {
+ libraries.add(f);
+ logger.info('Added to libraries: $f');
+ }
}
});
return libraries;
@@ -166,6 +194,17 @@
return packageRoot;
}
+/**
+ * Read a pubspec and return the library name.
+ */
+String _packageName(String pubspecName) {
+ File pubspec = new File(pubspecName);
+ if (!pubspec.existsSync()) return '';
+ var contents = pubspec.readAsStringSync();
+ var spec = loadYaml(contents);
+ return spec["name"];
+}
+
List<String> _listSdk() {
var sdk = new List<String>();
LIBRARIES.forEach((String name, LibraryInfo info) {
@@ -200,7 +239,10 @@
String libraryRoot, {String packageRoot}) {
SourceFileProvider provider = new CompilerSourceFileProvider();
api.DiagnosticHandler diagnosticHandler =
- new FormattingDiagnosticHandler(provider).diagnosticHandler;
+ (new FormattingDiagnosticHandler(provider)
+ ..showHints = false
+ ..showWarnings = false)
+ .diagnosticHandler;
Uri libraryUri = new Uri(scheme: 'file', path: appendSlash(libraryRoot));
Uri packageUri = null;
if (packageRoot != null) {
@@ -227,7 +269,7 @@
* Creates documentation for filtered libraries.
*/
void _documentLibraries(List<LibraryMirror> libs, {bool includeSdk: false,
- bool outputToYaml: true, bool append: false, bool parseSdk: false,
+ bool outputToYaml: true, bool append: false, bool parseSdk: false,
String introduction: ''}) {
libs.forEach((lib) {
// Files belonging to the SDK have a uri that begins with 'dart:'.
@@ -244,8 +286,8 @@
if (parseSdk) entityMap['dart.core.Object'].subclasses.clear();
var filteredEntities = entityMap.values.where(_isVisible);
-
- // Outputs a JSON file with all libraries and their preview comments.
+
+ // Outputs a JSON file with all libraries and their preview comments.
// This will help the viewer know what libraries are available to read in.
var libraryMap;
if (append) {
@@ -262,19 +304,19 @@
var intro = libraryMap['introduction'];
if (intro.isNotEmpty) intro += '<br/><br/>';
intro += markdown.markdownToHtml(
- new File(introduction).readAsStringSync(),
+ new File(introduction).readAsStringSync(),
linkResolver: linkResolver, inlineSyntaxes: markdownSyntaxes);
libraryMap['introduction'] = intro;
}
outputToYaml = libraryMap['filetype'] == 'yaml';
} else {
libraryMap = {
- 'libraries' : filteredEntities.where((e) =>
+ 'libraries' : filteredEntities.where((e) =>
e is Library).map((e) => e.previewMap).toList(),
- 'introduction' : introduction == '' ?
+ 'introduction' : introduction == '' ?
'' : markdown.markdownToHtml(new File(introduction)
- .readAsStringSync(), linkResolver: linkResolver,
- inlineSyntaxes: markdownSyntaxes),
+ .readAsStringSync(), linkResolver: linkResolver,
+ inlineSyntaxes: markdownSyntaxes),
'filetype' : outputToYaml ? 'yaml' : 'json'
};
}
@@ -285,9 +327,18 @@
});
// Outputs all the qualified names documented with their type.
// This will help generate search results.
- _writeToFile(filteredEntities.map((e) =>
- '${e.qualifiedName} ${e.typeName}').join('\n'),
+ _writeToFile(filteredEntities.map((e) =>
+ '${e.qualifiedName} ${e.typeName}').join('\n') + '\n',
'index.txt', append: append);
+ var index = new Map.fromIterables(
+ filteredEntities.map((e) => e.qualifiedName),
+ filteredEntities.map((e) => e.typeName));
+ if (append) {
+ var previousIndex =
+ JSON.decode(new File('docs/index.json').readAsStringSync());
+ index.addAll(previousIndex);
+ }
+ _writeToFile(JSON.encode(index), 'index.json');
}
Library generateLibrary(dart2js.Dart2JsLibraryMirror library) {
@@ -296,6 +347,7 @@
_variables(library.variables),
_methods(library.functions),
_classes(library.classes), _isHidden(library));
+ _findPackage(result, library);
logger.fine('Generated library for ${result.name}');
return result;
}
@@ -320,7 +372,7 @@
var sdkLibrary = LIBRARIES[mirror.simpleName];
if (sdkLibrary != null) {
return !sdkLibrary.documented;
- } else if (mirror.simpleName.startsWith('_') ||
+ } else if (mirror.simpleName.startsWith('_') ||
mirror.simpleName.contains('._')) {
return true;
}
@@ -392,12 +444,12 @@
}
/**
- * Generates MDN comments from database.json.
+ * Generates MDN comments from database.json.
*/
void _mdnComment(Indexable item) {
- //Check if MDN is loaded.
+ //Check if MDN is loaded.
if (_mdn == null) {
- // Reading in MDN related json file.
+ // Reading in MDN related json file.
var mdnDir = path.join(path.dirname(path.dirname(path.dirname(path.dirname(
path.absolute(new Options().script))))), 'utils', 'apidoc', 'mdn');
_mdn = JSON.decode(new File(path.join(mdnDir, 'database.json'))
@@ -414,12 +466,12 @@
}
/**
- * Generates the MDN Comment for variables and method DOM elements.
+ * Generates the MDN Comment for variables and method DOM elements.
*/
String _mdnMemberComment(String type, String member) {
var mdnType = _mdn[type];
if (mdnType == null) return '';
- var mdnMember = mdnType['members'].firstWhere((e) => e['name'] == member,
+ var mdnMember = mdnType['members'].firstWhere((e) => e['name'] == member,
orElse: () => null);
if (mdnMember == null) return '';
if (mdnMember['help'] == null || mdnMember['help'] == '') return '';
@@ -428,7 +480,7 @@
}
/**
- * Generates the MDN Comment for class DOM elements.
+ * Generates the MDN Comment for class DOM elements.
*/
String _mdnTypeComment(String type) {
var mdnType = _mdn[type];
@@ -627,10 +679,10 @@
Indexable(this.name, this.comment, this.qualifiedName, this.isPrivate,
this.owner);
-
+
/// The type of this member to be used in index.txt.
String get typeName => '';
-
+
/**
* Creates a [Map] with this [Indexable]'s name and a preview comment.
*/
@@ -658,6 +710,10 @@
/// Classes defined within the library
ClassGroup classes;
+ String packageName = '';
+
+ Map get previewMap => super.previewMap..['packageName'] = packageName;
+
Library(String name, String comment, this.variables,
this.functions, this.classes, bool isPrivate) : super(name, comment,
name, isPrivate, "") {}
@@ -669,9 +725,10 @@
'comment': comment,
'variables': recurseMap(variables),
'functions': functions.toMap(),
- 'classes': classes.toMap()
+ 'classes': classes.toMap(),
+ 'packageName': packageName,
};
-
+
String get typeName => 'library';
}
@@ -709,13 +766,13 @@
Class(String name, this.superclass, String comment, this.interfaces,
this.variables, this.methods, this.annotations, this.generics,
- String qualifiedName, bool isPrivate, String owner, this.isAbstract)
+ String qualifiedName, bool isPrivate, String owner, this.isAbstract)
: super(name, comment, qualifiedName, isPrivate, owner) {
_mdnComment(this);
}
String get typeName => 'class';
-
+
/**
* Returns a list of all the parent classes.
*/
@@ -752,12 +809,12 @@
subclasses.add(subclass.qualifiedName);
}
}
-
+
/**
* Check if this [Class] is an error or exception.
*/
bool isError() {
- if (qualifiedName == 'dart.core.Error' ||
+ if (qualifiedName == 'dart.core.Error' ||
qualifiedName == 'dart.core.Exception')
return true;
for (var interface in interfaces) {
@@ -847,16 +904,16 @@
}
} else {
var clazz = _class(mirror);
-
+
// Adding inherited parent variables and methods.
clazz.parent().forEach((parent) {
if (_isVisible(clazz)) {
parent.addSubclass(clazz);
}
});
-
+
clazz.ensureComments();
-
+
if (clazz.isError()) {
errors[mirror.simpleName] = clazz;
} else if (mirror.isClass) {
@@ -873,7 +930,7 @@
bool containsKey(String name) {
return classes.containsKey(name) || errors.containsKey(name);
}
-
+
Map toMap() => {
'class': classes.values.where(_isVisible)
.map((e) => e.previewMap).toList(),
@@ -896,7 +953,7 @@
Typedef(String name, this.returnType, String comment, this.generics,
this.parameters, this.annotations,
- String qualifiedName, bool isPrivate, String owner)
+ String qualifiedName, bool isPrivate, String owner)
: super(name, comment, qualifiedName, isPrivate, owner);
Map toMap() => {
@@ -908,7 +965,7 @@
'annotations': annotations.map((a) => a.toMap()).toList(),
'generics': recurseMap(generics)
};
-
+
String get typeName => 'typedef';
}
@@ -942,7 +999,7 @@
'type': new List.filled(1, type.toMap()),
'annotations': annotations.map((a) => a.toMap()).toList()
};
-
+
String get typeName => 'property';
}
@@ -972,7 +1029,7 @@
Method(String name, this.isStatic, this.isAbstract, this.isConst,
this.returnType, String comment, this.parameters, this.annotations,
String qualifiedName, bool isPrivate, String owner, this.isConstructor,
- this.isGetter, this.isSetter, this.isOperator)
+ this.isGetter, this.isSetter, this.isOperator)
: super(name, comment, qualifiedName, isPrivate, owner) {
_mdnComment(this);
}
@@ -1001,7 +1058,7 @@
'parameters': recurseMap(parameters),
'annotations': annotations.map((a) => a.toMap()).toList()
};
-
+
String get typeName => isConstructor ? 'constructor' :
isGetter ? 'getter' : isSetter ? 'setter' :
isOperator ? 'operator' : 'method';
diff --git a/pkg/docgen/pubspec.yaml b/pkg/docgen/pubspec.yaml
index 70e3958..254e477 100644
--- a/pkg/docgen/pubspec.yaml
+++ b/pkg/docgen/pubspec.yaml
@@ -5,5 +5,6 @@
logging: any
markdown: any
path: any
+ yaml: any
dev_dependencies:
unittest: any
diff --git a/pkg/html_import/README.md b/pkg/html_import/README.md
index c394a6e..066c525 100644
--- a/pkg/html_import/README.md
+++ b/pkg/html_import/README.md
@@ -7,7 +7,7 @@
definitions from external URLs.
-## Getting Started
+## Getting started
Include the `html_import.debug.js` or `html_import.min.js` (minified) file in
your project.
diff --git a/pkg/http_server/README.md b/pkg/http_server/README.md
index 8653f9f..9d82386 100644
--- a/pkg/http_server/README.md
+++ b/pkg/http_server/README.md
@@ -3,7 +3,7 @@
This package contains a set of high-level classes that, together with
HttpServer, makes is easy to provide content through HTTP servers.
-## Virtual Directory
+## Virtual directory
The VirtualDirectory class makes it possible to easy serve static content from
the drive. It supports:
@@ -25,7 +25,7 @@
http://api.dartlang.org/docs/http_server/VirtualDirectory.html)
for more info about how to customize the class.
-## Virtual Host
+## Virtual host
The VirtualHost class makes it possible to serve multiple hosts on the same
address, by using the `Host` field of the incoming requests. It also provides
diff --git a/pkg/http_server/lib/src/http_body_impl.dart b/pkg/http_server/lib/src/http_body_impl.dart
index 81c7ede..7682902 100644
--- a/pkg/http_server/lib/src/http_body_impl.dart
+++ b/pkg/http_server/lib/src/http_body_impl.dart
@@ -21,17 +21,27 @@
class _HttpBodyHandlerTransformerSink implements EventSink<HttpRequest> {
final Encoding _defaultEncoding;
final EventSink<HttpRequestBody> _outSink;
+ int _pending = 0;
+ bool _closed = false;
_HttpBodyHandlerTransformerSink(this._defaultEncoding, this._outSink);
void add(HttpRequest request) {
+ _pending++;
_HttpBodyHandler.processRequest(request, _defaultEncoding)
- .then(_outSink.add, onError: _outSink.addError);
+ .then(_outSink.add, onError: _outSink.addError)
+ .whenComplete(() {
+ _pending--;
+ if (_closed && _pending == 0) _outSink.close();
+ });
}
void addError(Object error, [StackTrace stackTrace]) {
_outSink.addError(error, stackTrace);
}
- void close() => _outSink.close();
+ void close() {
+ _closed = true;
+ if (_pending == 0) _outSink.close();
+ }
}
class _HttpBodyHandler {
@@ -44,7 +54,6 @@
// Try to send BAD_REQUEST response.
request.response.statusCode = HttpStatus.BAD_REQUEST;
request.response.close();
- request.response.done.catchError((_) {});
throw error;
});
}
diff --git a/pkg/http_server/lib/src/virtual_directory.dart b/pkg/http_server/lib/src/virtual_directory.dart
index 4b38466..88a9d50 100644
--- a/pkg/http_server/lib/src/virtual_directory.dart
+++ b/pkg/http_server/lib/src/virtual_directory.dart
@@ -64,7 +64,7 @@
return;
}
if (entity is File) {
- _serveFile(entity, request);
+ serveFile(entity, request);
} else if (entity is Directory) {
_serveDirectory(entity, request);
} else {
@@ -141,7 +141,20 @@
});
}
- void _serveFile(File file, HttpRequest request) {
+ /**
+ * Serve the content of [file] to [request].
+ *
+ * This is usefull when e.g. overriding [directoryHandler] to redirect to
+ * some index file.
+ *
+ * In the request contains the [HttpStatus.IF_MODIFIED_SINCE] header,
+ * [serveFile] will send a [HttpStatus.NOT_MODIFIED] response if the file
+ * was not changed.
+ *
+ * Note that if it was unabled to read from [file], the [request]s response
+ * is closed with error-code [HttpStatus.NOT_FOUND].
+ */
+ void serveFile(File file, HttpRequest request) {
var response = request.response;
// TODO(ajohnsen): Set up Zone support for these errors.
file.lastModified().then((lastModified) {
@@ -201,6 +214,7 @@
.catchError((_) {});
});
}).catchError((_) {
+ response.statusCode = HttpStatus.NOT_FOUND;
response.close();
});
}
diff --git a/pkg/http_server/test/http_body_test.dart b/pkg/http_server/test/http_body_test.dart
index bae4e1b..e8d84c0 100644
--- a/pkg/http_server/test/http_body_test.dart
+++ b/pkg/http_server/test/http_body_test.dart
@@ -90,6 +90,7 @@
HttpServer.bind("127.0.0.1", 0).then((server) {
server.transform(new HttpBodyHandler(defaultEncoding: defaultEncoding))
.listen((body) {
+ if (shouldFail) return;
expect(shouldFail, isFalse);
expect(body.type, equals(type));
switch (type) {
@@ -157,9 +158,12 @@
}
return response.drain();
})
- .then((_) {
+ .whenComplete(() {
client.close();
server.close();
+ })
+ .catchError((e) {
+ if (!shouldFail) throw e;
});
});
}
diff --git a/pkg/http_server/test/virtual_directory_test.dart b/pkg/http_server/test/virtual_directory_test.dart
index a368c73..027f044 100644
--- a/pkg/http_server/test/virtual_directory_test.dart
+++ b/pkg/http_server/test/virtual_directory_test.dart
@@ -669,5 +669,28 @@
testEncoding('%2f', HttpStatus.NOT_FOUND, false);
testEncoding('%2f', HttpStatus.OK, true);
});
+
+ group('serve-file', () {
+ test('from-dir-handler', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = Directory.systemTemp.createTempSync('http_server_virtual_');
+ new File('${dir.path}/file')..writeAsStringSync('file contents');
+ var virDir = new VirtualDirectory(dir.path);
+ virDir.allowDirectoryListing = true;
+ virDir.directoryHandler = (d, request) {
+ expect(FileSystemEntity.identicalSync(dir.path, d.path), isTrue);
+ virDir.serveFile(new File('${d.path}/file'), request);
+ };
+
+ virDir.serve(server);
+
+ return getAsString(server.port, '/')
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals('file contents')));
+ });
+ });
}
diff --git a/pkg/mutation_observer/test/mutation_observer_test.dart b/pkg/mutation_observer/test/mutation_observer_test.dart
index 24dbccf..e3bbdf4 100644
--- a/pkg/mutation_observer/test/mutation_observer_test.dart
+++ b/pkg/mutation_observer/test/mutation_observer_test.dart
@@ -101,14 +101,5 @@
container.append(div1);
div1.append(div2);
});
-
- test('mutation event', () {
- var event = new MutationEvent('something', prevValue: 'prev',
- newValue: 'new', attrName: 'attr');
- expect(event is MutationEvent, isTrue);
- expect(event.prevValue, 'prev');
- expect(event.newValue, 'new');
- expect(event.attrName, 'attr');
- });
});
}
diff --git a/pkg/observe/lib/observe.dart b/pkg/observe/lib/observe.dart
index abce718..9da8d5e 100644
--- a/pkg/observe/lib/observe.dart
+++ b/pkg/observe/lib/observe.dart
@@ -77,34 +77,15 @@
*/
library observe;
-import 'dart:async';
-import 'dart:collection';
-
-// Note: ObservableProperty is in this list only for the unusual use case of
-// dart2js without deploy tool. The deploy tool (see "transformer.dart") will
-// add the @reflectable annotation, which makes it work with Polymer's
-// @published.
-@MirrorsUsed(metaTargets: const [Reflectable, ObservableProperty],
- override: 'observe')
-import 'dart:mirrors';
-
-import 'package:meta/meta.dart';
-
-// Note: this is an internal library so we can import it from tests.
-// TODO(jmesserly): ideally we could import this with a prefix, but it caused
-// strange problems on the VM when I tested out the dirty-checking example
-// above.
-import 'src/dirty_check.dart';
-
-part 'src/bind_property.dart';
-part 'src/change_notifier.dart';
-part 'src/change_record.dart';
-part 'src/compound_binding.dart';
-part 'src/list_path_observer.dart';
-part 'src/metadata.dart';
-part 'src/observable.dart';
-part 'src/observable_box.dart';
-part 'src/observable_list.dart';
-part 'src/observable_map.dart';
-part 'src/path_observer.dart';
-part 'src/to_observable.dart';
+export 'src/bind_property.dart';
+export 'src/change_notifier.dart';
+export 'src/change_record.dart';
+export 'src/compound_path_observer.dart';
+export 'src/list_path_observer.dart';
+export 'src/metadata.dart';
+export 'src/observable.dart' hide notifyPropertyChangeHelper, objectType;
+export 'src/observable_box.dart';
+export 'src/observable_list.dart';
+export 'src/observable_map.dart';
+export 'src/path_observer.dart';
+export 'src/to_observable.dart';
diff --git a/pkg/observe/lib/src/bind_property.dart b/pkg/observe/lib/src/bind_property.dart
index a31d1ab..59f867f 100644
--- a/pkg/observe/lib/src/bind_property.dart
+++ b/pkg/observe/lib/src/bind_property.dart
@@ -2,7 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.bind_property;
+
+import 'dart:async';
+import 'package:observe/observe.dart';
/**
* Forwards an observable property from one object to another. For example:
diff --git a/pkg/observe/lib/src/change_notifier.dart b/pkg/observe/lib/src/change_notifier.dart
index a51fda6..133c6c8 100644
--- a/pkg/observe/lib/src/change_notifier.dart
+++ b/pkg/observe/lib/src/change_notifier.dart
@@ -2,7 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.change_notifier;
+
+import 'dart:async';
+import 'dart:collection' show UnmodifiableListView;
+import 'package:observe/observe.dart';
+import 'package:observe/src/observable.dart' show notifyPropertyChangeHelper;
/**
* Mixin and base class for implementing an [Observable] object that performs
@@ -19,7 +24,7 @@
Stream<List<ChangeRecord>> get changes {
if (_changes == null) {
_changes = new StreamController.broadcast(sync: true,
- onListen: _observed, onCancel: _unobserved);
+ onListen: observed, onCancel: unobserved);
}
return _changes.stream;
}
@@ -29,13 +34,13 @@
/**
* Override this method to be called when the [changes] are first observed.
*/
- void _observed() {}
+ void observed() {}
/**
* Override this method to be called when the [changes] are no longer being
* observed.
*/
- void _unobserved() {}
+ void unobserved() {}
bool deliverChanges() {
var records = _records;
@@ -69,7 +74,7 @@
* }
*/
notifyPropertyChange(Symbol field, Object oldValue, Object newValue)
- => _notifyPropertyChange(this, field, oldValue, newValue);
+ => notifyPropertyChangeHelper(this, field, oldValue, newValue);
void notifyChange(ChangeRecord record) {
if (!hasObservers) return;
diff --git a/pkg/observe/lib/src/change_record.dart b/pkg/observe/lib/src/change_record.dart
index bb584e8..39e5964 100644
--- a/pkg/observe/lib/src/change_record.dart
+++ b/pkg/observe/lib/src/change_record.dart
@@ -2,7 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.change_record;
+
+import 'package:observe/observe.dart';
+
/** Records a change to an [Observable]. */
// TODO(jmesserly): remove this type
@@ -10,13 +13,6 @@
/** A change record to a field of an observable object. */
class PropertyChangeRecord<T> extends ChangeRecord {
- /**
- * *Deprecated* use [name] instead.
- * The field that was changed.
- */
- @deprecated
- Symbol get field => name;
-
/** The object that changed. */
final object;
@@ -31,13 +27,6 @@
PropertyChangeRecord(this.object, this.name, this.oldValue, this.newValue);
- /*
- * *Deprecated* instead of `record.changes(key)` simply do
- * `key == record.name`.
- */
- @deprecated
- bool changes(key) => key is Symbol && name == key;
-
String toString() =>
'#<PropertyChangeRecord $name from: $oldValue to: $newValue>';
}
@@ -60,13 +49,6 @@
}
}
- /**
- * *Deprecated* use [indexChanged] instead.
- * Returns true if the provided index was changed by this operation.
- */
- @deprecated
- bool changes(value) => indexChanged(value);
-
/** Returns true if the provided index was changed by this operation. */
bool indexChanged(otherIndex) {
// If key isn't an int, or before the index, then it wasn't changed.
diff --git a/pkg/observe/lib/src/compound_binding.dart b/pkg/observe/lib/src/compound_binding.dart
deleted file mode 100644
index 3d27926..0000000
--- a/pkg/observe/lib/src/compound_binding.dart
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of observe;
-
-/** The callback used in the [CompoundBinding.combinator] field. */
-typedef Object CompoundBindingCombinator(Map objects);
-
-/**
- * CompoundBinding is an object which knows how to listen to multiple path
- * values (registered via [bind]) and invoke its [combinator] when one or more
- * of the values have changed and set its [value] property to the return value
- * of the function. When any value has changed, all current values are provided
- * to the [combinator] in the single `values` argument.
- *
- * For example:
- *
- * var binding = new CompoundBinding((values) {
- * var combinedValue;
- * // compute combinedValue based on the current values which are provided
- * return combinedValue;
- * });
- * binding.bind('name1', obj1, path1);
- * binding.bind('name2', obj2, path2);
- * //...
- * binding.bind('nameN', objN, pathN);
- */
-// TODO(jmesserly): rename to something that indicates it's a computed value?
-class CompoundBinding extends ChangeNotifier {
- CompoundBindingCombinator _combinator;
-
- // TODO(jmesserly): ideally these would be String keys, but sometimes we
- // use integers.
- Map<dynamic, StreamSubscription> _observers = new Map();
- Map _values = new Map();
- Object _value;
-
- /**
- * True if [resolve] is scheduled. You can set this to true if you plan to
- * call [resolve] manually, avoiding the need for scheduling an asynchronous
- * resolve.
- */
- // TODO(jmesserly): I don't like having this public, is the optimization
- // really needed? "scheduleMicrotask" in Dart should be pretty cheap.
- bool scheduled = false;
-
- /**
- * Creates a new CompoundBinding, optionally proving the [combinator] function
- * for computing the value. You can also set [schedule] to true if you plan
- * to invoke [resolve] manually after initial construction of the binding.
- */
- CompoundBinding([CompoundBindingCombinator combinator]) {
- // TODO(jmesserly): this is a tweak to the original code, it seemed to me
- // that passing the combinator to the constructor should be equivalent to
- // setting it via the property.
- // I also added a null check to the combinator setter.
- this.combinator = combinator;
- }
-
- CompoundBindingCombinator get combinator => _combinator;
-
- set combinator(CompoundBindingCombinator combinator) {
- _combinator = combinator;
- if (combinator != null) _scheduleResolve();
- }
-
- int get length => _observers.length;
-
- @reflectable get value => _value;
-
- @reflectable void set value(newValue) {
- _value = notifyPropertyChange(#value, _value, newValue);
- }
-
- void bind(name, model, String path) {
- unbind(name);
-
- // TODO(jmesserly): should we delay observing until we are observed,
- // similar to PathObserver?
- _observers[name] = new PathObserver(model, path).bindSync((value) {
- _values[name] = value;
- _scheduleResolve();
- });
- }
-
- void unbind(name, {bool suppressResolve: false}) {
- var binding = _observers.remove(name);
- if (binding == null) return;
-
- binding.cancel();
- _values.remove(name);
- if (!suppressResolve) _scheduleResolve();
- }
-
- // TODO(rafaelw): Is this the right processing model?
- // TODO(rafaelw): Consider having a seperate ChangeSummary for
- // CompoundBindings so to excess dirtyChecks.
- void _scheduleResolve() {
- if (scheduled) return;
- scheduled = true;
- scheduleMicrotask(resolve);
- }
-
- void resolve() {
- if (_observers.isEmpty) return;
- scheduled = false;
-
- if (_combinator == null) {
- throw new StateError(
- 'CompoundBinding attempted to resolve without a combinator');
- }
-
- value = _combinator(_values);
- }
-
- /**
- * Closes the observer.
- *
- * This happens automatically if the [value] property is no longer observed,
- * but this can also be called explicitly.
- */
- void close() {
- for (var binding in _observers.values) {
- binding.cancel();
- }
- _observers.clear();
- _values.clear();
- value = null;
- }
-
- _unobserved() => close();
-}
diff --git a/pkg/observe/lib/src/compound_path_observer.dart b/pkg/observe/lib/src/compound_path_observer.dart
new file mode 100644
index 0000000..6fee689
--- /dev/null
+++ b/pkg/observe/lib/src/compound_path_observer.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library observe.src.compound_path_observer;
+
+import 'dart:async';
+import 'package:observe/observe.dart';
+
+/**
+ * CompoundPathObserver is an object which knows how to listen to multiple path
+ * values (registered via [addPath]) and invoke a function when one or more
+ * of the values have changed. The result of this function will be set into the
+ * [value] property. When any value has changed, all current values are provided
+ * to the function in the single `values` argument.
+ *
+ * For example:
+ *
+ * var binding = new CompoundPathObserver(computeValue: (values) {
+ * var combinedValue;
+ * // compute combinedValue based on the current values which are provided
+ * return combinedValue;
+ * });
+ * binding.addPath(obj1, path1);
+ * binding.addPath(obj2, path2);
+ * //...
+ * binding.addPath(objN, pathN);
+ */
+// TODO(jmesserly): this isn't a full port of CompoundPathObserver. It is only
+// what was needed for TemplateBinding.
+class CompoundPathObserver extends ChangeNotifier {
+ List<PathObserver> _observers = [];
+ List<StreamSubscription> _subs = [];
+ Object _value; // the last computed value
+
+ // TODO(jmesserly): this is public in observe.js
+ final Function _computeValue;
+
+ bool _started = false;
+
+ /** True if [start] has been called, otherwise false. */
+ bool get started => _started;
+
+ bool _scheduled = false;
+
+ /**
+ * Creates a new observer, optionally proving the [computeValue] function
+ * for computing the value. You can also set [schedule] to true if you plan
+ * to invoke [resolve] manually after initial construction of the binding.
+ */
+ CompoundPathObserver({computeValue(List values)})
+ : _computeValue = computeValue;
+
+ int get length => _observers.length;
+
+ @reflectable get value => _value;
+
+ void addPath(model, String path) {
+ if (_started) {
+ throw new StateError('Cannot add more paths once started.');
+ }
+
+ _observers.add(new PathObserver(model, path));
+ }
+
+ void start() {
+ if (_started) return;
+ _started = true;
+
+ final scheduleResolve = _scheduleResolve;
+ for (var observer in _observers) {
+ _subs.add(observer.changes.listen(scheduleResolve));
+ }
+ _resolve();
+ }
+
+ // TODO(rafaelw): Is this the right processing model?
+ // TODO(rafaelw): Consider having a seperate ChangeSummary for
+ // CompoundBindings so to excess dirtyChecks.
+ void _scheduleResolve(_) {
+ if (_scheduled) return;
+ _scheduled = true;
+ scheduleMicrotask(_resolve);
+ }
+
+ void _resolve() {
+ _scheduled = false;
+ var newValue = _observers.map((o) => o.value).toList();
+ if (_computeValue != null) newValue = _computeValue(newValue);
+ _value = notifyPropertyChange(#value, _value, newValue);
+ }
+
+ /**
+ * Closes the observer.
+ *
+ * This happens automatically if the [value] property is no longer observed,
+ * but this can also be called explicitly.
+ */
+ void close() {
+ if (_observers.isEmpty) return;
+
+ if (_started) {
+ for (StreamSubscription sub in _subs) {
+ sub.cancel();
+ }
+ }
+ _observers.clear();
+ _subs.clear();
+ _value = null;
+ }
+
+ observed() => start();
+ unobserved() => close();
+}
diff --git a/pkg/observe/lib/src/list_path_observer.dart b/pkg/observe/lib/src/list_path_observer.dart
index f882e12..e67f9d3 100644
--- a/pkg/observe/lib/src/list_path_observer.dart
+++ b/pkg/observe/lib/src/list_path_observer.dart
@@ -2,7 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.list_path_observer;
+
+import 'dart:async';
+import 'package:observe/observe.dart';
// Inspired by ArrayReduction at:
// https://raw.github.com/rafaelw/ChangeSummary/master/util/array_reduction.js
diff --git a/pkg/observe/lib/src/metadata.dart b/pkg/observe/lib/src/metadata.dart
index 48d06c2..a1e4e15 100644
--- a/pkg/observe/lib/src/metadata.dart
+++ b/pkg/observe/lib/src/metadata.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.metadata;
/**
* Use `@observable` to make a field automatically observable, or to indicate
diff --git a/pkg/observe/lib/src/observable.dart b/pkg/observe/lib/src/observable.dart
index ca94085..ee25819 100644
--- a/pkg/observe/lib/src/observable.dart
+++ b/pkg/observe/lib/src/observable.dart
@@ -2,7 +2,26 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.observable;
+
+import 'dart:async';
+import 'dart:collection';
+
+// Note: ObservableProperty is in this list only for the unusual use case of
+// dart2js without deploy tool. The deploy tool (see "transformer.dart") will
+// add the @reflectable annotation, which makes it work with Polymer's
+// @published.
+@MirrorsUsed(metaTargets: const [Reflectable, ObservableProperty],
+ override: 'observe.src.observable')
+import 'dart:mirrors';
+
+import 'package:observe/observe.dart';
+
+// Note: this is an internal library so we can import it from tests.
+// TODO(jmesserly): ideally we could import this with a prefix, but it caused
+// strange problems on the VM when I tested out the dirty-checking example
+// above.
+import 'dirty_check.dart';
/**
* Represents an object with observable properties. This is used by data in
@@ -32,8 +51,6 @@
Map<Symbol, Object> _values;
List<ChangeRecord> _records;
- static final _objectType = reflectClass(Object);
-
/**
* The stream of change records to this object. Records will be delivered
* asynchronously.
@@ -64,7 +81,7 @@
// Note: we scan for @observable regardless of whether the base type
// actually includes this mixin. While perhaps too inclusive, it lets us
// avoid complex logic that walks "with" and "implements" clauses.
- for (var type = mirror.type; type != _objectType; type = type.superclass) {
+ for (var type = mirror.type; type != objectType; type = type.superclass) {
for (var field in type.variables.values) {
if (field.isFinal || field.isStatic || field.isPrivate) continue;
@@ -148,7 +165,7 @@
* For convenience this returns [newValue].
*/
notifyPropertyChange(Symbol field, Object oldValue, Object newValue)
- => _notifyPropertyChange(this, field, oldValue, newValue);
+ => notifyPropertyChangeHelper(this, field, oldValue, newValue);
/**
* Notify observers of a change.
@@ -188,7 +205,8 @@
// TODO(jmesserly): remove the instance method and make this top-level method
// public instead?
-_notifyPropertyChange(Observable obj, Symbol field, Object oldValue,
+// NOTE: this is not exported publically.
+notifyPropertyChangeHelper(Observable obj, Symbol field, Object oldValue,
Object newValue) {
if (obj.hasObservers && oldValue != newValue) {
@@ -196,3 +214,6 @@
}
return newValue;
}
+
+// NOTE: this is not exported publically.
+final objectType = reflectClass(Object);
diff --git a/pkg/observe/lib/src/observable_box.dart b/pkg/observe/lib/src/observable_box.dart
index 7db72bf..9455dbd 100644
--- a/pkg/observe/lib/src/observable_box.dart
+++ b/pkg/observe/lib/src/observable_box.dart
@@ -2,7 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.observable_box;
+
+import 'package:observe/observe.dart';
// TODO(jmesserly): should the property name be configurable?
// That would be more convenient.
diff --git a/pkg/observe/lib/src/observable_list.dart b/pkg/observe/lib/src/observable_list.dart
index 0cf181c..4137957 100644
--- a/pkg/observe/lib/src/observable_list.dart
+++ b/pkg/observe/lib/src/observable_list.dart
@@ -2,7 +2,11 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.observable_list;
+
+import 'dart:async';
+import 'dart:collection' show ListBase;
+import 'package:observe/observe.dart';
/**
* Represents an observable list of model values. If any items are added,
diff --git a/pkg/observe/lib/src/observable_map.dart b/pkg/observe/lib/src/observable_map.dart
index d4da646..27e25da 100644
--- a/pkg/observe/lib/src/observable_map.dart
+++ b/pkg/observe/lib/src/observable_map.dart
@@ -2,7 +2,11 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.observable_map;
+
+import 'dart:collection';
+import 'package:observe/observe.dart';
+
// TODO(jmesserly): this needs to be faster. We currently require multiple
// lookups per key to get the old value.
@@ -34,14 +38,10 @@
: isInsert = false, isRemove = false;
MapChangeRecord.insert(this.key, this.newValue)
- : isInsert = true, isRemove = false;
+ : isInsert = true, isRemove = false, oldValue = null;
MapChangeRecord.remove(this.key, this.oldValue)
- : isInsert = false, isRemove = true;
-
- /// *Deprecated* compare [key]s instead.
- @deprecated
- bool changes(otherKey) => key == otherKey;
+ : isInsert = false, isRemove = true, newValue = null;
String toString() {
var kind = isInsert ? 'insert' : isRemove ? 'remove' : 'set';
@@ -76,10 +76,11 @@
* you should use [toObservable].
*/
factory ObservableMap.from(Map<K, V> other) {
- return new ObservableMap<K, V>._createFromType(other)..addAll(other);
+ return new ObservableMap<K, V>.createFromType(other)..addAll(other);
}
- factory ObservableMap._createFromType(Map<K, V> other) {
+ /** Like [ObservableMap.from], but creates an empty map. */
+ factory ObservableMap.createFromType(Map<K, V> other) {
ObservableMap result;
if (other is SplayTreeMap) {
result = new ObservableMap<K, V>.sorted();
diff --git a/pkg/observe/lib/src/path_observer.dart b/pkg/observe/lib/src/path_observer.dart
index 1b6e1a3..6384f6e 100644
--- a/pkg/observe/lib/src/path_observer.dart
+++ b/pkg/observe/lib/src/path_observer.dart
@@ -2,7 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.path_observer;
+
+import 'dart:async';
+@MirrorsUsed(metaTargets: const [Reflectable, ObservableProperty],
+ override: 'observe.src.path_observer')
+import 'dart:mirrors';
+import 'package:logging/logging.dart' show Logger, Level;
+import 'package:observe/observe.dart';
+import 'package:observe/src/observable.dart' show objectType;
// This code is inspired by ChangeSummary:
// https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
@@ -21,6 +29,10 @@
*
* This class is used to implement [Node.bind] and similar functionality.
*/
+// TODO(jmesserly): consider specialized subclasses for:
+// * empty path
+// * "value"
+// * single token in path, e.g. "foo"
class PathObserver extends ChangeNotifier {
/** The path string. */
final String path;
@@ -32,13 +44,22 @@
List<Object> _values;
List<StreamSubscription> _subs;
+ final Function _computeValue;
+
/**
* Observes [path] on [object] for changes. This returns an object that can be
* used to get the changes and get/set the value at this path.
+ *
+ * You can optionally use [computeValue] to apply a function to the result of
+ * evaluating the path. The function should be pure, as PathObserver will not
+ * know to observe any of its dependencies. If you need to observe mutliple
+ * values, use [CompoundPathObserver] instead.
+ *
* See [PathObserver.bindSync] and [PathObserver.value].
*/
- PathObserver(Object object, String path)
+ PathObserver(Object object, String path, {computeValue(newValue)})
: path = path,
+ _computeValue = computeValue,
_isValid = _isPathValid(path),
_segments = <Object>[] {
@@ -54,11 +75,19 @@
// Note that the path itself can't change after it is initially
// constructed, even though the objects along the path can change.
_values = new List<Object>(_segments.length + 1);
+
+ // If we have an empty path, we need to apply the transformation function
+ // to the value. The "value" property should always show the transformed
+ // value.
+ if (_segments.isEmpty && computeValue != null) {
+ object = computeValue(object);
+ }
+
_values[0] = object;
_subs = new List<StreamSubscription>(_segments.length);
}
- /** The object being observed. */
+ /** The object being observed. If the path is empty this will be [value]. */
get object => _values[0];
/** Gets the last reported value at this path. */
@@ -69,19 +98,19 @@
}
/** Sets the value at this path. */
- @reflectable void set value(Object value) {
+ @reflectable void set value(Object newValue) {
int len = _segments.length;
// TODO(jmesserly): throw if property cannot be set?
// MDV seems tolerant of these errors.
if (len == 0) return;
- if (!hasObservers) _updateValues();
+ if (!hasObservers) _updateValues(end: len - 1);
- if (_setObjectProperty(_values[len - 1], _segments[len - 1], value)) {
+ if (_setObjectProperty(_values[len - 1], _segments[len - 1], newValue)) {
// Technically, this would get updated asynchronously via a change record.
// However, it is nice if calling the getter will yield the same value
// that was just set. So we use this opportunity to update our cache.
- _values[len] = value;
+ _values[len] = newValue;
}
}
@@ -96,33 +125,43 @@
return result;
}
- void _observed() {
- super._observed();
+ void observed() {
+ super.observed();
_updateValues();
_observePath();
}
- void _unobserved() {
+ void unobserved() {
for (int i = 0; i < _subs.length; i++) {
if (_subs[i] != null) {
_subs[i].cancel();
_subs[i] = null;
}
}
+ super.unobserved();
}
// TODO(jmesserly): should we be caching these values if not observing?
- void _updateValues() {
- for (int i = 0; i < _segments.length; i++) {
- _values[i + 1] = _getObjectProperty(_values[i], _segments[i]);
+ void _updateValues({int end}) {
+ if (end == null) end = _segments.length;
+ int last = _segments.length - 1;
+ for (int i = 0; i < end; i++) {
+ var newValue = _getObjectProperty(_values[i], _segments[i]);
+ if (i == last && _computeValue != null) {
+ newValue = _computeValue(newValue);
+ }
+ _values[i + 1] = newValue;
}
}
- void _updateObservedValues([int start = 0]) {
+ void _updateObservedValues({int start: 0}) {
var oldValue, newValue;
- for (int i = start; i < _segments.length; i++) {
+ for (int i = start, last = _segments.length - 1; i <= last; i++) {
oldValue = _values[i + 1];
newValue = _getObjectProperty(_values[i], _segments[i]);
+ if (i == last && _computeValue != null) {
+ newValue = _computeValue(newValue);
+ }
if (identical(oldValue, newValue)) {
_observePath(start, i);
return;
@@ -147,19 +186,14 @@
final object = _values[i];
if (object is Observable) {
// TODO(jmesserly): rather than allocating a new closure for each
- // property, we could try and have one for the entire path. In that case,
- // we would lose information about which object changed (note: unless
- // PropertyChangeRecord is modified to includes the sender object), so
- // we would need to re-evaluate the entire path. Need to evaluate perf.
+ // property, we could try and have one for the entire path. However we'd
+ // need to do a linear scan to find the index as soon as we got a change.
+ // Also we need to fix ListChangeRecord and MapChangeRecord to contain
+ // the target. Not sure if it's worth it.
_subs[i] = object.changes.listen((List<ChangeRecord> records) {
- if (!identical(_values[i], object)) {
- // Ignore this object if we're now tracking something else.
- return;
- }
-
for (var record in records) {
if (_changeRecordMatches(record, _segments[i])) {
- _updateObservedValues(i);
+ _updateObservedValues(start: i);
return;
}
}
@@ -183,85 +217,78 @@
}
_getObjectProperty(object, property) {
- if (object == null) {
- return null;
- }
+ if (object == null) return null;
- if (object is List && property is int) {
- if (property >= 0 && property < object.length) {
+ if (property is int) {
+ if (object is List && property >= 0 && property < object.length) {
return object[property];
- } else {
- return null;
+ }
+ } else if (property is Symbol) {
+ var mirror = reflect(object);
+ final type = mirror.type;
+ try {
+ if (_maybeHasGetter(type, property)) {
+ return mirror.getField(property).reflectee;
+ }
+ // Support indexer if available, e.g. Maps or polymer_expressions Scope.
+ // This is the default syntax used by polymer/nodebind and
+ // polymer/observe-js PathObserver.
+ if (_hasMethod(type, const Symbol('[]'))) {
+ return object[MirrorSystem.getName(property)];
+ }
+ } on NoSuchMethodError catch (e) {
+ // Rethrow, unless the type implements noSuchMethod, in which case we
+ // interpret the exception as a signal that the method was not found.
+ if (!_hasMethod(type, #noSuchMethod)) rethrow;
}
}
- if (property is Symbol) {
- var mirror = reflect(object);
- var result = _tryGetField(mirror, property);
- if (result != null) return result.reflectee;
+ if (_logger.isLoggable(Level.FINER)) {
+ _logger.log("can't get $property in $object");
}
-
- if (object is Map) {
- if (property is Symbol) property = MirrorSystem.getName(property);
- return object[property];
- }
-
return null;
}
bool _setObjectProperty(object, property, value) {
- if (object is List && property is int) {
- if (property >= 0 && property < object.length) {
+ if (object == null) return false;
+
+ if (property is int) {
+ if (object is List && property >= 0 && property < object.length) {
object[property] = value;
return true;
- } else {
- return false;
+ }
+ } else if (property is Symbol) {
+ var mirror = reflect(object);
+ final type = mirror.type;
+ try {
+ if (_maybeHasSetter(type, property)) {
+ mirror.setField(property, value);
+ return true;
+ }
+ // Support indexer if available, e.g. Maps or polymer_expressions Scope.
+ if (_hasMethod(type, const Symbol('[]='))) {
+ object[MirrorSystem.getName(property)] = value;
+ return true;
+ }
+ } on NoSuchMethodError catch (e) {
+ if (!_hasMethod(type, #noSuchMethod)) rethrow;
}
}
- if (property is Symbol) {
- var mirror = reflect(object);
- if (_trySetField(mirror, property, value)) return true;
+ if (_logger.isLoggable(Level.FINER)) {
+ _logger.log("can't set $property in $object");
}
-
- if (object is Map) {
- if (property is Symbol) property = MirrorSystem.getName(property);
- object[property] = value;
- return true;
- }
-
return false;
}
-InstanceMirror _tryGetField(InstanceMirror mirror, Symbol name) {
- try {
- return mirror.getField(name);
- } on NoSuchMethodError catch (e) {
- if (_hasMember(mirror, name, (m) =>
- m is VariableMirror || m is MethodMirror && m.isGetter)) {
- // The field/getter is there but threw a NoSuchMethod exception.
- // This is a legitimate error in the code so rethrow.
- rethrow;
- }
- // The field isn't there. PathObserver does not treat this as an error.
- return null;
+bool _maybeHasGetter(ClassMirror type, Symbol name) {
+ while (type != objectType) {
+ final members = type.members;
+ if (members.containsKey(name)) return true;
+ if (members.containsKey(#noSuchMethod)) return true;
+ type = _safeSuperclass(type);
}
-}
-
-bool _trySetField(InstanceMirror mirror, Symbol name, Object value) {
- try {
- mirror.setField(name, value);
- return true;
- } on NoSuchMethodError catch (e) {
- if (_hasMember(mirror, name, (m) => m is VariableMirror) ||
- _hasMember(mirror, _setterName(name))) {
- // The field/setter is there but threw a NoSuchMethod exception.
- // This is a legitimate error in the code so rethrow.
- rethrow;
- }
- // The field isn't there. PathObserver does not treat this as an error.
- return false;
- }
+ return false;
}
// TODO(jmesserly): workaround for:
@@ -269,23 +296,41 @@
Symbol _setterName(Symbol getter) =>
new Symbol('${MirrorSystem.getName(getter)}=');
-bool _hasMember(InstanceMirror mirror, Symbol name, [bool test(member)]) {
- var type = mirror.type;
- while (type != null) {
- final member = type.members[name];
- if (member != null && (test == null || test(member))) return true;
-
- try {
- type = type.superclass;
- } on UnsupportedError catch (e) {
- // TODO(jmesserly): dart2js throws this error when the type is not
- // reflectable.
- return false;
- }
+bool _maybeHasSetter(ClassMirror type, Symbol name) {
+ var setterName = _setterName(name);
+ while (type != objectType) {
+ final members = type.members;
+ if (members[name] is VariableMirror) return true;
+ if (members.containsKey(setterName)) return true;
+ if (members.containsKey(#noSuchMethod)) return true;
+ type = _safeSuperclass(type);
}
return false;
}
+/**
+ * True if the type has a method, other than on Object.
+ * Doesn't consider noSuchMethod, unless [name] is `#noSuchMethod`.
+ */
+bool _hasMethod(ClassMirror type, Symbol name) {
+ while (type != objectType) {
+ final member = type.members[name];
+ if (member is MethodMirror && member.isRegularMethod) return true;
+ type = _safeSuperclass(type);
+ }
+ return false;
+}
+
+ClassMirror _safeSuperclass(ClassMirror type) {
+ try {
+ return type.superclass;
+ } on UnsupportedError catch (e) {
+ // TODO(jmesserly): dart2js throws this error when the type is not
+ // reflectable.
+ return objectType;
+ }
+}
+
// From: https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
final _pathRegExp = () {
@@ -307,3 +352,5 @@
if (s[0] == '.') return false;
return _pathRegExp.hasMatch(s);
}
+
+final _logger = new Logger('observe.PathObserver');
diff --git a/pkg/observe/lib/src/to_observable.dart b/pkg/observe/lib/src/to_observable.dart
index d4b1668..4684935 100644
--- a/pkg/observe/lib/src/to_observable.dart
+++ b/pkg/observe/lib/src/to_observable.dart
@@ -2,7 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of observe;
+library observe.src.to_observable;
+
+import 'package:observe/observe.dart';
/**
* Converts the [Iterable] or [Map] to an [ObservableList] or [ObservableMap],
@@ -34,7 +36,7 @@
_toObservableDeep(value) {
if (value is Observable) return value;
if (value is Map) {
- var result = new ObservableMap._createFromType(value);
+ var result = new ObservableMap.createFromType(value);
value.forEach((k, v) {
result[_toObservableDeep(k)] = _toObservableDeep(v);
});
diff --git a/pkg/observe/lib/transform.dart b/pkg/observe/lib/transform.dart
index ede5a0d..5e261c0 100644
--- a/pkg/observe/lib/transform.dart
+++ b/pkg/observe/lib/transform.dart
@@ -256,11 +256,11 @@
}
SimpleIdentifier _getSimpleIdentifier(Identifier id) =>
- id is PrefixedIdentifier ? (id as PrefixedIdentifier).identifier : id;
+ id is PrefixedIdentifier ? id.identifier : id;
bool _hasKeyword(Token token, Keyword keyword) =>
- token is KeywordToken && (token as KeywordToken).keyword == keyword;
+ token is KeywordToken && token.keyword == keyword;
String _getOriginalCode(TextEditTransaction code, ASTNode node) =>
code.original.substring(node.offset, node.end);
diff --git a/pkg/observe/pubspec.yaml b/pkg/observe/pubspec.yaml
index 36aa73b..d55ca35 100644
--- a/pkg/observe/pubspec.yaml
+++ b/pkg/observe/pubspec.yaml
@@ -11,7 +11,6 @@
analyzer: any
barback: any
logging: any
- meta: any
path: any
source_maps: any
dev_dependencies:
diff --git a/pkg/observe/test/observe_test.dart b/pkg/observe/test/observe_test.dart
index 691634b..9376ed3 100644
--- a/pkg/observe/test/observe_test.dart
+++ b/pkg/observe/test/observe_test.dart
@@ -9,9 +9,6 @@
import 'package:unittest/unittest.dart';
import 'observe_test_utils.dart';
-// Note: this ensures we run the dartanalyzer on the @observe package.
-// @static-clean
-
void main() {
// Note: to test the basic Observable system, we use ObservableBox due to its
// simplicity. We also test a variant that is based on dirty-checking.
diff --git a/pkg/observe/test/path_observer_test.dart b/pkg/observe/test/path_observer_test.dart
index c620204..91d68a1 100644
--- a/pkg/observe/test/path_observer_test.dart
+++ b/pkg/observe/test/path_observer_test.dart
@@ -213,6 +213,105 @@
performMicrotaskCheckpoint();
expect(values, [1, 2]);
});
+
+ observeTest('errors thrown from getter/setter', () {
+ var model = new ObjectWithErrors();
+ var observer = new PathObserver(model, 'foo');
+
+ expect(() => observer.value, throws);
+ expect(model.getFooCalled, 1);
+
+ expect(() { observer.value = 123; }, throws);
+ expect(model.setFooCalled, [123]);
+ });
+
+ observeTest('object with noSuchMethod', () {
+ var model = new NoSuchMethodModel();
+ var observer = new PathObserver(model, 'foo');
+
+ expect(observer.value, 42);
+ observer.value = 'hi';
+ expect(model._foo, 'hi');
+ expect(observer.value, 'hi');
+
+ expect(model.log, [#foo, const Symbol('foo='), #foo]);
+
+ // These shouldn't throw
+ observer = new PathObserver(model, 'bar');
+ expect(observer.value, null, reason: 'path not found');
+ observer.value = 42;
+ expect(observer.value, null, reason: 'path not found');
+ });
+
+ observeTest('object with indexer', () {
+ var model = new IndexerModel();
+ var observer = new PathObserver(model, 'foo');
+
+ expect(observer.value, 42);
+ expect(model.log, ['[] foo']);
+ model.log.clear();
+
+ observer.value = 'hi';
+ expect(model.log, ['[]= foo hi']);
+ expect(model._foo, 'hi');
+
+ expect(observer.value, 'hi');
+
+ // These shouldn't throw
+ model.log.clear();
+ observer = new PathObserver(model, 'bar');
+ expect(observer.value, null, reason: 'path not found');
+ expect(model.log, ['[] bar']);
+ model.log.clear();
+
+ observer.value = 42;
+ expect(model.log, ['[]= bar 42']);
+ model.log.clear();
+ });
+}
+
+class ObjectWithErrors {
+ int getFooCalled = 0;
+ List setFooCalled = [];
+ @reflectable get foo {
+ getFooCalled++;
+ (this as dynamic).bar;
+ }
+ @reflectable set foo(value) {
+ setFooCalled.add(value);
+ (this as dynamic).bar = value;
+ }
+}
+
+class NoSuchMethodModel {
+ var _foo = 42;
+ List log = [];
+
+ noSuchMethod(Invocation invocation) {
+ final name = invocation.memberName;
+ log.add(name);
+ if (name == #foo && invocation.isGetter) return _foo;
+ if (name == const Symbol('foo=')) {
+ _foo = invocation.positionalArguments[0];
+ return null;
+ }
+ return super.noSuchMethod(invocation);
+ }
+}
+
+class IndexerModel {
+ var _foo = 42;
+ List log = [];
+
+ operator [](index) {
+ log.add('[] $index');
+ if (index == 'foo') return _foo;
+ }
+
+ operator []=(index, value) {
+ log.add('[]= $index $value');
+ if (index == 'foo') _foo = value;
+ }
}
@reflectable
diff --git a/pkg/observe/test/transform_test.dart b/pkg/observe/test/transform_test.dart
index 064ac87..b42f578 100644
--- a/pkg/observe/test/transform_test.dart
+++ b/pkg/observe/test/transform_test.dart
@@ -161,7 +161,7 @@
readInputAsString(id, {encoding}) => throw new UnimplementedError();
static void _mockLogFn(AssetId asset, LogLevel level, String message,
- Span span) {
+ span) {
// Do nothing.
}
}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index e5a8df6..2a8bfdc 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -29,6 +29,7 @@
collection_helpers/test/equality_test/04: Fail # Issue 1533
collection_helpers/test/equality_test/05: Fail # Issue 1533
collection_helpers/test/equality_test/none: Pass, Fail # Issue 14348
+intl/test/number_closure_test: Pass, CompileTimeError # Issue 14603
[ $compiler == dart2js && $checked && $runtime == ie9 ]
crypto/test/base64_test: Timeout # Issue 12486
@@ -55,6 +56,7 @@
polymer/test/prop_attr_bind_reflection_test: Skip #uses dart:html
polymer/test/prop_attr_reflection_test: Skip #uses dart:html
polymer/test/publish_attributes_test: Skip #uses dart:html
+polymer/test/publish_inherited_properties_test: Skip #uses dart:html
polymer/test/register_test: Skip #uses dart:html
polymer/test/take_attributes_test: Skip #uses dart:html
polymer/test/template_distribute_dynamic_test: Skip #uses dart:html
@@ -84,7 +86,6 @@
stack_trace/test/trace_test: Fail # http://dartbug.com/12380
crypto/test/sha256_test: Pass, Fail # Issue 12502
crypto/test/hmac_sha256_test: Pass, Fail # Issue 12502
-polymer_expressions/test/globals_test: Fail # Issue 13890
[ $runtime == ie9 || $runtime == ie10 ]
polymer/example/canonicalization/test/canonicalization_deploy_test: Pass, Timeout
@@ -102,11 +103,11 @@
polymer/test/prop_attr_reflection_test: Pass, Timeout # Issue 13260
polymer/test/prop_attr_bind_reflection_test: Pass, Timeout # Issue 13260
polymer/test/publish_attributes_test: Pass, Timeout # Issue 13260
+polymer/test/publish_inherited_properties_test: Pass, Timeout # Issue 13260
polymer/test/register_test: Pass, Timeout # Issue 13260
polymer/test/take_attributes_test: Pass, Timeout # Issue 13260
polymer/test/template_distribute_dynamic_test: Pass, Timeout # Issue 13260
polymer/test/unbind_test: Pass, Timeout # Issue 13260
-polymer_expressions/test/globals_test: Fail # Issue 13890
# Skip browser-specific tests on VM
[ $runtime == vm ]
@@ -149,7 +150,9 @@
# printed. Minified versions of these tests exist that test the behavior when
# minified.
unittest/test/*_unminified_test: Skip # DO NOT COPY THIS UNLESS YOU WORK ON DART2JS
-analyzer/test/generated/ast_test: Fail # Issue 12336
+
+ # Issue 9217: Uses unspecified Type.toString.
+analyzer/test/generated/ast_test: Fail
[ $compiler == dart2js && $browser ]
stack_trace/test/vm_test: Fail, OK # VM-specific traces
@@ -270,8 +273,6 @@
unittest/test/unittest_test_returning_future_using_runasync_test: Fail # 13921
unittest/test/unittest_testcases_immutable_test: Fail # 13921
unittest/test/unitttest_group_name_test: Fail # 13921
-template_binding/test/template_element_test: Pass, Fail # Flaky, 14330
-polymer_expressions/test/bindings_test: Pass, Fail # Flaky, 14330
polymer/test/custom_event_test: Pass, Crash # 14360
polymer/example/canonicalization/test/canonicalization_deploy_test: Fail, OK # tests deploy only behavior
@@ -290,7 +291,7 @@
scheduled_test/test/scheduled_server_test: Skip # Uses dart:io
[ $browser || $runtime == vm ]
-unittest/test/missing_tick_test: Fail, OK # This test should fail, not time out.
+unittest/test/missing_tick_test: Timeout, Fail, OK # This test should fail, not time out.
# Issue http://dartbug.com/12930
[ $runtime == vm ]
@@ -303,14 +304,82 @@
[ $compiler == dartanalyzer ]
# pkg issue 13944; Missing inherited member 'Observable._mirror'
custom_element/test/analyzer_test: fail
-template_binding/test/analyzer_test: fail
-observe/test/observe_test: fail
[ $compiler == dart2analyzer ]
# pkg issue 13944; Missing inherited members: 'ListChangeRecord.addedCount' and 'ListChangeRecord.removedCount'
custom_element/test/analyzer_test: fail
-template_binding/test/analyzer_test: fail
-observe/test/observe_test: fail
-# pkg issue 13945; Missing inherited member 'Trace.frames'
-observe/test/observe_test: fail
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+barback/test/asset_id_test: StaticWarning
+barback/test/asset_set_test: StaticWarning
+barback/test/asset_test: StaticWarning
+barback/test/cancelable_future_test: StaticWarning
+barback/test/mutliset_test: StaticWarning
+barback/test/package_graph/add_remove_transform_test: StaticWarning
+barback/test/package_graph/errors_test: StaticWarning
+barback/test/package_graph/get_all_assets_test: StaticWarning
+barback/test/package_graph/group_test: StaticWarning
+barback/test/package_graph/many_parallel_transformers_test: StaticWarning
+barback/test/package_graph/repetition_test: StaticWarning
+barback/test/package_graph/source_test: StaticWarning
+barback/test/package_graph/transform_test: StaticWarning
+barback/test/stream_pool_test: StaticWarning
+barback/test/stream_replayer_test: StaticWarning
+barback/test/too_many_open_files_test: StaticWarning
+barback/test/transformer_test: StaticWarning
+csslib/test/big_1_test: StaticWarning
+csslib/test/compiler_test: StaticWarning
+csslib/test/declaration_test: StaticWarning
+csslib/test/error_test: StaticWarning
+csslib/test/extend_test: StaticWarning
+csslib/test/mixin_test: StaticWarning
+csslib/test/nested_test: StaticWarning
+csslib/test/selector_test: StaticWarning
+csslib/test/var_test: StaticWarning
+csslib/test/visitor_test: StaticWarning
+docgen/test/single_library_test: StaticWarning
+http_server/test/http_body_test: StaticWarning
+http_server/test/http_multipart_test: StaticWarning
+http_server/test/virtual_directory_test: StaticWarning
+http_server/test/virtual_host_test: StaticWarning
+http/test/client_test: StaticWarning
+http/test/http_test: StaticWarning
+http/test/mock_client_test: StaticWarning
+http/test/multipart_test: StaticWarning
+http/test/request_test: StaticWarning
+http/test/streamed_request_test: StaticWarning
+intl/test/date_time_format_file_even_test: StaticWarning
+intl/test/date_time_format_file_odd_test: StaticWarning
+intl/test/date_time_format_http_request_test: StaticWarning
+intl/test/date_time_format_local_even_test: StaticWarning
+intl/test/date_time_format_local_odd_test: StaticWarning
+observe/test/transform_test: StaticWarning
+polymer/test/build/*: StaticWarning
+polymer/test/build/utils_test: Pass
+scheduled_test/test/descriptor/async_test: StaticWarning
+scheduled_test/test/descriptor/directory_test: StaticWarning
+scheduled_test/test/descriptor/file_test: StaticWarning
+scheduled_test/test/descriptor/nothing_test: StaticWarning
+scheduled_test/test/descriptor/pattern_test: StaticWarning
+scheduled_test/test/scheduled_future_matchers_test: StaticWarning
+scheduled_test/test/scheduled_process_test: StaticWarning
+scheduled_test/test/scheduled_test/abort_test: StaticWarning
+scheduled_test/test/scheduled_test/current_schedule_current_task_test: StaticWarning
+scheduled_test/test/scheduled_test/current_schedule_errors_test: StaticWarning
+scheduled_test/test/scheduled_test/current_schedule_state_test: StaticWarning
+scheduled_test/test/scheduled_test/nested_task_test: StaticWarning
+scheduled_test/test/scheduled_test/on_complete_test: StaticWarning
+scheduled_test/test/scheduled_test/on_exception_test: StaticWarning
+scheduled_test/test/scheduled_test/out_of_band_task_test: StaticWarning
+scheduled_test/test/scheduled_test/set_up_test: StaticWarning
+scheduled_test/test/scheduled_test/signal_error_test: StaticWarning
+scheduled_test/test/scheduled_test/simple_test: StaticWarning
+scheduled_test/test/scheduled_test/task_return_value_test: StaticWarning
+scheduled_test/test/scheduled_test/timeout_test: StaticWarning
+scheduled_test/test/scheduled_test/wrap_async_test: StaticWarning
+scheduled_test/test/scheduled_test/wrap_future_test: StaticWarning
+unittest/test/matchers_test: StaticWarning
+unittest/test/mock_test: StaticWarning
+watcher/test/directory_watcher_test: StaticWarning
+watcher/test/no_subscription_test: StaticWarning
+watcher/test/ready_test: StaticWarning
diff --git a/pkg/polymer/lib/src/build/script_compactor.dart b/pkg/polymer/lib/src/build/script_compactor.dart
index 01885f7..8ac8fd0 100644
--- a/pkg/polymer/lib/src/build/script_compactor.dart
+++ b/pkg/polymer/lib/src/build/script_compactor.dart
@@ -81,7 +81,10 @@
mainScriptTag.attributes['src'] =
path.url.basename(bootstrapId.path);
- libraries.add(mainLibraryId);
+ // TODO(sigmund): stop renaming the file (see dartbug.com/14554)
+ var modifiedMainId = mainLibraryId.addExtension('_modified.dart');
+
+ libraries.add(modifiedMainId);
var urls = libraries.map((id) => assetUrlFor(id, bootstrapId, logger))
.where((url) => url != null).toList();
var buffer = new StringBuffer()..writeln(MAIN_HEADER);
@@ -95,12 +98,17 @@
..writeln(' configureForDeployment([')
..writeAll(urls.map((url) => " '$url',\n"))
..writeln(' ]);')
- ..writeln(' i${i - 1}.main();')
+ ..writeln(' i${i - 1}.polymerMainWrapper();')
..writeln('}');
transform.addOutput(new Asset.fromString(
bootstrapId, buffer.toString()));
transform.addOutput(new Asset.fromString(id, document.outerHtml));
+
+ return transform.readInputAsString(mainLibraryId).then((contents) {
+ transform.addOutput(new Asset.fromString(modifiedMainId,
+ '$contents\n\npolymerMainWrapper() => main();\n'));
+ });
});
});
}
diff --git a/pkg/polymer/lib/src/declaration.dart b/pkg/polymer/lib/src/declaration.dart
index ba2beff..bb6b225 100644
--- a/pkg/polymer/lib/src/declaration.dart
+++ b/pkg/polymer/lib/src/declaration.dart
@@ -242,9 +242,13 @@
void publishAttributes(ClassMirror cls, PolymerDeclaration superDecl) {
// get properties to publish
if (superDecl != null && superDecl._publish != null) {
+ // Dart note: even though we walk the type hierarchy in
+ // _getPublishedProperties, this will additionally include any names
+ // published via the `attributes` attribute.
_publish = new Map.from(superDecl._publish);
}
- _publish = _getProperties(cls, _publish, (x) => x is PublishedProperty);
+
+ _publish = _getPublishedProperties(cls, _publish);
// merge names from 'attributes' attribute
var attrs = attributes['attributes'];
@@ -491,12 +495,14 @@
final _objectType = reflectClass(Object);
-Map _getProperties(ClassMirror cls, Map props, bool matches(metadata)) {
+Map _getPublishedProperties(ClassMirror cls, Map props) {
+ if (cls == _objectType) return props;
+ props = _getPublishedProperties(cls.superclass, props);
for (var field in cls.variables.values) {
if (field.isFinal || field.isStatic || field.isPrivate) continue;
for (var meta in field.metadata) {
- if (matches(meta.reflectee)) {
+ if (meta.reflectee is PublishedProperty) {
if (props == null) props = {};
props[field.simpleName] = field;
break;
@@ -508,7 +514,7 @@
if (getter.isStatic || getter.isPrivate) continue;
for (var meta in getter.metadata) {
- if (matches(meta.reflectee)) {
+ if (meta.reflectee is PublishedProperty) {
if (_hasSetter(cls, getter)) {
if (props == null) props = {};
props[getter.simpleName] = getter;
diff --git a/pkg/polymer/lib/src/instance.dart b/pkg/polymer/lib/src/instance.dart
index e46fda3..348a61f 100644
--- a/pkg/polymer/lib/src/instance.dart
+++ b/pkg/polymer/lib/src/instance.dart
@@ -437,6 +437,8 @@
}
Map<String, NodeBinding> get bindings => nodeBindFallback(this).bindings;
+ TemplateInstance get templateInstance =>
+ nodeBindFallback(this).templateInstance;
void unbind(String name) => nodeBindFallback(this).unbind(name);
@@ -579,7 +581,7 @@
}
}
- void unbindProperty(String name) => unregisterObserver(name);
+ bool unbindProperty(String name) => unregisterObserver(name);
void unbindAllProperties() {
if (_propertyObserver != null) {
@@ -738,38 +740,39 @@
// we implement this by wrapping/overriding getBinding instead.
// TODO(sorvell): we're patching the syntax while evaluating
// event bindings. we'll move this to a better spot when that's done
- static getBindingWithEvents(
- model, String path, name, node, originalGetBinding) {
+ static PrepareBindingFunction prepareBinding(String path, String name, node,
+ originalPrepareBinding) {
+
// if lhs an event prefix,
- if (name is! String || !_hasEventPrefix(name)) {
- return originalGetBinding(model, path, name, node);
- }
+ if (!_hasEventPrefix(name)) return originalPrepareBinding(path, name, node);
// provide an event-binding callback.
- // return (model, name, node) {
- if (_eventsLog.isLoggable(Level.FINE)) {
- _eventsLog.fine('event: [${node.localName}].$name => '
- '[${model.localName}].$path())');
- }
- var eventName = _removeEventPrefix(name);
- // TODO(sigmund): polymer.js dropped event translations. reconcile?
- var translated = _eventTranslations[eventName];
- eventName = translated != null ? translated : eventName;
- return node.on[eventName].listen((event) {
- var ctrlr = _findController(node);
- if (ctrlr is! Polymer) return;
- var obj = ctrlr;
- var method = path;
- if (path[0] == '@') {
- obj = model;
- // Dart note: using getBinding gets us the result of evaluating the
- // original path (without the @) as a normal expression.
- method = originalGetBinding(model, path.substring(1), name, node).value;
+ return (model, node) {
+ if (_eventsLog.isLoggable(Level.FINE)) {
+ _eventsLog.fine('event: [$node].$name => [$model].$path())');
}
- var detail = event is CustomEvent ?
- (event as CustomEvent).detail : null;
- ctrlr.dispatchMethod(obj, method, [event, detail, node]);
- });
+ var eventName = _removeEventPrefix(name);
+ // TODO(sigmund): polymer.js dropped event translations. reconcile?
+ var translated = _eventTranslations[eventName];
+ eventName = translated != null ? translated : eventName;
+
+ // TODO(jmesserly): returning a StreamSubscription as the model is quite
+ // strange. package:template_binding doesn't have any cleanup logic to
+ // handle that.
+ return node.on[eventName].listen((event) {
+ var ctrlr = _findController(node);
+ if (ctrlr is! Polymer) return;
+ var obj = ctrlr;
+ var method = path;
+ if (path[0] == '@') {
+ obj = model;
+ method = new PathObserver(model, path.substring(1)).value;
+ }
+ var detail = event is CustomEvent ?
+ (event as CustomEvent).detail : null;
+ ctrlr.dispatchMethod(obj, method, [event, detail, node]);
+ });
+ };
}
// TODO(jmesserly): this won't find the correct host unless the ShadowRoot
@@ -902,7 +905,7 @@
decl = decl.superDeclaration;
}
if (cssText.length > 0) {
- var style = this.element.cssTextToScopeStyle(cssText.toString(),
+ var style = decl.cssTextToScopeStyle(cssText.toString(),
_STYLE_CONTROLLER_SCOPE);
// TODO(sorvell): for now these styles are not shimmed
// but we may need to shim them
@@ -1074,8 +1077,6 @@
}
class _PolymerExpressionsWithEventDelegate extends PolymerExpressions {
- getBinding(model, String path, name, node) {
- return Polymer.getBindingWithEvents(
- model, path, name, node, super.getBinding);
- }
+ prepareBinding(String path, name, node) =>
+ Polymer.prepareBinding(path, name, node, super.prepareBinding);
}
diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart
index c999660..eb0a726 100644
--- a/pkg/polymer/lib/src/loader.dart
+++ b/pkg/polymer/lib/src/loader.dart
@@ -32,12 +32,13 @@
* The urls in [libraries] can be absolute or relative to
* `currentMirrorSystem().isolate.rootLibrary.uri`.
*/
-void initPolymer() {
+Zone initPolymer() {
if (_useDirtyChecking) {
- dirtyCheckZone().run(_initPolymerOptimized);
- } else {
- _initPolymerOptimized();
+ return dirtyCheckZone()..run(_initPolymerOptimized);
}
+
+ _initPolymerOptimized();
+ return Zone.current;
}
/**
diff --git a/pkg/polymer/lib/transformer.dart b/pkg/polymer/lib/transformer.dart
index 4d132cf..a4f0e10 100644
--- a/pkg/polymer/lib/transformer.dart
+++ b/pkg/polymer/lib/transformer.dart
@@ -35,26 +35,29 @@
TransformOptions _parseArgs(Map args) {
- var entryPoints;
- if (args.containsKey('entry_points')) {
- entryPoints = [];
- var value = args['entry_points'];
- bool error;
- if (value is List) {
- entryPoints = value;
- error = value.any((e) => e is! String);
- } else if (value is String) {
- entryPoints = [value];
- error = false;
- } else {
- error = true;
- }
+ return new TransformOptions(
+ entryPoints: _readEntrypoints(args['entry_points']),
+ directlyIncludeJS: args['js'] != false, // default to true
+ contentSecurityPolicy: args['csp'] == true); // default to false
+}
- if (error) {
- print('Invalid value for "entry_points" in the polymer transformer.');
- }
+_readEntrypoints(value) {
+ if (value == null) return null;
+ var entryPoints = [];
+ bool error;
+ if (value is List) {
+ entryPoints = value;
+ error = value.any((e) => e is! String);
+ } else if (value is String) {
+ entryPoints = [value];
+ error = false;
+ } else {
+ error = true;
}
- return new TransformOptions(entryPoints: entryPoints);
+ if (error) {
+ print('Invalid value for "entry_points" in the polymer transformer.');
+ }
+ return entryPoints;
}
List<List<Transformer>> _createDeployPhases(TransformOptions options) {
diff --git a/pkg/polymer/test/bind_test.dart b/pkg/polymer/test/bind_test.dart
index e3f25ca..1fd6515 100644
--- a/pkg/polymer/test/bind_test.dart
+++ b/pkg/polymer/test/bind_test.dart
@@ -50,5 +50,5 @@
setUp(() => Polymer.onReady);
- test('ready called', () => query('x-foo').onTestDone);
+ test('ready called', () => (query('x-foo') as XFoo).onTestDone);
}
diff --git a/pkg/polymer/test/build/all_phases_test.dart b/pkg/polymer/test/build/all_phases_test.dart
index 9a1fccd..4b6b759 100644
--- a/pkg/polymer/test/build/all_phases_test.dart
+++ b/pkg/polymer/test/build/all_phases_test.dart
@@ -33,7 +33,7 @@
'a|web/test.html':
'<!DOCTYPE html><html><head>'
'<script type="application/dart" src="a.dart"></script>',
- 'a|web/test.dart': _sampleObservable('A', 'foo'),
+ 'a|web/a.dart': _sampleObservable('A', 'foo'),
}, {
'a|web/test.html':
'<!DOCTYPE html><html><head>'
@@ -45,16 +45,18 @@
'a|web/test.html_bootstrap.dart':
'''$MAIN_HEADER
- import 'a.dart' as i0;
+ import 'a.dart_modified.dart' as i0;
void main() {
configureForDeployment([
- 'a.dart',
+ 'a.dart_modified.dart',
]);
- i0.main();
+ i0.polymerMainWrapper();
}
'''.replaceAll('\n ', '\n'),
- 'a|web/test.dart': _sampleObservableOutput('A', 'foo'),
+ 'a|web/a.dart': _sampleObservableOutput('A', 'foo'),
+ 'a|web/a.dart_modified.dart':
+ _sampleObservableOutput('A', 'foo', includeMain: true),
});
testPhases('single inline script', phases, {
@@ -73,16 +75,19 @@
'a|web/test.html_bootstrap.dart':
'''$MAIN_HEADER
- import 'test.html.0.dart' as i0;
+ import 'test.html.0.dart_modified.dart' as i0;
void main() {
configureForDeployment([
- 'test.html.0.dart',
+ 'test.html.0.dart_modified.dart',
]);
- i0.main();
+ i0.polymerMainWrapper();
}
'''.replaceAll('\n ', '\n'),
- 'a|web/test.html.0.dart': _sampleObservableOutput("B", "bar"),
+ 'a|web/test.html.0.dart':
+ _sampleObservableOutput("B", "bar"),
+ 'a|web/test.html.0.dart_modified.dart':
+ _sampleObservableOutput("B", "bar", includeMain: true),
});
testPhases('several scripts', phases, {
@@ -114,16 +119,18 @@
'a|web/test.html_bootstrap.dart':
'''$MAIN_HEADER
- import 'a.dart' as i0;
+ import 'a.dart_modified.dart' as i0;
void main() {
configureForDeployment([
- 'a.dart',
+ 'a.dart_modified.dart',
]);
- i0.main();
+ i0.polymerMainWrapper();
}
'''.replaceAll('\n ', '\n'),
'a|web/a.dart': _sampleObservableOutput('A', 'foo'),
+ 'a|web/a.dart_modified.dart':
+ _sampleObservableOutput('A', 'foo', includeMain: true),
'a|web/test.html.0.dart': _sampleObservableOutput("B", "bar"),
'a|web/test.html.1.dart': _sampleObservableOutput("C", "car"),
});
@@ -153,17 +160,19 @@
'a|web/index.html_bootstrap.dart':
'''$MAIN_HEADER
import 'test2.html.0.dart' as i0;
- import 'b.dart' as i1;
+ import 'b.dart_modified.dart' as i1;
void main() {
configureForDeployment([
'test2.html.0.dart',
- 'b.dart',
+ 'b.dart_modified.dart',
]);
- i1.main();
+ i1.polymerMainWrapper();
}
'''.replaceAll('\n ', '\n'),
'a|web/test2.html.0.dart': _sampleObservableOutput("A", "foo"),
+ 'a|web/test2.html.0.dart_modified.dart':
+ _sampleObservableOutput("A", "foo", includeMain: true),
'a|web/b.dart': _sampleObservableOutput('B', 'bar'),
});
}
@@ -178,7 +187,8 @@
}
''';
-String _sampleObservableOutput(String className, String field) =>
+String _sampleObservableOutput(String className, String field,
+ {bool includeMain: false}) =>
"library ${className}_$field;\n"
"import 'package:observe/observe.dart';\n\n"
"class $className extends ChangeNotifier {\n"
@@ -188,4 +198,5 @@
"__\$$field = notifyPropertyChange(#$field, __\$$field, value); "
"}\n"
" $className($field) : __\$$field = $field;\n"
- "}\n";
+ "}\n"
+ "${includeMain ? '\n\npolymerMainWrapper() => main();\n' : ''}";
diff --git a/pkg/polymer/test/build/script_compactor_test.dart b/pkg/polymer/test/build/script_compactor_test.dart
index 32bd762..946c90d 100644
--- a/pkg/polymer/test/build/script_compactor_test.dart
+++ b/pkg/polymer/test/build/script_compactor_test.dart
@@ -36,6 +36,7 @@
'<!DOCTYPE html><html><head>'
'<script type="application/dart" src="a.dart"></script>',
'a|web/test.html.scriptUrls': '[]',
+ 'a|web/a.dart': 'library a;\nmain(){}',
}, {
'a|web/test.html':
'<!DOCTYPE html><html><head>'
@@ -45,15 +46,19 @@
'a|web/test.html_bootstrap.dart':
'''$MAIN_HEADER
- import 'a.dart' as i0;
+ import 'a.dart_modified.dart' as i0;
void main() {
configureForDeployment([
- 'a.dart',
+ 'a.dart_modified.dart',
]);
- i0.main();
+ i0.polymerMainWrapper();
}
'''.replaceAll('\n ', '\n'),
+ 'a|web/a.dart': 'library a;\nmain(){}',
+ 'a|web/a.dart_modified.dart':
+ 'library a;\nmain(){}'
+ '\n\npolymerMainWrapper() => main();\n',
});
testPhases('several scripts', phases, {
@@ -64,6 +69,7 @@
'</div>',
'a|web/test.html.scriptUrls':
'[["a", "web/a.dart"],["a", "web/b.dart"],["a", "web/c.dart"]]',
+ 'a|web/d.dart': 'library d;\nmain(){}',
}, {
'a|web/test.html':
'<!DOCTYPE html><html><head></head><body><div>'
@@ -77,16 +83,16 @@
import 'a.dart' as i0;
import 'b.dart' as i1;
import 'c.dart' as i2;
- import 'd.dart' as i3;
+ import 'd.dart_modified.dart' as i3;
void main() {
configureForDeployment([
'a.dart',
'b.dart',
'c.dart',
- 'd.dart',
+ 'd.dart_modified.dart',
]);
- i3.main();
+ i3.polymerMainWrapper();
}
'''.replaceAll('\n ', '\n'),
});
diff --git a/pkg/polymer/test/event_handlers_test.dart b/pkg/polymer/test/event_handlers_test.dart
index 779ccb6..8267e0a 100644
--- a/pkg/polymer/test/event_handlers_test.dart
+++ b/pkg/polymer/test/event_handlers_test.dart
@@ -7,10 +7,11 @@
import 'dart:async';
import 'dart:html';
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
+import 'package:logging/logging.dart';
import 'package:polymer/polymer.dart';
import 'package:template_binding/template_binding.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
@CustomTag('x-test')
class XTest extends PolymerElement {
@@ -19,12 +20,9 @@
String _lastMessage;
List list1 = [];
List list2 = [];
- final _ready = new Completer();
Future _onTestDone;
- XTest.created() : super.created() {
- _onTestDone = _ready.future.then(_runTest);
- }
+ XTest.created() : super.created();
ready() {
super.ready();
@@ -33,7 +31,8 @@
list1.add(model);
list2.add(model);
}
- _ready.complete();
+
+ _onTestDone = new Future.sync(_runTests);
}
hostTapAction(event, detail, node) => _logEvent(event);
@@ -57,7 +56,7 @@
_lastMessage = message;
}
- _runTest(_) {
+ Future _runTests() {
fire('tap', toNode: $['div']);
expect(_testCount, 2, reason: 'event heard at div and host');
expect(_lastEvent, 'tap', reason: 'tap handled');
@@ -70,6 +69,7 @@
fire('scroll', toNode: $['list'], canBubble: false);
expect(_testCount, 5, reason: 'event heard by list');
expect(_lastEvent, 'scroll', reason: 'scroll handled');
+
return onMutation($['list']).then((_) {
var l1 = $['list'].querySelectorAll('.list1')[4];
fire('tap', toNode: l1, canBubble: false);
@@ -103,6 +103,9 @@
}
main() {
+ Logger.root..level = Level.FINE
+ ..onRecord.listen((m) => print('${m.loggerName} ${m.message}'));
+
initPolymer();
}
@@ -110,6 +113,8 @@
useHtmlConfiguration();
setUp(() => Polymer.onReady);
- test('events handled', () => (query('x-test') as XTest)._onTestDone);
+ test('events handled', () {
+ XTest test = query('x-test');
+ expect(test._onTestDone, isNotNull, reason: 'ready was called');
+ });
}
-
diff --git a/pkg/polymer/test/publish_attributes_test.dart b/pkg/polymer/test/publish_attributes_test.dart
index c6ea12a..b22132e 100644
--- a/pkg/polymer/test/publish_attributes_test.dart
+++ b/pkg/polymer/test/publish_attributes_test.dart
@@ -48,8 +48,8 @@
setUp(() => Polymer.onReady);
test('published properties', () {
- published(tag) =>
- query('polymer-element[name=$tag]').publishedProperties;
+ published(tag) => (query('polymer-element[name=$tag]')
+ as PolymerDeclaration).publishedProperties;
expect(published('x-foo'), [#Foo, #baz]);
expect(published('x-bar'), [#Foo, #baz, #Bar]);
diff --git a/pkg/polymer/test/publish_inherited_properties_test.dart b/pkg/polymer/test/publish_inherited_properties_test.dart
new file mode 100644
index 0000000..7eec80a
--- /dev/null
+++ b/pkg/polymer/test/publish_inherited_properties_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:polymer/polymer.dart';
+
+// Dart note: unlike JS, you can't publish something that doesn't
+// have a corresponding field because we can't dynamically add properties.
+// So we define XFoo and XBar types here.
+class XFoo extends PolymerElement {
+ XFoo.created() : super.created();
+
+ @published var Foo;
+}
+
+class XBar extends XFoo {
+ XBar.created() : super.created();
+
+ @published var Bar;
+}
+
+@CustomTag('x-zot')
+class XZot extends XBar {
+ XZot.created() : super.created();
+
+ var m;
+ @published int zot = 3;
+}
+
+// TODO(sigmund): uncomment this part of the test too (see dartbug.com/14559)
+// class XWho extends XZot {
+// XWho.created() : super.created();
+//
+// @published var zap;
+// }
+
+@CustomTag('x-squid')
+class XSquid extends XZot {
+ XSquid.created() : super.created();
+
+ @published int baz = 13;
+ @published int zot = 5;
+ @published int squid = 7;
+}
+
+main() {
+ initPolymer();
+ useHtmlConfiguration();
+
+ setUp(() => Polymer.onReady);
+
+ test('published properties', () {
+ published(tag) => (query('polymer-element[name=$tag]')
+ as PolymerDeclaration).publishedProperties;
+
+ expect(published('x-zot'), [#Foo, #Bar, #zot, #m]);
+ expect(published('x-squid'), [#Foo, #Bar, #zot, #m, #baz, #squid]);
+ expect(published('x-noscript'), [#Foo, #Bar, #zot, #m]);
+ // TODO(sigmund): uncomment, see above
+ // expect(published('x-squid'), [#Foo, #Bar, #zot, #zap, #baz, #squid]);
+ });
+}
diff --git a/pkg/polymer/test/publish_inherited_properties_test.html b/pkg/polymer/test/publish_inherited_properties_test.html
new file mode 100644
index 0000000..8fafba7
--- /dev/null
+++ b/pkg/polymer/test/publish_inherited_properties_test.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<!--
+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.
+-->
+<html>
+ <head>
+ <!--polymer-test: this comment is needed for test_suite.dart-->
+ <title>publish inherited properties</title>
+ <script src="packages/unittest/test_controller.js"></script>
+ </head>
+ <body>
+
+ <polymer-element name="x-zot" attributes="m">
+ </polymer-element>
+
+ <polymer-element name="x-squid" extends="x-zot" attributes="squid">
+ </polymer-element>
+
+ <polymer-element name="x-noscript" extends="x-zot" noscript>
+ </polymer-element>
+
+ <script type="application/dart" src="publish_inherited_properties_test.dart"></script>
+ </body>
+</html>
diff --git a/pkg/polymer/test/register_test.dart b/pkg/polymer/test/register_test.dart
index 070ee0f..8afb734 100644
--- a/pkg/polymer/test/register_test.dart
+++ b/pkg/polymer/test/register_test.dart
@@ -23,8 +23,8 @@
}
@CustomTag('x-div-two')
-class XDiv2lElement extends XDivElement {
- XDiv2lElement.created() : super.created();
+class XDiv2Element extends XDivElement {
+ XDiv2Element.created() : super.created();
}
main() {
diff --git a/pkg/polymer/test/template_distribute_dynamic_test.dart b/pkg/polymer/test/template_distribute_dynamic_test.dart
index 86c469e..e80c624 100644
--- a/pkg/polymer/test/template_distribute_dynamic_test.dart
+++ b/pkg/polymer/test/template_distribute_dynamic_test.dart
@@ -58,5 +58,5 @@
setUp(() => Polymer.onReady);
- test('inserted called', () => query('x-test').onTestDone);
+ test('inserted called', () => (query('x-test') as XTest).onTestDone);
}
diff --git a/pkg/polymer_expressions/README.md b/pkg/polymer_expressions/README.md
index 9cc3da4..6f0db01 100644
--- a/pkg/polymer_expressions/README.md
+++ b/pkg/polymer_expressions/README.md
@@ -48,7 +48,7 @@
[mdv]: http://www.polymer-project.org/platform/mdv.html
-### Custom Binding Syntaxes with BindingDelegate
+### Custom binding syntaxes with binding delegate
While MDV's built-in syntax is very basic, it does allow custom syntaxes called
"binding delegates" to be installed and used. A binding delegate can interpret
@@ -81,7 +81,7 @@
import 'package:polymer_expressions/polymer_expressions.dart';
-### Registering a Binding Delegate
+### Registering a binding delegate
**Polymer Expressions are now the default syntax for `<polymer-element>` custom
elements.**
@@ -106,7 +106,7 @@
}
```
-### Registering Top-Level Variables
+### Registering top-level variables
Before a top-level variable can be used, it must be registered. The
PolymerExpressions constructor takes a map of named values to use as variables.
@@ -124,7 +124,7 @@
## Features
-### The Model and Scope
+### The model and scope
Polymer Expressions allow binding to more than just the model assigned to a
template instance. Top-level variables can be defined so that you can use
@@ -132,7 +132,7 @@
model are held together in a container called a Scope. Scopes can be nested,
which happens when template tags are nested.
-### Two-way Bindings
+### Two-way bindings
Bindings can be used to modify the data model based on events in the DOM. The
most common case is to bind an <input> element's value field to a model
@@ -177,7 +177,7 @@
## Syntax
-### Property Access
+### Property access
Properties on the model and in the scope are looked up via simple property
names, like `foo`. Property names are looked up first in the top-level
@@ -200,7 +200,7 @@
List literals are planned, see [issue 9](https://github.com/dart-lang/polymer_expressions/issues/9)
-### Functions and Methods
+### Functions and methods
If a property is a function in the scope, a method on the model, or a method on
an object, it can be invoked with standard function syntax. Functions and
@@ -224,7 +224,7 @@
Expressions do not support bitwise operators such as &, |, << and >>, or increment/decrement operators (++ and --)
-### List and Map Indexing
+### List and Map indexing
List and Map like objects can be accessed via the index operator: []
@@ -238,7 +238,7 @@
and `people.john`. This ensures that access to properties and methods on Lists
and Maps is preserved.
-### Filters and Transformers
+### Filters and transformers
A filter is a function that transforms a value into another, used via the pipe
syntax: `value | filter` Any function that takes exactly one argument can be
@@ -254,7 +254,7 @@
has an inverse function. Transformers must extend or implement the `Transformer`
class, which has `forward()` and `reverse()` methods.
-### Repeating Templates
+### Repeating templates
A template can be repeated by using the "repeat" attribute with a binding. The
binding can either evaluate to an Iterable, in which case the template is
diff --git a/pkg/polymer_expressions/lib/filter.dart b/pkg/polymer_expressions/lib/filter.dart
index cd9b932..c972584 100644
--- a/pkg/polymer_expressions/lib/filter.dart
+++ b/pkg/polymer_expressions/lib/filter.dart
@@ -10,14 +10,15 @@
T forward(V v);
V reverse(T t);
- Transformer<V, T> get inverse => new _InverseTransformer<V, T>(this);
+ Transformer<V, T> get inverse => new _InverseTransformer/*<V, T>*/(this);
}
-class _InverseTransformer<V, T> implements Transformer<V, T> {
- final Transformer<T, V> _t;
+// TODO(jmesserly): restore types when Issue 14094 is fixed.
+class _InverseTransformer/*<V, T>*/ implements Transformer/*<V, T>*/ {
+ final Transformer/*<T, V>*/ _t;
_InverseTransformer(this._t);
- V forward(T v) => _t.reverse(v);
- T reverse(V t) => _t.forward(t);
- Transformer<T, V> get inverse => _t;
+ /*V*/ forward(/*T*/ v) => _t.reverse(v);
+ /*T*/ reverse(/*V*/ t) => _t.forward(t);
+ Transformer/*<T, V>*/ get inverse => _t;
}
diff --git a/pkg/polymer_expressions/lib/polymer_expressions.dart b/pkg/polymer_expressions/lib/polymer_expressions.dart
index 3f70c4b..354fb5e 100644
--- a/pkg/polymer_expressions/lib/polymer_expressions.dart
+++ b/pkg/polymer_expressions/lib/polymer_expressions.dart
@@ -67,28 +67,25 @@
: globals = (globals == null) ?
new Map<String, Object>.from(DEFAULT_GLOBALS) : globals;
- _Binding getBinding(model, String path, name, node) {
+ prepareBinding(String path, name, node) {
if (path == null) return null;
var expr = new Parser(path).parse();
- if (model is! Scope) {
- model = new Scope(model: model, variables: globals);
- }
- if (node is Element && name == "class") {
- return new _Binding(expr, model, _classAttributeConverter);
- }
- if (node is Element && name == "style") {
- return new _Binding(expr, model, _styleAttributeConverter);
- }
- return new _Binding(expr, model);
+ return (model, node) {
+ if (model is! Scope) {
+ model = new Scope(model: model, variables: globals);
+ }
+ if (node is Element && name == "class") {
+ return new _Binding(expr, model, _classAttributeConverter);
+ }
+ if (node is Element && name == "style") {
+ return new _Binding(expr, model, _styleAttributeConverter);
+ }
+ return new _Binding(expr, model);
+ };
}
- getInstanceModel(Element template, model) {
- if (model is! Scope) {
- var _scope = new Scope(model: model, variables: globals);
- return _scope;
- }
- return model;
- }
+ prepareInstanceModel(Element template) => (model) =>
+ model is Scope ? model : new Scope(model: model, variables: globals);
}
class _Binding extends ChangeNotifier {
diff --git a/pkg/polymer_expressions/test/bindings_test.dart b/pkg/polymer_expressions/test/bindings_test.dart
index 9851ded..26a3a14 100644
--- a/pkg/polymer_expressions/test/bindings_test.dart
+++ b/pkg/polymer_expressions/test/bindings_test.dart
@@ -37,7 +37,7 @@
observeTest('should update binding when data changes', () {
var model = new NotifyModel();
var binding = new PolymerExpressions()
- .getBinding(model, 'x', null, null);
+ .prepareBinding('x', null, null)(model, null);
expect(binding.value, isNull);
model.x = "hi";
performMicrotaskCheckpoint();
diff --git a/pkg/scheduled_test/lib/scheduled_test.dart b/pkg/scheduled_test/lib/scheduled_test.dart
index aab455e..1be401c 100644
--- a/pkg/scheduled_test/lib/scheduled_test.dart
+++ b/pkg/scheduled_test/lib/scheduled_test.dart
@@ -49,7 +49,7 @@
/// });
/// }
///
-/// ## Setting Up and Tearing Down
+/// ## Setting up and tearing down
///
/// The `scheduled_test` package defines its own [setUp] method that works just
/// like the one in `unittest`. Tasks can be scheduled in [setUp]; they'll be
@@ -77,7 +77,7 @@
/// // ...
/// }
///
-/// ## Passing Values Between Tasks
+/// ## Passing values between tasks
///
/// It's often useful to use values computed in one task in other tasks that are
/// scheduled afterwards. There are two ways to do this. The most
diff --git a/pkg/scheduled_test/test/descriptor/async_test.dart b/pkg/scheduled_test/test/descriptor/async_test.dart
index 48fa883..72e7ceb 100644
--- a/pkg/scheduled_test/test/descriptor/async_test.dart
+++ b/pkg/scheduled_test/test/descriptor/async_test.dart
@@ -10,8 +10,8 @@
import '../metatest.dart';
import 'utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/descriptor/directory_test.dart b/pkg/scheduled_test/test/descriptor/directory_test.dart
index dfc1f3b..0c9cdea 100644
--- a/pkg/scheduled_test/test/descriptor/directory_test.dart
+++ b/pkg/scheduled_test/test/descriptor/directory_test.dart
@@ -12,8 +12,8 @@
import '../metatest.dart';
import 'utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/descriptor/file_test.dart b/pkg/scheduled_test/test/descriptor/file_test.dart
index bf62f62..f319819 100644
--- a/pkg/scheduled_test/test/descriptor/file_test.dart
+++ b/pkg/scheduled_test/test/descriptor/file_test.dart
@@ -11,8 +11,8 @@
import '../metatest.dart';
import 'utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/descriptor/nothing_test.dart b/pkg/scheduled_test/test/descriptor/nothing_test.dart
index 8afe303..34d02e9 100644
--- a/pkg/scheduled_test/test/descriptor/nothing_test.dart
+++ b/pkg/scheduled_test/test/descriptor/nothing_test.dart
@@ -11,8 +11,8 @@
import '../metatest.dart';
import 'utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/descriptor/pattern_test.dart b/pkg/scheduled_test/test/descriptor/pattern_test.dart
index 826343d..9b92ad2 100644
--- a/pkg/scheduled_test/test/descriptor/pattern_test.dart
+++ b/pkg/scheduled_test/test/descriptor/pattern_test.dart
@@ -10,8 +10,8 @@
String sandbox;
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/metatest.dart b/pkg/scheduled_test/test/metatest.dart
index e846773..0c7725d 100644
--- a/pkg/scheduled_test/test/metatest.dart
+++ b/pkg/scheduled_test/test/metatest.dart
@@ -9,8 +9,8 @@
/// isolate, then reporting the results back to the parent isolate.
library metatest;
-import 'dart:io';
import 'dart:async';
+import 'dart:io';
import 'dart:isolate';
import 'package:path/path.dart' as path;
@@ -19,11 +19,6 @@
import 'utils.dart';
-// TODO(nweiz): get rid of this once issue 8863 is fixed.
-/// The path to the Dart executable. This is only set in a child isolate.
-String get dartExecutable => _executable;
-String _executable;
-
/// Declares a test with the given [description] and [body]. [body] corresponds
/// to the `main` method of a test file, and will be run in an isolate. By
/// default, this expects that all tests defined in [body] pass, but if
@@ -75,77 +70,62 @@
/// Runs [setUpFn] before every metatest. Note that [setUpFn] will be
/// overwritten if the test itself calls [setUp].
void metaSetUp(void setUpFn()) {
- _inChildIsolate.then((inIsolate) {
- if (inIsolate) scheduled_test.setUp(setUpFn);
- });
+ if (_inChildIsolate) scheduled_test.setUp(setUpFn);
}
/// Sets up a test with the given [description] and [body]. After the test runs,
/// calls [validate] with the result map.
void _setUpTest(String description, void body(), void validate(Map)) {
- _inChildIsolate.then((inIsolate) {
- if (inIsolate) {
- _ensureInitialized();
- if (_testToRun == description) body();
- } else {
- test(description, () {
- expect(_runInIsolate(description).then(validate), completes);
- });
- }
- });
+ if (_inChildIsolate) {
+ _ensureInitialized();
+ if (_testToRun == description) body();
+ } else {
+ test(description, () {
+ expect(_runInIsolate(description).then(validate), completes);
+ });
+ }
}
-/// The description of the test to run in the child isolate. `null` in the
-/// parent isolate. Not set until [_inChildIsolate] completes.
+/// The description of the test to run in the child isolate.
+///
+/// `null` in the parent isolate.
String _testToRun;
/// The port with which the child isolate should communicate with the parent
-/// isolate. `null` in the parent isolate. Not set until [_inChildIsolate]
-/// completes.
+/// isolate.
+///
+/// `null` in the parent isolate.
SendPort _replyTo;
-/// The cached [Future] for [_inChildIsolate].
-Future<bool> _inChildIsolateFuture;
+/// Whether or not we're running in a child isolate that's supposed to run a
+/// test.
+bool _inChildIsolate;
-/// The initial message received by the isolate.
-var _initialMessage;
-
-void metaTestInit(message) {
- _initialMessage = message;
-}
-
-/// Returns whether or not we're running in a child isolate that's supposed to
-/// run a test.
-Future<bool> get _inChildIsolate {
- if (_inChildIsolateFuture != null) return _inChildIsolateFuture;
-
- if (_initialMessage == null) {
- _inChildIsolateFuture = new Future.value(false);
+/// Initialize metatest.
+///
+/// [message] should be the second argument to [main]. It's used to determine
+/// whether this test is in the parent isolate or a child isolate.
+void initMetatest(message) {
+ if (message == null) {
+ _inChildIsolate = false;
} else {
- _testToRun = _initialMessage['testToRun'];
- _executable = _initialMessage['executable'];
- _replyTo = _initialMessage['replyTo'];
- _inChildIsolateFuture = new Future.value(true);
+ _testToRun = message['testToRun'];
+ _replyTo = message['replyTo'];
+ _inChildIsolate = true;
}
- return _inChildIsolateFuture;
}
/// Runs the test described by [description] in its own isolate. Returns a map
/// describing the results of that test run.
Future<Map> _runInIsolate(String description) {
var replyPort = new ReceivePort();
- // TODO(nweiz): Don't use path here once issue 8440 is fixed.
- return Isolate.spawnUri(Uri.parse(path.join(path.current, Platform.script)),
- [], {
+ return Isolate.spawnUri(Uri.parse(Platform.script), [], {
'testToRun': description,
- 'executable': Platform.executable,
'replyTo': replyPort.sendPort
}).then((_) {
- var future = replyPort.first;
-
// TODO(nweiz): Remove this timeout once issue 8417 is fixed and we can
// capture top-level exceptions.
- return timeout(future, 30 * 1000, () {
+ return timeout(replyPort.first, 30 * 1000, () {
throw 'Timed out waiting for test to complete.';
});
});
diff --git a/pkg/scheduled_test/test/scheduled_future_matchers_test.dart b/pkg/scheduled_test/test/scheduled_future_matchers_test.dart
index 10efdc1..1a0c77c 100644
--- a/pkg/scheduled_test/test/scheduled_future_matchers_test.dart
+++ b/pkg/scheduled_test/test/scheduled_future_matchers_test.dart
@@ -9,8 +9,8 @@
import 'metatest.dart';
import 'utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_process_test.dart b/pkg/scheduled_test/test/scheduled_process_test.dart
index 2f9387f..e09c536 100644
--- a/pkg/scheduled_test/test/scheduled_process_test.dart
+++ b/pkg/scheduled_test/test/scheduled_process_test.dart
@@ -15,8 +15,8 @@
import 'metatest.dart';
import 'utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
@@ -389,5 +389,6 @@
});
}, 'clean up temp dir');
- return new ScheduledProcess.start(dartExecutable, ['--checked', dartPath]);
+ return new ScheduledProcess.start(Platform.executable,
+ ['--checked', dartPath]);
}
diff --git a/pkg/scheduled_test/test/scheduled_server_test.dart b/pkg/scheduled_test/test/scheduled_server_test.dart
index 77dd13c..63edc69 100644
--- a/pkg/scheduled_test/test/scheduled_server_test.dart
+++ b/pkg/scheduled_test/test/scheduled_server_test.dart
@@ -15,8 +15,8 @@
import 'metatest.dart';
import 'utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/abort_test.dart b/pkg/scheduled_test/test/scheduled_test/abort_test.dart
index d41632f..fc4622c 100644
--- a/pkg/scheduled_test/test/scheduled_test/abort_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/abort_test.dart
@@ -9,8 +9,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/current_schedule_current_task_test.dart b/pkg/scheduled_test/test/scheduled_test/current_schedule_current_task_test.dart
index e2999d1..97f2d19 100644
--- a/pkg/scheduled_test/test/scheduled_test/current_schedule_current_task_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/current_schedule_current_task_test.dart
@@ -9,8 +9,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/current_schedule_errors_test.dart b/pkg/scheduled_test/test/scheduled_test/current_schedule_errors_test.dart
index 988ac79..a3648f1 100644
--- a/pkg/scheduled_test/test/scheduled_test/current_schedule_errors_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/current_schedule_errors_test.dart
@@ -10,8 +10,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/current_schedule_state_test.dart b/pkg/scheduled_test/test/scheduled_test/current_schedule_state_test.dart
index 1f84779..0c4f587 100644
--- a/pkg/scheduled_test/test/scheduled_test/current_schedule_state_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/current_schedule_state_test.dart
@@ -7,8 +7,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/nested_task_test.dart b/pkg/scheduled_test/test/scheduled_test/nested_task_test.dart
index 7ad9685..ecb88d0 100644
--- a/pkg/scheduled_test/test/scheduled_test/nested_task_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/nested_task_test.dart
@@ -10,8 +10,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/on_complete_test.dart b/pkg/scheduled_test/test/scheduled_test/on_complete_test.dart
index dc1cdac..b603456 100644
--- a/pkg/scheduled_test/test/scheduled_test/on_complete_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/on_complete_test.dart
@@ -9,8 +9,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/on_exception_test.dart b/pkg/scheduled_test/test/scheduled_test/on_exception_test.dart
index b100c36..890b8fa 100644
--- a/pkg/scheduled_test/test/scheduled_test/on_exception_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/on_exception_test.dart
@@ -9,8 +9,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/out_of_band_task_test.dart b/pkg/scheduled_test/test/scheduled_test/out_of_band_task_test.dart
index 35d292d..dec4a7c 100644
--- a/pkg/scheduled_test/test/scheduled_test/out_of_band_task_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/out_of_band_task_test.dart
@@ -10,8 +10,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/set_up_test.dart b/pkg/scheduled_test/test/scheduled_test/set_up_test.dart
index fa3d47e..1fbf80f 100644
--- a/pkg/scheduled_test/test/scheduled_test/set_up_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/set_up_test.dart
@@ -7,8 +7,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/signal_error_test.dart b/pkg/scheduled_test/test/scheduled_test/signal_error_test.dart
index 5d67443..e9b6476 100644
--- a/pkg/scheduled_test/test/scheduled_test/signal_error_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/signal_error_test.dart
@@ -10,8 +10,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/simple_test.dart b/pkg/scheduled_test/test/scheduled_test/simple_test.dart
index 3c6a9dd..00ab216 100644
--- a/pkg/scheduled_test/test/scheduled_test/simple_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/simple_test.dart
@@ -9,8 +9,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/task_return_value_test.dart b/pkg/scheduled_test/test/scheduled_test/task_return_value_test.dart
index 2abf508..ae7ddb1 100644
--- a/pkg/scheduled_test/test/scheduled_test/task_return_value_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/task_return_value_test.dart
@@ -10,8 +10,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/timeout_test.dart b/pkg/scheduled_test/test/scheduled_test/timeout_test.dart
index 7151a48..0328d73 100644
--- a/pkg/scheduled_test/test/scheduled_test/timeout_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/timeout_test.dart
@@ -10,8 +10,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/wrap_async_test.dart b/pkg/scheduled_test/test/scheduled_test/wrap_async_test.dart
index d28e22c..6e89962 100644
--- a/pkg/scheduled_test/test/scheduled_test/wrap_async_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/wrap_async_test.dart
@@ -10,8 +10,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/scheduled_test/test/scheduled_test/wrap_future_test.dart b/pkg/scheduled_test/test/scheduled_test/wrap_future_test.dart
index 84cb29c..307cba5 100644
--- a/pkg/scheduled_test/test/scheduled_test/wrap_future_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test/wrap_future_test.dart
@@ -10,8 +10,8 @@
import '../metatest.dart';
import '../utils.dart';
-void main(List<String> args, message) {
- metaTestInit(message);
+void main(_, message) {
+ initMetatest(message);
setUpTimeout();
diff --git a/pkg/shadow_dom/README.md b/pkg/shadow_dom/README.md
index 85f062a..9c2c1c2 100644
--- a/pkg/shadow_dom/README.md
+++ b/pkg/shadow_dom/README.md
@@ -25,7 +25,7 @@
Because it does extensive DOM patching, it should be included **before** other
script tags.
-## Useful Resources
+## Useful resources
- [What the Heck is Shadow DOM?](http://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/)
- [Web Components Explained - Shadow DOM](https://dvcs.w3.org/hg/webcomponents/raw-file/57f8cfc4a7dc/explainer/index.html#shadow-dom-section)
diff --git a/pkg/shadow_dom/lib/shadow_dom.debug.js b/pkg/shadow_dom/lib/shadow_dom.debug.js
index 158c3d1..c8a4d5b 100644
--- a/pkg/shadow_dom/lib/shadow_dom.debug.js
+++ b/pkg/shadow_dom/lib/shadow_dom.debug.js
@@ -750,6 +750,7 @@
},
start: function() {
+ this.started = true;
this.connect();
this.sync(true);
},
@@ -1511,20 +1512,24 @@
return /^on[a-z]+$/.test(name);
}
+ function isIdentifierName(name) {
+ return /^\w[a-zA-Z_0-9]*$/.test(name);
+ }
+
function getGetter(name) {
- return hasEval ?
+ return hasEval && isIdentifierName(name) ?
new Function('return this.impl.' + name) :
function() { return this.impl[name]; };
}
function getSetter(name) {
- return hasEval ?
+ return hasEval && isIdentifierName(name) ?
new Function('v', 'this.impl.' + name + ' = v') :
function(v) { this.impl[name] = v; };
}
function getMethod(name) {
- return hasEval ?
+ return hasEval && isIdentifierName(name) ?
new Function('return this.impl.' + name +
'.apply(this.impl, arguments)') :
function() { return this.impl[name].apply(this.impl, arguments); };
@@ -3592,7 +3597,8 @@
}
});
- registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement);
+ registerWrapper(OriginalHTMLCanvasElement, HTMLCanvasElement,
+ document.createElement('canvas'));
scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;
})(this.ShadowDOMPolyfill);
@@ -3646,6 +3652,49 @@
'use strict';
var HTMLElement = scope.wrappers.HTMLElement;
+ var registerWrapper = scope.registerWrapper;
+ var unwrap = scope.unwrap;
+ var rewrap = scope.rewrap;
+
+ var OriginalHTMLImageElement = window.HTMLImageElement;
+
+ function HTMLImageElement(node) {
+ HTMLElement.call(this, node);
+ }
+ HTMLImageElement.prototype = Object.create(HTMLElement.prototype);
+
+ registerWrapper(OriginalHTMLImageElement, HTMLImageElement,
+ document.createElement('img'));
+
+ function Image(width, height) {
+ if (!(this instanceof Image)) {
+ throw new TypeError(
+ 'DOM object constructor cannot be called as a function.');
+ }
+
+ var node = unwrap(document.createElement('img'));
+ if (width !== undefined)
+ node.width = width;
+ if (height !== undefined)
+ node.height = height;
+ HTMLElement.call(this, node);
+ rewrap(node, this);
+ }
+
+ Image.prototype = HTMLImageElement.prototype;
+
+ scope.wrappers.HTMLImageElement = HTMLImageElement;
+ scope.wrappers.Image = Image;
+})(this.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+ 'use strict';
+
+ var HTMLElement = scope.wrappers.HTMLElement;
var mixin = scope.mixin;
var registerWrapper = scope.registerWrapper;
@@ -3790,6 +3839,7 @@
var mixin = scope.mixin;
var registerWrapper = scope.registerWrapper;
var unwrap = scope.unwrap;
+ var unwrapIfNeeded = scope.unwrapIfNeeded;
var wrap = scope.wrap;
var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D;
@@ -3804,7 +3854,7 @@
},
drawImage: function() {
- arguments[0] = unwrap(arguments[0]);
+ arguments[0] = unwrapIfNeeded(arguments[0]);
this.impl.drawImage.apply(this.impl, arguments);
},
@@ -3828,7 +3878,7 @@
var mixin = scope.mixin;
var registerWrapper = scope.registerWrapper;
- var unwrap = scope.unwrap;
+ var unwrapIfNeeded = scope.unwrapIfNeeded;
var wrap = scope.wrap;
var OriginalWebGLRenderingContext = window.WebGLRenderingContext;
@@ -3847,12 +3897,12 @@
},
texImage2D: function() {
- arguments[5] = unwrap(arguments[5]);
+ arguments[5] = unwrapIfNeeded(arguments[5]);
this.impl.texImage2D.apply(this.impl, arguments);
},
texSubImage2D: function() {
- arguments[6] = unwrap(arguments[6]);
+ arguments[6] = unwrapIfNeeded(arguments[6]);
this.impl.texSubImage2D.apply(this.impl, arguments);
}
});
@@ -5205,10 +5255,10 @@
'base': 'HTMLBaseElement',
'body': 'HTMLBodyElement',
'button': 'HTMLButtonElement',
- 'canvas': 'HTMLCanvasElement',
// 'command': 'HTMLCommandElement', // Not fully implemented in Gecko.
'dl': 'HTMLDListElement',
'datalist': 'HTMLDataListElement',
+ 'data': 'HTMLDataElement',
'dir': 'HTMLDirectoryElement',
'div': 'HTMLDivElement',
'embed': 'HTMLEmbedElement',
@@ -5222,17 +5272,13 @@
'h1': 'HTMLHeadingElement',
'html': 'HTMLHtmlElement',
'iframe': 'HTMLIFrameElement',
-
- // Uses HTMLSpanElement in Firefox.
- // https://bugzilla.mozilla.org/show_bug.cgi?id=843881
- // 'image',
-
'input': 'HTMLInputElement',
'li': 'HTMLLIElement',
'label': 'HTMLLabelElement',
'legend': 'HTMLLegendElement',
'link': 'HTMLLinkElement',
'map': 'HTMLMapElement',
+ 'marquee': 'HTMLMarqueeElement',
// 'media', Covered by audio and video
'menu': 'HTMLMenuElement',
'menuitem': 'HTMLMenuItemElement',
@@ -5254,6 +5300,7 @@
'source': 'HTMLSourceElement',
'span': 'HTMLSpanElement',
'style': 'HTMLStyleElement',
+ 'time': 'HTMLTimeElement',
'caption': 'HTMLTableCaptionElement',
// WebKit and Moz are wrong:
// https://bugs.webkit.org/show_bug.cgi?id=111469
@@ -5265,6 +5312,7 @@
'thead': 'HTMLTableSectionElement',
'tbody': 'HTMLTableSectionElement',
'textarea': 'HTMLTextAreaElement',
+ 'track': 'HTMLTrackElement',
'title': 'HTMLTitleElement',
'ul': 'HTMLUListElement',
'video': 'HTMLVideoElement',
diff --git a/pkg/shadow_dom/lib/shadow_dom.min.js b/pkg/shadow_dom/lib/shadow_dom.min.js
index 9108bae..2017c03 100644
--- a/pkg/shadow_dom/lib/shadow_dom.min.js
+++ b/pkg/shadow_dom/lib/shadow_dom.min.js
@@ -1,3 +1,3 @@
-if(!HTMLElement.prototype.createShadowRoot||window.__forceShadowDomPolyfill){!function(){Element.prototype.webkitCreateShadowRoot&&(Element.prototype.webkitCreateShadowRoot=function(){return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot()})}(),function(a){"use strict";function b(){function a(a){"splice"===a[0].type&&"splice"===a[1].type&&(b=!0)}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=!1,c=[0];return Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),b}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:H(a)&&H(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:P.test(a))}function i(a,b){if(b!==Q)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),G&&!F&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=R[a];if(b)return b;if(!h(a))return S;var b=new i(a,Q);return R[a]=b,b}function k(b){for(var c=0;T>c&&b.check();)b.report(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,F){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}q(this)}function q(a){V&&(U.push(a),p._allObserversCount++)}function r(a,b,c,d){p.call(this,a,b,c,d),this.connect(),this.sync(!0)}function s(a,b,c,d){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c,d)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g,h){var b=b instanceof i?b:j(b);return b&&b.length&&f(a)?(p.call(this,a,c,d,e),this.valueFn=g,this.setValueFn=h,this.path=b,this.connect(),this.sync(!0),void 0):(this.value_=b?b.getValueFrom(a):void 0,this.value=g?g(this.value_):this.value_,this.closed=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b,c),this.valueFn=d,this.observed=[],this.values=[],this.value=void 0,this.oldValue=void 0,this.oldValues=void 0,this.changeFlags=void 0,this.started=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];$[g.type]?(g.name in c||(c[g.name]=g.oldValue),"updated"!=g.type&&("new"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return db.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case"splice":C(c,g.index,g.removed.slice(),g.addedCount);break;case"new":case"updated":case"deleted":if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F=b(),G=c(),H=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},I="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},J="[$_a-zA-Z]",K="[$_a-zA-Z0-9]",L=J+"+"+K+"*",M="(?:[0-9]|[1-9]+[0-9]+)",N="(?:"+L+"|"+M+")",O="(?:"+N+")(?:\\s*\\.\\s*"+N+")*",P=new RegExp("^"+O+"$"),Q={},R={};i.get=j,i.prototype=I({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++)this[e],c+=a[e],b+=" &&\n "+c+" != null";return b+=")\n",c+=a[e],b+=" return "+c+";\nelse\n return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var S=new i("",Q);S.valid=!1,S.getValueFrom=S.setValueFrom=function(){};var T=1e3;p.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.close&&this.object.close(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(F?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):k(this))},report:function(){this.reporting&&(this.sync(!1),this.callback&&(this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs)),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed||(F&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var U,V=!F||a.forceCollectObservers;p._allObserversCount=0,V&&(U=[]);var W=!1,X="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!W){if(X)return Object.deliverAllChangeRecords(),void 0;if(V){W=!0;var b=0,c={};do{b++;var d=U;U=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed||(F?f.deliver(c):f.check()&&(c.anyChanged=!0,f.report()),U.push(f))}}while(T>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=U.length,W=!1}}},V&&(a.Platform.clearObservers=function(){U=[]}),r.prototype=I({__proto__:p.prototype,connect:function(){F&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=o(this.object))},check:function(a){var b,c;if(F){if(!a)return!1;c={},b=x(this.object,a,c)}else c=this.oldObject,b=n(this.object,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){F?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}}),s.prototype=I({__proto__:r.prototype,connect:function(){F&&Array.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=this.object.slice())},check:function(a){var b;if(F){if(!a)return!1;b=E(this.object,a)}else b=A(this.object,0,this.object.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var Y=Object.getPrototypeOf({}),Z=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==Y&&a!==Z){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=I({__proto__:p.prototype,connect:function(){F&&(this.observedSet=new t(this.boundInternalCallback))},disconnect:function(){this.value=void 0,this.value_=void 0,this.observedSet&&(this.observedSet.reset(),this.observedSet.cleanup(),this.observedSet=void 0)},check:function(){return this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.observedSet&&this.observedSet.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync:function(a){a&&(this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.observedSet&&this.observedSet.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.path&&("function"==typeof this.setValueFn&&(a=this.setValueFn(a)),this.path.setValueFrom(this.object,a))}}),v.prototype=I({__proto__:u.prototype,addPath:function(a,b){if(this.started)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b?b.getValueFrom(a):void 0;this.observed.push(a,b),this.values.push(c)},start:function(){this.connect(),this.sync(!0)},getValues:function(){this.observedSet&&this.observedSet.reset();for(var a=!1,b=0;b<this.observed.length;b+=2){var c=this.observed[b+1];if(c){var d=this.observed[b],e=c.getValueFrom(d,this.observedSet),f=this.values[b/2];if(!g(e,f)){if(!a&&!this.valueFn){this.oldValues=this.oldValues||[],this.changeFlags=this.changeFlags||[];for(var h=0;h<this.values.length;h++)this.oldValues[h]=this.values[h],this.changeFlags[h]=!1}this.valueFn||(this.changeFlags[b/2]=!0),this.values[b/2]=e,a=!0}}}return this.observedSet&&this.observedSet.cleanup(),a},check:function(){if(this.getValues()){if(this.valueFn){if(this.value=this.valueFn(this.values),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values,this.oldValues,this.changeFlags,this.observed];return!0}},sync:function(a){a&&(this.getValues(),this.valueFn&&(this.value=this.valueFn(this.values))),this.valueFn&&(this.oldValue=this.value)},close:function(){if(this.observed){for(var a=0;a<this.observed.length;a+=2){var b=this.observed[a];b&&"function"==typeof b.close&&b.close()}this.observed=void 0,this.values=void 0}p.prototype.close.call(this)}});var $={"new":!0,updated:!0,deleted:!0};u.defineProperty=function(a,b,c){var d=c.object,e=j(c.path),f=w(a,b),g=new u(d,c.path,function(a,b){f&&f("updated",b)});return Object.defineProperty(a,b,{get:function(){return e.getValueFrom(d)},set:function(a){e.setValueFrom(d,a)},configurable:!0}),{close:function(){var c=e.getValueFrom(d);f&&g.deliver(),g.close(),Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}}};var _=0,ab=1,bb=2,cb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(_):(e.push(ab),d=g),b--,c--):f==h?(e.push(cb),b--,d=h):(e.push(bb),c--,d=i)}else e.push(cb),b--;else e.push(bb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,0==c-b&&0==f-e)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case _:j&&(l.push(j),j=void 0),m++,n++;break;case ab:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case bb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case cb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var db=new z;a.Observer=p,a.Observer.hasObjectObserve=F,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return db.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i}("undefined"!=typeof global&&global?global:this),"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}();var ShadowDOMPolyfill={};!function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function d(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=C.get(b);if(c)return c;var d=f(b),e=r(d);return o(b,e,a),e}function g(a,b){m(a,b,!0)}function h(a,b){m(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return F?new Function("return this.impl."+a):function(){return this.impl[a]}}function k(a){return F?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function l(a){return F?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function m(b,c,d){Object.getOwnPropertyNames(b).forEach(function(e){if(!(e in c)){I&&b.__lookupGetter__(e);var f;try{f=Object.getOwnPropertyDescriptor(b,e)}catch(g){f=J}var h,m;if(d&&"function"==typeof f.value)return c[e]=l(e),void 0;var n=i(e);h=n?a.getEventHandlerGetter(e):j(e),(f.writable||f.set)&&(m=n?a.getEventHandlerSetter(e):k(e)),Object.defineProperty(c,e,{get:h,set:m,configurable:f.configurable,enumerable:f.enumerable})}})}function n(a,b,c){var e=a.prototype;o(e,b,c),d(b,a)}function o(a,c,d){var e=c.prototype;b(void 0===C.get(a)),C.set(a,c),D.set(e,a),g(a,e),d&&h(e,d)}function p(a,b){return C.get(b.prototype)===a}function q(a){var b=Object.getPrototypeOf(a),c=f(b),d=r(c);return o(b,d,a),d}function r(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function s(a){return a instanceof E.EventTarget||a instanceof E.Event||a instanceof E.Range||a instanceof E.DOMImplementation||a instanceof E.CanvasRenderingContext2D||E.WebGLRenderingContext&&a instanceof E.WebGLRenderingContext}function t(a){return a instanceof M||a instanceof L||a instanceof N||a instanceof O||a instanceof K||a instanceof P||Q&&a instanceof Q}function u(a){return null===a?null:(b(t(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function v(a){return null===a?null:(b(s(a)),a.impl)}function w(a){return a&&s(a)?v(a):a}function x(a){return a&&!s(a)?u(a):a}function y(a,c){null!==c&&(b(t(a)),b(void 0===c||s(c)),a.polymerWrapper_=c)}function z(a,b,c){Object.defineProperty(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function A(a,b){z(a,b,function(){return u(this.impl[b])})}function B(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=x(this);return a[b].apply(a,arguments)}})})}var C=new WeakMap,D=new WeakMap,E=Object.create(null),F=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(F)try{var G=new Function("","return true;");F=G()}catch(H){}Object.getOwnPropertyNames(window);var I=/Firefox/.test(navigator.userAgent),J={get:function(){},set:function(){},configurable:!0,enumerable:!0},K=window.DOMImplementation,L=window.Event,M=window.Node,N=window.Window,O=window.Range,P=window.CanvasRenderingContext2D,Q=window.WebGLRenderingContext;a.assert=b,a.constructorTable=C,a.defineGetter=z,a.defineWrapGetter=A,a.forwardMethodsToWrapper=B,a.isWrapperFor=p,a.mixin=c,a.nativePrototypeTable=D,a.oneOf=e,a.registerObject=q,a.registerWrapper=n,a.rewrap=y,a.unwrap=v,a.unwrapIfNeeded=w,a.wrap=u,a.wrapIfNeeded=x,a.wrappers=E}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||a.getHostForShadowRoot(f);var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(d,e){for(var g=[];d;){for(var i=[],j=e,l=void 0;j;){var n=null;if(i.length){if(c(j)&&(n=h(i),k(l))){var o=i[i.length-1];i.push(o)}}else i.push(j);if(m(j,d))return i[i.length-1];b(j)&&i.pop(),l=j,j=f(j,n,g)}d=b(d)?a.getHostForShadowRoot(d):d.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(b,c){if(b===c)return!0;if(b instanceof O.ShadowRoot){var d=a.getHostForShadowRoot(b);return n(l(d),c)}return!1}function o(){Z++}function p(){Z--}function q(b){if(!Q.get(b)){if(Q.set(b,!0),b instanceof $){if(Z)return}else a.renderAllPending();var c=N(b.target),d=N(b);return r(d,c)}}function r(a,b){var c=g(b);return"load"===a.type&&2===c.length&&c[0].target instanceof O.Document&&c.shift(),Y.set(a,c),s(a,c)&&t(a,c)&&u(a,c),U.set(a,x.NONE),S.set(a,null),a.defaultPrevented}function s(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=x.CAPTURING_PHASE,!v(b[d],a,c)))return!1}return!0}function t(a,b){var c=x.AT_TARGET;return v(b[0],a,c)}function u(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=x.AT_TARGET;else{if(!d||W.get(a))continue;c=x.BUBBLING_PHASE}if(!v(b[e],a,c))return}}function v(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;T.set(b,j)}}U.set(b,c);var k=b.type,l=!1;R.set(b,d),S.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===x.CAPTURING_PHASE||n.capture&&c===x.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),W.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!V.get(b)}function w(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function x(a,b){return a instanceof _?(this.impl=a,void 0):N(B(_,"Event",a,b))}function y(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function z(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(B(d,a,b,c))};return e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d&&(d.prototype["init"+a]?L(d,e,document.createEvent(a)):L(d,e,new d("temp"))),e}function A(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function B(a,b,c,d){if(jb)return new a(c,y(d));var e=M(document.createEvent(b)),f=ib[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function C(a){return"function"==typeof a?!0:a&&a.handleEvent}function D(a){this.impl=a}function E(b){return b instanceof O.ShadowRoot&&(b=a.getHostForShadowRoot(b)),M(b)}function F(a){J(a,mb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(nb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=X.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=X.get(this);d||(d=Object.create(null),X.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers;new WeakMap;var P=new WeakMap,Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=0,$=window.MutationEvent;w.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var _=window.Event;x.prototype={get target(){return R.get(this)},get currentTarget(){return S.get(this)},get eventPhase(){return U.get(this)},get path(){var a=new O.NodeList,b=Y.get(this);if(b){for(var c=0,d=b.length-1,e=l(S.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){V.set(this,!0)},stopImmediatePropagation:function(){V.set(this,!0),W.set(this,!0)}},L(_,x,document.createEvent("Event"));var ab=z("UIEvent",x),bb=z("CustomEvent",x),cb={get relatedTarget(){return T.get(this)||N(M(this).relatedTarget)}},db=K({initMouseEvent:A("initMouseEvent",14)},cb),eb=K({initFocusEvent:A("initFocusEvent",5)},cb),fb=z("MouseEvent",ab,db),gb=z("FocusEvent",ab,eb),hb=z("MutationEvent",x,{initMutationEvent:A("initMutationEvent",3),get relatedNode(){return N(this.impl.relatedNode)}}),ib=Object.create(null),jb=function(){try{new window.MouseEvent("click")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=K(K({},d),b)}ib[a]=b};kb("Event",{bubbles:!1,cancelable:!1}),kb("CustomEvent",{detail:null},"Event"),kb("UIEvent",{view:null,detail:0},"Event"),kb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),kb("FocusEvent",{relatedTarget:null},"UIEvent")}var lb=window.EventTarget,mb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;mb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(C(b)){var d=new w(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,q,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,q,!0)}}},dispatchEvent:function(a){var b=E(this),c=M(a);return Q.set(c,!1),b.dispatchEvent_(c)}},lb&&L(lb,D);var nb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.muteMutationEvents=o,a.unmuteMutationEvents=p,a.wrapEventTargetMethods=F,a.wrappers.CustomEvent=bb,a.wrappers.Event=x,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=gb,a.wrappers.MouseEvent=fb,a.wrappers.MutationEvent=hb,a.wrappers.UIEvent=ab}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){o(a instanceof k)}function c(a,b,c,d){if(!(a instanceof DocumentFragment))return a.parentNode&&a.parentNode.removeChild(a),a.parentNode_=b,a.previousSibling_=c,a.nextSibling_=d,c&&(c.nextSibling_=a),d&&(d.previousSibling_=a),[a];for(var e,f=[];e=a.firstChild;)a.removeChild(e),f.push(e),e.parentNode_=b;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||c,f[g].nextSibling_=f[g+1]||d;return c&&(c.nextSibling_=f[0]),d&&(d.previousSibling_=f[f.length-1]),f}function d(a){if(a instanceof DocumentFragment){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}return[a]}function e(a){for(var b=0;b<a.length;b++)a[b].nodeWasAdded_()}function f(a,b){var c=a.nodeType===k.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function g(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function h(a,b){g(a,b);var c=b.length;if(1===c)return r(b[0]);for(var d=r(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(r(b[e]));return d}function i(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){o(b.parentNode===a);var c=b.nextSibling,d=r(b),e=d.parentNode;e&&y.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=r(a),g=f.firstChild;g;)c=g.nextSibling,y.call(f,g),g=c}function j(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function k(a){o(a instanceof u),l.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var l=a.wrappers.EventTarget,m=a.wrappers.NodeList,n=a.defineWrapGetter,o=a.assert,p=a.mixin,q=a.registerWrapper,r=a.unwrap,s=a.wrap,t=a.wrapIfNeeded,u=window.Node,v=u.prototype.appendChild,w=u.prototype.insertBefore,x=u.prototype.replaceChild,y=u.prototype.removeChild,z=u.prototype.compareDocumentPosition;k.prototype=Object.create(l.prototype),p(k.prototype,{appendChild:function(a){b(a);var g;if(this.invalidateShadowRenderer()||j(a)){var i=this.lastChild,k=null;g=c(a,this,i,k),this.lastChild_=g[g.length-1],i||(this.firstChild_=g[0]),v.call(this.impl,h(this,g))}else g=d(a),f(this,a),v.call(this.impl,r(a));return e(g),a},insertBefore:function(a,i){if(!i)return this.appendChild(a);b(a),b(i),o(i.parentNode===this);var k;if(this.invalidateShadowRenderer()||j(a)){var l=i.previousSibling,m=i;k=c(a,this,l,m),this.firstChild===i&&(this.firstChild_=k[0]);var n=r(i),p=n.parentNode;p?w.call(p,h(this,k),n):g(this,k)}else k=d(a),f(this,a),w.call(this.impl,r(a),r(i));return e(k),a},removeChild:function(a){if(b(a),a.parentNode!==this)throw new Error("NotFoundError");var c=r(a);if(this.invalidateShadowRenderer()){var d=this.firstChild,e=this.lastChild,f=a.nextSibling,g=a.previousSibling,h=c.parentNode;h&&y.call(h,c),d===a&&(this.firstChild_=f),e===a&&(this.lastChild_=g),g&&(g.nextSibling_=f),f&&(f.previousSibling_=g),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else y.call(this.impl,c);return a},replaceChild:function(a,g){if(b(a),b(g),g.parentNode!==this)throw new Error("NotFoundError");var i,k=r(g);if(this.invalidateShadowRenderer()||j(a)){var l=g.previousSibling,m=g.nextSibling;m===a&&(m=a.nextSibling),i=c(a,this,l,m),this.firstChild===g&&(this.firstChild_=i[0]),this.lastChild===g&&(this.lastChild_=i[i.length-1]),g.previousSibling_=g.nextSibling_=g.parentNode_=void 0,k.parentNode&&x.call(k.parentNode,h(this,i),k)}else i=d(a),f(this,a),x.call(this.impl,r(a),k);return e(i),g},nodeWasAdded_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeWasAdded_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:s(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:s(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:s(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:s(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:s(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==k.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){if(this.invalidateShadowRenderer()){if(i(this),""!==a){var b=this.impl.ownerDocument.createTextNode(a);this.appendChild(b)}}else this.impl.textContent=a},get childNodes(){for(var a=new m,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){if(!this.invalidateShadowRenderer())return s(this.impl.cloneNode(a));var b=s(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=t(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return z.call(this.impl,r(a))}}),n(k,"ownerDocument"),q(u,k,document.createDocumentFragment()),delete k.prototype.querySelector,delete k.prototype.querySelectorAll,k.prototype=p(Object.create(l.prototype),k.prototype),a.wrappers.Node=k}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;e=e.nextElementSibling}return null
-}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.mixin,f=a.registerWrapper,g=window.CharacterData;b.prototype=Object.create(d.prototype),e(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a}}),e(b.prototype,c),f(g,b,document.createTextNode("")),a.wrappers.CharacterData=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a){g.call(this,a)}function d(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var e=a.ChildNodeInterface,f=a.GetElementsByInterface,g=a.wrappers.Node,h=a.ParentNodeInterface,i=a.SelectorsInterface;a.addWrapNodeListMethod;var j=a.mixin,k=a.oneOf,l=a.registerWrapper,m=a.wrappers,n=window.Element,o=k(n.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),p=n.prototype[o];c.prototype=Object.create(g.prototype),j(c.prototype,{createShadowRoot:function(){var b=new m.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,c){this.impl.setAttribute(a,c),b(this,a)},removeAttribute:function(a){this.impl.removeAttribute(a),b(this,a)},matches:function(a){return p.call(this.impl,a)}}),c.prototype[o]=function(a){return this.matches(a)},n.prototype.webkitCreateShadowRoot&&(c.prototype.webkitCreateShadowRoot=c.prototype.createShadowRoot),d(c.prototype,"id"),d(c.prototype,"className","class"),j(c.prototype,e),j(c.prototype,f),j(c.prototype,h),j(c.prototype,i),l(n,c),a.matchesName=o,a.wrappers.Element=c}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&";case"<":return"<";case'"':return"""}}function c(a){return a.replace(r,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",s[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=p(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(q(f))}function g(a){l.call(this,a)}function h(b){return function(){return a.renderAllPending(),this.impl[b]}}function i(a){m(g,a,h(a))}function j(b){Object.defineProperty(g.prototype,b,{get:h(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function k(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var l=a.wrappers.Element,m=a.defineGetter,n=a.mixin,o=a.registerWrapper,p=a.unwrap,q=a.wrap,r=/&|<|"/g,s={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},t=window.HTMLElement;g.prototype=Object.create(l.prototype),n(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;b&&(b.invalidateShadowRenderer(),this.impl.outerHTML=a)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(i),["scrollLeft","scrollTop"].forEach(j),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(k),o(t,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b),a.wrappers.HTMLCanvasElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=o.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);o.set(a,b)}return b}function c(a){var c,d=b(a.ownerDocument),e=l(d.createDocumentFragment());for(h();c=a.firstChild;)e.appendChild(c);return k(),e}function d(a){if(e.call(this,a),!p){var b=c(a);n.set(this,m(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.muteMutationEvents,i=a.registerWrapper,j=a.setInnerHTML,k=a.unmuteMutationEvents,l=a.unwrap,m=a.wrap,n=new WeakMap,o=new WeakMap,p=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return p?m(this.impl.content):n.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){j(this.content,a)}}),p&&i(p,d),a.wrappers.HTMLTemplateElement=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement;a.mixin;var g=a.registerWrapper,h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return f(this.impl.canvas)},drawImage:function(){arguments[0]=e(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(g,b),a.wrappers.CanvasRenderingContext2D=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.WebGLRenderingContext;g&&(c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}}),d(g,b),a.wrappers.WebGLRenderingContext=b)}(this.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b,a.getHostForShadowRoot=function(a){return j.get(a)}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=G(a),g=G(c),h=e?G(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=H(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=G(a),d=c.parentNode;if(d){var e=H(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=J.get(a);c||J.set(a,c=[]),c.push(b)}function f(a){I.set(a,[])}function g(a){return I.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof y))return!1;if(!M.test(c))return!1;if(":"===c[0]&&!N.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<P.length;a++)P[a].render();P=[]}function l(){F=null,k()}function m(a){var b=L.get(a);return b||(b=new q(a),L.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof C)return a;return null}function o(a){return m(D(a))}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof z}function s(a){return a instanceof z}function t(a){return a instanceof A}function u(a){return a instanceof A}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){K.set(a,b)}var y=a.wrappers.Element,z=a.wrappers.HTMLContentElement,A=a.wrappers.HTMLShadowElement,B=a.wrappers.Node,C=a.wrappers.ShadowRoot;a.assert;var D=a.getHostForShadowRoot;a.mixin,a.muteMutationEvents;var E=a.oneOf;a.unmuteMutationEvents;var F,G=a.unwrap,H=a.wrap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=new WeakMap,M=/^[*.:#[a-zA-Z_|]/,N=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),O=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),P=[],Q=new ArraySplice;Q.equals=function(a,b){return G(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(G(b)),g=a||new WeakMap,i=Q.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=H(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&H(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,P.push(this),F)return;F=window[O](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},B.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},z.prototype.getDistributedNodes=function(){return k(),g(this)},A.prototype.nodeWasAdded_=z.prototype.nodeWasAdded_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=J,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=K,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOptionElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){y.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.wrapEventTargetMethods;a.wrapNodeList;var x=new WeakMap;b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var y=document.adoptNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)}}),document.register){var z=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);return["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){b.apply(v(this),arguments)})}),z.call(u(this),b,{prototype:i}),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i),d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=x.get(this);return a?a:(a=new g(u(this).implementation),x.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),w([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)},["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)}}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}function c(a){return new b(a)}function d(a){return a.map(c)}function e(a){var b=this;this.impl=new k(function(c){a.call(b,d(c),b)})}var f=a.defineGetter,g=a.defineWrapGetter,h=a.registerWrapper,i=a.unwrapIfNeeded,j=a.wrapNodeList;a.wrappers;var k=window.MutationObserver||window.WebKitMutationObserver;if(k){var l=window.MutationRecord;b.prototype={get addedNodes(){return j(this.impl.addedNodes)},get removedNodes(){return j(this.impl.removedNodes)}},["target","previousSibling","nextSibling"].forEach(function(a){g(b,a)}),["type","attributeName","attributeNamespace","oldValue"].forEach(function(a){f(b,a,function(){return this.impl[a]})}),l&&h(l,b),window.Node,e.prototype={observe:function(a,b){this.impl.observe(i(a),b)},disconnect:function(){this.impl.disconnect()},takeRecords:function(){return d(this.impl.takeRecords())}},a.wrappers.MutationObserver=e,a.wrappers.MutationRecord=b}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b),a.wrappers.Range=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}a.isWrapperFor;var c={a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"};Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(this.ShadowDOMPolyfill),function(){var a=window.ShadowDOMPolyfill;a.wrap,Object.defineProperties(HTMLElement.prototype,{webkitShadowRoot:{get:function(){return this.shadowRoot}}}),HTMLElement.prototype.webkitCreateShadowRoot=HTMLElement.prototype.createShadowRoot,window.dartExperimentalFixupGetTag=function(b){function c(a){if(a instanceof d)return"NodeList";if(a instanceof e)return"ShadowRoot";if(window.MutationRecord&&a instanceof MutationRecord)return"MutationRecord";if(window.MutationObserver&&a instanceof MutationObserver)return"MutationObserver";if(a instanceof HTMLTemplateElement)return"HTMLTemplateElement";var c=f(a);if(a!==c){var g=a.constructor;if(g===c.constructor){var h=g._ShadowDOMPolyfill$cacheTag_;return h||(h=Object.prototype.toString.call(c),h=h.substring(8,h.length-1),g._ShadowDOMPolyfill$cacheTag_=h),h}a=c}return b(a)}var d=a.wrappers.NodeList,e=a.wrappers.ShadowRoot,f=a.unwrapIfNeeded;return c}}();var Platform={};!function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(n,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=b.sheet.cssRules;return b.parentNode.removeChild(b),d}function e(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function f(a){a&&g().appendChild(document.createTextNode(a))}function g(){return h||(h=document.createElement("style"),h.setAttribute("ShadowCSSShim","")),h}var h,i={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var e=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b),this.insertPolyfillDirectives(g.rootStyles),this.insertPolyfillRules(g.rootStyles);var h=this.stylesToShimmedCssText(g.scopeStyles,b,e);h+=this.extractPolyfillUnscopedRules(g.rootStyles),g.shimmedStyle=c(h),a&&(a.shimmedStyle=g.shimmedStyle);for(var i,j=0,k=g.rootStyles.length;k>j&&(i=g.rootStyles[j]);j++)i.parentNode.removeChild(i);f(h)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a?a.querySelectorAll("style"):[];e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},isTypeExtension:function(a){return a&&a.indexOf("-")<0},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertPolyfillDirectives:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillDirectivesInCssText(a.textContent)},this)},insertPolyfillDirectivesInCssText:function(a){return a.replace(o,function(a,b){return b.slice(0,-2)+"{"})},insertPolyfillRules:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillRulesInCssText(a.textContent)},this)},insertPolyfillRulesInCssText:function(a){return a.replace(p,function(a,b){return b.slice(0,-1)})},extractPolyfillUnscopedRules:function(a){var b="";return a&&Array.prototype.forEach.call(a,function(a){b+=this.extractPolyfillUnscopedRulesFromCssText(a.textContent)+"\n\n"},this),b},extractPolyfillUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},stylesToShimmedCssText:function(a,b,c){return this.shimAtHost(a,b,c)+this.shimScoping(a,b,c)},shimAtHost:function(a,b,c){return a?this.convertAtHostStyles(a,b,c):void 0},convertAtHostStyles:function(a,c,f){var g=b(a),h=this;return g=g.replace(j,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),new RegExp("^"+c+u,"m")))},scopeHostCss:function(a,b,c){var d=this;return a.replace(k,function(a,e,f){return d.scopeHostSelector(e,b,c)+" "+f+"\n "})},scopeHostSelector:function(a,b,c){var d=[],e=a.split(","),f="[is="+b+"]";return e.forEach(function(a){a=a.trim(),a.match(l)?a=a.replace(l,c?f+"$1$3":b+"$1$3"):a.match(m)&&(a=c?f+a:b+a),d.push(a)},this),d.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a).replace(j,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return f=this.scopeRules(g,c,e)},convertPseudos:function(a){return a.replace(r," [pseudo=$1]")},convertParts:function(a){return a.replace(s," [part=$1]")},convertColonHost:function(a){return a.replace(t,function(a,b,c,d){return c?y+c+d+", "+c+" "+b+d:b+d})},convertCombinators:function(a){return a.replace("^^"," ").replace("^"," ")},scopeRules:function(a,b,c){var d="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(d+=this.scopeSelector(a.selectorText,b,c,this.strictStyling)+" {\n ",d+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(d+="@media "+a.media.mediaText+" {\n",d+=this.scopeRules(a.cssRules,b),d+="\n}\n\n"):a.cssText&&(d+=a.cssText+"\n\n")},this),d},scopeSelector:function(a,b,c,d){var e=[],f=a.split(",");return f.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b,c)&&(a=d?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=c?b:"\\[is="+b+"\\]",e=new RegExp("^("+d+")"+u,"m");return!a.match(e)},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(z)?(a=a.replace(y,d),a.replace(z,d+" ")):d+" "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(z,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(v,x).replace(w,x)},propertiesFromRule:function(a){var b=a.style.cssText;return a.style.content&&!a.style.content.match(/['"]+/)&&(b="content: '"+a.style.content+"';\n"+a.style.cssText.replace(/content:[^;]*;/g,"")),b}},j=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,k=/([^{]*)({[\s\S]*?})/gim,l=/(.*)((?:\*)|(?:\:scope))(.*)/,m=/^[.\[:]/,n=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,o=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,p=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/::(x-[^\s{,(]*)/gim,s=/::part\(([^)]*)\)/gim,t=/(-host)(?:\(([^)]*)\))?([^,{]*)/gim,u="([>\\s~+[.,{:][\\s\\S]*)?$",v=/@host/gim,w=/\:host/gim,x="-host",y="-host-no-combinator",z=/-host/gim;
-if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var A=document.querySelector("head");A.insertBefore(g(),A.childNodes[0])}a.ShadowCSS=i}(window.Platform)}
\ No newline at end of file
+if(!HTMLElement.prototype.createShadowRoot||window.__forceShadowDomPolyfill){!function(){Element.prototype.webkitCreateShadowRoot&&(Element.prototype.webkitCreateShadowRoot=function(){return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot()})}(),function(a){"use strict";function b(){function a(a){"splice"===a[0].type&&"splice"===a[1].type&&(b=!0)}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=!1,c=[0];return Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),b}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:H(a)&&H(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:P.test(a))}function i(a,b){if(b!==Q)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),G&&!F&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=R[a];if(b)return b;if(!h(a))return S;var b=new i(a,Q);return R[a]=b,b}function k(b){for(var c=0;T>c&&b.check();)b.report(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,F){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}q(this)}function q(a){V&&(U.push(a),p._allObserversCount++)}function r(a,b,c,d){p.call(this,a,b,c,d),this.connect(),this.sync(!0)}function s(a,b,c,d){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c,d)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g,h){var b=b instanceof i?b:j(b);return b&&b.length&&f(a)?(p.call(this,a,c,d,e),this.valueFn=g,this.setValueFn=h,this.path=b,this.connect(),this.sync(!0),void 0):(this.value_=b?b.getValueFrom(a):void 0,this.value=g?g(this.value_):this.value_,this.closed=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b,c),this.valueFn=d,this.observed=[],this.values=[],this.value=void 0,this.oldValue=void 0,this.oldValues=void 0,this.changeFlags=void 0,this.started=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];$[g.type]?(g.name in c||(c[g.name]=g.oldValue),"updated"!=g.type&&("new"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return db.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case"splice":C(c,g.index,g.removed.slice(),g.addedCount);break;case"new":case"updated":case"deleted":if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F=b(),G=c(),H=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},I="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},J="[$_a-zA-Z]",K="[$_a-zA-Z0-9]",L=J+"+"+K+"*",M="(?:[0-9]|[1-9]+[0-9]+)",N="(?:"+L+"|"+M+")",O="(?:"+N+")(?:\\s*\\.\\s*"+N+")*",P=new RegExp("^"+O+"$"),Q={},R={};i.get=j,i.prototype=I({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++)this[e],c+=a[e],b+=" &&\n "+c+" != null";return b+=")\n",c+=a[e],b+=" return "+c+";\nelse\n return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var S=new i("",Q);S.valid=!1,S.getValueFrom=S.setValueFrom=function(){};var T=1e3;p.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.close&&this.object.close(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(F?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):k(this))},report:function(){this.reporting&&(this.sync(!1),this.callback&&(this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs)),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed||(F&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var U,V=!F||a.forceCollectObservers;p._allObserversCount=0,V&&(U=[]);var W=!1,X="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!W){if(X)return Object.deliverAllChangeRecords(),void 0;if(V){W=!0;var b=0,c={};do{b++;var d=U;U=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed||(F?f.deliver(c):f.check()&&(c.anyChanged=!0,f.report()),U.push(f))}}while(T>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=U.length,W=!1}}},V&&(a.Platform.clearObservers=function(){U=[]}),r.prototype=I({__proto__:p.prototype,connect:function(){F&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=o(this.object))},check:function(a){var b,c;if(F){if(!a)return!1;c={},b=x(this.object,a,c)}else c=this.oldObject,b=n(this.object,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){F?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}}),s.prototype=I({__proto__:r.prototype,connect:function(){F&&Array.observe(this.object,this.boundInternalCallback)},sync:function(){F||(this.oldObject=this.object.slice())},check:function(a){var b;if(F){if(!a)return!1;b=E(this.object,a)}else b=A(this.object,0,this.object.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var Y=Object.getPrototypeOf({}),Z=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==Y&&a!==Z){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=I({__proto__:p.prototype,connect:function(){F&&(this.observedSet=new t(this.boundInternalCallback))},disconnect:function(){this.value=void 0,this.value_=void 0,this.observedSet&&(this.observedSet.reset(),this.observedSet.cleanup(),this.observedSet=void 0)},check:function(){return this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.observedSet&&this.observedSet.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync:function(a){a&&(this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.observedSet&&this.observedSet.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.path&&("function"==typeof this.setValueFn&&(a=this.setValueFn(a)),this.path.setValueFrom(this.object,a))}}),v.prototype=I({__proto__:u.prototype,addPath:function(a,b){if(this.started)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b?b.getValueFrom(a):void 0;this.observed.push(a,b),this.values.push(c)},start:function(){this.started=!0,this.connect(),this.sync(!0)},getValues:function(){this.observedSet&&this.observedSet.reset();for(var a=!1,b=0;b<this.observed.length;b+=2){var c=this.observed[b+1];if(c){var d=this.observed[b],e=c.getValueFrom(d,this.observedSet),f=this.values[b/2];if(!g(e,f)){if(!a&&!this.valueFn){this.oldValues=this.oldValues||[],this.changeFlags=this.changeFlags||[];for(var h=0;h<this.values.length;h++)this.oldValues[h]=this.values[h],this.changeFlags[h]=!1}this.valueFn||(this.changeFlags[b/2]=!0),this.values[b/2]=e,a=!0}}}return this.observedSet&&this.observedSet.cleanup(),a},check:function(){if(this.getValues()){if(this.valueFn){if(this.value=this.valueFn(this.values),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values,this.oldValues,this.changeFlags,this.observed];return!0}},sync:function(a){a&&(this.getValues(),this.valueFn&&(this.value=this.valueFn(this.values))),this.valueFn&&(this.oldValue=this.value)},close:function(){if(this.observed){for(var a=0;a<this.observed.length;a+=2){var b=this.observed[a];b&&"function"==typeof b.close&&b.close()}this.observed=void 0,this.values=void 0}p.prototype.close.call(this)}});var $={"new":!0,updated:!0,deleted:!0};u.defineProperty=function(a,b,c){var d=c.object,e=j(c.path),f=w(a,b),g=new u(d,c.path,function(a,b){f&&f("updated",b)});return Object.defineProperty(a,b,{get:function(){return e.getValueFrom(d)},set:function(a){e.setValueFrom(d,a)},configurable:!0}),{close:function(){var c=e.getValueFrom(d);f&&g.deliver(),g.close(),Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}}};var _=0,ab=1,bb=2,cb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(_):(e.push(ab),d=g),b--,c--):f==h?(e.push(cb),b--,d=h):(e.push(bb),c--,d=i)}else e.push(cb),b--;else e.push(bb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,0==c-b&&0==f-e)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case _:j&&(l.push(j),j=void 0),m++,n++;break;case ab:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case bb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case cb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var db=new z;a.Observer=p,a.Observer.hasObjectObserve=F,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return db.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i}("undefined"!=typeof global&&global?global:this),"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}();var ShadowDOMPolyfill={};!function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function d(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=D.get(b);if(c)return c;var d=f(b),e=s(d);return p(b,e,a),e}function g(a,b){n(a,b,!0)}function h(a,b){n(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return G&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return G&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return G&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(b,c,d){Object.getOwnPropertyNames(b).forEach(function(e){if(!(e in c)){J&&b.__lookupGetter__(e);var f;try{f=Object.getOwnPropertyDescriptor(b,e)}catch(g){f=K}var h,j;if(d&&"function"==typeof f.value)return c[e]=m(e),void 0;var n=i(e);h=n?a.getEventHandlerGetter(e):k(e),(f.writable||f.set)&&(j=n?a.getEventHandlerSetter(e):l(e)),Object.defineProperty(c,e,{get:h,set:j,configurable:f.configurable,enumerable:f.enumerable})}})}function o(a,b,c){var e=a.prototype;p(e,b,c),d(b,a)}function p(a,c,d){var e=c.prototype;b(void 0===D.get(a)),D.set(a,c),E.set(e,a),g(a,e),d&&h(e,d)}function q(a,b){return D.get(b.prototype)===a}function r(a){var b=Object.getPrototypeOf(a),c=f(b),d=s(c);return p(b,d,a),d}function s(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function t(a){return a instanceof F.EventTarget||a instanceof F.Event||a instanceof F.Range||a instanceof F.DOMImplementation||a instanceof F.CanvasRenderingContext2D||F.WebGLRenderingContext&&a instanceof F.WebGLRenderingContext}function u(a){return a instanceof N||a instanceof M||a instanceof O||a instanceof P||a instanceof L||a instanceof Q||R&&a instanceof R}function v(a){return null===a?null:(b(u(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function w(a){return null===a?null:(b(t(a)),a.impl)}function x(a){return a&&t(a)?w(a):a}function y(a){return a&&!t(a)?v(a):a}function z(a,c){null!==c&&(b(u(a)),b(void 0===c||t(c)),a.polymerWrapper_=c)}function A(a,b,c){Object.defineProperty(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function B(a,b){A(a,b,function(){return v(this.impl[b])})}function C(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=y(this);return a[b].apply(a,arguments)}})})}var D=new WeakMap,E=new WeakMap,F=Object.create(null),G=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(G)try{var H=new Function("","return true;");G=H()}catch(I){}Object.getOwnPropertyNames(window);var J=/Firefox/.test(navigator.userAgent),K={get:function(){},set:function(){},configurable:!0,enumerable:!0},L=window.DOMImplementation,M=window.Event,N=window.Node,O=window.Window,P=window.Range,Q=window.CanvasRenderingContext2D,R=window.WebGLRenderingContext;a.assert=b,a.constructorTable=D,a.defineGetter=A,a.defineWrapGetter=B,a.forwardMethodsToWrapper=C,a.isWrapperFor=q,a.mixin=c,a.nativePrototypeTable=E,a.oneOf=e,a.registerObject=r,a.registerWrapper=o,a.rewrap=z,a.unwrap=w,a.unwrapIfNeeded=x,a.wrap=v,a.wrapIfNeeded=y,a.wrappers=F}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||a.getHostForShadowRoot(f);var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(d,e){for(var g=[];d;){for(var i=[],j=e,l=void 0;j;){var n=null;if(i.length){if(c(j)&&(n=h(i),k(l))){var o=i[i.length-1];i.push(o)}}else i.push(j);if(m(j,d))return i[i.length-1];b(j)&&i.pop(),l=j,j=f(j,n,g)}d=b(d)?a.getHostForShadowRoot(d):d.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(b,c){if(b===c)return!0;if(b instanceof O.ShadowRoot){var d=a.getHostForShadowRoot(b);return n(l(d),c)}return!1}function o(){Z++}function p(){Z--}function q(b){if(!Q.get(b)){if(Q.set(b,!0),b instanceof $){if(Z)return}else a.renderAllPending();var c=N(b.target),d=N(b);return r(d,c)}}function r(a,b){var c=g(b);return"load"===a.type&&2===c.length&&c[0].target instanceof O.Document&&c.shift(),Y.set(a,c),s(a,c)&&t(a,c)&&u(a,c),U.set(a,x.NONE),S.set(a,null),a.defaultPrevented}function s(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=x.CAPTURING_PHASE,!v(b[d],a,c)))return!1}return!0}function t(a,b){var c=x.AT_TARGET;return v(b[0],a,c)}function u(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=x.AT_TARGET;else{if(!d||W.get(a))continue;c=x.BUBBLING_PHASE}if(!v(b[e],a,c))return}}function v(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;T.set(b,j)}}U.set(b,c);var k=b.type,l=!1;R.set(b,d),S.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===x.CAPTURING_PHASE||n.capture&&c===x.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),W.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!V.get(b)}function w(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function x(a,b){return a instanceof _?(this.impl=a,void 0):N(B(_,"Event",a,b))}function y(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function z(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(B(d,a,b,c))};return e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d&&(d.prototype["init"+a]?L(d,e,document.createEvent(a)):L(d,e,new d("temp"))),e}function A(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function B(a,b,c,d){if(jb)return new a(c,y(d));var e=M(document.createEvent(b)),f=ib[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function C(a){return"function"==typeof a?!0:a&&a.handleEvent}function D(a){this.impl=a}function E(b){return b instanceof O.ShadowRoot&&(b=a.getHostForShadowRoot(b)),M(b)}function F(a){J(a,mb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(nb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=X.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=X.get(this);d||(d=Object.create(null),X.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers;new WeakMap;var P=new WeakMap,Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=0,$=window.MutationEvent;w.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var _=window.Event;x.prototype={get target(){return R.get(this)},get currentTarget(){return S.get(this)},get eventPhase(){return U.get(this)},get path(){var a=new O.NodeList,b=Y.get(this);if(b){for(var c=0,d=b.length-1,e=l(S.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){V.set(this,!0)},stopImmediatePropagation:function(){V.set(this,!0),W.set(this,!0)}},L(_,x,document.createEvent("Event"));var ab=z("UIEvent",x),bb=z("CustomEvent",x),cb={get relatedTarget(){return T.get(this)||N(M(this).relatedTarget)}},db=K({initMouseEvent:A("initMouseEvent",14)},cb),eb=K({initFocusEvent:A("initFocusEvent",5)},cb),fb=z("MouseEvent",ab,db),gb=z("FocusEvent",ab,eb),hb=z("MutationEvent",x,{initMutationEvent:A("initMutationEvent",3),get relatedNode(){return N(this.impl.relatedNode)}}),ib=Object.create(null),jb=function(){try{new window.MouseEvent("click")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=K(K({},d),b)}ib[a]=b};kb("Event",{bubbles:!1,cancelable:!1}),kb("CustomEvent",{detail:null},"Event"),kb("UIEvent",{view:null,detail:0},"Event"),kb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),kb("FocusEvent",{relatedTarget:null},"UIEvent")}var lb=window.EventTarget,mb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;mb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(C(b)){var d=new w(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,q,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,q,!0)}}},dispatchEvent:function(a){var b=E(this),c=M(a);return Q.set(c,!1),b.dispatchEvent_(c)}},lb&&L(lb,D);var nb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.muteMutationEvents=o,a.unmuteMutationEvents=p,a.wrapEventTargetMethods=F,a.wrappers.CustomEvent=bb,a.wrappers.Event=x,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=gb,a.wrappers.MouseEvent=fb,a.wrappers.MutationEvent=hb,a.wrappers.UIEvent=ab}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){o(a instanceof k)}function c(a,b,c,d){if(!(a instanceof DocumentFragment))return a.parentNode&&a.parentNode.removeChild(a),a.parentNode_=b,a.previousSibling_=c,a.nextSibling_=d,c&&(c.nextSibling_=a),d&&(d.previousSibling_=a),[a];for(var e,f=[];e=a.firstChild;)a.removeChild(e),f.push(e),e.parentNode_=b;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||c,f[g].nextSibling_=f[g+1]||d;return c&&(c.nextSibling_=f[0]),d&&(d.previousSibling_=f[f.length-1]),f}function d(a){if(a instanceof DocumentFragment){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}return[a]}function e(a){for(var b=0;b<a.length;b++)a[b].nodeWasAdded_()}function f(a,b){var c=a.nodeType===k.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function g(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function h(a,b){g(a,b);var c=b.length;if(1===c)return r(b[0]);for(var d=r(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(r(b[e]));return d}function i(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){o(b.parentNode===a);var c=b.nextSibling,d=r(b),e=d.parentNode;e&&y.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=r(a),g=f.firstChild;g;)c=g.nextSibling,y.call(f,g),g=c}function j(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function k(a){o(a instanceof u),l.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var l=a.wrappers.EventTarget,m=a.wrappers.NodeList,n=a.defineWrapGetter,o=a.assert,p=a.mixin,q=a.registerWrapper,r=a.unwrap,s=a.wrap,t=a.wrapIfNeeded,u=window.Node,v=u.prototype.appendChild,w=u.prototype.insertBefore,x=u.prototype.replaceChild,y=u.prototype.removeChild,z=u.prototype.compareDocumentPosition;k.prototype=Object.create(l.prototype),p(k.prototype,{appendChild:function(a){b(a);var g;if(this.invalidateShadowRenderer()||j(a)){var i=this.lastChild,k=null;g=c(a,this,i,k),this.lastChild_=g[g.length-1],i||(this.firstChild_=g[0]),v.call(this.impl,h(this,g))}else g=d(a),f(this,a),v.call(this.impl,r(a));return e(g),a},insertBefore:function(a,i){if(!i)return this.appendChild(a);b(a),b(i),o(i.parentNode===this);var k;if(this.invalidateShadowRenderer()||j(a)){var l=i.previousSibling,m=i;k=c(a,this,l,m),this.firstChild===i&&(this.firstChild_=k[0]);var n=r(i),p=n.parentNode;p?w.call(p,h(this,k),n):g(this,k)}else k=d(a),f(this,a),w.call(this.impl,r(a),r(i));return e(k),a},removeChild:function(a){if(b(a),a.parentNode!==this)throw new Error("NotFoundError");var c=r(a);if(this.invalidateShadowRenderer()){var d=this.firstChild,e=this.lastChild,f=a.nextSibling,g=a.previousSibling,h=c.parentNode;h&&y.call(h,c),d===a&&(this.firstChild_=f),e===a&&(this.lastChild_=g),g&&(g.nextSibling_=f),f&&(f.previousSibling_=g),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else y.call(this.impl,c);return a},replaceChild:function(a,g){if(b(a),b(g),g.parentNode!==this)throw new Error("NotFoundError");var i,k=r(g);if(this.invalidateShadowRenderer()||j(a)){var l=g.previousSibling,m=g.nextSibling;m===a&&(m=a.nextSibling),i=c(a,this,l,m),this.firstChild===g&&(this.firstChild_=i[0]),this.lastChild===g&&(this.lastChild_=i[i.length-1]),g.previousSibling_=g.nextSibling_=g.parentNode_=void 0,k.parentNode&&x.call(k.parentNode,h(this,i),k)}else i=d(a),f(this,a),x.call(this.impl,r(a),k);return e(i),g},nodeWasAdded_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeWasAdded_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:s(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:s(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:s(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:s(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:s(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==k.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){if(this.invalidateShadowRenderer()){if(i(this),""!==a){var b=this.impl.ownerDocument.createTextNode(a);this.appendChild(b)}}else this.impl.textContent=a},get childNodes(){for(var a=new m,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){if(!this.invalidateShadowRenderer())return s(this.impl.cloneNode(a));var b=s(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=t(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return z.call(this.impl,r(a))}}),n(k,"ownerDocument"),q(u,k,document.createDocumentFragment()),delete k.prototype.querySelector,delete k.prototype.querySelectorAll,k.prototype=p(Object.create(l.prototype),k.prototype),a.wrappers.Node=k}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;
+if(d=b(e,c))return d;e=e.nextElementSibling}return null}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.mixin,f=a.registerWrapper,g=window.CharacterData;b.prototype=Object.create(d.prototype),e(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a}}),e(b.prototype,c),f(g,b,document.createTextNode("")),a.wrappers.CharacterData=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a){g.call(this,a)}function d(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var e=a.ChildNodeInterface,f=a.GetElementsByInterface,g=a.wrappers.Node,h=a.ParentNodeInterface,i=a.SelectorsInterface;a.addWrapNodeListMethod;var j=a.mixin,k=a.oneOf,l=a.registerWrapper,m=a.wrappers,n=window.Element,o=k(n.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),p=n.prototype[o];c.prototype=Object.create(g.prototype),j(c.prototype,{createShadowRoot:function(){var b=new m.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,c){this.impl.setAttribute(a,c),b(this,a)},removeAttribute:function(a){this.impl.removeAttribute(a),b(this,a)},matches:function(a){return p.call(this.impl,a)}}),c.prototype[o]=function(a){return this.matches(a)},n.prototype.webkitCreateShadowRoot&&(c.prototype.webkitCreateShadowRoot=c.prototype.createShadowRoot),d(c.prototype,"id"),d(c.prototype,"className","class"),j(c.prototype,e),j(c.prototype,f),j(c.prototype,h),j(c.prototype,i),l(n,c),a.matchesName=o,a.wrappers.Element=c}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&";case"<":return"<";case'"':return"""}}function c(a){return a.replace(r,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",s[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=p(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(q(f))}function g(a){l.call(this,a)}function h(b){return function(){return a.renderAllPending(),this.impl[b]}}function i(a){m(g,a,h(a))}function j(b){Object.defineProperty(g.prototype,b,{get:h(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function k(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var l=a.wrappers.Element,m=a.defineGetter,n=a.mixin,o=a.registerWrapper,p=a.unwrap,q=a.wrap,r=/&|<|"/g,s={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},t=window.HTMLElement;g.prototype=Object.create(l.prototype),n(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;b&&(b.invalidateShadowRenderer(),this.impl.outerHTML=a)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(i),["scrollLeft","scrollTop"].forEach(j),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(k),o(t,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));void 0!==a&&(e.width=a),void 0!==b&&(e.height=b),d.call(this,e),g(e,this)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=o.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);o.set(a,b)}return b}function c(a){var c,d=b(a.ownerDocument),e=l(d.createDocumentFragment());for(h();c=a.firstChild;)e.appendChild(c);return k(),e}function d(a){if(e.call(this,a),!p){var b=c(a);n.set(this,m(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.muteMutationEvents,i=a.registerWrapper,j=a.setInnerHTML,k=a.unmuteMutationEvents,l=a.unwrap,m=a.wrap,n=new WeakMap,o=new WeakMap,p=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return p?m(this.impl.content):n.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){j(this.content,a)}}),p&&i(p,d),a.wrappers.HTMLTemplateElement=d}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement;a.mixin;var g=a.registerWrapper,h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(h,b),a.wrappers.CanvasRenderingContext2D=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;g&&(c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}}),d(g,b),a.wrappers.WebGLRenderingContext=b)}(this.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b,a.getHostForShadowRoot=function(a){return j.get(a)}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=G(a),g=G(c),h=e?G(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=H(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=G(a),d=c.parentNode;if(d){var e=H(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=J.get(a);c||J.set(a,c=[]),c.push(b)}function f(a){I.set(a,[])}function g(a){return I.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof y))return!1;if(!M.test(c))return!1;if(":"===c[0]&&!N.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<P.length;a++)P[a].render();P=[]}function l(){F=null,k()}function m(a){var b=L.get(a);return b||(b=new q(a),L.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof C)return a;return null}function o(a){return m(D(a))}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof z}function s(a){return a instanceof z}function t(a){return a instanceof A}function u(a){return a instanceof A}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){K.set(a,b)}var y=a.wrappers.Element,z=a.wrappers.HTMLContentElement,A=a.wrappers.HTMLShadowElement,B=a.wrappers.Node,C=a.wrappers.ShadowRoot;a.assert;var D=a.getHostForShadowRoot;a.mixin,a.muteMutationEvents;var E=a.oneOf;a.unmuteMutationEvents;var F,G=a.unwrap,H=a.wrap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=new WeakMap,M=/^[*.:#[a-zA-Z_|]/,N=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),O=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),P=[],Q=new ArraySplice;Q.equals=function(a,b){return G(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(G(b)),g=a||new WeakMap,i=Q.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=H(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&H(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,P.push(this),F)return;F=window[O](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},B.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},z.prototype.getDistributedNodes=function(){return k(),g(this)},A.prototype.nodeWasAdded_=z.prototype.nodeWasAdded_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=J,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=K,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOptionElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){y.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.wrapEventTargetMethods;a.wrapNodeList;var x=new WeakMap;b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var y=document.adoptNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)}}),document.register){var z=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);return["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){b.apply(v(this),arguments)})}),z.call(u(this),b,{prototype:i}),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i),d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=x.get(this);return a?a:(a=new g(u(this).implementation),x.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),w([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)},["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)}}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}function c(a){return new b(a)}function d(a){return a.map(c)}function e(a){var b=this;this.impl=new k(function(c){a.call(b,d(c),b)})}var f=a.defineGetter,g=a.defineWrapGetter,h=a.registerWrapper,i=a.unwrapIfNeeded,j=a.wrapNodeList;a.wrappers;var k=window.MutationObserver||window.WebKitMutationObserver;if(k){var l=window.MutationRecord;b.prototype={get addedNodes(){return j(this.impl.addedNodes)},get removedNodes(){return j(this.impl.removedNodes)}},["target","previousSibling","nextSibling"].forEach(function(a){g(b,a)}),["type","attributeName","attributeNamespace","oldValue"].forEach(function(a){f(b,a,function(){return this.impl[a]})}),l&&h(l,b),window.Node,e.prototype={observe:function(a,b){this.impl.observe(i(a),b)},disconnect:function(){this.impl.disconnect()},takeRecords:function(){return d(this.impl.takeRecords())}},a.wrappers.MutationObserver=e,a.wrappers.MutationRecord=b}}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b),a.wrappers.Range=b}(this.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}a.isWrapperFor;var c={a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",data:"HTMLDataElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",time:"HTMLTimeElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",track:"HTMLTrackElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"};Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(this.ShadowDOMPolyfill),function(){var a=window.ShadowDOMPolyfill;a.wrap,Object.defineProperties(HTMLElement.prototype,{webkitShadowRoot:{get:function(){return this.shadowRoot}}}),HTMLElement.prototype.webkitCreateShadowRoot=HTMLElement.prototype.createShadowRoot,window.dartExperimentalFixupGetTag=function(b){function c(a){if(a instanceof d)return"NodeList";if(a instanceof e)return"ShadowRoot";if(window.MutationRecord&&a instanceof MutationRecord)return"MutationRecord";if(window.MutationObserver&&a instanceof MutationObserver)return"MutationObserver";if(a instanceof HTMLTemplateElement)return"HTMLTemplateElement";var c=f(a);if(a!==c){var g=a.constructor;if(g===c.constructor){var h=g._ShadowDOMPolyfill$cacheTag_;return h||(h=Object.prototype.toString.call(c),h=h.substring(8,h.length-1),g._ShadowDOMPolyfill$cacheTag_=h),h}a=c}return b(a)}var d=a.wrappers.NodeList,e=a.wrappers.ShadowRoot,f=a.unwrapIfNeeded;return c}}();var Platform={};!function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(n,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=b.sheet.cssRules;return b.parentNode.removeChild(b),d}function e(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function f(a){a&&g().appendChild(document.createTextNode(a))}function g(){return h||(h=document.createElement("style"),h.setAttribute("ShadowCSSShim","")),h}var h,i={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var e=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b),this.insertPolyfillDirectives(g.rootStyles),this.insertPolyfillRules(g.rootStyles);var h=this.stylesToShimmedCssText(g.scopeStyles,b,e);h+=this.extractPolyfillUnscopedRules(g.rootStyles),g.shimmedStyle=c(h),a&&(a.shimmedStyle=g.shimmedStyle);for(var i,j=0,k=g.rootStyles.length;k>j&&(i=g.rootStyles[j]);j++)i.parentNode.removeChild(i);f(h)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a?a.querySelectorAll("style"):[];e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},isTypeExtension:function(a){return a&&a.indexOf("-")<0},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertPolyfillDirectives:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillDirectivesInCssText(a.textContent)},this)},insertPolyfillDirectivesInCssText:function(a){return a.replace(o,function(a,b){return b.slice(0,-2)+"{"})},insertPolyfillRules:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillRulesInCssText(a.textContent)},this)},insertPolyfillRulesInCssText:function(a){return a.replace(p,function(a,b){return b.slice(0,-1)})},extractPolyfillUnscopedRules:function(a){var b="";return a&&Array.prototype.forEach.call(a,function(a){b+=this.extractPolyfillUnscopedRulesFromCssText(a.textContent)+"\n\n"},this),b},extractPolyfillUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},stylesToShimmedCssText:function(a,b,c){return this.shimAtHost(a,b,c)+this.shimScoping(a,b,c)},shimAtHost:function(a,b,c){return a?this.convertAtHostStyles(a,b,c):void 0},convertAtHostStyles:function(a,c,f){var g=b(a),h=this;return g=g.replace(j,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),new RegExp("^"+c+u,"m")))},scopeHostCss:function(a,b,c){var d=this;return a.replace(k,function(a,e,f){return d.scopeHostSelector(e,b,c)+" "+f+"\n "})},scopeHostSelector:function(a,b,c){var d=[],e=a.split(","),f="[is="+b+"]";return e.forEach(function(a){a=a.trim(),a.match(l)?a=a.replace(l,c?f+"$1$3":b+"$1$3"):a.match(m)&&(a=c?f+a:b+a),d.push(a)},this),d.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a).replace(j,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return f=this.scopeRules(g,c,e)},convertPseudos:function(a){return a.replace(r," [pseudo=$1]")},convertParts:function(a){return a.replace(s," [part=$1]")},convertColonHost:function(a){return a.replace(t,function(a,b,c,d){return c?y+c+d+", "+c+" "+b+d:b+d})},convertCombinators:function(a){return a.replace("^^"," ").replace("^"," ")},scopeRules:function(a,b,c){var d="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(d+=this.scopeSelector(a.selectorText,b,c,this.strictStyling)+" {\n ",d+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(d+="@media "+a.media.mediaText+" {\n",d+=this.scopeRules(a.cssRules,b),d+="\n}\n\n"):a.cssText&&(d+=a.cssText+"\n\n")},this),d},scopeSelector:function(a,b,c,d){var e=[],f=a.split(",");return f.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b,c)&&(a=d?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=c?b:"\\[is="+b+"\\]",e=new RegExp("^("+d+")"+u,"m");return!a.match(e)},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(z)?(a=a.replace(y,d),a.replace(z,d+" ")):d+" "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(z,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(v,x).replace(w,x)
+},propertiesFromRule:function(a){var b=a.style.cssText;return a.style.content&&!a.style.content.match(/['"]+/)&&(b="content: '"+a.style.content+"';\n"+a.style.cssText.replace(/content:[^;]*;/g,"")),b}},j=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,k=/([^{]*)({[\s\S]*?})/gim,l=/(.*)((?:\*)|(?:\:scope))(.*)/,m=/^[.\[:]/,n=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,o=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,p=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/::(x-[^\s{,(]*)/gim,s=/::part\(([^)]*)\)/gim,t=/(-host)(?:\(([^)]*)\))?([^,{]*)/gim,u="([>\\s~+[.,{:][\\s\\S]*)?$",v=/@host/gim,w=/\:host/gim,x="-host",y="-host-no-combinator",z=/-host/gim;if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var A=document.querySelector("head");A.insertBefore(g(),A.childNodes[0])}a.ShadowCSS=i}(window.Platform)}
\ No newline at end of file
diff --git a/pkg/stack_trace/lib/src/frame.dart b/pkg/stack_trace/lib/src/frame.dart
index 0b4f577..b15f651 100644
--- a/pkg/stack_trace/lib/src/frame.dart
+++ b/pkg/stack_trace/lib/src/frame.dart
@@ -19,6 +19,10 @@
r'^\s*at (?:([^\s].*?)(?: \[as [^\]]+\])? '
r'\((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$');
+/// foo$bar$0@http://pub.dartlang.org/stuff.dart.js:560:28
+/// http://pub.dartlang.org/stuff.dart.js:560:28
+final _safariFrame = new RegExp(r"^(?:([0-9A-Za-z_$]*)@)?(.*):(\d*):(\d*)$");
+
// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560
// .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560
// .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560
@@ -169,11 +173,27 @@
return new Frame(uri, int.parse(match[4]), null, member);
}
- /// Parses a string representation of a Safari stack frame.
+ /// Parses a string representation of a Safari 6.0 stack frame.
///
- /// Safari 6+ frames look just like Firefox frames. Prior to Safari 6, stack
- /// traces can't be retrieved.
- factory Frame.parseSafari(String frame) => new Frame.parseFirefox(frame);
+ /// Safari 6.0 frames look just like Firefox frames. Prior to Safari 6.0,
+ /// stack traces can't be retrieved.
+ factory Frame.parseSafari6_0(String frame) => new Frame.parseFirefox(frame);
+
+ /// Parses a string representation of a Safari 6.1+ stack frame.
+ factory Frame.parseSafari6_1(String frame) {
+ var match = _safariFrame.firstMatch(frame);
+ if (match == null) {
+ throw new FormatException(
+ "Couldn't parse Safari stack trace line '$frame'.");
+ }
+
+ var uri = Uri.parse(match[2]);
+ var member = match[1];
+ if (member == null) member = '<fn>';
+ var line = match[3] == '' ? null : int.parse(match[3]);
+ var column = match[4] == '' ? null : int.parse(match[4]);
+ return new Frame(uri, line, column, member);
+ }
/// Parses this package's string representation of a stack frame.
factory Frame.parseFriendly(String frame) {
diff --git a/pkg/stack_trace/lib/src/trace.dart b/pkg/stack_trace/lib/src/trace.dart
index 95d41ad..c3db43e 100644
--- a/pkg/stack_trace/lib/src/trace.dart
+++ b/pkg/stack_trace/lib/src/trace.dart
@@ -28,6 +28,19 @@
/// though it is possible for the message to match this as well.
final _v8TraceLine = new RegExp(r" ?at ");
+/// A RegExp to match Safari's stack traces.
+///
+/// Prior to version 6, Safari's stack traces were uncapturable. In v6 they were
+/// almost identical to Firefox traces, and so are handled by the Firefox code.
+/// In v6.1+, they have their own format that's similar to Firefox but distinct
+/// enough to warrant handling separately.
+///
+/// Most notably, Safari traces occasionally don't include the initial method
+/// name followed by "@", and they always have both the line and column number
+/// (or just a trailing colon if no column number is available).
+final _safariTrace = new RegExp(r"^([0-9A-Za-z_$]*@)?.*:\d*:\d*$",
+ multiLine: true);
+
/// A RegExp to match Firefox's stack traces.
///
/// Firefox's trace frames start with the name of the function in which the
@@ -36,7 +49,8 @@
final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]|\(.*\))*@");
/// A RegExp to match this package's stack traces.
-final _friendlyTrace = new RegExp(r"^[^\s]+( \d+(:\d+)?)?\s+[^\s]+($|\n)");
+final _friendlyTrace = new RegExp(r"^[^\s]+( \d+(:\d+)?)?[ \t]+[^\s]+$",
+ multiLine: true);
/// A stack trace, comprised of a list of stack frames.
class Trace implements StackTrace {
@@ -89,9 +103,15 @@
try {
if (trace.isEmpty) return new Trace(<Frame>[]);
if (trace.contains(_v8Trace)) return new Trace.parseV8(trace);
- // Valid Safari traces are a superset of valid Firefox traces.
- if (trace.contains(_firefoxTrace)) return new Trace.parseSafari(trace);
- if (trace.contains(_friendlyTrace)) return new Trace.parseFriendly(trace);
+ // Safari 6.1+ traces could be misinterpreted as Firefox traces, so we
+ // check for them first.
+ if (trace.contains(_safariTrace)) return new Trace.parseSafari6_1(trace);
+ // Safari 6.0 traces are a superset of Firefox traces, so we parse those
+ // two together.
+ if (trace.contains(_firefoxTrace)) return new Trace.parseSafari6_0(trace);
+ if (trace.contains(_friendlyTrace)) {
+ return new Trace.parseFriendly(trace);
+ }
// Default to parsing the stack trace as a VM trace. This is also hit on
// IE and Safari, where the stack trace is just an empty string (issue
@@ -129,11 +149,25 @@
/// Parses a string representation of a Safari stack trace.
///
- /// Safari 6+ stack traces look just like Firefox traces, except that they
+ /// This will automatically decide between [parseSafari6_0] and
+ /// [parseSafari6_1] based on the contents of [trace].
+ factory Trace.parseSafari(String trace) {
+ if (trace.contains(_safariTrace)) return new Trace.parseSafari6_1(trace);
+ return new Trace.parseSafari6_0(trace);
+ }
+
+ /// Parses a string representation of a Safari 6.1+ stack trace.
+ Trace.parseSafari6_1(String trace)
+ : this(trace.trim().split("\n")
+ .map((line) => new Frame.parseSafari6_1(line)));
+
+ /// Parses a string representation of a Safari 6.0 stack trace.
+ ///
+ /// Safari 6.0 stack traces look just like Firefox traces, except that they
/// sometimes (e.g. in isolates) have a "[native code]" frame. We just ignore
/// this frame to make the stack format more consistent between browsers.
- /// Prior to Safari 6, stack traces can't be retrieved.
- Trace.parseSafari(String trace)
+ /// Prior to Safari 6.0, stack traces can't be retrieved.
+ Trace.parseSafari6_0(String trace)
: this(trace.trim().split("\n")
.where((line) => line != '[native code]')
.map((line) => new Frame.parseFirefox(line)));
diff --git a/pkg/stack_trace/test/frame_test.dart b/pkg/stack_trace/test/frame_test.dart
index ab7c401..97cf48a 100644
--- a/pkg/stack_trace/test/frame_test.dart
+++ b/pkg/stack_trace/test/frame_test.dart
@@ -226,6 +226,53 @@
});
});
+ group('.parseSafari6_1', () {
+ test('parses a simple stack frame correctly', () {
+ var frame = new Frame.parseSafari6_1(
+ "foo\$bar@http://dartlang.org/foo/bar.dart:10:11");
+ expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+ expect(frame.line, equals(10));
+ expect(frame.column, equals(11));
+ expect(frame.member, equals('foo\$bar'));
+ });
+
+ test('parses an anonymous stack frame correctly', () {
+ var frame = new Frame.parseSafari6_1(
+ "http://dartlang.org/foo/bar.dart:10:11");
+ expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+ expect(frame.line, equals(10));
+ expect(frame.column, equals(11));
+ expect(frame.member, equals('<fn>'));
+ });
+
+ test('parses a stack frame with no line correctly', () {
+ var frame = new Frame.parseSafari6_1(
+ "foo\$bar@http://dartlang.org/foo/bar.dart::11");
+ expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+ expect(frame.line, isNull);
+ expect(frame.column, equals(11));
+ expect(frame.member, equals('foo\$bar'));
+ });
+
+ test('parses a stack frame with no column correctly', () {
+ var frame = new Frame.parseSafari6_1(
+ "foo\$bar@http://dartlang.org/foo/bar.dart:10:");
+ expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+ expect(frame.line, equals(10));
+ expect(frame.column, isNull);
+ expect(frame.member, equals('foo\$bar'));
+ });
+
+ test('parses a stack frame with no line or column correctly', () {
+ var frame = new Frame.parseSafari6_1(
+ "foo\$bar@http://dartlang.org/foo/bar.dart:10:11");
+ expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+ expect(frame.line, equals(10));
+ expect(frame.column, equals(11));
+ expect(frame.member, equals('foo\$bar'));
+ });
+ });
+
group('.parseFriendly', () {
test('parses a simple stack frame correctly', () {
var frame = new Frame.parseFriendly(
diff --git a/pkg/stack_trace/test/trace_test.dart b/pkg/stack_trace/test/trace_test.dart
index c3ce039..ad916f1 100644
--- a/pkg/stack_trace/test/trace_test.dart
+++ b/pkg/stack_trace/test/trace_test.dart
@@ -130,7 +130,7 @@
equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
});
- test('.parseSafari', () {
+ test('parses a Safari 6.0 stack trace correctly', () {
var trace = new Trace.parse(
'Foo._bar@http://pub.dartlang.org/stuff.js:42\n'
'zip/<@http://pub.dartlang.org/stuff.js:0\n'
@@ -146,6 +146,20 @@
expect(trace.frames.length, equals(3));
});
+ test('parses a Safari 6.1 stack trace correctly', () {
+ var trace = new Trace.parse(
+ 'http://pub.dartlang.org/stuff.js:42:43\n'
+ 'zip@http://pub.dartlang.org/stuff.js:0:1\n'
+ 'zip\$zap@http://pub.dartlang.org/thing.js:1:2');
+
+ expect(trace.frames[0].uri,
+ equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+ expect(trace.frames[1].uri,
+ equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+ expect(trace.frames[2].uri,
+ equals(Uri.parse("http://pub.dartlang.org/thing.js")));
+ });
+
test('parses a package:stack_trace stack trace correctly', () {
var trace = new Trace.parse(
'http://dartlang.org/foo/bar.dart 10:11 Foo.<fn>.bar\n'
diff --git a/pkg/template_binding/lib/src/binding_delegate.dart b/pkg/template_binding/lib/src/binding_delegate.dart
new file mode 100644
index 0000000..0a9cb51
--- /dev/null
+++ b/pkg/template_binding/lib/src/binding_delegate.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library template_binding.src.binding_delegate;
+
+import 'dart:html';
+import 'package:template_binding/template_binding.dart' show TemplateInstance;
+
+/**
+ * Template Bindings native features enables a wide-range of use cases,
+ * but (by design) don't attempt to implement a wide array of specialized
+ * behaviors.
+ *
+ * Enabling these features is a matter of implementing and registering a
+ * BindingDelegate. A binding delegate is an object which contains one or more
+ * delegation functions which implement specialized behavior. This object is
+ * registered via [TemplateBindExtension.bindingDelegate]:
+ *
+ * HTML:
+ * <template bind>
+ * {{ What!Ever('crazy')->thing^^^I+Want(data) }}
+ * </template>
+ *
+ * Dart:
+ * class MySyntax extends BindingDelegate {
+ * prepareBinding(path, name, node) {
+ * // The magic happens here!
+ * }
+ * }
+ * ...
+ * templateBind(query('template'))
+ * ..bindingDelegate = new MySyntax()
+ * ..model = new MyModel();
+ *
+ *
+ * See
+ * <http://www.polymer-project.org/platform/template.html#binding-delegate-api>
+ * for more information about the binding delegate.
+ */
+// TODO(jmesserly): need better api docs here. The link above seems out of date.
+abstract class BindingDelegate {
+ /**
+ * Prepares a binding. This is called immediately after parsing a mustache
+ * token with `{{ path }}` in the context of the [node] and the property named
+ * [name]. This should return a function that will be passed the actual
+ * node and model, and either returns null or an object with a `value`
+ * property. This allows the syntax to reinterpret the model for each binding.
+ */
+ PrepareBindingFunction prepareBinding(String path, String name, Node node)
+ => null;
+
+ /**
+ * Returns a function that can optionally replace the model that will be
+ * passed to [TemplateBindExtension.createInstance]. This can be used to
+ * implement syntax such as `<template repeat="{{ item in items }}">` by
+ * ensuring that the returned model has the "item" name available.
+ */
+ PrepareInstanceModelFunction prepareInstanceModel(Element template) => null;
+
+ /**
+ * Returns a function that will be called whenever the position of an item
+ * inside this template changes.
+ */
+ PrepareInstancePositionChangedFunction prepareInstancePositionChanged(
+ Element template) => null;
+}
+
+typedef PrepareBindingFunction(model, Node node);
+
+typedef PrepareInstanceModelFunction(model);
+
+typedef PrepareInstancePositionChangedFunction(TemplateInstance instance,
+ int index);
diff --git a/pkg/template_binding/lib/src/element.dart b/pkg/template_binding/lib/src/element.dart
index c3c4992..1ee43f9 100644
--- a/pkg/template_binding/lib/src/element.dart
+++ b/pkg/template_binding/lib/src/element.dart
@@ -15,7 +15,7 @@
if (_node is OptionElement && name == 'value') {
// Note: because <option> can be a semantic template, <option> will be
// a TemplateBindExtension sometimes. So we need to handle it here.
- _node.attributes.remove(name);
+ (_node as OptionElement).attributes.remove(name);
binding = new _OptionValueBinding(_node, model, path);
} else {
binding = new _AttributeBinding(_node, name, model, path);
diff --git a/pkg/template_binding/lib/src/input_bindings.dart b/pkg/template_binding/lib/src/input_bindings.dart
index fc89dc5..8e5b3b0 100644
--- a/pkg/template_binding/lib/src/input_bindings.dart
+++ b/pkg/template_binding/lib/src/input_bindings.dart
@@ -148,11 +148,12 @@
// Instead we use scheduleMicrotask. Each <template repeat> needs a delay of
// 2:
// * once to happen after the child _TemplateIterator is created
- // * once to be after _TemplateIterator.inputs CompoundBinding resolve
+ // * once to be after _TemplateIterator's CompoundPathObserver resolve
// And then we need to do this delay sequence twice:
// * once for OPTGROUP
// * once for OPTION.
// The resulting 2 * 2 is our maxRetries.
+ //
// TODO(jmesserly): a much better approach would be to find the nested
// <template> and wait on some future that completes when it has expanded.
var maxRetries = 4;
diff --git a/pkg/template_binding/lib/src/instance_binding_map.dart b/pkg/template_binding/lib/src/instance_binding_map.dart
new file mode 100644
index 0000000..3868343
--- /dev/null
+++ b/pkg/template_binding/lib/src/instance_binding_map.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of template_binding;
+
+class _InstanceBindingMap {
+ final List bindings;
+ final List<_InstanceBindingMap> children;
+ final Node templateRef;
+ final bool hasSubTemplate;
+
+ _InstanceBindingMap._(this.bindings, this.children, this.templateRef,
+ this.hasSubTemplate);
+
+ factory _InstanceBindingMap(Node node, BindingDelegate delegate) {
+ var bindings = _getBindings(node, delegate);
+
+ bool hasSubTemplate = false;
+ Node templateRef = null;
+
+ if (isSemanticTemplate(node)) {
+ templateRef = node;
+ hasSubTemplate = true;
+ }
+
+ List children = null;
+ for (var c = node.firstChild, i = 0; c != null; c = c.nextNode, i++) {
+ var childMap = new _InstanceBindingMap(c, delegate);
+ if (childMap == null) continue;
+
+ if (children == null) children = new List(node.nodes.length);
+ children[i] = childMap;
+ if (childMap.hasSubTemplate) {
+ hasSubTemplate = true;
+ }
+ }
+
+ return new _InstanceBindingMap._(bindings, children, templateRef,
+ hasSubTemplate);
+ }
+}
+
+
+void _addMapBindings(Node node, _InstanceBindingMap map, model,
+ BindingDelegate delegate, List bound) {
+ if (map == null) return;
+
+ if (map.templateRef != null) {
+ TemplateBindExtension.decorate(node, map.templateRef);
+ if (delegate != null) {
+ templateBindFallback(node)._bindingDelegate = delegate;
+ }
+ }
+
+ if (map.bindings != null) {
+ _processBindings(map.bindings, node, model, bound);
+ }
+
+ if (map.children == null) return;
+
+ int i = 0;
+ for (var c = node.firstChild; c != null; c = c.nextNode) {
+ _addMapBindings(c, map.children[i++], model, delegate, bound);
+ }
+}
diff --git a/pkg/template_binding/lib/src/list_diff.dart b/pkg/template_binding/lib/src/list_diff.dart
index ba96d15..fc7430d 100644
--- a/pkg/template_binding/lib/src/list_diff.dart
+++ b/pkg/template_binding/lib/src/list_diff.dart
@@ -39,7 +39,7 @@
int get removedCount => _removed.length;
/** Returns true if the provided index was changed by this operation. */
- bool changes(key) {
+ bool indexChanged(key) {
// If key isn't an int, or before the index, then it wasn't changed.
if (key is! int || key < index) return false;
diff --git a/pkg/template_binding/lib/src/node.dart b/pkg/template_binding/lib/src/node.dart
index 791214b..a5fb835 100644
--- a/pkg/template_binding/lib/src/node.dart
+++ b/pkg/template_binding/lib/src/node.dart
@@ -31,7 +31,7 @@
/** Unbinds all bound attributes. */
void unbindAll() {
if (_bindings == null) return;
- for (var binding in bindings.values) {
+ for (var binding in bindings.values.toList()) {
if (binding != null) binding.close();
}
_bindings = null;
@@ -56,7 +56,7 @@
/** Gets the template instance that instantiated this node, if any. */
TemplateInstance get templateInstance =>
_templateInstance != null ? _templateInstance :
- (_node.parent != null ? _node.parent.templateInstance : null);
+ (_node.parent != null ? nodeBind(_node.parent).templateInstance : null);
}
@@ -80,160 +80,3 @@
TemplateInstance(this.firstNode, this.lastNode, this.model);
}
-
-
-/**
- * Template Bindings native features enables a wide-range of use cases,
- * but (by design) don't attempt to implement a wide array of specialized
- * behaviors.
- *
- * Enabling these features is a matter of implementing and registering a
- * BindingDelegate. A binding delegate is an object which contains one or more
- * delegation functions which implement specialized behavior. This object is
- * registered via [TemplateBindExtension.bindingDelegate]:
- *
- * HTML:
- * <template bind>
- * {{ What!Ever('crazy')->thing^^^I+Want(data) }}
- * </template>
- *
- * Dart:
- * class MySyntax extends BindingDelegate {
- * getBinding(model, path, name, node) {
- * // The magic happens here!
- * }
- * }
- * ...
- * templateBind(query('template'))
- * ..bindingDelegate = new MySyntax()
- * ..model = new MyModel();
- *
- * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
- * more information about Custom Syntax.
- */
-abstract class BindingDelegate {
- /**
- * This syntax method allows for a custom interpretation of the contents of
- * mustaches (`{{` ... `}}`).
- *
- * When a template is inserting an instance, it will invoke this method for
- * each mustache which is encountered. The function is invoked with four
- * arguments:
- *
- * - [model]: The data context for which this instance is being created.
- * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
- * - [name]: The context in which the mustache occurs. Within element
- * attributes, this will be the name of the attribute. Within text,
- * this will be 'text'.
- * - [node]: A reference to the node to which this binding will be created.
- *
- * If the method wishes to handle binding, it is required to return an object
- * which has at least a `value` property that can be observed. If it does,
- * then MDV will call [NodeBindExtension.bind] on the node:
- *
- * nodeBind(node).bind(name, retval, 'value');
- *
- * If the 'getBinding' does not wish to override the binding, it should return
- * null.
- */
- // TODO(jmesserly): I had to remove type annotations from "name" and "node"
- // Normally they are String and Node respectively. But sometimes it will pass
- // (int name, CompoundBinding node). That seems very confusing; we may want
- // to change this API.
- getBinding(model, String path, name, node) => null;
-
- /**
- * This syntax method allows a syntax to provide an alterate model than the
- * one the template would otherwise use when producing an instance.
- *
- * When a template is about to create an instance, it will invoke this method
- * The function is invoked with two arguments:
- *
- * - [template]: The template element which is about to create and insert an
- * instance.
- * - [model]: The data context for which this instance is being created.
- *
- * The template element will always use the return value of `getInstanceModel`
- * as the model for the new instance. If the syntax does not wish to override
- * the value, it should simply return the `model` value it was passed.
- */
- getInstanceModel(Element template, model) => model;
-}
-
-/**
- * A data binding on a [Node].
- * See [NodeBindExtension.bindings] and [NodeBindExtension.bind].
- */
-abstract class NodeBinding {
- Node _node;
- var _model;
- PathObserver _observer;
- StreamSubscription _pathSub;
-
- /** The property of [node] which will be data bound. */
- final String property;
-
- /** The property of [node] which will be data bound. */
- final String path;
-
- /** The node that has [property] which will be data bound. */
- Node get node => _node;
-
- /**
- * The bound data model.
- */
- get model => _model;
-
- /** True if this binding has been [closed]. */
- bool get closed => _node == null;
-
- /** The value at the [path] on [model]. */
- get value => _observer.value;
-
- set value(newValue) {
- _observer.value = newValue;
- }
-
- NodeBinding(this._node, this.property, this._model, [String path])
- : path = path != null ? path : '' {
- _observePath();
- }
-
- _observePath() {
- // Fast path if we're observing PathObserver.value
- if (model is PathObserver && path == 'value') {
- _observer = model;
- } else {
- // Create the path observer
- _observer = new PathObserver(model, path);
- }
- _pathSub = _observer.bindSync(valueChanged);
- }
-
- /** Called when [value] changes to update the [node]. */
- // TODO(jmesserly): the impl in template_binding uses reflection to set the
- // property, but that isn't used except for specific known fields like
- // "textContent", so I'm overridding this in the subclasses instead.
- void valueChanged(newValue);
-
- /** Called to sanitize the value before it is assigned into the property. */
- sanitizeBoundValue(value) => value == null ? '' : '$value';
-
- /**
- * Called by [NodeBindExtension.unbind] to close this binding and unobserve
- * the [path].
- *
- * This can be overridden in subclasses, but they must call `super.close()`
- * to free associated resources. They must also check [closed] and return
- * immediately if already closed.
- */
- void close() {
- if (closed) return;
-
- if (_pathSub != null) _pathSub.cancel();
- _pathSub = null;
- _observer = null;
- _node = null;
- _model = null;
- }
-}
diff --git a/pkg/template_binding/lib/src/node_binding.dart b/pkg/template_binding/lib/src/node_binding.dart
new file mode 100644
index 0000000..95c5e00
--- /dev/null
+++ b/pkg/template_binding/lib/src/node_binding.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library template_binding.src.node_binding;
+
+import 'dart:async' show StreamSubscription;
+import 'dart:html' show Node;
+import 'package:observe/observe.dart' show PathObserver, CompoundPathObserver;
+
+/** Test only method. Not re-exported. */
+getObserverForTest(NodeBinding binding) => binding._observer;
+
+/**
+ * A data binding on a [Node].
+ * See [NodeBindExtension.bindings] and [NodeBindExtension.bind].
+ */
+abstract class NodeBinding {
+ Node _node;
+ var _model;
+
+ // TODO(jmesserly): need common interface for PathObserver,
+ // CompoundPathObserver.
+ var _observer;
+ StreamSubscription _pathSub;
+
+ /** The property of [node] which will be data bound. */
+ final String property;
+
+ /** The property of [node] which will be data bound. */
+ final String path;
+
+ /** The node that has [property] which will be data bound. */
+ Node get node => _node;
+
+ /** The bound data model. */
+ get model => _model;
+
+ /** True if this binding has been [closed]. */
+ bool get closed => _node == null;
+
+ /** The value at the [path] on [model]. */
+ get value => _observer.value;
+
+ set value(newValue) {
+ _observer.value = newValue;
+ }
+
+ NodeBinding(this._node, this.property, this._model, [String path])
+ : path = path != null ? path : '' {
+
+ // Fast path if we're observing "value"
+ if ((model is PathObserver || model is CompoundPathObserver) &&
+ path == 'value') {
+
+ _observer = model;
+ } else {
+ // Create the path observer
+ _observer = new PathObserver(model, this.path);
+ }
+
+ _pathSub = _observer.changes.listen((r) => valueChanged(value));
+ valueChanged(value);
+ }
+
+ /** Called when [value] changes to update the [node]. */
+ // TODO(jmesserly): the impl in template_binding uses reflection to set the
+ // property, but that isn't used except for specific known fields like
+ // "textContent", so I'm overridding this in the subclasses instead.
+ void valueChanged(newValue);
+
+ /** Called to sanitize the value before it is assigned into the property. */
+ sanitizeBoundValue(value) => value == null ? '' : '$value';
+
+ /**
+ * Called by [NodeBindExtension.unbind] to close this binding and unobserve
+ * the [path].
+ *
+ * This can be overridden in subclasses, but they must call `super.close()`
+ * to free associated resources. They must also check [closed] and return
+ * immediately if already closed.
+ */
+ void close() {
+ if (closed) return;
+
+ if (_pathSub != null) _pathSub.cancel();
+ _pathSub = null;
+ _observer = null;
+ _node = null;
+ _model = null;
+ }
+}
diff --git a/pkg/template_binding/lib/src/template.dart b/pkg/template_binding/lib/src/template.dart
index be6a6fd..ad35eb8 100644
--- a/pkg/template_binding/lib/src/template.dart
+++ b/pkg/template_binding/lib/src/template.dart
@@ -8,7 +8,7 @@
class TemplateBindExtension extends _ElementExtension {
var _model;
BindingDelegate _bindingDelegate;
- _TemplateIterator _templateIterator;
+ _TemplateIterator _iterator;
bool _scheduled = false;
Element _templateInstanceRef;
@@ -17,34 +17,115 @@
DocumentFragment _content;
bool _templateIsDecorated;
+ var _bindingMap;
+
TemplateBindExtension._(Element node) : super(node);
Element get _node => super._node;
+ TemplateBindExtension get _self => super._node is TemplateBindExtension
+ ? _node : this;
+
NodeBinding bind(String name, model, [String path]) {
+ path = path != null ? path : '';
+
+ if (_iterator == null) {
+ // TODO(jmesserly): since there's only one iterator, we could just
+ // inline it into this object.
+ _iterator = new _TemplateIterator(this);
+ }
+
+ // Dart note: we return _TemplateBinding instead of _iterator.
+ // See comment on _TemplateBinding class.
switch (name) {
case 'bind':
+ _iterator..hasBind = true
+ ..bindModel = model
+ ..bindPath = path;
+ _scheduleIterator();
+ return bindings[name] = new _TemplateBinding(this, name, model, path);
case 'repeat':
+ _iterator..hasRepeat = true
+ ..repeatModel = model
+ ..repeatPath = path;
+ _scheduleIterator();
+ return bindings[name] = new _TemplateBinding(this, name, model, path);
case 'if':
- _self.unbind(name);
- if (_templateIterator == null) {
- _templateIterator = new _TemplateIterator(_node);
- }
+ _iterator..hasIf = true
+ ..ifModel = model
+ ..ifPath = path;
+ _scheduleIterator();
return bindings[name] = new _TemplateBinding(this, name, model, path);
default:
return super.bind(name, model, path);
}
}
+ void unbind(String name) {
+ switch (name) {
+ case 'bind':
+ if (_iterator == null) return;
+ _iterator..hasBind = false
+ ..bindModel = null
+ ..bindPath = null;
+ _scheduleIterator();
+ bindings.remove(name);
+ return;
+ case 'repeat':
+ if (_iterator == null) return;
+ _iterator..hasRepeat = false
+ ..repeatModel = null
+ ..repeatPath = null;
+ _scheduleIterator();
+ bindings.remove(name);
+ return;
+ case 'if':
+ if (_iterator == null) return;
+ _iterator..hasIf = false
+ ..ifModel = null
+ ..ifPath = null;
+ _scheduleIterator();
+ bindings.remove(name);
+ return;
+ default:
+ super.unbind(name);
+ return;
+ }
+ }
+
+ void _scheduleIterator() {
+ if (!_iterator.depsChanging) {
+ _iterator.depsChanging = true;
+ scheduleMicrotask(_iterator.resolve);
+ }
+ }
+
/**
* Creates an instance of the template, using the provided model and optional
* binding delegate.
*/
- DocumentFragment createInstance([model, BindingDelegate delegate]) {
- var instance = _createDeepCloneAndDecorateTemplates(
- templateBind(ref).content, delegate);
+ DocumentFragment createInstance([model, BindingDelegate delegate,
+ List<NodeBinding> bound]) {
+ var ref = templateBind(this.ref);
+ var content = ref.content;
+ // Dart note: we store _bindingMap on the TemplateBindExtension instead of
+ // the "content" because we already have an expando for it.
+ var map = ref._bindingMap;
+ if (map == null) {
+ // TODO(rafaelw): Setup a MutationObserver on content to detect
+ // when the instanceMap is invalid.
+ map = new _InstanceBindingMap(content, delegate);
+ ref._bindingMap = map;
+ }
- _addBindings(instance, model, delegate);
+ var instance = map.hasSubTemplate
+ ? _deepCloneIgnoreTemplateContent(content)
+ : content.clone(true);
+
+ _addMapBindings(instance, map, model, delegate, bound);
+ // TODO(rafaelw): We can do this more lazily, but setting a sentinel
+ // in the parent of the template element, and creating it when it's
+ // asked for by walking back to find the iterating template.
_addTemplateInstanceRecord(instance, model);
return instance;
}
@@ -57,6 +138,16 @@
_ensureSetModelScheduled();
}
+ static Node _deepCloneIgnoreTemplateContent(Node node) {
+ var clone = node.clone(false); // Shallow clone.
+ if (isSemanticTemplate(clone)) return clone;
+
+ for (var c = node.firstChild; c != null; c = c.nextNode) {
+ clone.append(_deepCloneIgnoreTemplateContent(c));
+ }
+ return clone;
+ }
+
/**
* The binding delegate which is inherited through the tree. It can be used
* to configure custom syntax for `{{bindings}}` inside this template.
@@ -138,7 +229,7 @@
if (!isNative && _isAttributeTemplate(_node)) {
if (instanceRef != null) {
- // TODO(jmesserly): this is just an assert in MDV.
+ // TODO(jmesserly): this is just an assert in TemplateBinding.
throw new ArgumentError('instanceRef should not be supplied for '
'attribute templates.');
}
@@ -269,48 +360,64 @@
static bool _initStyles;
+ // This is to replicate template_element.css
+ // TODO(jmesserly): move this to an opt-in CSS file?
static void _injectStylesheet() {
if (_initStyles == true) return;
_initStyles = true;
- var style = new StyleElement();
- style.text = r'''
-template,
-thead[template],
-tbody[template],
-tfoot[template],
-th[template],
-tr[template],
-td[template],
-caption[template],
-colgroup[template],
-col[template],
-option[template] {
- display: none;
-}''';
+ var style = new StyleElement()
+ ..text = '$_allTemplatesSelectors { display: none; }';
document.head.append(style);
}
}
-class _TemplateBinding extends NodeBinding {
+// TODO(jmesserly): https://github.com/polymer/templatebinding uses
+// TemplateIterator as the binding. This is a nice performance optimization,
+// however it means it doesn't share any of the reflective APIs with
+// NodeBinding: https://github.com/Polymer/TemplateBinding/issues/147
+class _TemplateBinding implements NodeBinding {
TemplateBindExtension _ext;
+ Object _model;
+ final String property;
+ final String path;
- // TODO(jmesserly): MDV uses TemplateIterator as the node, see:
- // https://github.com/Polymer/mdv/issues/127
- _TemplateBinding(ext, name, model, path)
- : _ext = ext, super(ext._node, name, model, path) {
- _ext._templateIterator.inputs.bind(property, model, this.path);
+ Node get node => _ext._node;
+
+ get model => _model;
+
+ bool get closed => _ext == null;
+
+ get value => _observer.value;
+
+ set value(newValue) {
+ _observer.value = newValue;
}
- // These are no-ops because we don't use the underlying PathObserver.
- void _observePath() {}
+ // No need to cache this since we only have it to support get/set value.
+ get _observer {
+ if ((_model is PathObserver || _model is CompoundPathObserver) &&
+ path == 'value') {
+ return _model;
+ }
+ return new PathObserver(_model, path);
+ }
+
+ _TemplateBinding(this._ext, this.property, this._model, this.path);
+
void valueChanged(newValue) {}
+ sanitizeBoundValue(value) => value == null ? '' : '$value';
+
void close() {
if (closed) return;
- var templateIterator = _ext._templateIterator;
- if (templateIterator != null) templateIterator.inputs.unbind(property);
- super.close();
+
+ // TODO(jmesserly): unlike normal NodeBinding.close methods this will remove
+ // the binding from _node.bindings. Is that okay?
+ _ext.unbind(property);
+
+ _model = null;
+ _ext = null;
}
}
diff --git a/pkg/template_binding/lib/src/template_iterator.dart b/pkg/template_binding/lib/src/template_iterator.dart
index 981adf5..878e2e7 100644
--- a/pkg/template_binding/lib/src/template_iterator.dart
+++ b/pkg/template_binding/lib/src/template_iterator.dart
@@ -17,32 +17,23 @@
// See: https://github.com/polymer/TemplateBinding/issues/59
bool _toBoolean(value) => null != value && false != value;
-Node _createDeepCloneAndDecorateTemplates(Node node, BindingDelegate delegate) {
- var clone = node.clone(false); // Shallow clone.
- if (isSemanticTemplate(clone)) {
- TemplateBindExtension.decorate(clone, node);
- if (delegate != null) {
- templateBindFallback(clone)._bindingDelegate = delegate;
- }
+List _getBindings(Node node, BindingDelegate delegate) {
+ if (node is Element) {
+ return _parseAttributeBindings(node, delegate);
}
- for (var c = node.firstChild; c != null; c = c.nextNode) {
- clone.append(_createDeepCloneAndDecorateTemplates(c, delegate));
+ if (node is Text) {
+ var tokens = _parseMustaches(node.text, 'text', node, delegate);
+ if (tokens != null) return ['text', tokens];
}
- return clone;
+
+ return null;
}
void _addBindings(Node node, model, [BindingDelegate delegate]) {
- List bindings = null;
- if (node is Element) {
- bindings = _parseAttributeBindings(node);
- } else if (node is Text) {
- var tokens = _parseMustacheTokens(node.text);
- if (tokens != null) bindings = ['text', tokens];
- }
-
+ var bindings = _getBindings(node, delegate);
if (bindings != null) {
- _processBindings(bindings, node, model, delegate);
+ _processBindings(bindings, node, model);
}
for (var c = node.firstChild; c != null; c = c.nextNode) {
@@ -50,23 +41,34 @@
}
}
-List _parseAttributeBindings(Element element) {
+
+List _parseAttributeBindings(Element element, BindingDelegate delegate) {
var bindings = null;
var ifFound = false;
var bindFound = false;
var isTemplateNode = isSemanticTemplate(element);
element.attributes.forEach((name, value) {
+ // Allow bindings expressed in attributes to be prefixed with underbars.
+ // We do this to allow correct semantics for browsers that don't implement
+ // <template> where certain attributes might trigger side-effects -- and
+ // for IE which sanitizes certain attributes, disallowing mustache
+ // replacements in their text.
+ while (name[0] == '_') {
+ name = name.substring(1);
+ }
+
if (isTemplateNode) {
if (name == 'if') {
ifFound = true;
+ if (value == '') value = '{{}}'; // Accept 'naked' if.
} else if (name == 'bind' || name == 'repeat') {
bindFound = true;
- if (value == '') value = '{{}}';
+ if (value == '') value = '{{}}'; // Accept 'naked' bind & repeat.
}
}
- var tokens = _parseMustacheTokens(value);
+ var tokens = _parseMustaches(value, name, element, delegate);
if (tokens != null) {
if (bindings == null) bindings = [];
bindings..add(name)..add(tokens);
@@ -76,90 +78,70 @@
// Treat <template if> as <template bind if>
if (ifFound && !bindFound) {
if (bindings == null) bindings = [];
- bindings..add('bind')..add(_parseMustacheTokens('{{}}'));
+ bindings..add('bind')
+ ..add(_parseMustaches('{{}}', 'bind', element, delegate));
}
return bindings;
}
void _processBindings(List bindings, Node node, model,
- BindingDelegate delegate) {
+ [List<NodeBinding> bound]) {
for (var i = 0; i < bindings.length; i += 2) {
- _setupBinding(node, bindings[i], bindings[i + 1], model, delegate);
- }
-}
-
-void _setupBinding(Node node, String name, List tokens, model,
- BindingDelegate delegate) {
-
- if (_isSimpleBinding(tokens)) {
- _bindOrDelegate(node, name, model, tokens[1], delegate);
- return;
- }
-
- // TODO(jmesserly): MDV caches the closure on the tokens, but I'm not sure
- // why they do that instead of just caching the entire CompoundBinding object
- // and unbindAll then bind to the new model.
- var replacementBinding = new CompoundBinding()
- ..scheduled = true
- ..combinator = (values) {
- var newValue = new StringBuffer();
-
- for (var i = 0, text = true; i < tokens.length; i++, text = !text) {
- if (text) {
- newValue.write(tokens[i]);
- } else {
- var value = values[i];
- if (value != null) {
- newValue.write(value);
+ var name = bindings[i];
+ var tokens = bindings[i + 1];
+ var bindingModel = model;
+ var bindingPath = tokens.tokens[1];
+ if (tokens.hasOnePath) {
+ var delegateFn = tokens.tokens[2];
+ if (delegateFn != null) {
+ var delegateBinding = delegateFn(model, node);
+ if (delegateBinding != null) {
+ bindingModel = delegateBinding;
+ bindingPath = 'value';
}
}
+
+ if (!tokens.isSimplePath) {
+ bindingModel = new PathObserver(bindingModel, bindingPath,
+ computeValue: tokens.combinator);
+ bindingPath = 'value';
+ }
+ } else {
+ var observer = new CompoundPathObserver(computeValue: tokens.combinator);
+ for (var j = 1; j < tokens.tokens.length; j += 3) {
+ var subModel = model;
+ var subPath = tokens.tokens[j];
+ var delegateFn = tokens.tokens[j + 1];
+ var delegateBinding = delegateFn != null ?
+ delegateFn(subModel, node) : null;
+
+ if (delegateBinding != null) {
+ subModel = delegateBinding;
+ subPath = 'value';
+ }
+
+ observer.addPath(subModel, subPath);
+ }
+
+ observer.start();
+ bindingModel = observer;
+ bindingPath = 'value';
}
- return newValue.toString();
- };
-
- for (var i = 1; i < tokens.length; i += 2) {
- // TODO(jmesserly): not sure if this index is correct. See my comment here:
- // https://github.com/Polymer/mdv/commit/f1af6fe683fd06eed2a7a7849f01c227db12cda3#L0L1035
- _bindOrDelegate(replacementBinding, i, model, tokens[i], delegate);
- }
-
- replacementBinding.resolve();
-
- nodeBind(node).bind(name, replacementBinding, 'value');
-}
-
-void _bindOrDelegate(node, name, model, String path,
- BindingDelegate delegate) {
-
- if (delegate != null) {
- var delegateBinding = delegate.getBinding(model, path, name, node);
- if (delegateBinding != null) {
- model = delegateBinding;
- path = 'value';
- }
- }
-
- if (node is CompoundBinding) {
- node.bind(name, model, path);
- } else {
- nodeBind(node).bind(name, model, path);
+ var binding = nodeBind(node).bind(name, bindingModel, bindingPath);
+ if (bound != null) bound.add(binding);
}
}
-/** True if and only if [tokens] is of the form `['', path, '']`. */
-bool _isSimpleBinding(List<String> tokens) =>
- tokens.length == 3 && tokens[0].isEmpty && tokens[2].isEmpty;
-
/**
* Parses {{ mustache }} bindings.
*
- * Returns null if there are no matches. Otherwise returns
- * [TEXT, (PATH, TEXT)+] if there is at least one mustache.
+ * Returns null if there are no matches. Otherwise returns the parsed tokens.
*/
-List<String> _parseMustacheTokens(String s) {
+_MustacheTokens _parseMustaches(String s, String name, Node node,
+ BindingDelegate delegate) {
if (s.isEmpty) return null;
var tokens = null;
@@ -172,18 +154,63 @@
if (endIndex < 0) {
if (tokens == null) return null;
- tokens.add(s.substring(lastIndex));
+ tokens.add(s.substring(lastIndex)); // TEXT
break;
}
- if (tokens == null) tokens = <String>[];
+ if (tokens == null) tokens = [];
tokens.add(s.substring(lastIndex, startIndex)); // TEXT
- tokens.add(s.substring(startIndex + 2, endIndex).trim()); // PATH
+ var pathString = s.substring(startIndex + 2, endIndex).trim();
+ tokens.add(pathString); // PATH
+ var delegateFn = delegate == null ? null :
+ delegate.prepareBinding(pathString, name, node);
+ tokens.add(delegateFn);
+
lastIndex = endIndex + 2;
}
if (lastIndex == length) tokens.add('');
- return tokens;
+
+ return new _MustacheTokens(tokens);
+}
+
+class _MustacheTokens {
+ bool get hasOnePath => tokens.length == 4;
+ bool get isSimplePath => hasOnePath && tokens[0] == '' && tokens[3] == '';
+
+ /** [TEXT, (PATH, TEXT, DELEGATE_FN)+] if there is at least one mustache. */
+ // TODO(jmesserly): clean up the type here?
+ final List tokens;
+
+ // Dart note: I think this is cached in JavaScript to avoid an extra
+ // allocation per template instance. Seems reasonable, so we do the same.
+ Function _combinator;
+ Function get combinator => _combinator;
+
+ _MustacheTokens(this.tokens) {
+ // Should be: [TEXT, (PATH, TEXT, DELEGATE_FN)+].
+ assert((tokens.length + 2) % 3 == 0);
+
+ _combinator = hasOnePath ? _singleCombinator : _listCombinator;
+ }
+
+ // Dart note: split "combinator" into the single/list variants, so the
+ // argument can be typed.
+ String _singleCombinator(Object value) {
+ if (value == null) value = '';
+ return '${tokens[0]}$value${tokens[3]}';
+ }
+
+ String _listCombinator(List<Object> values) {
+ var newValue = new StringBuffer(tokens[0]);
+ for (var i = 1; i < tokens.length; i += 3) {
+ var value = values[(i - 1) ~/ 3];
+ if (value != null) newValue.write(value);
+ newValue.write(tokens[i + 2]);
+ }
+
+ return newValue.toString();
+ }
}
void _addTemplateInstanceRecord(fragment, model) {
@@ -201,106 +228,150 @@
}
}
-
class _TemplateIterator {
- final Element _templateElement;
- final List<Node> terminators = [];
- CompoundBinding inputs;
+ final TemplateBindExtension _templateExt;
+
+ /**
+ * Flattened array of tuples:
+ * <instanceTerminatorNode, [bindingsSetupByInstance]>
+ */
+ final List terminators = [];
List iteratedValue;
bool closed = false;
+ bool depsChanging = false;
- StreamSubscription _sub;
+ bool hasRepeat = false, hasBind = false, hasIf = false;
+ Object repeatModel, bindModel, ifModel;
+ String repeatPath, bindPath, ifPath;
- _TemplateIterator(this._templateElement) {
- inputs = new CompoundBinding(resolveInputs);
- }
+ StreamSubscription _valueSub, _arraySub;
- resolveInputs(Map values) {
- if (closed) return;
+ bool _initPrepareFunctions = false;
+ PrepareInstanceModelFunction _instanceModelFn;
+ PrepareInstancePositionChangedFunction _instancePositionChangedFn;
- if (values.containsKey('if') && !_toBoolean(values['if'])) {
- valueChanged(null);
- } else if (values.containsKey('repeat')) {
- valueChanged(values['repeat']);
- } else if (values.containsKey('bind') || values.containsKey('if')) {
- valueChanged([values['bind']]);
- } else {
- valueChanged(null);
+ _TemplateIterator(this._templateExt);
+
+ Element get _templateElement => _templateExt._node;
+
+ resolve() {
+ depsChanging = false;
+
+ if (_valueSub != null) {
+ _valueSub.cancel();
+ _valueSub = null;
}
- // We don't return a value to the CompoundBinding; instead we skip a hop and
- // call valueChanged directly.
- return null;
+
+ if (!hasRepeat && !hasBind) {
+ _valueChanged(null);
+ return;
+ }
+
+ final model = hasRepeat ? repeatModel : bindModel;
+ final path = hasRepeat ? repeatPath : bindPath;
+
+ var valueObserver;
+ if (!hasIf) {
+ valueObserver = new PathObserver(model, path,
+ computeValue: hasRepeat ? null : (x) => [x]);
+ } else {
+ // TODO(jmesserly): I'm not sure if closing over this is necessary for
+ // correctness. It does seem useful if the valueObserver gets fired after
+ // hasRepeat has changed, due to async nature of things.
+ final isRepeat = hasRepeat;
+
+ valueFn(List values) {
+ var modelValue = values[0];
+ var ifValue = values[1];
+ if (!_toBoolean(ifValue)) return null;
+ return isRepeat ? modelValue : [ modelValue ];
+ }
+
+ valueObserver = new CompoundPathObserver(computeValue: valueFn)
+ ..addPath(model, path)
+ ..addPath(ifModel, ifPath)
+ ..start();
+ }
+
+ _valueSub = valueObserver.changes.listen(
+ (r) => _valueChanged(r.last.newValue));
+ _valueChanged(valueObserver.value);
}
- void valueChanged(value) {
- if (value is! List) value = null;
-
+ void _valueChanged(newValue) {
var oldValue = iteratedValue;
unobserve();
- iteratedValue = value;
- if (iteratedValue is Observable) {
- _sub = (iteratedValue as Observable).changes.listen(_handleChanges);
+ if (newValue is List) {
+ iteratedValue = newValue;
+ } else if (newValue is Iterable) {
+ // Dart note: we support Iterable by calling toList.
+ // But we need to be careful to observe the original iterator if it
+ // supports that.
+ iteratedValue = (newValue as Iterable).toList();
+ } else {
+ iteratedValue = null;
+ }
+
+ if (iteratedValue != null && newValue is Observable) {
+ _arraySub = (newValue as Observable).changes.listen(
+ _handleSplices);
}
var splices = calculateSplices(
iteratedValue != null ? iteratedValue : [],
oldValue != null ? oldValue : []);
- if (splices.length > 0) _handleChanges(splices);
-
- if (inputs.length == 0) {
- close();
- templateBindFallback(_templateElement)._templateIterator = null;
- }
+ if (splices.isNotEmpty) _handleSplices(splices);
}
Node getTerminatorAt(int index) {
if (index == -1) return _templateElement;
- var terminator = terminators[index];
- if (isSemanticTemplate(terminator) &&
- !identical(terminator, _templateElement)) {
- var subIterator = templateBindFallback(terminator)._templateIterator;
- if (subIterator != null) {
- return subIterator.getTerminatorAt(subIterator.terminators.length - 1);
- }
+ var terminator = terminators[index * 2];
+ if (!isSemanticTemplate(terminator) ||
+ identical(terminator, _templateElement)) {
+ return terminator;
}
- return terminator;
+ var subIter = templateBindFallback(terminator)._iterator;
+ if (subIter == null) return terminator;
+
+ return subIter.getTerminatorAt(subIter.terminators.length ~/ 2 - 1);
}
+ // TODO(rafaelw): If we inserting sequences of instances we can probably
+ // avoid lots of calls to getTerminatorAt(), or cache its result.
void insertInstanceAt(int index, DocumentFragment fragment,
- List<Node> instanceNodes) {
+ List<Node> instanceNodes, List<NodeBinding> bound) {
var previousTerminator = getTerminatorAt(index - 1);
var terminator = null;
if (fragment != null) {
terminator = fragment.lastChild;
- } else if (instanceNodes.length > 0) {
+ } else if (instanceNodes != null && instanceNodes.isNotEmpty) {
terminator = instanceNodes.last;
}
if (terminator == null) terminator = previousTerminator;
- terminators.insert(index, terminator);
-
+ terminators.insertAll(index * 2, [terminator, bound]);
var parent = _templateElement.parentNode;
var insertBeforeNode = previousTerminator.nextNode;
if (fragment != null) {
parent.insertBefore(fragment, insertBeforeNode);
- return;
- }
-
- for (var node in instanceNodes) {
- parent.insertBefore(node, insertBeforeNode);
+ } else if (instanceNodes != null) {
+ for (var node in instanceNodes) {
+ parent.insertBefore(node, insertBeforeNode);
+ }
}
}
- List<Node> extractInstanceAt(int index) {
+ _BoundNodes extractInstanceAt(int index) {
var instanceNodes = <Node>[];
var previousTerminator = getTerminatorAt(index - 1);
var terminator = getTerminatorAt(index);
- terminators.removeAt(index);
+ var bound = terminators[index * 2 + 1];
+ terminators.removeRange(index * 2, index * 2 + 2);
var parent = _templateElement.parentNode;
while (terminator != previousTerminator) {
@@ -309,45 +380,41 @@
node.remove();
instanceNodes.add(node);
}
- return instanceNodes;
+ return new _BoundNodes(instanceNodes, bound);
}
- getInstanceModel(model, BindingDelegate delegate) {
- if (delegate != null) {
- return delegate.getInstanceModel(_templateElement, model);
- }
- return model;
- }
-
- DocumentFragment getInstanceFragment(model, BindingDelegate delegate) {
- return templateBind(_templateElement).createInstance(model, delegate);
- }
-
- void _handleChanges(Iterable<ChangeRecord> splices) {
+ void _handleSplices(Iterable<ChangeRecord> splices) {
if (closed) return;
splices = splices.where((s) => s is ListChangeRecord);
- var template = _templateElement;
- var delegate = templateBind(template).bindingDelegate;
+ final template = _templateElement;
+ final delegate = _templateExt._self.bindingDelegate;
if (template.parentNode == null || template.ownerDocument.window == null) {
close();
- // TODO(jmesserly): MDV calls templateIteratorTable.delete(this) here,
- // but I think that's a no-op because only nodes are used as keys.
- // See https://github.com/Polymer/mdv/pull/114.
return;
}
- var instanceCache = new HashMap(equals: identical);
+ // Dart note: the JavaScript code relies on the distinction between null
+ // and undefined to track whether the functions are prepared. We use a bool.
+ if (!_initPrepareFunctions) {
+ _initPrepareFunctions = true;
+ if (delegate != null) {
+ _instanceModelFn = delegate.prepareInstanceModel(template);
+ _instancePositionChangedFn =
+ delegate.prepareInstancePositionChanged(template);
+ }
+ }
+
+ var instanceCache = new HashMap<Object, _BoundNodes>(equals: identical);
var removeDelta = 0;
for (var splice in splices) {
for (int i = 0; i < splice.removedCount; i++) {
- var instanceNodes = extractInstanceAt(splice.index + removeDelta);
- if (instanceNodes.length == 0) continue;
- var model = nodeBindFallback(instanceNodes.first)
- ._templateInstance.model;
- instanceCache[model] = instanceNodes;
+ var instance = extractInstanceAt(splice.index + removeDelta);
+ if (instance.nodes.length == 0) continue;
+ var model = nodeBind(instance.nodes.first).templateInstance.model;
+ instanceCache[model] = instance;
}
removeDelta -= splice.addedCount;
@@ -360,51 +427,109 @@
var model = iteratedValue[addIndex];
var fragment = null;
- var instanceNodes = instanceCache.remove(model);
- if (instanceNodes == null) {
- var actualModel = getInstanceModel(model, delegate);
- fragment = getInstanceFragment(actualModel, delegate);
+ var instance = instanceCache.remove(model);
+ List bound;
+ List instanceNodes = null;
+ if (instance != null && instance.nodes.isNotEmpty) {
+ bound = instance.bound;
+ instanceNodes = instance.nodes;
+ } else {
+ bound = [];
+ if (_instanceModelFn != null) {
+ model = _instanceModelFn(model);
+ }
+ if (model != null) {
+ fragment = _templateExt.createInstance(model, delegate, bound);
+ }
}
- insertInstanceAt(addIndex, fragment, instanceNodes);
+ insertInstanceAt(addIndex, fragment, instanceNodes, bound);
}
}
- for (var instanceNodes in instanceCache.values) {
- instanceNodes.forEach(_unbindAllRecursively);
+ for (var instance in instanceCache.values) {
+ closeInstanceBindings(instance.bound);
+ }
+
+ if (_instancePositionChangedFn != null) reportInstancesMoved(splices);
+ }
+
+ void reportInstanceMoved(int index) {
+ var previousTerminator = getTerminatorAt(index - 1);
+ var terminator = getTerminatorAt(index);
+ if (identical(previousTerminator, terminator)) {
+ return; // instance has zero nodes.
+ }
+
+ // We must use the first node of the instance, because any subsequent
+ // nodes may have been generated by sub-templates.
+ // TODO(rafaelw): This is brittle WRT instance mutation -- e.g. if the
+ // first node was removed by script.
+ var instance = nodeBind(previousTerminator.nextNode).templateInstance;
+ _instancePositionChangedFn(instance, index);
+ }
+
+ void reportInstancesMoved(Iterable<ChangeRecord> splices) {
+ var index = 0;
+ var offset = 0;
+ for (ListChangeRecord splice in splices) {
+ if (offset != 0) {
+ while (index < splice.index) {
+ reportInstanceMoved(index);
+ index++;
+ }
+ } else {
+ index = splice.index;
+ }
+
+ while (index < splice.index + splice.addedCount) {
+ reportInstanceMoved(index);
+ index++;
+ }
+
+ offset += splice.addedCount - splice.removedCount;
+ }
+
+ if (offset == 0) return;
+
+ var length = terminators.length ~/ 2;
+ while (index < length) {
+ reportInstanceMoved(index);
+ index++;
}
}
+ void closeInstanceBindings(List<NodeBinding> bound) {
+ for (var binding in bound) binding.close();
+ }
+
void unobserve() {
- if (_sub == null) return;
- _sub.cancel();
- _sub = null;
+ if (_arraySub == null) return;
+ _arraySub.cancel();
+ _arraySub = null;
}
void close() {
if (closed) return;
unobserve();
- inputs.close();
+ for (var i = 1; i < terminators.length; i += 2) {
+ closeInstanceBindings(terminators[i]);
+ }
+
terminators.clear();
+ if (_valueSub != null) {
+ _valueSub.cancel();
+ _valueSub = null;
+ }
+ _templateExt._iterator = null;
closed = true;
}
+}
- static void _unbindAllRecursively(Node node) {
- var nodeExt = nodeBindFallback(node);
- nodeExt._templateInstance = null;
- if (isSemanticTemplate(node)) {
- // Make sure we stop observing when we remove an element.
- var templateIterator = nodeExt._templateIterator;
- if (templateIterator != null) {
- templateIterator.close();
- nodeExt._templateIterator = null;
- }
- }
-
- nodeBind(node).unbindAll();
- for (var c = node.firstChild; c != null; c = c.nextNode) {
- _unbindAllRecursively(c);
- }
- }
+// Dart note: the JavaScript version just puts an expando on the array.
+class _BoundNodes {
+ final List<Node> nodes;
+ final List<NodeBinding> bound;
+ _BoundNodes(this.nodes, this.bound);
}
diff --git a/pkg/template_binding/lib/template_binding.dart b/pkg/template_binding/lib/template_binding.dart
index c8bd3b6..b1ef7b5 100644
--- a/pkg/template_binding/lib/template_binding.dart
+++ b/pkg/template_binding/lib/template_binding.dart
@@ -24,11 +24,17 @@
import 'dart:svg' show SvgSvgElement;
import 'package:observe/observe.dart';
+import 'src/binding_delegate.dart';
+import 'src/node_binding.dart';
import 'src/list_diff.dart' show calculateSplices, ListChangeDelta;
+export 'src/binding_delegate.dart';
+export 'src/node_binding.dart' show NodeBinding;
+
part 'src/element.dart';
part 'src/input_bindings.dart';
part 'src/input_element.dart';
+part 'src/instance_binding_map.dart';
part 'src/node.dart';
part 'src/select_element.dart';
part 'src/template.dart';
@@ -141,7 +147,7 @@
* and COL), OPTION, and OPTGROUP.
*/
bool isSemanticTemplate(Node n) => n is Element &&
- ((n as Element).localName == 'template' || _isAttributeTemplate(n));
+ (n.localName == 'template' || _isAttributeTemplate(n));
// TODO(jmesserly): const set would be better
const _SEMANTIC_TEMPLATE_TAGS = const {
diff --git a/pkg/template_binding/test/analyzer_test.dart b/pkg/template_binding/test/analyzer_test.dart
deleted file mode 100644
index 5b47d43..0000000
--- a/pkg/template_binding/test/analyzer_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library template_binding.test.analyzer_test;
-
-import 'dart:html';
-import 'package:template_binding/template_binding.dart';
-
-// @static-clean
-
-// This test ensures template_binding compiles without errors.
-void main() {
- // To make analyzer happy about unused imports.
- nodeBind(document);
-}
diff --git a/pkg/template_binding/test/binding_syntax.dart b/pkg/template_binding/test/binding_syntax.dart
new file mode 100644
index 0000000..384dbf9
--- /dev/null
+++ b/pkg/template_binding/test/binding_syntax.dart
@@ -0,0 +1,206 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library template_binding.test.binding_syntax;
+
+import 'dart:collection';
+import 'dart:html';
+import 'package:template_binding/template_binding.dart';
+import 'package:observe/observe.dart';
+import 'package:unittest/html_config.dart';
+import 'package:unittest/unittest.dart';
+import 'utils.dart';
+
+// Note: this test is executed by template_element_test.dart
+
+syntaxTests(FooBarModel fooModel([foo, bar])) {
+ observeTest('prepareBinding', () {
+ var model = fooModel('bar');
+ var testSyntax = new TestBindingSyntax();
+ var div = createTestHtml(
+ '<template bind>{{ foo }}'
+ '<template bind>{{ foo }}</template>'
+ '</template>');
+ recursivelySetTemplateModel(div, model, testSyntax);
+ performMicrotaskCheckpoint();
+ expect(div.nodes.length, 4);
+ expect(div.nodes.last.text, 'bar');
+ expect(div.nodes[2].tagName, 'TEMPLATE');
+ expect(testSyntax.log, [
+ ['prepare', '', 'bind', 'TEMPLATE'],
+ ['bindFn', model, 'TEMPLATE', 0],
+ ['prepare', 'foo', 'text', 'TEXT'],
+ ['prepare', '', 'bind', 'TEMPLATE'],
+ ['bindFn', model, 'TEXT', 2],
+ ['bindFn', model, 'TEMPLATE', 3],
+ ['prepare', 'foo', 'text', 'TEXT'],
+ ['bindFn', model, 'TEXT', 6],
+ ]);
+ });
+
+ observeTest('prepareInstanceModel', () {
+ var model = toObservable([fooModel(1), fooModel(2), fooModel(3)]);
+
+ var testSyntax = new TestModelSyntax();
+ testSyntax.altModels.addAll([fooModel('a'), fooModel('b'), fooModel('c')]);
+
+ var div = createTestHtml('<template repeat>{{ foo }}</template>');
+
+ var template = div.nodes[0];
+ recursivelySetTemplateModel(div, model, testSyntax);
+ performMicrotaskCheckpoint();
+
+ expect(div.nodes.length, 4);
+ expect(div.nodes[0].tagName, 'TEMPLATE');
+ expect(div.nodes[1].text, 'a');
+ expect(div.nodes[2].text, 'b');
+ expect(div.nodes[3].text, 'c');
+
+ expect(testSyntax.log, [
+ ['prepare', template],
+ ['bindFn', model[0]],
+ ['bindFn', model[1]],
+ ['bindFn', model[2]],
+ ]);
+ });
+
+ observeTest('prepareInstanceModel - reorder instances', () {
+ var model = toObservable([0, 1, 2]);
+
+ var div = createTestHtml('<template repeat>{{}}</template>');
+ var template = div.firstChild;
+ var delegate = new TestInstanceModelSyntax();
+
+ recursivelySetTemplateModel(div, model, delegate);
+ performMicrotaskCheckpoint();
+ expect(delegate.prepareCount, 1);
+ expect(delegate.callCount, 3);
+
+ // Note: intentionally mutate in place.
+ model.replaceRange(0, model.length, model.reversed.toList());
+ performMicrotaskCheckpoint();
+ expect(delegate.prepareCount, 1);
+ expect(delegate.callCount, 3);
+ });
+
+ observeTest('prepareInstancePositionChanged', () {
+ var model = toObservable(['a', 'b', 'c']);
+
+ var div = createTestHtml('<template repeat>{{}}</template>');
+ var delegate = new TestPositionChangedSyntax();
+
+ var template = div.nodes[0];
+ recursivelySetTemplateModel(div, model, delegate);
+ performMicrotaskCheckpoint();
+
+ expect(div.nodes.length, 4);
+ expect(div.nodes[0].tagName, 'TEMPLATE');
+ expect(div.nodes[1].text, 'a');
+ expect(div.nodes[2].text, 'b');
+ expect(div.nodes[3].text, 'c');
+
+ expect(delegate.log, [
+ ['prepare', template],
+ ['bindFn', model[0], 0],
+ ['bindFn', model[1], 1],
+ ['bindFn', model[2], 2],
+ ]);
+
+ delegate.log.clear();
+
+ model.removeAt(1);
+ performMicrotaskCheckpoint();
+
+ expect(delegate.log, [['bindFn', 'c', 1]], reason: 'removed item');
+
+ expect(div.nodes.skip(1).map((n) => n.text), ['a', 'c']);
+ });
+
+ observeTest('Basic', () {
+ var model = fooModel(2, 4);
+ var div = createTestHtml(
+ '<template bind>'
+ '{{ foo }} + {{ 2x: bar }} + {{ 4x: bar }}</template>');
+ recursivelySetTemplateModel(div, model, new TimesTwoSyntax());
+ performMicrotaskCheckpoint();
+ expect(div.nodes.length, 2);
+ expect(div.nodes.last.text, '2 + 8 + ');
+
+ model.foo = 4;
+ model.bar = 8;
+ performMicrotaskCheckpoint();
+ expect(div.nodes.last.text, '4 + 16 + ');
+ });
+
+ // Note: issue-141 test not included here as it's not related to the
+ // BindingDelegate
+}
+
+// TODO(jmesserly): mocks would be cleaner here.
+
+class TestBindingSyntax extends BindingDelegate {
+ var log = [];
+
+ prepareBinding(String path, String name, Node node) {
+ var tagName = node is Element ? node.tagName : 'TEXT';
+ int id = log.length;
+ log.add(['prepare', path, name, tagName]);
+ final outerNode = node;
+ return (model, node) {
+ var tagName = node is Element ? node.tagName : 'TEXT';
+ log.add(['bindFn', model, tagName, id]);
+ };
+ }
+}
+
+class TestModelSyntax extends BindingDelegate {
+ var log = [];
+ var altModels = new ListQueue();
+
+ prepareInstanceModel(template) {
+ log.add(['prepare', template]);
+ return (model) {
+ log.add(['bindFn', model]);
+ return altModels.removeFirst();
+ };
+ }
+}
+
+class TestInstanceModelSyntax extends BindingDelegate {
+ int prepareCount = 0;
+ int callCount = 0;
+ prepareInstanceModel(template) {
+ prepareCount++;
+ return (model) {
+ callCount++;
+ return model;
+ };
+ }
+}
+
+
+class TestPositionChangedSyntax extends BindingDelegate {
+ var log = [];
+
+ prepareInstancePositionChanged(template) {
+ int id = log.length;
+ log.add(['prepare', template]);
+ return (templateInstance, index) {
+ log.add(['bindFn', templateInstance.model, index]);
+ };
+ }
+}
+
+
+class TimesTwoSyntax extends BindingDelegate {
+ prepareBinding(path, name, node) {
+ path = path.trim();
+ if (!path.startsWith('2x:')) return null;
+
+ path = path.substring(3);
+ return (model, _) {
+ return new PathObserver(model, path, computeValue: (x) => 2 * x);
+ };
+ }
+}
diff --git a/pkg/template_binding/test/binding_syntax_test.dart b/pkg/template_binding/test/binding_syntax_test.dart
deleted file mode 100644
index b8b6283..0000000
--- a/pkg/template_binding/test/binding_syntax_test.dart
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library template_binding.test.binding_syntax_test;
-
-import 'dart:collection';
-import 'dart:html';
-import 'package:template_binding/template_binding.dart';
-import 'package:observe/observe.dart';
-import 'package:unittest/html_config.dart';
-import 'package:unittest/unittest.dart';
-import 'utils.dart';
-
-// Note: this file ported from
-// https://github.com/toolkitchen/mdv/blob/master/tests/syntax.js
-
-main() {
- useHtmlConfiguration();
-
- group('Syntax FooBarModel', () {
- syntaxTests(([f, b]) => new FooBarModel(f, b));
- });
- group('Syntax FooBarNotifyModel', () {
- syntaxTests(([f, b]) => new FooBarNotifyModel(f, b));
- });
-}
-
-syntaxTests(FooBarModel fooModel([foo, bar])) {
- setUp(() {
- document.body.append(testDiv = new DivElement());
- });
-
- tearDown(() {
- testDiv.remove();
- testDiv = null;
- });
-
- observeTest('Registration', () {
- var model = fooModel('bar');
- var testSyntax = new TestBindingSyntax();
- var div = createTestHtml('<template bind>{{ foo }}'
- '<template bind>{{ foo }}</template></template>');
- recursivelySetTemplateModel(div, model, testSyntax);
- performMicrotaskCheckpoint();
- expect(div.nodes.length, 4);
- expect(div.nodes.last.text, 'bar');
- expect(div.nodes[2].tagName, 'TEMPLATE');
- expect(testSyntax.log, [
- [model, '', 'bind', 'TEMPLATE'],
- [model, 'foo', 'text', null],
- [model, '', 'bind', 'TEMPLATE'],
- [model, 'foo', 'text', null],
- ]);
- });
-
- observeTest('getInstanceModel', () {
- var model = toObservable([fooModel(1), fooModel(2), fooModel(3)]);
-
- var testSyntax = new TestModelSyntax();
- testSyntax.altModels.addAll([fooModel('a'), fooModel('b'), fooModel('c')]);
-
- var div = createTestHtml('<template repeat>{{ foo }}</template>');
-
- var template = div.nodes[0];
- recursivelySetTemplateModel(div, model, testSyntax);
- performMicrotaskCheckpoint();
-
- expect(div.nodes.length, 4);
- expect(div.nodes[0].tagName, 'TEMPLATE');
- expect(div.nodes[1].text, 'a');
- expect(div.nodes[2].text, 'b');
- expect(div.nodes[3].text, 'c');
-
- expect(testSyntax.log, [
- [template, model[0]],
- [template, model[1]],
- [template, model[2]],
- ]);
- });
-
- observeTest('getInstanceModel - reorder instances', () {
- var model = toObservable([0, 1, 2]);
-
- var div = createTestHtml('<template repeat syntax="Test">{{}}</template>');
- var template = div.firstChild;
- var delegate = new TestInstanceModelSyntax();
-
- recursivelySetTemplateModel(div, model, delegate);
- performMicrotaskCheckpoint();
- expect(delegate.count, 3);
-
- // Note: intentionally mutate in place.
- model.replaceRange(0, model.length, model.reversed.toList());
- performMicrotaskCheckpoint();
- expect(delegate.count, 3);
- });
-
- observeTest('Basic', () {
- var model = fooModel(2, 4);
- var div = createTestHtml(
- '<template bind syntax="2x">'
- '{{ foo }} + {{ 2x: bar }} + {{ 4x: bar }}</template>');
- recursivelySetTemplateModel(div, model, new TimesTwoSyntax());
- performMicrotaskCheckpoint();
- expect(div.nodes.length, 2);
- expect(div.nodes.last.text, '2 + 8 + ');
-
- model.foo = 4;
- model.bar = 8;
- performMicrotaskCheckpoint();
- expect(div.nodes.last.text, '4 + 16 + ');
- });
-}
-
-// TODO(jmesserly): mocks would be cleaner here.
-
-class TestBindingSyntax extends BindingDelegate {
- var log = [];
-
- getBinding(model, String path, String name, node) {
- log.add([model, path, name, node is Element ? node.tagName : null]);
- }
-}
-
-class TestModelSyntax extends BindingDelegate {
- var log = [];
- var altModels = new ListQueue();
-
- getInstanceModel(template, model) {
- log.add([template, model]);
- return altModels.removeFirst();
- }
-}
-
-class TestInstanceModelSyntax extends BindingDelegate {
- int count = 0;
- getInstanceModel(template, model) {
- count++;
- return model;
- }
-}
-
-// Note: this isn't a very smart whitespace handler. A smarter one would only
-// trim indentation, not all whitespace.
-// See "trimOrCompact" in the web_ui Pub package.
-class WhitespaceRemover extends BindingDelegate {
- int trimmed = 0;
- int removed = 0;
-
- DocumentFragment getInstanceFragment(Element template) {
- var instance = templateBind(template).createInstance();
- var walker = new TreeWalker(instance, NodeFilter.SHOW_TEXT);
-
- var toRemove = [];
- while (walker.nextNode() != null) {
- var node = walker.currentNode;
- var text = node.text.replaceAll('\n', '').trim();
- if (text.length != node.text.length) {
- if (text.length == 0) {
- toRemove.add(node);
- } else {
- trimmed++;
- node.text = text;
- }
- }
- }
-
- for (var node in toRemove) node.remove();
- removed += toRemove.length;
-
- return instance;
- }
-}
-
-class TimesTwoSyntax extends BindingDelegate {
- getBinding(model, path, name, node) {
- path = path.trim();
- if (!path.startsWith('2x:')) return null;
-
- path = path.substring(3);
- return new CompoundBinding((values) => values['value'] * 2)
- ..bind('value', model, path);
- }
-}
diff --git a/pkg/template_binding/test/custom_element_bindings_test.dart b/pkg/template_binding/test/custom_element_bindings_test.dart
index c9556d5..cc12875 100644
--- a/pkg/template_binding/test/custom_element_bindings_test.dart
+++ b/pkg/template_binding/test/custom_element_bindings_test.dart
@@ -124,7 +124,7 @@
var element = div.nodes[1];
expect(element is MyCustomElement, true,
- reason: '${element} should be a MyCustomElement');
+ reason: '$element should be a MyCustomElement');
expect(element.myPoint, model['a']);
expect(element.scaryMonster, model['b']);
@@ -179,6 +179,7 @@
unbind(name) => nodeBindFallback(this).unbind(name);
unbindAll() => nodeBindFallback(this).unbindAll();
get bindings => nodeBindFallback(this).bindings;
+ get templateInstance => nodeBindFallback(this).templateInstance;
}
class _MyCustomBinding extends NodeBinding {
diff --git a/pkg/template_binding/test/node_bindings_test.dart b/pkg/template_binding/test/node_bind_test.dart
similarity index 95%
rename from pkg/template_binding/test/node_bindings_test.dart
rename to pkg/template_binding/test/node_bind_test.dart
index 6391b38..fbedcfa 100644
--- a/pkg/template_binding/test/node_bindings_test.dart
+++ b/pkg/template_binding/test/node_bind_test.dart
@@ -2,17 +2,14 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library template_binding.test.node_bindings_test;
+library template_binding.test.node_bind_test;
import 'dart:html';
-@MirrorsUsed(targets: const [NodeBinding], override:
- 'template_binding.test.node_bindings_test')
-import 'dart:mirrors';
-
import 'package:observe/observe.dart' show toObservable, PathObserver;
-import 'package:template_binding/template_binding.dart'
- show nodeBind, NodeBinding;
+import 'package:template_binding/template_binding.dart' show nodeBind;
+import 'package:template_binding/src/node_binding.dart' show getObserverForTest;
+
import 'package:unittest/html_config.dart';
import 'package:unittest/unittest.dart';
import 'utils.dart';
@@ -72,9 +69,6 @@
});
observeTest('Observer is Model', () {
- _observer(x) => reflect(x).getField(
- privateSymbol(NodeBinding, '_observer')).reflectee;
-
var text = new Text('');
var model = toObservable({'a': {'b': {'c': 1}}});
var observer = new PathObserver(model, 'a.b.c');
@@ -83,7 +77,7 @@
var binding = nodeBind(text).bindings['text'];
expect(binding, isNotNull);
- expect(privateField(binding, '_observer'), observer,
+ expect(getObserverForTest(binding), observer,
reason: 'should reuse observer');
model['a']['b']['c'] = 2;
@@ -654,17 +648,3 @@
expect(select.value, 'a');
});
}
-
-privateField(x, name) => reflect(x).getField(
- privateSymbol(reflect(x).type, name)).reflectee;
-
-// TODO(jmesserly): fix this when it's easier to get a private symbol.
-privateSymbol(TypeMirror type, String name) {
- while (type != null) {
- var symbol = type.variables.keys.firstWhere(
- (s) => MirrorSystem.getName(s) == name, orElse: () => null);
- if (symbol != null) return symbol;
- type = type.superclass;
- }
- return null;
-}
diff --git a/pkg/template_binding/test/template_element_test.dart b/pkg/template_binding/test/template_binding_test.dart
similarity index 89%
rename from pkg/template_binding/test/template_element_test.dart
rename to pkg/template_binding/test/template_binding_test.dart
index a878090..2e5c327 100644
--- a/pkg/template_binding/test/template_element_test.dart
+++ b/pkg/template_binding/test/template_binding_test.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library template_binding.test.template_element_test;
+library template_binding.test.template_binding_test;
import 'dart:async';
import 'dart:collection';
@@ -12,20 +12,21 @@
import 'package:template_binding/template_binding.dart';
import 'package:unittest/html_config.dart';
import 'package:unittest/unittest.dart';
+
+// TODO(jmesserly): merge this file?
+import 'binding_syntax.dart' show syntaxTests;
import 'utils.dart';
// Note: this file ported from
-// https://github.com/toolkitchen/mdv/blob/master/tests/template_element.js
+// https://github.com/Polymer/TemplateBinding/blob/ed3266266e751b5ab1f75f8e0509d0d5f0ef35d8/tests/tests.js
+
// TODO(jmesserly): submit a small cleanup patch to original. I fixed some
// cases where "div" and "t" were unintentionally using the JS global scope;
// look for "assertNodesAre".
main() {
useHtmlConfiguration();
- group('Template Element', templateElementTests);
-}
-templateElementTests() {
setUp(() {
document.body.append(testDiv = new DivElement());
});
@@ -35,36 +36,57 @@
testDiv = null;
});
- var expando = new Expando('observeTest');
- void addExpandos(node) {
- while (node != null) {
- expando[node] = node.text;
- node = node.nextNode;
- }
- }
+ group('Template Instantiation', templateInstantiationTests);
- void checkExpandos(node) {
- expect(node, isNotNull);
- while (node != null) {
- expect(expando[node], node.text);
- node = node.nextNode;
- }
+ group('Binding Delegate API', () {
+ group('with Observable', () {
+ syntaxTests(([f, b]) => new FooBarModel(f, b));
+ });
+
+ group('with ChangeNotifier', () {
+ syntaxTests(([f, b]) => new FooBarNotifyModel(f, b));
+ });
+ });
+
+ group('Compat', compatTests);
+}
+
+var expando = new Expando('test');
+void addExpandos(node) {
+ while (node != null) {
+ expando[node] = node.text;
+ node = node.nextNode;
}
+}
+
+void checkExpandos(node) {
+ expect(node, isNotNull);
+ while (node != null) {
+ expect(expando[node], node.text);
+ node = node.nextNode;
+ }
+}
+
+templateInstantiationTests() {
observeTest('Template', () {
var div = createTestHtml('<template bind={{}}>text</template>');
- recursivelySetTemplateModel(div, null);
+ templateBind(div.firstChild).model = {};
performMicrotaskCheckpoint();
expect(div.nodes.length, 2);
expect(div.nodes.last.text, 'text');
+
+ templateBind(div.firstChild).model = null;
+ performMicrotaskCheckpoint();
+ expect(div.nodes.length, 1);
});
observeTest('Template bind, no parent', () {
var div = createTestHtml('<template bind>text</template>');
- var template = div.nodes[0];
+ var template = div.firstChild;
template.remove();
- recursivelySetTemplateModel(template, toObservable({}));
+ templateBind(template).model = {};
performMicrotaskCheckpoint();
expect(template.nodes.length, 0);
expect(template.nextNode, null);
@@ -72,17 +94,18 @@
observeTest('Template bind, no defaultView', () {
var div = createTestHtml('<template bind>text</template>');
- var template = div.nodes[0];
+ var template = div.firstChild;
var doc = document.implementation.createHtmlDocument('');
doc.adoptNode(div);
- recursivelySetTemplateModel(template, toObservable({}));
+ recursivelySetTemplateModel(template, {});
performMicrotaskCheckpoint();
expect(div.nodes.length, 1);
});
observeTest('Template-Empty Bind', () {
var div = createTestHtml('<template bind>text</template>');
- recursivelySetTemplateModel(div, null);
+ var template = div.firstChild;
+ templateBind(template).model = {};
performMicrotaskCheckpoint();
expect(div.nodes.length, 2);
expect(div.nodes.last.text, 'text');
@@ -93,7 +116,8 @@
// Note: changed this value from 0->null because zero is not falsey in Dart.
// See https://code.google.com/p/dart/issues/detail?id=11956
var m = toObservable({ 'foo': null });
- recursivelySetTemplateModel(div, m);
+ var template = div.firstChild;
+ templateBind(template).model = m;
performMicrotaskCheckpoint();
expect(div.nodes.length, 1);
@@ -101,6 +125,10 @@
performMicrotaskCheckpoint();
expect(div.nodes.length, 2);
expect(div.lastChild.text, 'text');
+
+ templateBind(template).model = null;
+ performMicrotaskCheckpoint();
+ expect(div.nodes.length, 1);
});
observeTest('Template Bind If, 2', () {
@@ -119,10 +147,11 @@
observeTest('Template If', () {
var div = createTestHtml('<template if="{{ foo }}">{{ value }}</template>');
- // Note: changed this value from 0->null because zero is not falsey in Dart.
- // See https://code.google.com/p/dart/issues/detail?id=11956
+ // Note: changed this value from 0->null because zero is not falsey in
+ // Dart. See https://code.google.com/p/dart/issues/detail?id=11956
var m = toObservable({ 'foo': null, 'value': 'foo' });
- recursivelySetTemplateModel(div, m);
+ var template = div.firstChild;
+ templateBind(template).model = m;
performMicrotaskCheckpoint();
expect(div.nodes.length, 1);
@@ -130,6 +159,23 @@
performMicrotaskCheckpoint();
expect(div.nodes.length, 2);
expect(div.lastChild.text, 'foo');
+
+ templateBind(template).model = null;
+ performMicrotaskCheckpoint();
+ expect(div.nodes.length, 1);
+ });
+
+ observeTest('Template Empty-If', () {
+ var div = createTestHtml('<template if>{{ value }}</template>');
+ var m = toObservable({ 'value': 'foo' });
+ recursivelySetTemplateModel(div, null);
+ performMicrotaskCheckpoint();
+ expect(div.nodes.length, 1);
+
+ recursivelySetTemplateModel(div, m);
+ performMicrotaskCheckpoint();
+ expect(div.nodes.length, 2);
+ expect(div.lastChild.text, 'foo');
});
observeTest('Template Repeat If', () {
@@ -138,7 +184,8 @@
// Note: changed this value from 0->null because zero is not falsey in Dart.
// See https://code.google.com/p/dart/issues/detail?id=11956
var m = toObservable({ 'bar': null, 'foo': [1, 2, 3] });
- recursivelySetTemplateModel(div, m);
+ var template = div.firstChild;
+ templateBind(template).model = m;
performMicrotaskCheckpoint();
expect(div.nodes.length, 1);
@@ -148,6 +195,10 @@
expect(div.nodes[1].text, '1');
expect(div.nodes[2].text, '2');
expect(div.nodes[3].text, '3');
+
+ templateBind(template).model = null;
+ performMicrotaskCheckpoint();
+ expect(div.nodes.length, 1);
});
observeTest('TextTemplateWithNullStringBinding', () {
@@ -177,7 +228,8 @@
var div = createTestHtml(
'<template bind="{{ data }}">a{{b}}c</template>');
var model = toObservable({ 'data': {'b': 'B'} });
- recursivelySetTemplateModel(div, model);
+ var template = div.firstChild;
+ templateBind(template).model = model;
performMicrotaskCheckpoint();
expect(div.nodes.length, 2);
@@ -191,9 +243,14 @@
performMicrotaskCheckpoint();
expect(div.nodes.last.text, 'aXc');
- model['data'] = null;
+ // Dart note: changed from `null` since our null means don't render a model.
+ model['data'] = toObservable({});
performMicrotaskCheckpoint();
expect(div.nodes.last.text, 'ac');
+
+ model['data'] = null;
+ performMicrotaskCheckpoint();
+ expect(div.nodes.length, 1);
});
observeTest('TextTemplateWithBindingAndConditional', () {
@@ -599,7 +656,7 @@
});
observeTest('BindWithRef', () {
- var id = 't${new math.Random().nextDouble()}';
+ var id = 't${new math.Random().nextInt(100)}';
var div = createTestHtml(
'<template id="$id">'
'Hi {{ name }}'
@@ -618,6 +675,23 @@
expect(t2.nextNode.text, 'Hi Fry');
});
+ observeTest('BindWithDynamicRef', () {
+ var id = 't${new math.Random().nextInt(100)}';
+ var div = createTestHtml(
+ '<template id="$id">'
+ 'Hi {{ name }}'
+ '</template>'
+ '<template ref="{{ id }}" bind="{{}}"></template>');
+
+ var t1 = div.firstChild;
+ var t2 = div.nodes[1];
+ var model = toObservable({'name': 'Fry', 'id': id });
+ recursivelySetTemplateModel(div, model);
+
+ performMicrotaskCheckpoint();
+ expect(t2.nextNode.text, 'Hi Fry');
+ });
+
observeTest('BindChanged', () {
var model = toObservable({
'XX': {'name': 'Leela', 'title': 'Captain'},
@@ -1548,6 +1622,7 @@
}
});
+ // Dart note: this test seems gone from JS. Keeping for posterity sake.
observeTest('BindShadowDOM createInstance', () {
if (ShadowRoot.supported) {
var model = toObservable({'name': 'Leela'});
@@ -1674,11 +1749,100 @@
expect(template3.content.nodes.length, 1);
expect(template3.content.nodes.first.text, 'Hello');
});
+
+ observeTest('issue-285', () {
+ var div = createTestHtml(
+ '<template>'
+ '<template bind if="{{show}}">'
+ '<template id=del repeat="{{items}}">'
+ '{{}}'
+ '</template>'
+ '</template>'
+ '</template>');
+
+ var template = div.firstChild;
+
+ var model = toObservable({
+ 'show': true,
+ 'items': [1]
+ });
+
+ div.append(templateBind(template).createInstance(model,
+ new Issue285Syntax()));
+
+ performMicrotaskCheckpoint();
+ expect(template.nextNode.nextNode.nextNode.text, '2');
+ model['show'] = false;
+ performMicrotaskCheckpoint();
+ model['show'] = true;
+ performMicrotaskCheckpoint();
+ expect(template.nextNode.nextNode.nextNode.text, '2');
+ });
+
+ observeTest('issue-141', () {
+ var div = createTestHtml(
+ '<template bind>' +
+ '<div foo="{{foo1}} {{foo2}}" bar="{{bar}}"></div>' +
+ '</template>');
+
+ var model = toObservable({
+ 'foo1': 'foo1Value',
+ 'foo2': 'foo2Value',
+ 'bar': 'barValue'
+ });
+
+ recursivelySetTemplateModel(div, model);
+ performMicrotaskCheckpoint();
+
+ expect(div.lastChild.attributes['bar'], 'barValue');
+ });
+}
+
+compatTests() {
+ observeTest('underbar bindings', () {
+ var div = createTestHtml(
+ '<template bind>'
+ '<div _style="color: {{ color }};"></div>'
+ '<img _src="{{ url }}">'
+ '<a _href="{{ url2 }}">Link</a>'
+ '<input type="number" _value="{{ number }}">'
+ '</template>');
+
+ var model = toObservable({
+ 'color': 'red',
+ 'url': 'pic.jpg',
+ 'url2': 'link.html',
+ 'number': 4
+ });
+
+ recursivelySetTemplateModel(div, model);
+ performMicrotaskCheckpoint();
+
+ var subDiv = div.firstChild.nextNode;
+ expect(subDiv.attributes['style'], 'color: red;');
+
+ var img = subDiv.nextNode;
+ expect(img.attributes['src'], 'pic.jpg');
+
+ var a = img.nextNode;
+ expect(a.attributes['href'], 'link.html');
+
+ var input = a.nextNode;
+ expect(input.value, '4');
+ });
+}
+
+class Issue285Syntax extends BindingDelegate {
+ prepareInstanceModel(template) {
+ if (template.id == 'del') return (val) => val * 2;
+ }
}
class TestBindingSyntax extends BindingDelegate {
- getBinding(model, String path, name, node) {
- if (path.trim() == 'replaceme') return new ObservableBox('replaced');
+ prepareBinding(String path, name, node) {
+ if (path.trim() == 'replaceme') {
+ return (x, y) => new ObservableBox('replaced');
+ }
return null;
}
}
@@ -1687,11 +1851,13 @@
int expectedAge = 42;
int count = 0;
- getBinding(model, path, name, node) {
- if (name != 'text' || path != 'age')
- return;
+ prepareBinding(path, name, node) {
+ if (name != 'text' || path != 'age') return null;
- expect(model['age'], expectedAge);
- count++;
+ return (model, node) {
+ expect(model['age'], expectedAge);
+ count++;
+ return model;
+ };
}
}
diff --git a/pkg/unittest/lib/matcher.dart b/pkg/unittest/lib/matcher.dart
index 4830b8f..5cbbed48 100644
--- a/pkg/unittest/lib/matcher.dart
+++ b/pkg/unittest/lib/matcher.dart
@@ -21,7 +21,6 @@
library matcher;
import 'dart:async';
-import 'package:meta/meta.dart';
import 'src/pretty_print.dart';
import 'src/utils.dart';
diff --git a/pkg/unittest/lib/src/configuration.dart b/pkg/unittest/lib/src/configuration.dart
index d8d6c81..2a2ea0c 100644
--- a/pkg/unittest/lib/src/configuration.dart
+++ b/pkg/unittest/lib/src/configuration.dart
@@ -30,7 +30,7 @@
/// How long a [TestCase] can run before it is considered an error.
/// A [timeout] value of [:null:] means that the limit is infinite.
- Duration get timeout => const Duration(seconds: 20);
+ Duration get timeout => const Duration(minutes: 2);
/**
* Called as soon as the unittest framework becomes initialized. This is done
diff --git a/pkg/unittest/lib/src/numeric_matchers.dart b/pkg/unittest/lib/src/numeric_matchers.dart
index d040efb..2a725ff 100644
--- a/pkg/unittest/lib/src/numeric_matchers.dart
+++ b/pkg/unittest/lib/src/numeric_matchers.dart
@@ -74,7 +74,7 @@
'a non-negative value', false);
bool _isNumeric(value) {
- return value is int || value is double;
+ return value is num;
}
class _OrderingComparison extends Matcher {
diff --git a/pkg/unittest/lib/src/simple_configuration.dart b/pkg/unittest/lib/src/simple_configuration.dart
index 267fd62..78c303e 100644
--- a/pkg/unittest/lib/src/simple_configuration.dart
+++ b/pkg/unittest/lib/src/simple_configuration.dart
@@ -54,7 +54,7 @@
/// How long a [TestCase] can run before it is considered an error.
/// A [timeout] value of [:null:] means that the limit is infinite.
- Duration timeout = const Duration(seconds: 20);
+ Duration timeout = const Duration(minutes: 2);
/**
* The constructor sets up a failure handler for [expect] that redirects
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 047cd84..7546f40 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -236,6 +236,7 @@
// http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
//
// Drop the leading / before the drive letter.
+ // TODO(14577): Handle paths like \\server\share\dir\file.
path = path.substring(1);
_logResolution('# Path: Removed leading / -> $path');
}
@@ -310,27 +311,3 @@
_logResolution('# Path: $uri -> $uri');
return uri.toString();
}
-
-
-class _PlatformHook {
- // TODO(whesse): Replace uses of Platform with uses of internal _Platform
- // class, to prepare for removal of (deprecated) Platform class.
- // Also merge _Platform and _PlatformHook class into _Platform class
- // at that time, since _PlatformHook is the only user of _Platform.
- int get numberOfProcessors => Platform.numberOfProcessors;
- String get pathSeparator => Platform.pathSeparator;
- String get operatingSystem => Platform.operatingSystem;
- String get localHostname => Platform.localHostname;
- String get version => Platform.version;
- Map<String, String> get environment => Platform.environment;
- Uri get script => new Uri.file(Platform.script);
- String get executable => Platform.executable;
- List<String> get executableArguments => Platform.executableArguments;
- String get packageRoot => Platform.packageRoot;
-}
-
-
-_getPlatform() => new _PlatformHook();
-
-
-
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index a3a2f69..657a457 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -29,7 +29,6 @@
const char* DartUtils::kIOLibURL = "dart:io";
const char* DartUtils::kIOLibPatchURL = "dart:io-patch";
const char* DartUtils::kUriLibURL = "dart:uri";
-const char* DartUtils::kPlatformLibURL = "dart:platform";
const char* DartUtils::kHttpScheme = "http:";
const char* DartUtils::kIdFieldName = "_id";
@@ -712,29 +711,17 @@
// Set up package root if specified.
if (package_root != NULL) {
- Dart_Handle package_root_string = NewString(package_root);
- if (Dart_IsError(package_root_string)) {
- return package_root_string;
- }
- const int kNumArgs = 1;
- Dart_Handle dart_args[kNumArgs];
- dart_args[0] = package_root_string;
- result = Dart_Invoke(builtin_lib,
+ result = NewString(package_root);
+ if (!Dart_IsError(result)) {
+ const int kNumArgs = 1;
+ Dart_Handle dart_args[kNumArgs];
+ dart_args[0] = result;
+ return Dart_Invoke(builtin_lib,
NewString("_setPackageRoot"),
kNumArgs,
dart_args);
- if (Dart_IsError(result)) {
- return result;
}
}
-
- // Setup the platform library's _platform object.
- internal_lib = Dart_LookupLibrary(NewString(kPlatformLibURL));
- DART_CHECK_VALID(internal_lib);
- Dart_Handle platform =
- Dart_Invoke(builtin_lib, NewString("_getPlatform"), 0, NULL);
- result = Dart_SetField(internal_lib, NewString("_platform"), platform);
- DART_CHECK_VALID(result);
return result;
}
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index ca8fa06..375a9bc 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -204,7 +204,6 @@
static const char* kIOLibURL;
static const char* kIOLibPatchURL;
static const char* kUriLibURL;
- static const char* kPlatformLibURL;
static const char* kHttpScheme;
static const char* kIdFieldName;
@@ -251,6 +250,7 @@
return type() == Dart_CObject_kTypedData &&
byte_array_type() == Dart_TypedData_kUint8;
}
+ bool IsSendPort() { return type() == Dart_CObject_kSendPort; }
bool IsTrue() {
return type() == Dart_CObject_kBool && cobject_->value.as_bool;
@@ -468,6 +468,17 @@
};
+class CObjectSendPort : public CObject {
+ public:
+ DECLARE_COBJECT_CONSTRUCTORS(SendPort)
+
+ Dart_Port Value() const { return cobject_->value.as_send_port; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CObjectSendPort);
+};
+
+
class CObjectTypedData : public CObject {
public:
explicit CObjectTypedData(Dart_CObject *cobject) : CObject(cobject) {
diff --git a/runtime/bin/dbg_connection.cc b/runtime/bin/dbg_connection.cc
index e5abc5e..45edc0c7 100644
--- a/runtime/bin/dbg_connection.cc
+++ b/runtime/bin/dbg_connection.cc
@@ -21,6 +21,8 @@
namespace dart {
namespace bin {
+extern bool trace_debug_protocol;
+
int DebuggerConnectionHandler::listener_fd_ = -1;
dart::Monitor* DebuggerConnectionHandler::handler_lock_ = new dart::Monitor();
@@ -29,6 +31,9 @@
// handler in a static variable.
static DebuggerConnectionHandler* singleton_handler = NULL;
+// The maximum message length to print when --trace_debug_protocol is
+// specified.
+static const int kMaxPrintMessageLen = 1024;
class MessageBuffer {
public:
@@ -196,6 +201,19 @@
return;
}
+ if (trace_debug_protocol) {
+ dart::JSONReader r(msgbuf_->buf());
+ const char* msg_end = r.EndOfObject();
+ if (msg_end != NULL) {
+ intptr_t msg_len = msg_end - msgbuf_->buf();
+ int print_len = ((msg_len > kMaxPrintMessageLen)
+ ? kMaxPrintMessageLen : msg_len);
+ Log::Print("[<<<] Receiving message from debug fd %d:\n%.*s%s\n",
+ debug_fd_, print_len, msgbuf_->buf(),
+ ((msg_len > print_len) ? "..." : ""));
+ }
+ }
+
// Parse out the command portion from the message.
dart::JSONReader r(msgbuf_->buf());
bool found = r.Seek("command");
@@ -344,6 +362,15 @@
dart::TextBuffer* msg) {
ASSERT(debug_fd >= 0);
ASSERT(IsValidJSON(msg->buf()));
+
+ if (trace_debug_protocol) {
+ int print_len = ((msg->length() > kMaxPrintMessageLen)
+ ? kMaxPrintMessageLen : msg->length());
+ Log::Print("[>>>] Sending message to debug fd %d:\n%.*s%s\n",
+ debug_fd, print_len, msg->buf(),
+ ((msg->length() > print_len) ? "..." : ""));
+ }
+
// Sending messages in short pieces can be used to stress test the
// debugger front-end's message handling code.
const bool send_in_pieces = false;
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 058d638..01f9f75 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -262,6 +262,9 @@
CObjectIntptr ptr(request[0]);
AsyncDirectoryListing* dir_listing =
reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
+ if (dir_listing->IsEmpty()) {
+ return new CObjectArray(CObject::NewArray(0));
+ }
const int kArraySize = 128;
CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize));
dir_listing->SetArray(response, kArraySize);
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index fd78e80..1417c23 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -65,9 +65,7 @@
explicit DirectoryListingEntry(DirectoryListingEntry* parent)
: parent_(parent), lister_(0), done_(false), link_(NULL) {}
- ~DirectoryListingEntry() {
- ResetLink();
- }
+ ~DirectoryListingEntry();
ListType Next(DirectoryListing* listing);
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index 7dd450a..02f841d 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -187,14 +187,18 @@
return kListError;
}
- if (closedir(reinterpret_cast<DIR*>(lister_)) == -1) {
- return kListError;
- }
-
return kListDone;
}
+DirectoryListingEntry::~DirectoryListingEntry() {
+ ResetLink();
+ if (lister_ != 0) {
+ closedir(reinterpret_cast<DIR*>(lister_));
+ }
+}
+
+
void DirectoryListingEntry::ResetLink() {
if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) {
delete link_;
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
index c26289c..0bb07e7 100644
--- a/runtime/bin/directory_linux.cc
+++ b/runtime/bin/directory_linux.cc
@@ -105,8 +105,8 @@
dirent entry;
dirent* result;
if ((status = TEMP_FAILURE_RETRY(readdir_r(reinterpret_cast<DIR*>(lister_),
- &entry,
- &result))) == 0 &&
+ &entry,
+ &result))) == 0 &&
result != NULL) {
if (!listing->path_buffer().Add(entry.d_name)) {
done_ = true;
@@ -188,14 +188,18 @@
return kListError;
}
- if (closedir(reinterpret_cast<DIR*>(lister_)) == -1) {
- return kListError;
- }
-
return kListDone;
}
+DirectoryListingEntry::~DirectoryListingEntry() {
+ ResetLink();
+ if (lister_ != 0) {
+ closedir(reinterpret_cast<DIR*>(lister_));
+ }
+}
+
+
void DirectoryListingEntry::ResetLink() {
if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) {
delete link_;
diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc
index 074647f..feb9a9c 100644
--- a/runtime/bin/directory_macos.cc
+++ b/runtime/bin/directory_macos.cc
@@ -187,14 +187,18 @@
return kListError;
}
- if (closedir(reinterpret_cast<DIR*>(lister_)) == -1) {
- return kListError;
- }
-
return kListDone;
}
+DirectoryListingEntry::~DirectoryListingEntry() {
+ ResetLink();
+ if (lister_ != 0) {
+ closedir(reinterpret_cast<DIR*>(lister_));
+ }
+}
+
+
void DirectoryListingEntry::ResetLink() {
if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) {
delete link_;
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index e3e390f..3733a71 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -206,14 +206,18 @@
return kListError;
}
- if (FindClose(reinterpret_cast<HANDLE>(lister_)) == 0) {
- return kListError;
- }
-
return kListDone;
}
+DirectoryListingEntry::~DirectoryListingEntry() {
+ ResetLink();
+ if (lister_ != 0) {
+ FindClose(reinterpret_cast<HANDLE>(lister_));
+ }
+}
+
+
void DirectoryListingEntry::ResetLink() {
if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) {
delete link_;
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 96a5d16..4b5e5e6 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -70,10 +70,10 @@
try {
socketId = _watchPath(_path, _events, identical(true, _recursive));
} catch (e) {
- throw new FileSystemException(
- "Failed to watch path",
- _path,
- e);
+ _controller.addError(new FileSystemException(
+ "Failed to watch path", _path, e));
+ _controller.close();
+ return;
}
var socket = new _RawSocket(new _NativeSocket.watch(socketId));
_subscription = socket.expand((event) {
@@ -89,48 +89,63 @@
}
return path;
}
+ bool getIsDir(event) {
+ if (Platform.isWindows) {
+ // Windows does not get 'isDir' as part of the event.
+ return FileSystemEntity.isDirectorySync(getPath(event));
+ }
+ return (event[0] & FileSystemEvent._IS_DIR) != 0;
+ }
void add(event) {
if ((event.type & _events) == 0) return;
events.add(event);
}
+ void rewriteMove(event, isDir) {
+ if (event[3]) {
+ add(new FileSystemCreateEvent._(getPath(event), isDir));
+ } else {
+ add(new FileSystemDeleteEvent._(getPath(event), isDir));
+ }
+ }
while (socket.available() > 0) {
for (var event in _readEvents()) {
if (event == null) continue;
+ bool isDir = getIsDir(event);
var path = getPath(event);
if ((event[0] & FileSystemEvent.CREATE) != 0) {
- add(new FileSystemCreateEvent._(path));
+ add(new FileSystemCreateEvent._(path, isDir));
}
if ((event[0] & FileSystemEvent.MODIFY) != 0) {
- add(new FileSystemModifyEvent._(path, true));
+ add(new FileSystemModifyEvent._(path, isDir, true));
}
if ((event[0] & FileSystemEvent._MODIFY_ATTRIBUTES) != 0) {
- add(new FileSystemModifyEvent._(path, false));
+ add(new FileSystemModifyEvent._(path, isDir, false));
}
if ((event[0] & FileSystemEvent.MOVE) != 0) {
int link = event[1];
if (link > 0) {
if (pair.containsKey(link)) {
- events.add(
- new FileSystemMoveEvent._(getPath(pair[link]), path));
+ events.add(new FileSystemMoveEvent._(
+ getPath(pair[link]), isDir, path));
pair.remove(link);
} else {
pair[link] = event;
}
} else {
- add(new FileSystemMoveEvent._(path, null));
+ rewriteMove(event, isDir);
}
}
if ((event[0] & FileSystemEvent.DELETE) != 0) {
- add(new FileSystemDeleteEvent._(path));
+ add(new FileSystemDeleteEvent._(path, isDir));
}
if ((event[0] & FileSystemEvent._DELETE_SELF) != 0) {
- add(new FileSystemDeleteEvent._(path));
+ add(new FileSystemDeleteEvent._(path, isDir));
stop = true;
}
}
}
for (var event in pair.values) {
- events.add(new FileSystemMoveEvent._(getPath(event), null));
+ rewriteMove(event, getIsDir(event));
}
} else if (event == RawSocketEvent.CLOSED) {
} else if (event == RawSocketEvent.READ_CLOSED) {
diff --git a/runtime/bin/file_system_watcher.h b/runtime/bin/file_system_watcher.h
index 9434674..21c334f 100644
--- a/runtime/bin/file_system_watcher.h
+++ b/runtime/bin/file_system_watcher.h
@@ -25,7 +25,8 @@
kDelete = 1 << 2,
kMove = 1 << 3,
kModefyAttribute = 1 << 4,
- kDeleteSelf = 1 << 5
+ kDeleteSelf = 1 << 5,
+ kIsDir = 1 << 6
};
struct Event {
diff --git a/runtime/bin/file_system_watcher_android.cc b/runtime/bin/file_system_watcher_android.cc
index 63a244a..333bc86 100644
--- a/runtime/bin/file_system_watcher_android.cc
+++ b/runtime/bin/file_system_watcher_android.cc
@@ -67,7 +67,7 @@
while (offset < bytes) {
struct inotify_event* e =
reinterpret_cast<struct inotify_event*>(buffer + offset);
- Dart_Handle event = Dart_NewList(3);
+ Dart_Handle event = Dart_NewList(4);
int mask = 0;
if (e->mask & IN_MODIFY) mask |= kModifyContent;
if (e->mask & IN_ATTRIB) mask |= kModefyAttribute;
@@ -82,6 +82,7 @@
} else {
Dart_ListSetAt(event, 2, Dart_Null());
}
+ Dart_ListSetAt(event, 3, Dart_NewBoolean(e->mask & IN_MOVED_TO));
Dart_ListSetAt(events, i, event);
i++;
offset += kEventSize + e->len;
diff --git a/runtime/bin/file_system_watcher_linux.cc b/runtime/bin/file_system_watcher_linux.cc
index da5dee1..43fe4e1 100644
--- a/runtime/bin/file_system_watcher_linux.cc
+++ b/runtime/bin/file_system_watcher_linux.cc
@@ -26,7 +26,7 @@
if (fd < 0) return -1;
int list_events = IN_DELETE_SELF;
if (events & kCreate) list_events |= IN_CREATE;
- if (events & kModifyContent) list_events |= IN_MODIFY | IN_ATTRIB;
+ if (events & kModifyContent) list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
if (events & kDelete) list_events |= IN_DELETE;
if (events & kMove) list_events |= IN_MOVE;
int path_fd = TEMP_FAILURE_RETRY(inotify_add_watch(fd, path, list_events));
@@ -63,14 +63,15 @@
while (offset < bytes) {
struct inotify_event* e =
reinterpret_cast<struct inotify_event*>(buffer + offset);
- Dart_Handle event = Dart_NewList(3);
+ Dart_Handle event = Dart_NewList(4);
int mask = 0;
- if (e->mask & IN_MODIFY) mask |= kModifyContent;
+ if (e->mask & IN_CLOSE_WRITE) mask |= kModifyContent;
if (e->mask & IN_ATTRIB) mask |= kModefyAttribute;
if (e->mask & IN_CREATE) mask |= kCreate;
if (e->mask & IN_MOVE) mask |= kMove;
if (e->mask & IN_DELETE) mask |= kDelete;
if (e->mask & IN_DELETE_SELF) mask |= kDeleteSelf;
+ if (e->mask & IN_ISDIR) mask |= kIsDir;
Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie));
if (e->len > 0) {
@@ -79,6 +80,7 @@
} else {
Dart_ListSetAt(event, 2, Dart_Null());
}
+ Dart_ListSetAt(event, 3, Dart_NewBoolean(e->mask & IN_MOVED_TO));
Dart_ListSetAt(events, i, event);
i++;
offset += kEventSize + e->len;
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index 4aed2e3..65ad6e9 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -264,13 +264,14 @@
return DartUtils::NewDartOSError();
}
size_t path_len = strlen(e.data.path);
- Dart_Handle event = Dart_NewList(3);
+ Dart_Handle event = Dart_NewList(4);
int flags = e.data.flags;
int mask = 0;
if (flags & kFSEventStreamEventFlagItemModified) mask |= kModifyContent;
if (flags & kFSEventStreamEventFlagItemRenamed) mask |= kMove;
if (flags & kFSEventStreamEventFlagItemXattrMod) mask |= kModefyAttribute;
if (flags & kFSEventStreamEventFlagItemCreated) mask |= kCreate;
+ if (flags & kFSEventStreamEventFlagItemIsDir) mask |= kIsDir;
if (flags & kFSEventStreamEventFlagItemRemoved) {
if (path_len == 0) {
// The removed path is the path being watched.
@@ -283,6 +284,7 @@
Dart_ListSetAt(event, 1, Dart_NewInteger(1));
Dart_ListSetAt(event, 2, Dart_NewStringFromUTF8(
reinterpret_cast<uint8_t*>(e.data.path), path_len));
+ Dart_ListSetAt(event, 3, Dart_NewBoolean(true));
Dart_ListSetAt(events, i, event);
}
return events;
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc
index e08c28d..9731009 100644
--- a/runtime/bin/file_system_watcher_win.cc
+++ b/runtime/bin/file_system_watcher_win.cc
@@ -83,7 +83,7 @@
FILE_NOTIFY_INFORMATION* e =
reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer + offset);
- Dart_Handle event = Dart_NewList(3);
+ Dart_Handle event = Dart_NewList(4);
int mask = 0;
if (e->Action == FILE_ACTION_ADDED) mask |= kCreate;
if (e->Action == FILE_ACTION_REMOVED) mask |= kDelete;
@@ -95,7 +95,7 @@
Dart_ListSetAt(event, 1, Dart_NewInteger(1));
Dart_ListSetAt(event, 2, Dart_NewStringFromUTF16(
reinterpret_cast<uint16_t*>(e->FileName), e->FileNameLength / 2));
-
+ Dart_ListSetAt(event, 3, Dart_NewBoolean(true));
Dart_ListSetAt(events, i, event);
i++;
if (e->NextEntryOffset == 0) break;
diff --git a/runtime/bin/io_service.cc b/runtime/bin/io_service.cc
index 922b98c..c58931c 100644
--- a/runtime/bin/io_service.cc
+++ b/runtime/bin/io_service.cc
@@ -28,18 +28,21 @@
break;
void IOServiceCallback(Dart_Port dest_port_id,
- Dart_Port reply_port_id,
Dart_CObject* message) {
+ Dart_Port reply_port_id = ILLEGAL_PORT;
CObject* response = CObject::IllegalArgumentError();
CObjectArray request(message);
if (message->type == Dart_CObject_kArray &&
- request.Length() == 3 &&
+ request.Length() == 4 &&
request[0]->IsInt32() &&
- request[1]->IsInt32() &&
- request[2]->IsArray()) {
+ request[1]->IsSendPort() &&
+ request[2]->IsInt32() &&
+ request[3]->IsArray()) {
CObjectInt32 message_id(request[0]);
- CObjectInt32 request_id(request[1]);
- CObjectArray data(request[2]);
+ CObjectSendPort reply_port(request[1]);
+ CObjectInt32 request_id(request[2]);
+ CObjectArray data(request[3]);
+ reply_port_id = reply_port.Value();
switch (request_id.Value()) {
IO_SERVICE_REQUEST_LIST(CASE_REQUEST);
default:
@@ -75,4 +78,3 @@
} // namespace bin
} // namespace dart
-
diff --git a/runtime/bin/io_service_patch.dart b/runtime/bin/io_service_patch.dart
index 85f5124..612703e 100644
--- a/runtime/bin/io_service_patch.dart
+++ b/runtime/bin/io_service_patch.dart
@@ -20,7 +20,7 @@
_initialize(index);
var completer = new Completer();
_messageMap[id] = completer;
- _servicePort[index].send([id, request, data], _replyToPort);
+ _servicePort[index].send([id, _replyToPort, request, data]);
return completer.future;
}
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index b6e8ee9..59501a9 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -225,6 +225,16 @@
return true;
}
+bool trace_debug_protocol = false;
+static bool ProcessTraceDebugProtocolOption(const char* arg) {
+ if (*arg != '\0') {
+ return false;
+ }
+ trace_debug_protocol = true;
+ return true;
+}
+
+
static struct {
const char* option_name;
bool (*process)(const char* option);
@@ -244,6 +254,7 @@
{ "--print-script", ProcessPrintScriptOption },
{ "--check-function-fingerprints", ProcessFingerprintedFunctions },
{ "--enable-vm-service", ProcessEnableVmServiceOption },
+ { "--trace-debug-protocol", ProcessTraceDebugProtocolOption },
{ NULL, NULL }
};
@@ -495,9 +506,7 @@
Dart_SetField(platform_type, script_name_name, dart_script);
CHECK_RESULT(set_script_name);
- Dart_Handle debug_name = Dart_DebugName();
- CHECK_RESULT(debug_name);
- VmService::SendIsolateStartupMessage(Dart_GetMainPortId(), debug_name);
+ VmService::SendIsolateStartupMessage();
// Make the isolate runnable so that it is ready to handle messages.
Dart_ExitScope();
diff --git a/runtime/bin/vmservice/running_isolate.dart b/runtime/bin/vmservice/running_isolate.dart
index 13b358a..cf726c8 100644
--- a/runtime/bin/vmservice/running_isolate.dart
+++ b/runtime/bin/vmservice/running_isolate.dart
@@ -5,10 +5,11 @@
part of vmservice;
class RunningIsolate implements ServiceRequestRouter {
+ final int portId;
final SendPort sendPort;
final String name;
- RunningIsolate(this.sendPort, this.name);
+ RunningIsolate(this.portId, this.sendPort, this.name);
Future sendMessage(List request) {
final completer = new Completer.sync();
diff --git a/runtime/bin/vmservice/running_isolates.dart b/runtime/bin/vmservice/running_isolates.dart
index 5b38223..0cfa02f 100644
--- a/runtime/bin/vmservice/running_isolates.dart
+++ b/runtime/bin/vmservice/running_isolates.dart
@@ -9,28 +9,28 @@
RunningIsolates();
- void isolateStartup(SendPort sp, String name) {
- if (isolates[sp.hashCode] != null) {
+ void isolateStartup(int portId, SendPort sp, String name) {
+ if (isolates[portId] != null) {
throw new StateError('Duplicate isolate startup.');
}
- var ri = new RunningIsolate(sp, name);
- isolates[sp.hashCode] = ri;
+ var ri = new RunningIsolate(portId, sp, name);
+ isolates[portId] = ri;
}
- void isolateShutdown(SendPort sp) {
- if (isolates[sp.hashCode] == null) {
+ void isolateShutdown(int portId, SendPort sp) {
+ if (isolates[portId] == null) {
throw new StateError('Unknown isolate.');
}
- isolates.remove(sp.hashCode);
+ isolates.remove(portId);
}
void _isolateCollectionRequest(ServiceRequest request) {
var members = [];
var result = {};
- isolates.forEach((sp, ri) {
+ isolates.forEach((portId, runningIsolate) {
members.add({
- 'id': sp,
- 'name': ri.name
+ 'id': portId,
+ 'name': runningIsolate.name
});
});
result['type'] = 'IsolateList';
diff --git a/runtime/bin/vmservice/vmservice.dart b/runtime/bin/vmservice/vmservice.dart
index 83c2168..9c58842fe 100644
--- a/runtime/bin/vmservice/vmservice.dart
+++ b/runtime/bin/vmservice/vmservice.dart
@@ -5,7 +5,7 @@
library vmservice;
import 'dart:async';
-import "dart:convert";
+import 'dart:convert';
import 'dart:isolate';
import 'dart:typed_data';
@@ -19,26 +19,29 @@
class VMService {
static VMService _instance;
RunningIsolates runningIsolates = new RunningIsolates();
+ final RawReceivePort receivePort;
- void controlMessageHandler(int code, SendPort sp, String name) {
+ void controlMessageHandler(int code, int port_id, SendPort sp, String name) {
switch (code) {
case Constants.ISOLATE_STARTUP_MESSAGE_ID:
- runningIsolates.isolateStartup(sp, name);
+ runningIsolates.isolateStartup(port_id, sp, name);
break;
case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID:
- runningIsolates.isolateShutdown(sp);
+ runningIsolates.isolateShutdown(port_id, sp);
break;
}
}
void messageHandler(message) {
- if (message is List && message.length == 3) {
- controlMessageHandler(message[0], message[1], message[2]);
+ assert(message is List);
+ assert(message.length == 4);
+ if (message is List && message.length == 4) {
+ controlMessageHandler(message[0], message[1], message[2], message[3]);
}
}
- VMService._internal() {
- port.listen(messageHandler);
+ VMService._internal() : receivePort = new RawReceivePort() {
+ receivePort.handler = messageHandler;
}
factory VMService() {
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index ee4ffb2..d4590ce 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -9,11 +9,16 @@
part 'server.dart';
-var _port;
+// The TCP port that the HTTP server listens on.
+int _port;
+
+// The receive port that isolate startup / shutdown messages are delivered on.
+RawReceivePort _receivePort;
main() {
// Create VmService.
var service = new VMService();
+ _receivePort = service.receivePort;
// Start HTTP server.
var server = new Server(service, _port);
server.startServer();
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 7da20cc..36130fa 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -143,20 +143,42 @@
Dart_Handle library = Dart_RootLibrary();
- // Set requested port.
+ // Set requested TCP port.
DartUtils::SetIntegerField(library, "_port", server_port);
result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL);
SHUTDOWN_ON_ERROR(result);
+ // Retrieve the ReceivePort that the service is waiting on. The _receivePort
+ // variable is setup in the call to main.
+ Dart_Handle receivePort = Dart_GetField(library,
+ DartUtils::NewString("_receivePort"));
+ SHUTDOWN_ON_ERROR(receivePort);
+
+ {
+ // Extract the Dart_Port from the receive port.
+ HANDLESCOPE(Isolate::Current());
+ const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(receivePort));
+ const Instance& rp = Instance::Cast(unwrapped_rp);
+ // Extract ReceivePort port id.
+ const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp));
+ if (rp_id_obj.IsError()) {
+ const Error& error = Error::Cast(rp_id_obj);
+ error_msg_ = strdup(error.ToErrorCString());
+ Dart_ExitScope();
+ Dart_ShutdownIsolate();
+ return false;
+ }
+ ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint());
+ Integer& id = Integer::Handle();
+ id ^= rp_id_obj.raw();
+ port_ = static_cast<Dart_Port>(id.AsInt64Value());
+ }
+
Dart_Handle library_name = Dart_NewStringFromCString(kVMServiceLibraryName);
library = Dart_LookupLibrary(library_name);
SHUTDOWN_ON_ERROR(library);
result = LoadResources(library);
SHUTDOWN_ON_ERROR(result);
- result = Dart_CompileAll();
- SHUTDOWN_ON_ERROR(result);
-
- port_ = Dart_GetMainPortId();
Dart_ExitScope();
Dart_ExitIsolate();
@@ -392,47 +414,58 @@
}
-static Dart_Handle MakeServiceControlMessage(Dart_Port port, intptr_t code) {
+static Dart_Handle MakeServiceControlMessage(Dart_Port port_id, intptr_t code,
+ Dart_Handle name) {
Dart_Handle result;
- Dart_Handle list = Dart_NewList(3);
+ Dart_Handle list = Dart_NewList(4);
ASSERT(!Dart_IsError(list));
- Dart_Handle codeHandle = Dart_NewInteger(code);
- ASSERT(!Dart_IsError(codeHandle));
- result = Dart_ListSetAt(list, 0, codeHandle);
+ Dart_Handle code_handle = Dart_NewInteger(code);
+ ASSERT(!Dart_IsError(code_handle));
+ result = Dart_ListSetAt(list, 0, code_handle);
ASSERT(!Dart_IsError(result));
- Dart_Handle sendPort = Dart_NewSendPort(port);
+ Dart_Handle port_id_handle = Dart_NewInteger(port_id);
+ ASSERT(!Dart_IsError(port_id_handle));
+ result = Dart_ListSetAt(list, 1, port_id_handle);
+ ASSERT(!Dart_IsError(result));
+ Dart_Handle sendPort = Dart_NewSendPort(port_id);
ASSERT(!Dart_IsError(sendPort));
- result = Dart_ListSetAt(list, 1, sendPort);
+ result = Dart_ListSetAt(list, 2, sendPort);
+ ASSERT(!Dart_IsError(result));
+ result = Dart_ListSetAt(list, 3, name);
ASSERT(!Dart_IsError(result));
return list;
}
-bool VmService::SendIsolateStartupMessage(Dart_Port port, Dart_Handle name) {
+bool VmService::SendIsolateStartupMessage() {
if (!IsRunning()) {
return false;
}
- Dart_Isolate isolate = Dart_CurrentIsolate();
+ Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
- ASSERT(Dart_GetMainPortId() == port);
+ HANDLESCOPE(isolate);
+ Dart_Handle name = Api::NewHandle(isolate, String::New(isolate->name()));
+ ASSERT(!Dart_IsError(name));
Dart_Handle list =
- MakeServiceControlMessage(port, VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID);
+ MakeServiceControlMessage(Dart_GetMainPortId(),
+ VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID,
+ name);
ASSERT(!Dart_IsError(list));
- Dart_Handle result = Dart_ListSetAt(list, 2, name);
- ASSERT(!Dart_IsError(result));
return Dart_Post(port_, list);
}
-bool VmService::SendIsolateShutdownMessage(Dart_Port port) {
+bool VmService::SendIsolateShutdownMessage() {
if (!IsRunning()) {
return false;
}
- Dart_Isolate isolate = Dart_CurrentIsolate();
+ Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
- ASSERT(Dart_GetMainPortId() == port);
+ HANDLESCOPE(isolate);
Dart_Handle list =
- MakeServiceControlMessage(port, VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID);
+ MakeServiceControlMessage(Dart_GetMainPortId(),
+ VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID,
+ Dart_Null());
ASSERT(!Dart_IsError(list));
return Dart_Post(port_, list);
}
@@ -441,7 +474,7 @@
void VmService::VmServiceShutdownCallback(void* callback_data) {
ASSERT(Dart_CurrentIsolate() != NULL);
Dart_EnterScope();
- VmService::SendIsolateShutdownMessage(Dart_GetMainPortId());
+ VmService::SendIsolateShutdownMessage();
Dart_ExitScope();
}
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 6a64560..0a19ebe 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -23,8 +23,8 @@
static bool IsRunning();
- static bool SendIsolateStartupMessage(Dart_Port port, Dart_Handle name);
- static bool SendIsolateShutdownMessage(Dart_Port port);
+ static bool SendIsolateStartupMessage();
+ static bool SendIsolateShutdownMessage();
static void VmServiceShutdownCallback(void* callback_data);
diff --git a/runtime/include/dart_debugger_api.h b/runtime/include/dart_debugger_api.h
index 12433b9..0c9c404 100755
--- a/runtime/include/dart_debugger_api.h
+++ b/runtime/include/dart_debugger_api.h
@@ -600,6 +600,15 @@
/**
+ * Returns in \library_id the library id of the given \library.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
+ intptr_t* library_id);
+
+
+/**
* Returns an array containing all variable names and values of
* the given library \library_id.
*
diff --git a/runtime/include/dart_mirrors_api.h b/runtime/include/dart_mirrors_api.h
index be50e49..3a4c9ce 100644
--- a/runtime/include/dart_mirrors_api.h
+++ b/runtime/include/dart_mirrors_api.h
@@ -122,14 +122,6 @@
DART_EXPORT Dart_Handle Dart_LibraryName(Dart_Handle library);
/**
- * Returns in \library_id the library id of the given \library.
- *
- * \return A valid handle if no error occurs during the operation.
- */
-DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
- intptr_t* library_id);
-
-/**
* Returns a list of the names of all classes and interfaces declared
* in a library.
*
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index cdfc5df..ffadba8 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -39,6 +39,7 @@
Dart_CObject_kArray,
Dart_CObject_kTypedData,
Dart_CObject_kExternalTypedData,
+ Dart_CObject_kSendPort,
Dart_CObject_kUnsupported,
Dart_CObject_kNumberOfTypes
} Dart_CObject_Type;
@@ -52,6 +53,7 @@
double as_double;
char* as_string;
char* as_bigint;
+ Dart_Port as_send_port;
struct {
intptr_t length;
struct _Dart_CObject** values;
@@ -101,8 +103,7 @@
*/
typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id,
-Dart_Port reply_port_id,
-Dart_CObject* message);
+ Dart_CObject* message);
/**
* Creates a new native port. When messages are received on this
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 8e4ecbe..4545715 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -110,6 +110,11 @@
final String _msg;
}
+patch class CyclicInitializationError {
+ static _throwNew(String variableName) {
+ throw new CyclicInitializationError(variableName);
+ }
+}
patch class AbstractClassInstantiationError {
AbstractClassInstantiationError._create(
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 28ff352..c11ea61 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -1425,11 +1425,9 @@
}
-DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 3) {
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
- ASSERT(!closure.IsNull() && closure.IsCallable(NULL, NULL));
- GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(1));
- GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(2));
+DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(1));
const Array& args_descriptor =
Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
@@ -1530,9 +1528,10 @@
Function& function = Function::Handle();
bool callable = closure.IsCallable(&function, NULL);
- ASSERT(callable);
-
- return CreateMethodMirror(function, Instance::null_instance());
+ if (callable) {
+ return CreateMethodMirror(function, Instance::null_instance());
+ }
+ return Instance::null();
}
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 5bb24ac..cdcf3e3 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -401,7 +401,7 @@
InstanceMirror apply(List<Object> positionalArguments,
[Map<Symbol, Object> namedArguments]) {
- // TODO(iposva): When closures get an ordinary call method, this can be
+ // TODO(12602): When closures get an ordinary call method, this can be
// replaced with
// return this.invoke(#call, positionalArguments, namedArguments);
// and the native ClosureMirror_apply can be removed.
@@ -423,7 +423,7 @@
// It is tempting to implement this in terms of Function.apply, but then
// lazy compilation errors would be fatal.
- return reflect(_apply(_reflectee, arguments, names));
+ return reflect(_apply(arguments, names));
}
Future<InstanceMirror> applyAsync(List positionalArguments,
@@ -448,7 +448,7 @@
String toString() => "ClosureMirror on '${Error.safeToString(_reflectee)}'";
- static _apply(reflectee, arguments, argumentNames)
+ static _apply(arguments, argumentNames)
native 'ClosureMirror_apply';
static _computeFunction(reflectee)
diff --git a/runtime/lib/mirrors_patch.dart b/runtime/lib/mirrors_patch.dart
index 364b0ab..4af60c6 100644
--- a/runtime/lib/mirrors_patch.dart
+++ b/runtime/lib/mirrors_patch.dart
@@ -17,7 +17,7 @@
* Creates a [MirrorSystem] for the isolate which is listening on
* the [SendPort].
*/
-patch Future<MirrorSystem> mirrorSystemOf(SendPort port) {
+Future<MirrorSystem> mirrorSystemOf(SendPort port) {
return _Mirrors.mirrorSystemOf(port);
}
diff --git a/runtime/lib/platform_patch.dart b/runtime/lib/platform_patch.dart
deleted file mode 100644
index 80dfef9..0000000
--- a/runtime/lib/platform_patch.dart
+++ /dev/null
@@ -1,81 +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.
-
-patch int get numberOfProcessors => _platform.numberOfProcessors;
-
-patch String get pathSeparator => _platform.pathSeparator;
-
-patch String get operatingSystem => _platform.operatingSystem;
-
-patch String get localHostname => _platform.localHostname;
-
-patch String get version => _platform.version;
-
-patch Map<String, String> get environment => _platform.environment;
-
-patch String get executable => _platform.executable;
-
-patch Uri get script => _platform.script;
-
-patch List<String> get executableArguments => _platform.executableArguments;
-
-patch String get packageRoot => _platform.packageRoot;
-
-class _Platform {
- int get numberOfProcessors;
- String get pathSeparator;
- String get operatingSystem;
- String get localHostname;
- String get version;
- Map get environment;
- Uri get script;
- String get executable;
- List<String> get executableArguments;
- String get packageRoot;
-}
-
-// A non-default _Platform, with real values, is stored here by the embedder.
-_Platform _platform = new _DefaultPlatform();
-
-class _DefaultPlatform implements _Platform {
- int get numberOfProcessors {
- return null;
- }
-
- String get pathSeparator {
- return null;
- }
-
- String get operatingSystem {
- return null;
- }
-
- String get localHostname {
- return null;
- }
-
- String get version {
- return null;
- }
-
- Map get environment {
- return null;
- }
-
- Uri get script {
- return null;
- }
-
- String get executable {
- return null;
- }
-
- List<String> get executableArguments {
- return new List<String>(0);
- }
-
- String get packageRoot {
- return null;
- }
-}
diff --git a/runtime/lib/platform_sources.gypi b/runtime/lib/platform_sources.gypi
deleted file mode 100644
index dd1b34f..0000000
--- a/runtime/lib/platform_sources.gypi
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# This file contains all sources for the dart:platform library.
-{
- 'sources': [
- 'platform_patch.dart',
- ],
-}
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index bab0aba..6b45135 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -210,7 +210,7 @@
}
-DEFINE_NATIVE_ENTRY(Strings_concatAll, 3) {
+DEFINE_NATIVE_ENTRY(String_concatRange, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, argument, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, start, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, end, arguments->NativeArgAt(2));
diff --git a/runtime/lib/string_buffer_patch.dart b/runtime/lib/string_buffer_patch.dart
index 72ec095..5d8b9b4 100644
--- a/runtime/lib/string_buffer_patch.dart
+++ b/runtime/lib/string_buffer_patch.dart
@@ -102,7 +102,7 @@
_consumeBuffer();
return (_partsCodeUnits == 0) ?
"" :
- _StringBase._concatAllNative(_parts, 0, _parts.length);
+ _StringBase._concatRange(_parts, 0, _parts.length);
}
/** Ensures that the buffer has enough capacity to add n code units. */
@@ -153,7 +153,7 @@
*/
void _compact() {
if (_partsCodeUnitsSinceCompaction < _PARTS_TO_COMPACT_SIZE_LIMIT) {
- String compacted = _StringBase._concatAllNative(
+ String compacted = _StringBase._concatRange(
_parts,
_partsCompactionIndex, // Start
_partsCompactionIndex + _PARTS_TO_COMPACT // End
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index f19b305..93726b2 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -84,9 +84,8 @@
if (identical(this, other)) {
return true;
}
- if ((other is !String) ||
+ if ((other is! String) ||
(this.length != other.length)) {
- // TODO(5413632): Compare hash codes when both are present.
return false;
}
final len = this.length;
@@ -120,7 +119,7 @@
bool _substringMatches(int start, String other) {
if (other.isEmpty) return true;
- final int len = other.length;
+ final len = other.length;
if ((start < 0) || (start + len > this.length)) {
return false;
}
@@ -265,7 +264,7 @@
}
String trim() {
- final int len = this.length;
+ final len = this.length;
int first = 0;
for (; first < len; first++) {
if (!_isWhitespace(this.codeUnitAt(first))) {
@@ -405,7 +404,7 @@
* into a result string.
*/
static String _interpolate(List<String> values) {
- final int numValues = values.length;
+ final numValues = values.length;
_List stringList = new List<String>(numValues);
bool isOneByteString = true;
int totalLength = 0;
@@ -424,7 +423,7 @@
if (isOneByteString) {
return _OneByteString._concatAll(stringList, totalLength);
}
- return _concatAllNative(stringList, 0, stringList.length);
+ return _concatRangeNative(stringList, 0, stringList.length);
}
Iterable<Match> allMatches(String str) {
@@ -509,10 +508,31 @@
String toLowerCase() native "String_toLowerCase";
+ // Concatenate ['start', 'end'[ elements of 'strings'. 'strings' must contain
+ // String elements. Optimized for OneByteStrings.
+ static String _concatRange(List<String> strings, int start, int end) {
+ if ((end - start) == 1) {
+ return strings[start];
+ }
+ final numValues = strings.length;
+ if ((start == 0) && (end == numValues)) {
+ int totalLength = 0;
+ for (int i = 0; i < numValues; i++) {
+ String s = strings[i];
+ if (s._cid != _OneByteString._classId) {
+ return _concatRangeNative(strings, start, end);
+ }
+ totalLength += s.length;
+ }
+ return _OneByteString._concatAll(strings, totalLength);
+ }
+ return _concatRangeNative(strings, start, end);
+ }
+
// Call this method if not all list elements are known to be OneByteString(s).
// 'strings' must be an _List or _GrowableList.
- static String _concatAllNative(List<String> strings, int start, int end)
- native "Strings_concatAll";
+ static String _concatRangeNative(List<String> strings, int start, int end)
+ native "String_concatRange";
}
@@ -548,11 +568,11 @@
}
// All element of 'strings' must be OneByteStrings.
- static _concatAll(_List<String> strings, int totalLength) {
+ static _concatAll(List<String> strings, int totalLength) {
// TODO(srdjan): Improve code below and raise or eliminate the limit.
if (totalLength > 128) {
// Native is quicker.
- return _StringBase._concatAllNative(strings, 0, strings.length);
+ return _StringBase._concatRangeNative(strings, 0, strings.length);
}
var res = _OneByteString._allocate(totalLength);
final stringsLength = strings.length;
@@ -567,6 +587,24 @@
return res;
}
+ int indexOf(Pattern pattern, [int start = 0]) {
+ final len = this.length;
+ // Specialize for single character pattern.
+ // TODO(srdjan): Implement for other string classes.
+ if ((pattern._cid == _OneByteString._classId) &&
+ (pattern.length == 1) &&
+ (start >= 0) && (start < len)) {
+ final patternCu0 = pattern.codeUnitAt(0);
+ for (int i = start; i < len; i++) {
+ if (this.codeUnitAt(i) == patternCu0) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ return super.indexOf(pattern, start);
+ }
+
// Allocates a string of given length, expecting its content to be
// set using _setAt.
static _OneByteString _allocate(int length) native "OneByteString_allocate";
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index be2665c..704bfec 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -68,3 +68,10 @@
dart/isolate_mirror_remote_test: Fail # Issue 13921
dart/isolate_unhandled_exception_test: Fail # Issue 13921
dart/mirrored_compilation_error_test: Skip # Can't pass needed VM flag
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+dart/optimized_stacktrace_test: StaticWarning
+
+dart/isolate_mirror_local_test: Fail, OK # API being removed.
+dart/isolate_mirror_remote_test: Fail, OK # API being removed.
+dart/mirrored_compilation_error_test: CompileTimeError, OK # This test intentionally includes invalid method bodies.
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 0ee04fc..9fca435 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -62,10 +62,6 @@
mirrors,
Bootstrap::mirrors_source_paths_,
Bootstrap::mirrors_patch_paths_),
- INIT_LIBRARY(ObjectStore::kPlatform,
- platform,
- Bootstrap::platform_source_paths_,
- Bootstrap::platform_patch_paths_),
INIT_LIBRARY(ObjectStore::kTypedData,
typed_data,
Bootstrap::typed_data_source_paths_,
diff --git a/runtime/vm/bootstrap.h b/runtime/vm/bootstrap.h
index dd525d8..6ebc812 100644
--- a/runtime/vm/bootstrap.h
+++ b/runtime/vm/bootstrap.h
@@ -29,7 +29,6 @@
static const char* json_source_paths_[];
static const char* math_source_paths_[];
static const char* mirrors_source_paths_[];
- static const char* platform_source_paths_[];
static const char* typed_data_source_paths_[];
static const char* utf_source_paths_[];
@@ -42,7 +41,6 @@
static const char* isolate_patch_paths_[];
static const char* math_patch_paths_[];
static const char* mirrors_patch_paths_[];
- static const char* platform_patch_paths_[];
static const char* typed_data_patch_paths_[];
};
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index 70c27e5..a072563 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -76,10 +76,6 @@
ASSERT(!library.IsNull());
library.set_native_entry_resolver(resolver);
- library = Library::PlatformLibrary();
- ASSERT(!library.IsNull());
- library.set_native_entry_resolver(resolver);
-
library = Library::TypedDataLibrary();
ASSERT(!library.IsNull());
library.set_native_entry_resolver(resolver);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 8aed894..1c3ea31 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -101,7 +101,7 @@
V(String_concat, 2) \
V(String_toLowerCase, 1) \
V(String_toUpperCase, 1) \
- V(Strings_concatAll, 3) \
+ V(String_concatRange, 3) \
V(Math_sqrt, 1) \
V(Math_sin, 1) \
V(Math_cos, 1) \
@@ -264,7 +264,7 @@
V(InstanceMirror_computeType, 1) \
V(ClosureMirror_find_in_context, 2) \
V(ClosureMirror_function, 1) \
- V(ClosureMirror_apply, 3) \
+ V(ClosureMirror_apply, 2) \
V(ClassMirror_library, 1) \
V(ClassMirror_supertype, 1) \
V(ClassMirror_supertype_instantiated, 1) \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index a141dc3..789489f 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -584,12 +584,12 @@
// Such legal self-references occur with F-bounded quantification.
// Example 1: class Derived extends Base<Derived>.
// The type 'Derived' forms a cycle by pointing to itself via its
- // flattened type argument vector: Derived[Base[Derived[Base[...]]]]
- // We break the cycle as follows: Derived[Base[Derived[dynamic]]]
+ // flattened type argument vector: Derived[Derived[...]]
+ // We break the cycle as follows: Derived[Derived[dynamic]]
// Example 2: class Derived extends Base<Middle<Derived>> results in
- // Derived[Base[Middle[Derived[dynamic]]]]
+ // Derived[Middle[Derived[dynamic]]]
// Example 3: class Derived<T> extends Base<Derived<T>> results in
- // Derived[Base[Derived[dynamic]], T].
+ // Derived[Derived[dynamic], T].
ASSERT(super_type_args.IsNull()); // Same as a vector of dynamic.
} else {
super_type ^= FinalizeType(cls, super_type, finalization);
@@ -2127,7 +2127,7 @@
// Helper function called by IsAliasCycleFree.
-bool ClassFinalizer::IsParameterTypeCycleFree(
+bool ClassFinalizer::IsTypeCycleFree(
const Class& cls,
const AbstractType& type,
GrowableArray<intptr_t>* visited) {
@@ -2146,7 +2146,7 @@
AbstractType& type_arg = AbstractType::Handle();
for (intptr_t i = 0; i < type_args.Length(); i++) {
type_arg = type_args.TypeAt(i);
- if (!IsParameterTypeCycleFree(cls, type_arg, visited)) {
+ if (!IsTypeCycleFree(cls, type_arg, visited)) {
return false;
}
}
@@ -2170,19 +2170,35 @@
}
}
- // Visit the result type and parameter types of this signature type.
+ // Visit the bounds, result type, and parameter types of this signature type.
visited->Add(cls.id());
+ AbstractType& type = AbstractType::Handle();
+
+ // Check the bounds of this signature type.
+ const intptr_t num_type_params = cls.NumTypeParameters();
+ TypeParameter& type_param = TypeParameter::Handle();
+ const AbstractTypeArguments& type_params =
+ AbstractTypeArguments::Handle(cls.type_parameters());
+ ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
+ (type_params.Length() == num_type_params));
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ type = type_param.bound();
+ if (!IsTypeCycleFree(cls, type, visited)) {
+ return false;
+ }
+ }
+ // Check the result type of the function of this signature type.
const Function& function = Function::Handle(cls.signature_function());
- // Check class of result type.
- AbstractType& type = AbstractType::Handle(function.result_type());
- if (!IsParameterTypeCycleFree(cls, type, visited)) {
+ type = function.result_type();
+ if (!IsTypeCycleFree(cls, type, visited)) {
return false;
}
- // Check classes of formal parameter types.
+ // Check the formal parameter types of the function of this signature type.
const intptr_t num_parameters = function.NumParameters();
for (intptr_t i = 0; i < num_parameters; i++) {
type = function.ParameterTypeAt(i);
- if (!IsParameterTypeCycleFree(cls, type, visited)) {
+ if (!IsTypeCycleFree(cls, type, visited)) {
return false;
}
}
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index 793674b..197e1d6 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -98,9 +98,9 @@
private:
static bool IsSuperCycleFree(const Class& cls);
- static bool IsParameterTypeCycleFree(const Class& cls,
- const AbstractType& type,
- GrowableArray<intptr_t>* visited);
+ static bool IsTypeCycleFree(const Class& cls,
+ const AbstractType& type,
+ GrowableArray<intptr_t>* visited);
static bool IsAliasCycleFree(const Class& cls,
GrowableArray<intptr_t>* visited);
static bool IsMixinCycleFree(const Class& cls,
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index a5f45bf..d4893a4 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1383,6 +1383,7 @@
DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) {
const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
ASSERT(!function.IsNull());
+ ASSERT(function.HasCode());
if (CanOptimizeFunction(function, isolate)) {
const Error& error =
@@ -1441,6 +1442,7 @@
target_code.EntryPoint());
}
arguments.SetReturn(target_code);
+ ASSERT(target_function.HasCode());
}
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 63ea3a1..fefdd51 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -5775,34 +5775,35 @@
void NewNativePort_send123(Dart_Port dest_port_id,
- Dart_Port reply_port_id,
Dart_CObject *message) {
- // Gets a null message.
+ // Gets a send port message.
EXPECT_NOTNULL(message);
- EXPECT_EQ(Dart_CObject_kNull, message->type);
+ EXPECT_EQ(Dart_CObject_kArray, message->type);
+ EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
// Post integer value.
Dart_CObject* response =
reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
response->type = Dart_CObject_kInt32;
response->value.as_int32 = 123;
- Dart_PostCObject(reply_port_id, response);
+ Dart_PostCObject(
+ message->value.as_array.values[0]->value.as_send_port, response);
}
void NewNativePort_send321(Dart_Port dest_port_id,
- Dart_Port reply_port_id,
Dart_CObject* message) {
// Gets a null message.
EXPECT_NOTNULL(message);
- EXPECT_EQ(Dart_CObject_kNull, message->type);
+ EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
// Post integer value.
Dart_CObject* response =
reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
response->type = Dart_CObject_kInt32;
response->value.as_int32 = 321;
- Dart_PostCObject(reply_port_id, response);
+ Dart_PostCObject(
+ message->value.as_array.values[0]->value.as_send_port, response);
}
@@ -5820,7 +5821,8 @@
"import 'dart:isolate';\n"
"void callPort(SendPort port) {\n"
" var receivePort = new RawReceivePort();\n"
- " port.send(null, receivePort.sendPort);\n"
+ " var replyPort = receivePort.sendPort;\n"
+ " port.send([replyPort]);\n"
" receivePort.handler = (message) {\n"
" receivePort.close();\n"
" throw new Exception(message);\n"
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index c8484f9..0208c40 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -221,7 +221,8 @@
static Dart_TypedData_Type GetTypedDataTypeFromView(
- Dart_CObject_Internal* object) {
+ Dart_CObject_Internal* object,
+ char* class_name) {
struct {
const char* name;
Dart_TypedData_Type type;
@@ -241,13 +242,6 @@
{ NULL, Dart_TypedData_kInvalid },
};
- char* library_url =
- object->cls->internal.as_class.library_url->value.as_string;
- char* class_name =
- object->cls->internal.as_class.class_name->value.as_string;
- if (strcmp("dart:typed_data", library_url) != 0) {
- return Dart_TypedData_kInvalid;
- }
int i = 0;
while (view_class_names[i].name != NULL) {
if (strncmp(view_class_names[i].name,
@@ -286,31 +280,54 @@
static_cast<Dart_CObject_Type>(
Dart_CObject_Internal::kUninitialized));
+ char* library_uri =
+ object->cls->internal.as_class.library_url->value.as_string;
+ char* class_name =
+ object->cls->internal.as_class.class_name->value.as_string;
+
// Handle typed data views.
- Dart_TypedData_Type type = GetTypedDataTypeFromView(object);
- if (type != Dart_TypedData_kInvalid) {
- object->type =
- static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView);
+ if (strcmp("dart:typed_data", library_uri) == 0) {
+ Dart_TypedData_Type type = GetTypedDataTypeFromView(object, class_name);
+ if (type != Dart_TypedData_kInvalid) {
+ object->type =
+ static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView);
+ ReadObjectImpl(); // Skip type arguments.
+ object->internal.as_view.buffer = ReadObjectImpl();
+ object->internal.as_view.offset_in_bytes = ReadSmiValue();
+ object->internal.as_view.length = ReadSmiValue();
+ ReadObjectImpl(); // Skip last field.
+
+ // The buffer is fully read now as typed data objects are
+ // serialized in-line.
+ Dart_CObject* buffer = object->internal.as_view.buffer;
+ ASSERT(buffer->type == Dart_CObject_kTypedData);
+
+ // Now turn the view into a byte array.
+ object->type = Dart_CObject_kTypedData;
+ object->value.as_typed_data.type = type;
+ object->value.as_typed_data.length =
+ object->internal.as_view.length *
+ GetTypedDataSizeInBytes(type);
+ object->value.as_typed_data.values =
+ buffer->value.as_typed_data.values +
+ object->internal.as_view.offset_in_bytes;
+ } else {
+ // TODO(sgjesse): Handle other instances. Currently this will
+ // skew the reading as the fields of the instance is not read.
+ }
+ } else if (strcmp("dart:isolate", library_uri) == 0 &&
+ strncmp("_SendPortImpl@", class_name, 14) == 0) {
ReadObjectImpl(); // Skip type arguments.
- object->internal.as_view.buffer = ReadObjectImpl();
- object->internal.as_view.offset_in_bytes = ReadSmiValue();
- object->internal.as_view.length = ReadSmiValue();
+ // Read the port id.
+ Dart_CObject* port = ReadObjectImpl();
+ if (port->type == Dart_CObject_kInt32) {
+ object->type = Dart_CObject_kSendPort;
+ object->value.as_send_port = port->value.as_int32;
+ } else if (port->type == Dart_CObject_kInt64) {
+ object->type = Dart_CObject_kSendPort;
+ object->value.as_send_port = port->value.as_int64;
+ }
ReadObjectImpl(); // Skip last field.
-
- // The buffer is fully read now as typed data objects are
- // serialized in-line.
- Dart_CObject* buffer = object->internal.as_view.buffer;
- ASSERT(buffer->type == Dart_CObject_kTypedData);
-
- // Now turn the view into a byte array.
- object->type = Dart_CObject_kTypedData;
- object->value.as_typed_data.type = type;
- object->value.as_typed_data.length =
- object->internal.as_view.length *
- GetTypedDataSizeInBytes(type);
- object->value.as_typed_data.values =
- buffer->value.as_typed_data.values +
- object->internal.as_view.offset_in_bytes;
} else {
// TODO(sgjesse): Handle other instances. Currently this will
// skew the reading as the fields of the instance is not read.
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 3ffff4a..c20bf67 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -796,6 +796,22 @@
}
+DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
+ intptr_t* library_id) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ if (lib.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, library, Library);
+ }
+ if (library_id == NULL) {
+ RETURN_NULL_ERROR(library_id);
+ }
+ *library_id = lib.index();
+ return Api::Success();
+}
+
+
DART_EXPORT Dart_Handle Dart_GetLibraryImports(intptr_t library_id) {
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 474b313..c5266d1 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -1168,7 +1168,11 @@
// TODO(vegorov): verify after deoptimization targets as well.
#ifdef DEBUG
const Code& code = Code::Handle(function.unoptimized_code());
- ASSERT(Isolate::IsDeoptAfter(deopt_id) ||
+ // The inlined function's code pointer may be null if there is a GC during
+ // compilation.
+ // TODO(zra): See if we can avoid this check by ensuring that code is not
+ // removed during inlining.
+ ASSERT(code.IsNull() || Isolate::IsDeoptAfter(deopt_id) ||
(code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0));
#endif
const intptr_t object_table_index = FindOrAddObjectInTable(function);
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index eac4aa7..bf34043 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -1164,13 +1164,23 @@
FlowGraphOptimizer optimizer(owner_->caller_graph());
TargetEntryInstr* entry;
Definition* last;
+ // Replace the receiver argument with a redefinition to prevent code from
+ // the inlined body from being hoisted above the inlined entry.
+ GrowableArray<Definition*> arguments(call_->ArgumentCount());
+ Definition* receiver = call_->ArgumentAt(0);
+ RedefinitionInstr* redefinition =
+ new RedefinitionInstr(new Value(receiver));
+ redefinition->set_ssa_temp_index(
+ owner_->caller_graph()->alloc_ssa_temp_index());
if (optimizer.TryInlineRecognizedMethod(receiver_cid,
target,
call_,
+ redefinition,
call_->instance_call()->token_pos(),
*call_->instance_call()->ic_data(),
&entry, &last)) {
// Create a graph fragment.
+ redefinition->InsertAfter(entry);
InlineExitCollector* exit_collector =
new InlineExitCollector(owner_->caller_graph(), call_);
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 87e4c88..da6de7b 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -832,6 +832,7 @@
if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0),
target,
call,
+ call->ArgumentAt(0),
call->token_pos(),
*call->ic_data(),
&entry, &last)) {
@@ -865,6 +866,7 @@
MethodRecognizer::Kind kind,
const Function& target,
Instruction* call,
+ Definition* receiver,
intptr_t token_pos,
const ICData* ic_data,
const ICData& value_check,
@@ -873,7 +875,7 @@
intptr_t array_cid = MethodKindToCid(kind);
ASSERT(array_cid != kIllegalCid);
- Definition* array = call->ArgumentAt(0);
+ Definition* array = receiver;
Definition* index = call->ArgumentAt(1);
Definition* stored_value = call->ArgumentAt(2);
@@ -999,6 +1001,7 @@
bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid,
const Function& target,
Instruction* call,
+ Definition* receiver,
intptr_t token_pos,
const ICData& ic_data,
TargetEntryInstr** entry,
@@ -1019,14 +1022,14 @@
case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
case MethodRecognizer::kInt16ArrayGetIndexed:
case MethodRecognizer::kUint16ArrayGetIndexed:
- return InlineGetIndexed(kind, call, ic_data, entry, last);
+ return InlineGetIndexed(kind, call, receiver, ic_data, entry, last);
case MethodRecognizer::kFloat32x4ArrayGetIndexed:
if (!ShouldInlineSimd()) return false;
- return InlineGetIndexed(kind, call, ic_data, entry, last);
+ return InlineGetIndexed(kind, call, receiver, ic_data, entry, last);
case MethodRecognizer::kInt32ArrayGetIndexed:
case MethodRecognizer::kUint32ArrayGetIndexed:
if (!CanUnboxInt32()) return false;
- return InlineGetIndexed(kind, call, ic_data, entry, last);
+ return InlineGetIndexed(kind, call, receiver, ic_data, entry, last);
// Recognized []= operators.
case MethodRecognizer::kObjectArraySetIndexed:
@@ -1034,7 +1037,7 @@
if (ArgIsAlways(kSmiCid, ic_data, 2)) {
value_check = ic_data.AsUnaryClassChecksForArgNr(2);
}
- return InlineSetIndexed(kind, target, call, token_pos,
+ return InlineSetIndexed(kind, target, call, receiver, token_pos,
&ic_data, value_check, entry, last);
case MethodRecognizer::kInt8ArraySetIndexed:
case MethodRecognizer::kUint8ArraySetIndexed:
@@ -1045,7 +1048,7 @@
case MethodRecognizer::kUint16ArraySetIndexed:
if (!ArgIsAlways(kSmiCid, ic_data, 2)) return false;
value_check = ic_data.AsUnaryClassChecksForArgNr(2);
- return InlineSetIndexed(kind, target, call, token_pos,
+ return InlineSetIndexed(kind, target, call, receiver, token_pos,
&ic_data, value_check, entry, last);
case MethodRecognizer::kInt32ArraySetIndexed:
case MethodRecognizer::kUint32ArraySetIndexed:
@@ -1060,59 +1063,59 @@
} else if (!HasOnlyOneSmi(value_check)) {
return false;
}
- return InlineSetIndexed(kind, target, call, token_pos,
+ return InlineSetIndexed(kind, target, call, receiver, token_pos,
&ic_data, value_check, entry, last);
case MethodRecognizer::kFloat32ArraySetIndexed:
case MethodRecognizer::kFloat64ArraySetIndexed:
// Check that value is always double.
if (!ArgIsAlways(kDoubleCid, ic_data, 2)) return false;
value_check = ic_data.AsUnaryClassChecksForArgNr(2);
- return InlineSetIndexed(kind, target, call, token_pos,
+ return InlineSetIndexed(kind, target, call, receiver, token_pos,
&ic_data, value_check, entry, last);
case MethodRecognizer::kFloat32x4ArraySetIndexed:
if (!ShouldInlineSimd()) return false;
// Check that value is always a Float32x4.
if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) return false;
value_check = ic_data.AsUnaryClassChecksForArgNr(2);
- return InlineSetIndexed(kind, target, call, token_pos,
+ return InlineSetIndexed(kind, target, call, receiver, token_pos,
&ic_data, value_check, entry, last);
case MethodRecognizer::kByteArrayBaseGetInt8:
- return InlineByteArrayViewLoad(call, receiver_cid,
+ return InlineByteArrayViewLoad(call, receiver, receiver_cid,
kTypedDataInt8ArrayCid,
ic_data, entry, last);
case MethodRecognizer::kByteArrayBaseGetUint8:
- return InlineByteArrayViewLoad(call, receiver_cid,
+ return InlineByteArrayViewLoad(call, receiver, receiver_cid,
kTypedDataUint8ArrayCid,
ic_data, entry, last);
case MethodRecognizer::kByteArrayBaseGetInt16:
- return InlineByteArrayViewLoad(call, receiver_cid,
+ return InlineByteArrayViewLoad(call, receiver, receiver_cid,
kTypedDataInt16ArrayCid,
ic_data, entry, last);
case MethodRecognizer::kByteArrayBaseGetUint16:
- return InlineByteArrayViewLoad(call, receiver_cid,
+ return InlineByteArrayViewLoad(call, receiver, receiver_cid,
kTypedDataUint16ArrayCid,
ic_data, entry, last);
case MethodRecognizer::kByteArrayBaseGetInt32:
if (!CanUnboxInt32()) return false;
- return InlineByteArrayViewLoad(call, receiver_cid,
+ return InlineByteArrayViewLoad(call, receiver, receiver_cid,
kTypedDataInt32ArrayCid,
ic_data, entry, last);
case MethodRecognizer::kByteArrayBaseGetUint32:
if (!CanUnboxInt32()) return false;
- return InlineByteArrayViewLoad(call, receiver_cid,
+ return InlineByteArrayViewLoad(call, receiver, receiver_cid,
kTypedDataUint32ArrayCid,
ic_data, entry, last);
case MethodRecognizer::kByteArrayBaseGetFloat32:
- return InlineByteArrayViewLoad(call, receiver_cid,
+ return InlineByteArrayViewLoad(call, receiver, receiver_cid,
kTypedDataFloat32ArrayCid,
ic_data, entry, last);
case MethodRecognizer::kByteArrayBaseGetFloat64:
- return InlineByteArrayViewLoad(call, receiver_cid,
+ return InlineByteArrayViewLoad(call, receiver, receiver_cid,
kTypedDataFloat64ArrayCid,
ic_data, entry, last);
case MethodRecognizer::kByteArrayBaseGetFloat32x4:
if (!ShouldInlineSimd()) return false;
- return InlineByteArrayViewLoad(call, receiver_cid,
+ return InlineByteArrayViewLoad(call, receiver, receiver_cid,
kTypedDataFloat32x4ArrayCid,
ic_data, entry, last);
default:
@@ -1186,13 +1189,14 @@
bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind,
Instruction* call,
+ Definition* receiver,
const ICData& ic_data,
TargetEntryInstr** entry,
Definition** last) {
intptr_t array_cid = MethodKindToCid(kind);
ASSERT(array_cid != kIllegalCid);
- Definition* array = call->ArgumentAt(0);
+ Definition* array = receiver;
Definition* index = call->ArgumentAt(1);
*entry = new TargetEntryInstr(flow_graph()->allocate_block_id(),
call->GetBlock()->try_index());
@@ -1242,6 +1246,7 @@
if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0),
target,
call,
+ call->ArgumentAt(0),
call->token_pos(),
*call->ic_data(),
&entry, &last)) {
@@ -2483,13 +2488,14 @@
bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call,
+ Definition* receiver,
intptr_t array_cid,
intptr_t view_cid,
const ICData& ic_data,
TargetEntryInstr** entry,
Definition** last) {
ASSERT(array_cid != kIllegalCid);
- Definition* array = call->ArgumentAt(0);
+ Definition* array = receiver;
Definition* index = call->ArgumentAt(1);
*entry = new TargetEntryInstr(flow_graph()->allocate_block_id(),
call->GetBlock()->try_index());
@@ -2625,6 +2631,7 @@
if (!TryInlineRecognizedMethod(receiver_cid,
target,
call,
+ call->ArgumentAt(0),
call->token_pos(),
*call->ic_data(),
&entry, &last)) {
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 17fd3cf..2940c6b 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -47,6 +47,7 @@
bool TryInlineRecognizedMethod(intptr_t receiver_cid,
const Function& target,
Instruction* call,
+ Definition* receiver,
intptr_t token_pos,
const ICData& ic_data,
TargetEntryInstr** entry,
@@ -77,6 +78,7 @@
bool InlineSetIndexed(MethodRecognizer::Kind kind,
const Function& target,
Instruction* call,
+ Definition* receiver,
intptr_t token_pos,
const ICData* ic_data,
const ICData& value_check,
@@ -85,6 +87,7 @@
bool TryReplaceWithLoadIndexed(InstanceCallInstr* call);
bool InlineGetIndexed(MethodRecognizer::Kind kind,
Instruction* call,
+ Definition* receiver,
const ICData& ic_data,
TargetEntryInstr** entry,
Definition** last);
@@ -120,6 +123,7 @@
intptr_t cid);
bool InlineByteArrayViewLoad(Instruction* call,
+ Definition* receiver,
intptr_t array_cid,
intptr_t view_cid,
const ICData& ic_data,
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index deebded..0c6c274 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -70,7 +70,7 @@
V(_StringBase, get:isEmpty, StringBaseIsEmpty, 879849436) \
V(_StringBase, codeUnitAt, StringBaseCodeUnitAt, 1958436584) \
V(_StringBase, [], StringBaseCharAt, 990046076) \
- V(_StringBase, _interpolate, StringBaseInterpolate, 908021574) \
+ V(_StringBase, _interpolate, StringBaseInterpolate, 1824308855) \
V(_OneByteString, _setAt, OneByteStringSetAt, 308408714) \
V(_IntegerImplementation, toDouble, IntegerToDouble, 2011998508) \
V(_IntegerImplementation, _leftShiftWithMask32, IntegerLeftShiftWithMask32, \
diff --git a/runtime/vm/mirrors_api_impl.cc b/runtime/vm/mirrors_api_impl.cc
index af7c096..1ab2323 100644
--- a/runtime/vm/mirrors_api_impl.cc
+++ b/runtime/vm/mirrors_api_impl.cc
@@ -323,20 +323,6 @@
return Api::NewHandle(isolate, name.raw());
}
-DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
- intptr_t* library_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
- if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
- }
- if (library_id != NULL) {
- *library_id = lib.index();
- }
- return Api::Success();
-}
-
DART_EXPORT Dart_Handle Dart_LibraryGetClassNames(Dart_Handle library) {
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
diff --git a/runtime/vm/native_message_handler.cc b/runtime/vm/native_message_handler.cc
index 83bcf5e..7b3d9b9 100644
--- a/runtime/vm/native_message_handler.cc
+++ b/runtime/vm/native_message_handler.cc
@@ -51,7 +51,7 @@
ApiNativeScope scope;
ApiMessageReader reader(message->data(), message->len(), zone_allocator);
Dart_CObject* object = reader.ReadMessage();
- (*func())(message->dest_port(), message->reply_port(), object);
+ (*func())(message->dest_port(), object);
delete message;
return true;
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 314f142..b28e24f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2416,29 +2416,46 @@
void Class::PatchSignatureFunction(const Function& signature_function) const {
ASSERT(!signature_function.IsNull());
+ set_signature_function(signature_function);
const Class& owner_class = Class::Handle(signature_function.Owner());
ASSERT(!owner_class.IsNull());
- TypeArguments& type_parameters = TypeArguments::Handle();
- // A signature class extends class Instance and is parameterized in the same
- // way as the owner class of its non-static signature function.
- // It is not type parameterized if its signature function is static.
- // In case of a function type alias, the function owner is the alias class
- // instead of the enclosing class.
- if (!signature_function.is_static() &&
- (owner_class.NumTypeParameters() > 0) &&
- !signature_function.HasInstantiatedSignature()) {
- type_parameters = owner_class.type_parameters();
- }
- set_signature_function(signature_function);
- set_type_parameters(type_parameters);
+ // A signature class extends class Instance and is either not parameterized or
+ // parameterized with exactly the same list of type parameters as the owner
+ // class of its function.
+ // In case of a function type alias, the function owner is the alias class,
+ // which is also the signature class. The signature class is therefore
+ // parameterized according to the alias class declaration, even if the
+ // function type is not generic.
+ // Otherwise, if the function is static or if its signature type is
+ // non-generic, i.e. it does not depend on any type parameter of the owner
+ // class, then the signature class is not parameterized, although the owner
+ // class may be.
if (owner_class.raw() == raw()) {
// This signature class is an alias, which cannot be the canonical
// signature class for this signature function.
ASSERT(!IsCanonicalSignatureClass());
- } else if (signature_function.signature_class() == Object::null()) {
- // Make this signature class the canonical signature class.
- signature_function.set_signature_class(*this);
- ASSERT(IsCanonicalSignatureClass());
+ // Do not modify the declared type parameters of the alias, even if unused.
+ } else {
+ // Copy the type parameters only for an instance function type that is not
+ // instantiated, i.e. that depends on the type parameters of the owner
+ // class.
+ // TODO(regis): Verify that it is not a problem for the copied type
+ // parameters to refer to the owner class rather than to the signature
+ // class. In other words, uninstantiated function types should only get
+ // instantiated by the owner class as instantiator and never by the
+ // signature class itself.
+ TypeArguments& type_parameters = TypeArguments::Handle();
+ if (!signature_function.is_static() &&
+ (owner_class.NumTypeParameters() > 0) &&
+ !signature_function.HasInstantiatedSignature()) {
+ type_parameters = owner_class.type_parameters();
+ }
+ set_type_parameters(type_parameters);
+ if (signature_function.signature_class() == Object::null()) {
+ // Make this signature class the canonical signature class.
+ signature_function.set_signature_class(*this);
+ ASSERT(IsCanonicalSignatureClass());
+ }
}
set_is_prefinalized();
}
@@ -4051,8 +4068,8 @@
void Function::ReattachCode(const Code& code) const {
- set_unoptimized_code(code);
- SetCode(code);
+ StorePointer(&raw_ptr()->code_, code.raw());
+ StorePointer(&raw_ptr()->unoptimized_code_, code.raw());
CodePatcher::RestoreEntry(code);
}
@@ -4510,7 +4527,9 @@
bool Function::IsInlineable() const {
- return InlinableBit::decode(raw_ptr()->kind_tag_) && HasCode();
+ return (InlinableBit::decode(raw_ptr()->kind_tag_) &&
+ HasCode() &&
+ !Isolate::Current()->debugger()->HasBreakpoint(*this));
}
@@ -7926,10 +7945,6 @@
return Isolate::Current()->object_store()->native_wrappers_library();
}
-RawLibrary* Library::PlatformLibrary() {
- return Isolate::Current()->object_store()->platform_library();
-}
-
RawLibrary* Library::TypedDataLibrary() {
return Isolate::Current()->object_store()->typed_data_library();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index d477a41..1a2e1d2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2543,7 +2543,6 @@
static RawLibrary* MathLibrary();
static RawLibrary* MirrorsLibrary();
static RawLibrary* NativeWrappersLibrary();
- static RawLibrary* PlatformLibrary();
static RawLibrary* TypedDataLibrary();
static RawLibrary* UtfLibrary();
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index d131951..37add48 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -29,7 +29,6 @@
kIsolate,
kMath,
kMirrors,
- kPlatform,
kTypedData,
kUtf,
};
@@ -279,7 +278,6 @@
RawLibrary* isolate_library() const { return isolate_library_; }
RawLibrary* math_library() const { return math_library_; }
RawLibrary* mirrors_library() const { return mirrors_library_; }
- RawLibrary* platform_library() const { return platform_library_; }
RawLibrary* typed_data_library() const { return typed_data_library_; }
RawLibrary* utf_library() const { return utf_library_; }
void set_bootstrap_library(BootstrapLibraryId index, const Library& value) {
@@ -308,9 +306,6 @@
case kMirrors:
mirrors_library_ = value.raw();
break;
- case kPlatform:
- platform_library_ = value.raw();
- break;
case kTypedData:
typed_data_library_ = value.raw();
break;
@@ -483,7 +478,6 @@
RawLibrary* math_library_;
RawLibrary* mirrors_library_;
RawLibrary* native_wrappers_library_;
- RawLibrary* platform_library_;
RawLibrary* root_library_;
RawLibrary* typed_data_library_;
RawLibrary* utf_library_;
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index cba6d44..70dd982 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -7,6 +7,7 @@
#include "vm/class_finalizer.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
+#include "vm/debugger.h"
#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/object_store.h"
@@ -3546,6 +3547,45 @@
}
+TEST_CASE(FunctionWithBreakpointNotInlined) {
+ const char* kScriptChars =
+ "class A {\n"
+ " a() {\n"
+ " }\n"
+ " b() {\n"
+ " a();\n" // This is line 5.
+ " }\n"
+ "}\n"
+ "test() {\n"
+ " new A().b();\n"
+ "}";
+ const int kBreakpointLine = 5;
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+ EXPECT_VALID(lib);
+
+ // Run function A.b one time.
+ Dart_Handle result = Dart_Invoke(lib, NewString("test"), 0, NULL);
+ EXPECT_VALID(result);
+
+ // With no breakpoint, function A.b is inlineable.
+ const String& name = String::Handle(String::New(TestCase::url()));
+ const Library& vmlib = Library::Handle(Library::LookupLibrary(name));
+ EXPECT(!vmlib.IsNull());
+ const Class& class_a = Class::Handle(
+ vmlib.LookupClass(String::Handle(Symbols::New("A"))));
+ const Function& func_b =
+ Function::Handle(GetFunction(class_a, "b"));
+ EXPECT(func_b.IsInlineable());
+
+ // After setting a breakpoint in a function A.b, it is no longer inlineable.
+ SourceBreakpoint* bpt =
+ Isolate::Current()->debugger()->SetBreakpointAtLine(name,
+ kBreakpointLine);
+ ASSERT(bpt != NULL);
+ EXPECT(!func_b.IsInlineable());
+}
+
+
TEST_CASE(SpecialClassesHaveEmptyArrays) {
ObjectStore* object_store = Isolate::Current()->object_store();
Class& cls = Class::Handle();
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index c9b1539..9b26bc3 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -23,7 +23,7 @@
"Print free list statistics before a GC");
DEFINE_FLAG(bool, print_free_list_after_gc, false,
"Print free list statistics after a GC");
-DEFINE_FLAG(bool, collect_code, true,
+DEFINE_FLAG(bool, collect_code, false,
"Attempt to GC infrequently used code.");
DEFINE_FLAG(int, code_collection_interval_in_us, 30000000,
"Time between attempts to collect unused code.");
@@ -384,7 +384,6 @@
}
-
class CodeDetacherVisitor : public ObjectVisitor {
public:
explicit CodeDetacherVisitor(Isolate* isolate) : ObjectVisitor(isolate) { }
@@ -392,20 +391,26 @@
virtual void VisitObject(RawObject* obj);
private:
+ static bool MayDetachCode(const Function& fn);
DISALLOW_COPY_AND_ASSIGN(CodeDetacherVisitor);
};
+bool CodeDetacherVisitor::MayDetachCode(const Function& fn) {
+ return fn.HasCode() && // Not already detached.
+ !fn.HasOptimizedCode() &&
+ !fn.HasBreakpoint() &&
+ (fn.usage_counter() > 0);
+}
+
+
void CodeDetacherVisitor::VisitObject(RawObject* raw_obj) {
Isolate* isolate = Isolate::Current();
HANDLESCOPE(isolate);
const Object& obj = Object::Handle(raw_obj);
if (obj.GetClassId() == kFunctionCid) {
const Function& fn = Function::Cast(obj);
- if (!fn.HasOptimizedCode() &&
- !fn.HasBreakpoint() &&
- fn.HasCode() && // Not already detached.
- (fn.usage_counter() > 0)) {
+ if (CodeDetacherVisitor::MayDetachCode(fn)) {
fn.set_usage_counter(fn.usage_counter() / 2);
if (fn.usage_counter() == 0) {
if (FLAG_log_code_drop) {
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 1801810..fea9b98 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -968,13 +968,13 @@
ident_pos,
field,
new LiteralNode(ident_pos, Instance::ZoneHandle())));
- // TODO(regis, 5802): Exception to throw is not specified by spec.
- const String& circular_error = String::ZoneHandle(
- Symbols::New("circular dependency in field initialization"));
+ // Call CyclicInitializationError._throwNew(field_name).
+ ArgumentListNode* error_arguments = new ArgumentListNode(ident_pos);
+ error_arguments->Add(new LiteralNode(ident_pos, field_name));
report_circular->Add(
- new ThrowNode(ident_pos,
- new LiteralNode(ident_pos, circular_error),
- NULL));
+ MakeStaticCall(Symbols::CyclicInitializationError(),
+ Library::PrivateCoreLibName(Symbols::ThrowNew()),
+ error_arguments));
AstNode* circular_check =
new IfNode(ident_pos, compare_circular, report_circular, NULL);
current_block_->statements->Add(circular_check);
@@ -3995,7 +3995,7 @@
bool is_alias_name = false;
if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) {
ConsumeToken();
- if (TryParseTypeParameter() && (CurrentToken() == Token::kLPAREN)) {
+ if (TryParseTypeParameters() && (CurrentToken() == Token::kLPAREN)) {
is_alias_name = true;
}
}
@@ -4014,7 +4014,7 @@
bool is_mixin_def = false;
if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) {
ConsumeToken();
- if (TryParseTypeParameter() && (CurrentToken() == Token::kASSIGN)) {
+ if (TryParseTypeParameters() && (CurrentToken() == Token::kASSIGN)) {
is_mixin_def = true;
}
}
@@ -5587,7 +5587,7 @@
// Returns true if the current and next tokens can be parsed as type
// parameters. Current token position is not saved and restored.
-bool Parser::TryParseTypeParameter() {
+bool Parser::TryParseTypeParameters() {
if (CurrentToken() == Token::kLT) {
// We are possibly looking at type parameters. Find closing ">".
int nesting_level = 0;
@@ -5672,7 +5672,7 @@
if (CurrentToken() == Token::kIDENT) {
QualIdent type_name;
ParseQualIdent(&type_name);
- if ((CurrentToken() == Token::kLT) && !TryParseTypeParameter()) {
+ if ((CurrentToken() == Token::kLT) && !TryParseTypeParameters()) {
return false;
}
}
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 5d8cc9b..5ccaca5 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -534,7 +534,7 @@
bool IsSimpleLiteral(const AbstractType& type, Instance* value);
bool IsFunctionTypeAliasName();
bool IsMixinTypedef();
- bool TryParseTypeParameter();
+ bool TryParseTypeParameters();
bool TryParseOptionalType();
bool TryParseReturnType();
bool IsVariableDeclaration();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 27b64cf..887a361 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -40,6 +40,7 @@
V(FallThroughError, "FallThroughError") \
V(AbstractClassInstantiationError, "AbstractClassInstantiationError") \
V(NoSuchMethodError, "NoSuchMethodError") \
+ V(CyclicInitializationError, "CyclicInitializationError") \
V(ThrowNew, "_throwNew") \
V(Symbol, "Symbol") \
V(SymbolCtor, "Symbol.") \
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index d8ff0b4..b55ac29 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -23,8 +23,6 @@
'mirrors_patch_cc_file': '<(gen_source_dir)/mirrors_patch_gen.cc',
'isolate_cc_file': '<(gen_source_dir)/isolate_gen.cc',
'isolate_patch_cc_file': '<(gen_source_dir)/isolate_patch_gen.cc',
- 'platform_cc_file': '<(gen_source_dir)/platform_gen.cc',
- 'platform_patch_cc_file': '<(gen_source_dir)/platform_patch_gen.cc',
'typed_data_cc_file': '<(gen_source_dir)/typed_data_gen.cc',
'typed_data_patch_cc_file': '<(gen_source_dir)/typed_data_patch_gen.cc',
'utf_cc_file': '<(gen_source_dir)/utf_gen.cc',
@@ -111,8 +109,6 @@
'generate_isolate_patch_cc_file#host',
'generate_mirrors_cc_file#host',
'generate_mirrors_patch_cc_file#host',
- 'generate_platform_cc_file#host',
- 'generate_platform_patch_cc_file#host',
'generate_typed_data_cc_file#host',
'generate_typed_data_patch_cc_file#host',
'generate_utf_cc_file#host',
@@ -124,7 +120,6 @@
'../lib/isolate_sources.gypi',
'../lib/math_sources.gypi',
'../lib/mirrors_sources.gypi',
- '../lib/platform_sources.gypi',
'../lib/typed_data_sources.gypi',
],
'sources': [
@@ -146,8 +141,6 @@
'<(isolate_patch_cc_file)',
'<(mirrors_cc_file)',
'<(mirrors_patch_cc_file)',
- '<(platform_cc_file)',
- '<(platform_patch_cc_file)',
'<(typed_data_cc_file)',
'<(typed_data_patch_cc_file)',
'<(utf_cc_file)',
@@ -167,7 +160,6 @@
'../lib/isolate_sources.gypi',
'../lib/math_sources.gypi',
'../lib/mirrors_sources.gypi',
- '../lib/platform_sources.gypi',
'../lib/typed_data_sources.gypi',
],
'sources': [
@@ -817,85 +809,6 @@
]
},
{
- 'target_name': 'generate_platform_cc_file',
- 'type': 'none',
- 'toolsets':['host'],
- 'includes': [
- '../../sdk/lib/platform/platform_sources.gypi',
- ],
- 'sources/': [
- # Exclude all .[cc|h] files.
- # This is only here for reference. Excludes happen after
- # variable expansion, so the script has to do its own
- # exclude processing of the sources being passed.
- ['exclude', '\\.cc|h$'],
- ],
- 'actions': [
- {
- 'action_name': 'generate_platform_cc',
- 'inputs': [
- '../tools/gen_library_src_paths.py',
- '<(libgen_in_cc_file)',
- '<@(_sources)',
- ],
- 'outputs': [
- '<(platform_cc_file)',
- ],
- 'action': [
- 'python',
- 'tools/gen_library_src_paths.py',
- '--output', '<(platform_cc_file)',
- '--input_cc', '<(libgen_in_cc_file)',
- '--include', 'vm/bootstrap.h',
- '--var_name', 'dart::Bootstrap::platform_source_paths_',
- '--library_name', 'dart:platform',
- '<@(_sources)',
- ],
- 'message': 'Generating ''<(platform_cc_file)'' file.'
- },
- ]
- },
- {
- 'target_name': 'generate_platform_patch_cc_file',
- 'type': 'none',
- 'toolsets':['host'],
- 'includes': [
- # Load the runtime implementation sources.
- '../lib/platform_sources.gypi',
- ],
- 'sources/': [
- # Exclude all .[cc|h] files.
- # This is only here for reference. Excludes happen after
- # variable expansion, so the script has to do its own
- # exclude processing of the sources being passed.
- ['exclude', '\\.cc|h$'],
- ],
- 'actions': [
- {
- 'action_name': 'generate_platform_patch_cc',
- 'inputs': [
- '../tools/gen_library_src_paths.py',
- '<(libgen_in_cc_file)',
- '<@(_sources)',
- ],
- 'outputs': [
- '<(platform_patch_cc_file)',
- ],
- 'action': [
- 'python',
- 'tools/gen_library_src_paths.py',
- '--output', '<(platform_patch_cc_file)',
- '--input_cc', '<(libgen_in_cc_file)',
- '--include', 'vm/bootstrap.h',
- '--var_name', 'dart::Bootstrap::platform_patch_paths_',
- '--library_name', 'dart:platform',
- '<@(_sources)',
- ],
- 'message': 'Generating ''<(platform_patch_cc_file)'' file.'
- },
- ]
- },
- {
'target_name': 'generate_typed_data_cc_file',
'type': 'none',
'toolsets':['host'],
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 921078b..e1fa84f 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -129,6 +129,7 @@
'disassembler_x64.cc',
'double_conversion.cc',
'double_conversion.h',
+ 'double_internals.h',
'exceptions.cc',
'exceptions.h',
'exceptions_test.cc',
diff --git a/sdk/lib/_collection_dev/collection_dev.dart b/sdk/lib/_collection_dev/collection_dev.dart
index d82d903..6e883f6 100644
--- a/sdk/lib/_collection_dev/collection_dev.dart
+++ b/sdk/lib/_collection_dev/collection_dev.dart
@@ -9,7 +9,6 @@
import 'dart:core' hide Symbol;
import 'dart:core' as core;
import 'dart:math' show Random;
-import 'dart:collection' show HashSet;
part 'arrays.dart';
part 'iterable.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index e30543a..a827bf6 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -6,7 +6,7 @@
import 'dart:async';
import 'dart:io'
- show exit, File, FileMode, Options, Platform, RandomAccessFile;
+ show exit, File, FileMode, Platform, RandomAccessFile;
import 'dart:math' as math;
import '../compiler.dart' as api;
@@ -452,11 +452,11 @@
exit(1);
}
-Future compilerMain(Options options) {
+Future compilerMain(List<String> arguments) {
var root = uriPathToNative("/$LIBRARY_ROOT");
- List<String> argv = ['--library-root=${options.script}$root'];
- argv.addAll(options.arguments);
- return compile(argv);
+ arguments =
+ <String>['--library-root=${Platform.script}$root']..addAll(arguments);
+ return compile(arguments);
}
void help() {
@@ -589,8 +589,8 @@
fail(message);
}
-void mainWithErrorHandler(Options options) {
- runZoned(() => compilerMain(options), onError: (exception) {
+void main(List<String> arguments) {
+ runZoned(() => compilerMain(arguments), onError: (exception) {
try {
print('Internal error: $exception');
} catch (ignored) {
@@ -607,7 +607,3 @@
}
});
}
-
-void main() {
- mainWithErrorHandler(new Options());
-}
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index 4168c72..836d999 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -595,14 +595,17 @@
final newTypedefElementCallback;
final newClassElementCallback;
- ReferencedElementCollector(
- this.compiler,
- Element rootElement, this.treeElements,
- this.newTypedefElementCallback, this.newClassElementCallback)
- : this.rootElement = (rootElement is VariableElement)
- ? (rootElement as VariableElement).variables : rootElement;
+ ReferencedElementCollector(this.compiler,
+ Element rootElement,
+ this.treeElements,
+ this.newTypedefElementCallback,
+ this.newClassElementCallback)
+ : this.rootElement =
+ rootElement is VariableElement ? rootElement.variables : rootElement;
- visitNode(Node node) { node.visitChildren(this); }
+ visitNode(Node node) {
+ node.visitChildren(this);
+ }
visitTypeAnnotation(TypeAnnotation typeAnnotation) {
// We call [resolveReturnType] to allow having 'void'.
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index ff98bd4..b6d3234 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -1121,12 +1121,16 @@
: super(compiler, dynamicType, voidType);
bool isMoreSpecific(DartType t, DartType s) {
- if (identical(t, s) ||
- t.treatAsDynamic ||
- identical(s.element, compiler.objectClass) ||
+ if (identical(t, s) || s.treatAsDynamic ||
identical(t.element, compiler.nullClass)) {
return true;
}
+ if (t.treatAsDynamic) {
+ return false;
+ }
+ if (identical(s.element, compiler.objectClass)) {
+ return true;
+ }
t = t.unalias(compiler);
s = s.unalias(compiler);
@@ -1138,6 +1142,7 @@
}
bool invalidFunctionReturnTypes(DartType t, DartType s) {
+ if (s.treatAsDynamic && t.isVoid) return true;
return !s.isVoid && !isMoreSpecific(t, s);
}
@@ -1161,7 +1166,7 @@
: super(compiler, dynamicType, voidType);
bool isSubtype(DartType t, DartType s) {
- return s.treatAsDynamic || isMoreSpecific(t, s);
+ return t.treatAsDynamic || isMoreSpecific(t, s);
}
bool isAssignable(DartType t, DartType s) {
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index 06ed03b..e97f3dcb 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -218,7 +218,8 @@
// need to emit the method.
if (universe.hasInvokedGetter(member, compiler)) {
registerClosurizedMember(member, compiler.globalDependencies);
- return addToWorkList(member);
+ addToWorkList(member);
+ return;
}
// Store the member in [instanceFunctionsByName] to catch
// getters on the function.
@@ -226,20 +227,24 @@
memberName, () => const Link<Element>());
instanceFunctionsByName[memberName] = members.prepend(member);
if (universe.hasInvocation(member, compiler)) {
- return addToWorkList(member);
+ addToWorkList(member);
+ return;
}
} else if (member.kind == ElementKind.GETTER) {
if (universe.hasInvokedGetter(member, compiler)) {
- return addToWorkList(member);
+ addToWorkList(member);
+ return;
}
// We don't know what selectors the returned closure accepts. If
// the set contains any selector we have to assume that it matches.
if (universe.hasInvocation(member, compiler)) {
- return addToWorkList(member);
+ addToWorkList(member);
+ return;
}
} else if (member.kind == ElementKind.SETTER) {
if (universe.hasInvokedSetter(member, compiler)) {
- return addToWorkList(member);
+ addToWorkList(member);
+ return;
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/filenames.dart b/sdk/lib/_internal/compiler/implementation/filenames.dart
index e357757..32aca53 100644
--- a/sdk/lib/_internal/compiler/implementation/filenames.dart
+++ b/sdk/lib/_internal/compiler/implementation/filenames.dart
@@ -4,7 +4,7 @@
library filenames;
-import 'dart:io';
+import 'dart:io' show Platform;
// For information about how to convert Windows file names to URIs:
// http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
@@ -29,8 +29,6 @@
}
}
-final Uri currentDirectory = new Uri(
- scheme: 'file',
- path: appendSlash(nativeToUriPath(new File('.').fullPathSync())));
+final Uri currentDirectory = Uri.base;
String appendSlash(String path) => path.endsWith('/') ? path : '$path/';
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
index e1f31b9..a134ac6 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
@@ -110,6 +110,7 @@
// From List.
'[]',
+ '[]=',
'length',
'reversed',
'sort',
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
index 09ddeb7..46170e4 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -256,6 +256,10 @@
positional.forEach(f);
named.values.forEach(f);
}
+
+ bool every(bool f(T type)) {
+ return positional.every(f) && named.values.every(f);
+ }
}
abstract class MinimalInferrerEngine<T> {
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
index 8f41971..9be28ab 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
@@ -781,21 +781,23 @@
T visitSuperSend(Send node) {
Element element = elements[node];
- if (Elements.isUnresolved(element)) {
- return types.dynamicType;
- }
Selector selector = elements.getSelector(node);
// TODO(ngeoffray): We could do better here if we knew what we
// are calling does not expose this.
isThisExposed = true;
- if (node.isPropertyAccess) {
- return handleStaticSend(node, selector, element, null);
- } else if (element.isFunction() || element.isGenerativeConstructor()) {
- if (!selector.applies(element, compiler)) return types.dynamicType;
- ArgumentsTypes arguments = analyzeArguments(node.arguments);
+ ArgumentsTypes arguments = node.isPropertyAccess
+ ? null
+ : analyzeArguments(node.arguments);
+ if (Elements.isUnresolved(element)
+ || !selector.applies(element, compiler)) {
+ // Ensure we create a node, to make explicit the call to the
+ // `noSuchMethod` handler.
+ return handleDynamicSend(node, selector, superType, arguments);
+ } else if (node.isPropertyAccess
+ || element.isFunction()
+ || element.isGenerativeConstructor()) {
return handleStaticSend(node, selector, element, arguments);
} else {
- ArgumentsTypes arguments = analyzeArguments(node.arguments);
return inferrer.registerCalledClosure(
node, selector, inferrer.typeOfElement(element),
outermostElement, arguments, sideEffects, inLoop);
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
index f621f46..0e5cf70 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
@@ -382,6 +382,7 @@
final List<CallSiteTypeInformation> allocatedCalls =
<CallSiteTypeInformation>[];
final WorkQueue workQueue = new WorkQueue();
+ final Element mainElement;
/// The maximum number of times we allow a node in the graph to
/// change types. If a node reaches that limit, we give up
@@ -390,7 +391,7 @@
int overallRefineCount = 0;
- TypeGraphInferrerEngine(Compiler compiler)
+ TypeGraphInferrerEngine(Compiler compiler, this.mainElement)
: super(compiler, new TypeInformationSystem(compiler));
void runOverAllElements() {
@@ -541,10 +542,12 @@
if ((info.type = newType) != oldType) {
overallRefineCount++;
info.refineCount++;
- if (info.refineCount > MAX_CHANGE_COUNT) {
+ workQueue.addAll(info.users);
+ if (info.hasStableType(this)) {
+ info.stabilize(this);
+ } else if (info.refineCount > MAX_CHANGE_COUNT) {
info.giveUp(this);
}
- workQueue.addAll(info.users);
}
}
}
@@ -848,8 +851,8 @@
String get name => 'Graph inferrer';
- void analyzeMain(_) {
- inferrer = new TypeGraphInferrerEngine(compiler);
+ void analyzeMain(Element main) {
+ inferrer = new TypeGraphInferrerEngine(compiler, main);
inferrer.runOverAllElements();
}
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
index ea4c22e..1057dcb 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -39,6 +39,10 @@
/// work queue.
bool inQueue = false;
+ /// Whether this [TypeInformation] has a stable [type] that will not
+ /// change.
+ bool isStable = false;
+
// TypeInformations are unique.
static int staticHashCode = 0;
final int hashCode = staticHashCode++;
@@ -51,11 +55,13 @@
void addUser(TypeInformation user) {
+ if (isStable) return;
assert(!user.isConcrete);
users.add(user);
}
void removeUser(TypeInformation user) {
+ if (isStable) return;
assert(!user.isConcrete);
users.remove(user);
}
@@ -89,7 +95,12 @@
void giveUp(TypeGraphInferrerEngine inferrer) {
abandonInferencing = true;
type = inferrer.types.dynamicType.type;
+ // Do not remove [this] as a user of nodes in [assignments],
+ // because our tracing analysis could be interested in tracing
+ // this node.
assignments = const <TypeInformation>[];
+ // Do not remove users because our tracing analysis could be
+ // interested in tracing the users of this node.
}
void clear() {
@@ -114,6 +125,24 @@
/// for some [TypeInformation] nodes, where we do not need to store
/// the information.
Element get owner => null;
+
+ /// Returns whether the type cannot change after it has been
+ /// inferred.
+ bool hasStableType(TypeGraphInferrerEngine inferrer) {
+ return !abandonInferencing && assignments.every((e) => e.isStable);
+ }
+
+ void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
+ assignments.forEach((info) { info.removeUser(this); });
+ }
+
+ void stabilize(TypeGraphInferrerEngine inferrer) {
+ removeAndClearReferences(inferrer);
+ users = const <TypeInformation>[];
+ assignments = const <TypeInformation>[];
+ abandonInferencing = true;
+ isStable = true;
+ }
}
/**
@@ -228,6 +257,14 @@
// [call] instance methods.
giveUp(inferrer);
return type;
+ } else if (enclosing == inferrer.mainElement) {
+ // The implicit call to main is not seen by the inferrer,
+ // therefore we explicitly set the type of its parameters as
+ // dynamic.
+ // TODO(14566): synthesize a call instead to get the exact
+ // types.
+ giveUp(inferrer);
+ return type;
}
}
if (element.isField()
@@ -294,6 +331,21 @@
}
Element get owner => element.getOutermostEnclosingMemberOrTopLevel();
+
+ bool hasStableType(TypeGraphInferrerEngine inferrer) {
+ // The number of assignments of parameters of instance methods is
+ // not stable. Therefore such a parameter cannot be stable.
+ if (element.isParameter() && element.enclosingElement.isInstanceMember()) {
+ return false;
+ }
+ // The number of assignments of non-final fields is
+ // not stable. Therefore such a field cannot be stable.
+ if (element.isField()
+ && !(element.modifiers.isConst() || element.modifiers.isFinal())) {
+ return false;
+ }
+ return super.hasStableType(inferrer);
+ }
}
/**
@@ -380,6 +432,22 @@
accept(TypeInformationVisitor visitor) {
return visitor.visitStaticCallSiteTypeInformation(this);
}
+
+ bool hasStableType(TypeGraphInferrerEngine inferrer) {
+ return inferrer.types.getInferredTypeOf(calledElement).isStable
+ && (arguments == null || arguments.every((info) => info.isStable))
+ && super.hasStableType(inferrer);
+ }
+
+ void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
+ ElementTypeInformation callee =
+ inferrer.types.getInferredTypeOf(calledElement);
+ callee.removeUser(this);
+ if (arguments != null) {
+ arguments.forEach((info) => info.removeUser(this));
+ }
+ super.removeAndClearReferences(inferrer);
+ }
}
class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
@@ -479,7 +547,21 @@
Iterable<Element> oldTargets = targets;
Selector typedSelector = computeTypedSelector(inferrer);
inferrer.updateSelectorInTree(caller, call, typedSelector);
- targets = inferrer.compiler.world.allFunctions.filter(typedSelector);
+
+ Compiler compiler = inferrer.compiler;
+ Selector selectorToUse = typedSelector.extendIfReachesAll(compiler);
+
+ bool canReachAll = compiler.enabledInvokeOn
+ && (selectorToUse != typedSelector);
+
+ // If this call could potentially reach all methods that satisfy
+ // the untyped selector (through noSuchMethod's `Invocation`
+ // and a call to `delegate`), we iterate over all these methods to
+ // update their parameter types.
+ targets = compiler.world.allFunctions.filter(selectorToUse);
+ Iterable<Element> typedTargets = canReachAll
+ ? compiler.world.allFunctions.filter(typedSelector)
+ : targets;
// Walk over the found targets, and compute the joined union type mask
// for all these targets.
@@ -493,6 +575,15 @@
this, element, arguments, typedSelector, remove: false);
}
+ // If [canReachAll] is true, then we are iterating over all
+ // targets that satisfy the untyped selector. We skip the return
+ // type of the targets that can only be reached through
+ // `Invocation.delegate`. Note that the `noSuchMethod` targets
+ // are included in [typedTargets].
+ if (canReachAll && !typedTargets.contains(element)) {
+ return const TypeMask.nonNullEmpty();
+ }
+
if (returnsElementType(typedSelector)) {
ContainerTypeMask mask = receiver.type;
return mask.elementType;
@@ -516,6 +607,7 @@
this, element, arguments, typedSelector, remove: true);
}
});
+
return newType;
}
@@ -535,6 +627,17 @@
super.giveUp(inferrer);
}
+ void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
+ for (Element element in targets) {
+ ElementTypeInformation callee = inferrer.types.getInferredTypeOf(element);
+ callee.removeUser(this);
+ }
+ if (arguments != null) {
+ arguments.forEach((info) => info.removeUser(this));
+ }
+ super.removeAndClearReferences(inferrer);
+ }
+
bool reachedBy(TypeInformation info, TypeGraphInferrerEngine inferrer) {
return targets
.map((element) => inferrer.types.getInferredTypeOf(element))
@@ -546,6 +649,14 @@
accept(TypeInformationVisitor visitor) {
return visitor.visitDynamicCallSiteTypeInformation(this);
}
+
+ bool hasStableType(TypeGraphInferrerEngine inferrer) {
+ return receiver.isStable
+ && targets.every(
+ (element) => inferrer.types.getInferredTypeOf(element).isStable)
+ && (arguments == null || arguments.every((info) => info.isStable))
+ && super.hasStableType(inferrer);
+ }
}
class ClosureCallSiteTypeInformation extends CallSiteTypeInformation {
@@ -576,6 +687,16 @@
accept(TypeInformationVisitor visitor) {
return visitor.visitClosureCallSiteTypeInformation(this);
}
+
+ void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
+ // This method is a placeholder for the following comment:
+ // We should maintain the information that the closure is a user
+ // of its arguments because we do not check that the arguments
+ // have a stable type for a closure call to be stable; our tracing
+ // analysis want to know whether an (non-stable) argument is
+ // passed to a closure.
+ return super.removeAndClearReferences(inferrer);
+ }
}
/**
@@ -592,6 +713,7 @@
ConcreteTypeInformation(TypeMask type)
: super(const <TypeInformation>[], const <TypeInformation>[]) {
this.type = type;
+ this.isStable = true;
}
bool get isConcrete => true;
@@ -620,6 +742,10 @@
accept(TypeInformationVisitor visitor) {
return visitor.visitConcreteTypeInformation(this);
}
+
+ bool hasStableType(TypeGraphInferrerEngine inferrer) {
+ return true;
+ }
}
/**
@@ -652,7 +778,9 @@
return assignments[0].type.intersection(typeAnnotation, inferrer.compiler);
}
- String toString() => 'Narrow ${assignments.first} to $typeAnnotation $type';
+ String toString() {
+ return 'Narrow to $typeAnnotation $type';
+ }
accept(TypeInformationVisitor visitor) {
return visitor.visitNarrowTypeInformation(this);
@@ -689,6 +817,10 @@
return visitor.visitContainerTypeInformation(this);
}
+ bool hasStableType(TypeGraphInferrerEngine inferrer) {
+ return elementType.isStable && super.hasStableType(inferrer);
+ }
+
TypeMask refine(TypeGraphInferrerEngine inferrer) {
var mask = type;
if (!mask.isContainer
@@ -728,6 +860,10 @@
accept(TypeInformationVisitor visitor) {
return visitor.visitElementInContainerTypeInformation(this);
}
+
+ bool hasStableType(TypeGraphInferrerEngine inferrer) {
+ return inferred && super.hasStableType(inferrer);
+ }
}
/**
diff --git a/sdk/lib/_internal/compiler/implementation/js/printer.dart b/sdk/lib/_internal/compiler/implementation/js/printer.dart
index a21e713..1cf97a3 100644
--- a/sdk/lib/_internal/compiler/implementation/js/printer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/printer.dart
@@ -456,7 +456,7 @@
(requiredPrecedence != EXPRESSION &&
node.precedenceLevel < requiredPrecedence) ||
// for (a = (x in o); ... ; ... ) { ... }
- (newInForInit && node is Binary && (node as Binary).op == "in") ||
+ (newInForInit && node is Binary && node.op == "in") ||
// (function() { ... })().
// ({a: 2, b: 3}.toString()).
(newAtStatementBegin && (node is NamedFunction ||
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 4cbc51c..0638d86 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -208,11 +208,19 @@
Element mapTypeToInterceptor;
HType stringType;
+ HType doubleType;
+ HType intType;
+ HType numType;
+ HType boolType;
HType indexablePrimitiveType;
HType readableArrayType;
HType mutableArrayType;
HType fixedArrayType;
HType extendableArrayType;
+ HType nonNullType;
+ HType dynamicType;
+ HType nullType = const HBoundedType(const TypeMask.empty());
+ HType emptyType = const HBoundedType(const TypeMask.nonNullEmpty());
// TODO(9577): Make it so that these are not needed when there are no native
// classes.
@@ -419,7 +427,6 @@
bool invokedReflectively(Element element) {
if (element.isParameter() || element.isFieldParameter()) {
- if (hasInsufficientMirrorsUsed && compiler.enabledInvokeOn) return true;
if (invokedReflectively(element.enclosingElement)) return true;
}
@@ -428,7 +435,6 @@
&& (element.modifiers.isFinal() || element.modifiers.isConst())) {
return false;
}
- if (hasInsufficientMirrorsUsed && compiler.enabledInvokeOn) return true;
}
return isNeededForReflection(element.declaration);
@@ -615,6 +621,14 @@
stringType = new HBoundedType(
new TypeMask.nonNullExact(jsStringClass));
+ doubleType = new HBoundedType(
+ new TypeMask.nonNullExact(jsDoubleClass));
+ intType = new HBoundedType(
+ new TypeMask.nonNullExact(jsIntClass));
+ numType = new HBoundedType(
+ new TypeMask.nonNullSubclass(jsNumberClass));
+ boolType = new HBoundedType(
+ new TypeMask.nonNullExact(jsBoolClass));
indexablePrimitiveType = new HBoundedType(
new TypeMask.nonNullSubtype(jsIndexableClass));
readableArrayType = new HBoundedType(
@@ -625,6 +639,10 @@
new TypeMask.nonNullExact(jsFixedArrayClass));
extendableArrayType = new HBoundedType(
new TypeMask.nonNullExact(jsExtendableArrayClass));
+ nonNullType = new HBoundedType(
+ compiler.typesTask.dynamicType.nonNullable());
+ dynamicType = new HBoundedType(
+ compiler.typesTask.dynamicType);
typeVariableClass = compiler.findHelper('TypeVariable');
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
index 04f983b..c6ee2e5 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -155,6 +155,11 @@
final Namer namer;
final ConstantReferenceEmitter referenceEmitter;
+ // Matches blank lines, comment lines and trailing comments that can't be part
+ // of a string.
+ static final RegExp COMMENT_RE =
+ new RegExp(r'''^ *(//.*)?\n| *//[^''"\n]*$''' , multiLine: true);
+
ConstantInitializerEmitter(this.compiler, this.namer, this.referenceEmitter);
jsAst.Expression generate(Constant constant) {
@@ -313,7 +318,8 @@
if (element.isForeign(compiler)
&& element.name == 'JS_CONST') {
StringConstant str = constant.fields[0];
- return new jsAst.LiteralExpression(str.value.slowToString());
+ String value = str.value.slowToString();
+ return new jsAst.LiteralExpression(stripComments(value));
}
jsAst.New instantiation = new jsAst.New(
new jsAst.VariableUse(getJsConstructor(constant.type.element)),
@@ -321,6 +327,10 @@
return maybeAddTypeArguments(constant.type, instantiation);
}
+ String stripComments(String rawJavaScript) {
+ return rawJavaScript.replaceAll(COMMENT_RE, '');
+ }
+
List<jsAst.Expression> _array(List<Constant> values) {
List<jsAst.Expression> valueList = <jsAst.Expression>[];
for (int i = 0; i < values.length; i++) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
index 49c7121..9598af7 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -5,7 +5,7 @@
library js_backend;
import 'dart:async' show Future;
-import 'dart:collection' show Queue;
+import 'dart:collection' show Queue, LinkedHashMap;
import '../closure.dart';
import '../elements/elements.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index 6febc82..e22454b 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -223,6 +223,9 @@
final String methodsWithOptionalArgumentsField =
r'$methodsWithOptionalArguments';
+ // Name of property in a class description for the native dispatch metadata.
+ final String nativeSpecProperty = '%';
+
/**
* Map from top-level or static elements to their unique identifiers provided
* by [getName].
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index d7c0b4e..0ddad2a6 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -111,9 +111,14 @@
* [classes] contains native classes, mixin applications, and user subclasses
* of native classes. ONLY the native classes are generated here. [classes]
* is sorted in desired output order.
+ *
+ * [additionalProperties] is used to collect properties that are pushed up
+ * from the above optimizations onto a non-native class, e.g, `Interceptor`.
*/
- void generateNativeClasses(List<ClassElement> classes,
- CodeBuffer mainBuffer) {
+ void generateNativeClasses(
+ List<ClassElement> classes,
+ CodeBuffer mainBuffer,
+ Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties) {
// Compute a pre-order traversal of the subclass forest. We actually want a
// post-order traversal but it is easier to compute the pre-order and use it
// in reverse.
@@ -259,17 +264,14 @@
// No builder because this is an intermediate mixin application or
// Interceptor - these are not direct native classes.
if (encoding != '') {
- // TODO(sra): Figure out how to emit this as a property onto
- // Interceptor's ClassBuilder.
- jsAst.Expression assignment =
- js.assign(
- js(backend.namer.isolateAccess(classElement))['%'],
- js.string(encoding));
- nativeBuffer.add(jsAst.prettyPrint(assignment, compiler));
- nativeBuffer.add('$N$n');
+ Map<String, jsAst.Expression> properties =
+ additionalProperties.putIfAbsent(classElement,
+ () => new LinkedHashMap<String, jsAst.Expression>());
+ properties[backend.namer.nativeSpecProperty] = js.string(encoding);
}
} else {
- builder.addProperty('%', js.string(encoding));
+ builder.addProperty(
+ backend.namer.nativeSpecProperty, js.string(encoding));
}
}
generateClassInfo(backend.jsInterceptorClass);
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
index 53285fd..6ea330e 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
@@ -10,7 +10,9 @@
*
* Invariant: [classElement] must be a declaration element.
*/
- void generateClass(ClassElement classElement, CodeBuffer buffer) {
+ void generateClass(ClassElement classElement,
+ CodeBuffer buffer,
+ Map<String, jsAst.Expression> additionalProperties) {
final onlyForRti =
task.typeTestEmitter.rtiNeededClasses.contains(classElement);
@@ -41,6 +43,9 @@
emitClassGettersSetters(classElement, builder, onlyForRti: onlyForRti);
emitInstanceMembers(classElement, builder, onlyForRti: onlyForRti);
task.typeTestEmitter.emitIsTests(classElement, builder);
+ if (additionalProperties != null) {
+ additionalProperties.forEach(builder.addProperty);
+ }
emitClassBuilderWithReflectionData(
className, classElement, builder, buffer);
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
index ac0cec4..1019547 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
@@ -39,6 +39,9 @@
final Map<String, String> mangledGlobalFieldNames = <String, String>{};
final Set<String> recordedMangledNames = new Set<String>();
+ final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties =
+ new Map<ClassElement, Map<String, jsAst.Expression>>();
+
// TODO(ngeoffray): remove this field.
Set<ClassElement> instantiatedClasses;
@@ -408,6 +411,8 @@
}
jsAst.FunctionDeclaration buildFinishClass() {
+ String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
+
// function finishClass(cls) {
jsAst.Fun fun = js.fun(['cls'], [
@@ -461,8 +466,8 @@
//
// The information is used to build tables referenced by
// getNativeInterceptor and custom element support.
- js.if_('hasOwnProperty.call(prototype, "%")', [
- js('var nativeSpec = prototype["%"].split(";")'),
+ js.if_('hasOwnProperty.call(prototype, $specProperty)', [
+ js('var nativeSpec = prototype[$specProperty].split(";")'),
js.if_('nativeSpec[0]', [
js('var tags = nativeSpec[0].split("|")'),
js.for_('var i = 0', 'i < tags.length', 'i++', [
@@ -734,7 +739,8 @@
}
void generateClass(ClassElement classElement, CodeBuffer buffer) {
- classEmitter.generateClass(classElement, buffer);
+ classEmitter.generateClass(
+ classElement, buffer, additionalProperties[classElement]);
}
int _selectorRank(Selector selector) {
@@ -1177,6 +1183,16 @@
mainBuffer.add('var $classesCollector$_=$_{}$N$n');
}
+ // Emit native classes on [nativeBuffer].
+ // Might create methodClosures.
+ final CodeBuffer nativeBuffer = new CodeBuffer();
+ if (!nativeClasses.isEmpty) {
+ addComment('Native classes', nativeBuffer);
+ addComment('Native classes', mainBuffer);
+ nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer,
+ additionalProperties);
+ }
+
// As a side-effect, emitting classes will produce "bound closures" in
// [methodClosures]. The bound closures are JS AST nodes that add
// properties to $$ [classesCollector]. The bound closures are not
@@ -1189,14 +1205,6 @@
}
}
- // Emit native classes on [nativeBuffer].
- // Might create methodClosures.
- final CodeBuffer nativeBuffer = new CodeBuffer();
- if (!nativeClasses.isEmpty) {
- addComment('Native classes', nativeBuffer);
- addComment('Native classes', mainBuffer);
- nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer);
- }
nativeEmitter.finishGenerateNativeClasses();
nativeEmitter.assembleCode(nativeBuffer);
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index d7b26d6d..94ace737 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -492,8 +492,7 @@
return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>(
_members,
(MemberMirror member) =>
- member is MethodMirror && (member as MethodMirror).isGetter ?
- member : null);
+ member is MethodMirror && member.isGetter ? member : null);
}
Map<String, MethodMirror> get setters {
@@ -501,8 +500,7 @@
return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>(
_members,
(MemberMirror member) =>
- member is MethodMirror && (member as MethodMirror).isSetter ?
- member : null);
+ member is MethodMirror && member.isSetter ? member : null);
}
Map<String, VariableMirror> get variables {
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index 0d24f1d..bb42db9 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -1062,6 +1062,7 @@
Compiler compiler = builder.compiler;
FunctionElement element = builder.work.element;
NativeEmitter nativeEmitter = builder.emitter.nativeEmitter;
+ JavaScriptBackend backend = builder.backend;
HInstruction convertDartClosure(Element parameter, FunctionType type) {
HInstruction local = builder.localsHandler.readLocal(parameter);
@@ -1070,7 +1071,7 @@
HInstruction arity = builder.graph.addConstant(arityConstant, compiler);
// TODO(ngeoffray): For static methods, we could pass a method with a
// defined arity.
- Element helper = builder.backend.getClosureConverter();
+ Element helper = backend.getClosureConverter();
builder.pushInvokeStatic(nativeBody, helper, [local, arity]);
HInstruction closure = builder.pop();
return closure;
@@ -1134,7 +1135,7 @@
element: element);
}
- builder.push(new HForeign(js.js(nativeMethodCall), HType.UNKNOWN,
+ builder.push(new HForeign(js.js(nativeMethodCall), backend.dynamicType,
inputs, effects: new SideEffects()));
builder.close(new HReturn(builder.pop())).addSuccessor(builder.graph.exit);
} else {
@@ -1148,6 +1149,7 @@
new js.LiteralStatement(jsCode.dartString.slowToString()),
<HInstruction>[],
new SideEffects(),
- null));
+ null,
+ backend.dynamicType));
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/patch_parser.dart b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
index b528fa2..06430af 100644
--- a/sdk/lib/_internal/compiler/implementation/patch_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
@@ -25,7 +25,7 @@
* element, regardless of whether the element is one of the three patchable
* element types or not.
*
- * ## Variants of Classes and Functions ##
+ * ## Variants of classes and functions ##
*
* With patches there are four variants of classes and function:
*
@@ -67,7 +67,7 @@
* }
*
*
- * ## Declaration and Implementation ##
+ * ## Declaration and implementation ##
*
* With patches we have two views on elements: as the 'declaration' which
* introduces the entity and defines its interface, and as the 'implementation'
@@ -178,7 +178,7 @@
// of calling its [parseNode] method.
if (element.cachedNode != null) return;
- return measure(() => compiler.withCurrentElement(element, () {
+ measure(() => compiler.withCurrentElement(element, () {
PatchMemberListener listener = new PatchMemberListener(compiler, element);
Parser parser = new PatchClassElementParser(listener);
Token token = parser.parseTopLevelDeclaration(element.beginToken);
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index bab8bfe..cbc31ee 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -461,7 +461,7 @@
FunctionExpression tree = element.parseNode(compiler);
if (tree.modifiers.isExternal()) {
error(tree, MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION);
- return;
+ return null;
}
if (isConstructor || element.isFactoryConstructor()) {
if (tree.returnType != null) {
@@ -1926,6 +1926,12 @@
int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION
| ElementCategory.IMPLIES_TYPE;
+ /**
+ * Record of argument nodes to JS_INTERCEPTOR_CONSTANT for deferred
+ * processing.
+ */
+ Set<Node> argumentsToJsInterceptorConstant = null;
+
/// When visiting the type declaration of the variable in a [ForIn] loop,
/// the initializer of the variable is implicit and we should not emit an
/// error when verifying that all final variables are initialized.
@@ -2602,7 +2608,7 @@
// If the selector is null, it means that we will not be generating
// code for this as a send.
Selector selector = mapping.getSelector(node);
- if (selector == null) return;
+ if (selector == null) return null;
if (node.isCall) {
if (Elements.isUnresolved(target) ||
@@ -2622,10 +2628,17 @@
warnArgumentMismatch(node, target);
}
- if (target != null &&
- target.isForeign(compiler) &&
- selector.name == 'JS') {
- world.registerJsCall(node, this);
+ if (target != null && target.isForeign(compiler)) {
+ if (selector.name == 'JS') {
+ world.registerJsCall(node, this);
+ } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') {
+ if (!node.argumentsNode.isEmpty) {
+ Node argument = node.argumentsNode.nodes.head;
+ if (argumentsToJsInterceptorConstant == null)
+ argumentsToJsInterceptorConstant = new Set<Node>();
+ argumentsToJsInterceptorConstant.add(argument);
+ }
+ }
}
}
@@ -3042,8 +3055,28 @@
void analyzeConstant(Node node, {bool isConst: true}) {
addDeferredAction(enclosingElement, () {
- compiler.constantHandler.compileNodeWithDefinitions(
+ Constant constant = compiler.constantHandler.compileNodeWithDefinitions(
node, mapping, isConst: isConst);
+
+ // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names
+ // a class that will be instantiated outside the program by attaching a
+ // native class dispatch record referencing the interceptor.
+ if (argumentsToJsInterceptorConstant != null &&
+ argumentsToJsInterceptorConstant.contains(node)) {
+ if (constant.isType()) {
+ TypeConstant typeConstant = constant;
+ if (typeConstant.representedType is InterfaceType) {
+ world.registerInstantiatedType(typeConstant.representedType,
+ mapping);
+ } else {
+ compiler.reportError(node,
+ MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
+ }
+ } else {
+ compiler.reportError(node,
+ MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
+ }
+ }
});
}
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
index 0d00bd0..8659ead 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
@@ -428,7 +428,7 @@
if (identical(next, $CLOSE_SQUARE_BRACKET)) {
Token token = previousToken();
if (token is KeywordToken &&
- identical((token as KeywordToken).keyword.syntax, 'operator')) {
+ identical(token.keyword.syntax, 'operator')) {
return select($EQ, INDEX_EQ_INFO, INDEX_INFO);
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index a0df363..0a88bd3 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -141,8 +141,9 @@
HInstruction createBox() {
// TODO(floitsch): Clean up this hack. Should we create a box-object by
// just creating an empty object literal?
+ JavaScriptBackend backend = builder.backend;
HInstruction box = new HForeign(new js.ObjectInitializer([]),
- HType.UNKNOWN,
+ backend.nonNullType,
<HInstruction>[]);
builder.add(box);
return box;
@@ -162,7 +163,8 @@
if (element != null && element.isGenerativeConstructorBody()) {
// The box is passed as a parameter to a generative
// constructor body.
- box = builder.addParameter(scopeData.boxElement);
+ JavaScriptBackend backend = builder.backend;
+ box = builder.addParameter(scopeData.boxElement, backend.nonNullType);
} else {
box = createBox();
}
@@ -235,11 +237,11 @@
return;
}
}
- HInstruction parameter = builder.addParameter(parameterElement);
+ HInstruction parameter = builder.addParameter(
+ parameterElement,
+ new HType.inferredTypeForElement(parameterElement, compiler));
builder.parameters[parameterElement] = parameter;
directLocals[parameterElement] = parameter;
- parameter.instructionType =
- new HType.inferredTypeForElement(parameterElement, compiler);
});
}
@@ -251,10 +253,11 @@
closureData.freeVariableMapping.forEach((Element from, Element to) {
redirectElement(from, to);
});
+ JavaScriptBackend backend = compiler.backend;
if (closureData.isClosure()) {
// Inside closure redirect references to itself to [:this:].
HThis thisInstruction = new HThis(closureData.thisElement,
- HType.NON_NULL);
+ backend.nonNullType);
builder.graph.thisInstruction = thisInstruction;
builder.graph.entry.addAtEntry(thisInstruction);
updateLocal(closureData.closureElement, thisInstruction);
@@ -273,7 +276,6 @@
// parameter to it, that is the actual receiver for intercepted
// classes, or the same as [:this:] for non-intercepted classes.
ClassElement cls = element.getEnclosingClass();
- JavaScriptBackend backend = compiler.backend;
// When the class extends a native class, the instance is pre-constructed
// and passed to the generative constructor factory function as a parameter.
@@ -286,7 +288,8 @@
String name = isInterceptorClass ? 'receiver' : '_';
Element parameter = new InterceptedElement(
cls.computeType(compiler), name, element);
- HParameterValue value = new HParameterValue(parameter);
+ HParameterValue value =
+ new HParameterValue(parameter, builder.getTypeOfThis());
builder.graph.explicitReceiverParameter = value;
builder.graph.entry.addAfter(
directLocals[closureData.thisElement], value);
@@ -294,16 +297,15 @@
// Only use the extra parameter in intercepted classes.
directLocals[closureData.thisElement] = value;
}
- value.instructionType = builder.getTypeOfThis();
} else if (isNativeUpgradeFactory) {
Element parameter = new InterceptedElement(
cls.computeType(compiler), 'receiver', element);
- HParameterValue value = new HParameterValue(parameter);
- builder.graph.explicitReceiverParameter = value;
- builder.graph.entry.addAtEntry(value);
// Unlike `this`, receiver is nullable since direct calls to generative
// constructor call the constructor with `null`.
- value.instructionType = new HType.exact(cls, compiler);
+ HParameterValue value =
+ new HParameterValue(parameter, new HType.exact(cls, compiler));
+ builder.graph.explicitReceiverParameter = value;
+ builder.graph.entry.addAtEntry(value);
}
}
@@ -367,8 +369,8 @@
} else if (isStoredInClosureField(element)) {
Element redirect = redirectionMapping[element];
HInstruction receiver = readLocal(closureData.closureElement);
- HInstruction fieldGet = new HFieldGet(redirect, receiver);
- fieldGet.instructionType = builder.getTypeOfCapturedVariable(redirect);
+ HInstruction fieldGet = new HFieldGet(
+ redirect, receiver, builder.getTypeOfCapturedVariable(redirect));
builder.add(fieldGet);
return fieldGet;
} else if (isBoxed(element)) {
@@ -380,14 +382,15 @@
// the box.
assert(redirect.enclosingElement.isVariable());
HInstruction box = readLocal(redirect.enclosingElement);
- HInstruction lookup = new HFieldGet(redirect, box);
- lookup.instructionType = builder.getTypeOfCapturedVariable(redirect);
+ HInstruction lookup = new HFieldGet(
+ redirect, box, builder.getTypeOfCapturedVariable(redirect));
builder.add(lookup);
return lookup;
} else {
assert(isUsedInTry(element));
HLocalValue local = getLocal(element);
- HInstruction variable = new HLocalGet(element, local);
+ HInstruction variable = new HLocalGet(
+ element, local, builder.backend.dynamicType);
builder.add(variable);
return variable;
}
@@ -410,7 +413,8 @@
if (element.isParameter()) return builder.parameters[element];
return builder.activationVariables.putIfAbsent(element, () {
- HLocalValue local = new HLocalValue(element);
+ JavaScriptBackend backend = builder.backend;
+ HLocalValue local = new HLocalValue(element, backend.nonNullType);
builder.graph.entry.addAtExit(local);
return local;
});
@@ -507,12 +511,14 @@
Map<Element, HInstruction> savedDirectLocals =
new Map<Element, HInstruction>.from(directLocals);
+ JavaScriptBackend backend = builder.backend;
// Create phis for all elements in the definitions environment.
savedDirectLocals.forEach((Element element, HInstruction instruction) {
if (isAccessedDirectly(element)) {
// We know 'this' cannot be modified.
if (!identical(element, closureData.thisElement)) {
- HPhi phi = new HPhi.singleInput(element, instruction);
+ HPhi phi = new HPhi.singleInput(
+ element, instruction, backend.dynamicType);
loopEntry.addPhi(phi);
directLocals[element] = phi;
} else {
@@ -574,6 +580,7 @@
// true for nodes where we do joins.
Map<Element, HInstruction> joinedLocals =
new Map<Element, HInstruction>();
+ JavaScriptBackend backend = builder.backend;
otherLocals.directLocals.forEach((element, instruction) {
// We know 'this' cannot be modified.
if (identical(element, closureData.thisElement)) {
@@ -585,8 +592,8 @@
if (identical(instruction, mine)) {
joinedLocals[element] = instruction;
} else {
- HInstruction phi =
- new HPhi.manyInputs(element, <HInstruction>[mine, instruction]);
+ HInstruction phi = new HPhi.manyInputs(
+ element, <HInstruction>[mine, instruction], backend.dynamicType);
joinBlock.addPhi(phi);
joinedLocals[element] = phi;
}
@@ -609,9 +616,10 @@
Map<Element, HInstruction> joinedLocals =
new Map<Element,HInstruction>();
HInstruction thisValue = null;
+ JavaScriptBackend backend = builder.backend;
directLocals.forEach((Element element, HInstruction instruction) {
if (element != closureData.thisElement) {
- HPhi phi = new HPhi.noInputs(element);
+ HPhi phi = new HPhi.noInputs(element, backend.dynamicType);
joinedLocals[element] = phi;
joinBlock.addPhi(phi);
} else {
@@ -1047,7 +1055,8 @@
() {
HParameterValue parameter = parameters.values.first;
push(new HIdentity(
- parameter, graph.addConstantNull(compiler)));
+ parameter, graph.addConstantNull(compiler), null,
+ backend.boolType));
},
() {
closeAndGotoExit(new HReturn(
@@ -1113,9 +1122,9 @@
return bodyElement;
}
- HParameterValue addParameter(Element element) {
+ HParameterValue addParameter(Element element, HType type) {
assert(inliningStack.isEmpty);
- HParameterValue result = new HParameterValue(element);
+ HParameterValue result = new HParameterValue(element, type);
if (lastAddedParameter == null) {
graph.entry.addBefore(graph.entry.first, result);
} else {
@@ -1349,7 +1358,8 @@
&& !element.isGenerativeConstructorBody()
&& (selector.mask == null || selector.mask.isNullable)) {
addWithPosition(
- new HFieldGet(null, providedArguments[0], isAssignable: false),
+ new HFieldGet(null, providedArguments[0], backend.dynamicType,
+ isAssignable: false),
currentNode);
}
InliningState state = enterInlinedMethod(
@@ -1723,7 +1733,8 @@
// Null guard ensures an error if we are being called from an explicit
// 'new' of the constructor instead of via an upgrade. It is optimized out
// if there are field initializers.
- add(new HFieldGet(null, newObject, isAssignable: false));
+ add(new HFieldGet(
+ null, newObject, backend.dynamicType, isAssignable: false));
for (int i = 0; i < fields.length; i++) {
add(new HFieldSet(fields[i], newObject, constructorArguments[i]));
}
@@ -1792,8 +1803,8 @@
tryInlineMethod(body, null, bodyCallInputs, function)) {
pop();
} else {
- HInvokeConstructorBody invoke =
- new HInvokeConstructorBody(body.declaration, bodyCallInputs);
+ HInvokeConstructorBody invoke = new HInvokeConstructorBody(
+ body.declaration, bodyCallInputs, backend.nonNullType);
invoke.sideEffects =
compiler.world.getSideEffectsOfElement(constructor);
add(invoke);
@@ -1830,7 +1841,8 @@
if ((element.isConstructor() || element.isGenerativeConstructorBody())
&& backend.classNeedsRti(enclosing)) {
enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
- HParameterValue param = addParameter(typeVariable.element);
+ HParameterValue param = addParameter(
+ typeVariable.element, backend.nonNullType);
localsHandler.directLocals[typeVariable.element] = param;
});
}
@@ -2008,7 +2020,7 @@
compiler.boolClass.computeType(compiler),
kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
}
- HInstruction result = new HBoolify(value);
+ HInstruction result = new HBoolify(value, backend.boolType);
add(result);
return result;
}
@@ -2622,7 +2634,7 @@
void visitLogicalNot(Send node) {
assert(node.argumentsNode is Prefix);
visit(node.receiver);
- HNot not = new HNot(popBoolified());
+ HNot not = new HNot(popBoolified(), backend.boolType);
pushWithPosition(not, node);
}
@@ -2653,18 +2665,19 @@
Send send) {
switch (op.source) {
case "===":
- pushWithPosition(new HIdentity(left, right), op);
+ pushWithPosition(
+ new HIdentity(left, right, null, backend.boolType), op);
return;
case "!==":
- HIdentity eq = new HIdentity(left, right);
+ HIdentity eq = new HIdentity(left, right, null, backend.boolType);
add(eq);
- pushWithPosition(new HNot(eq), op);
+ pushWithPosition(new HNot(eq, backend.boolType), op);
return;
}
pushInvokeDynamic(send, selector, [left, right], location: op);
if (op.source == '!=') {
- pushWithPosition(new HNot(popBoolified()), op);
+ pushWithPosition(new HNot(popBoolified(), backend.boolType), op);
}
}
@@ -2712,11 +2725,11 @@
// handler in the case of lists, because the constant handler
// does not look at elements in the list.
HType type = new HType.inferredTypeForElement(element, compiler);
- if (!type.isUnknown()) instruction.instructionType = type;
+ if (!type.containsAll(compiler)) instruction.instructionType = type;
} else if (element.isField() && isLazilyInitialized(element)) {
- HInstruction instruction = new HLazyStatic(element);
- instruction.instructionType =
- new HType.inferredTypeForElement(element, compiler);
+ HInstruction instruction = new HLazyStatic(
+ element,
+ new HType.inferredTypeForElement(element, compiler));
push(instruction);
} else {
if (element.isGetter()) {
@@ -2724,9 +2737,9 @@
} else {
// TODO(5346): Try to avoid the need for calling [declaration] before
// creating an [HStatic].
- HInstruction instruction = new HStatic(element.declaration);
- instruction.instructionType =
- new HType.inferredTypeForElement(element, compiler);
+ HInstruction instruction = new HStatic(
+ element.declaration,
+ new HType.inferredTypeForElement(element, compiler));
push(instruction);
}
}
@@ -2737,7 +2750,7 @@
} else if (Elements.isStaticOrTopLevelFunction(element)) {
// TODO(5346): Try to avoid the need for calling [declaration] before
// creating an [HStatic].
- push(new HStatic(element.declaration));
+ push(new HStatic(element.declaration, backend.nonNullType));
// TODO(ahe): This should be registered in codegen.
compiler.enqueuer.codegen.registerGetOfStaticFunction(
element.declaration);
@@ -2813,7 +2826,7 @@
}
HInstruction invokeInterceptor(HInstruction receiver) {
- HInterceptor interceptor = new HInterceptor(receiver);
+ HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType);
add(interceptor);
return interceptor;
}
@@ -2901,7 +2914,7 @@
HInstruction instruction = buildIsNode(node, type, expression);
if (isNot) {
add(instruction);
- instruction = new HNot(instruction);
+ instruction = new HNot(instruction, backend.boolType);
}
push(instruction);
}
@@ -2921,7 +2934,8 @@
if (type.kind == TypeKind.FUNCTION) {
if (backend.rti.isSimpleFunctionType(type)) {
// TODO(johnniwinther): Avoid interceptor if unneeded.
- return new HIs.raw(type, expression, invokeInterceptor(expression));
+ return new HIs.raw(
+ type, expression, invokeInterceptor(expression), backend.boolType);
}
Element checkFunctionSubtype = backend.getCheckFunctionSubtype();
@@ -2957,16 +2971,16 @@
contextName,
context,
typeArguments];
- pushInvokeStatic(node, checkFunctionSubtype, inputs, HType.BOOLEAN);
+ pushInvokeStatic(node, checkFunctionSubtype, inputs, backend.boolType);
HInstruction call = pop();
- return new HIs.compound(type, expression, call);
+ return new HIs.compound(type, expression, call, backend.boolType);
} else if (type.kind == TypeKind.TYPE_VARIABLE) {
HInstruction runtimeType = addTypeVariableReference(type);
Element helper = backend.getCheckSubtypeOfRuntimeType();
List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
- pushInvokeStatic(null, helper, inputs, HType.BOOLEAN);
+ pushInvokeStatic(null, helper, inputs, backend.boolType);
HInstruction call = pop();
- return new HIs.variable(type, expression, call);
+ return new HIs.variable(type, expression, call, backend.boolType);
} else if (RuntimeTypes.hasTypeArguments(type)) {
ClassElement element = type.element;
Element helper = backend.getCheckSubtype();
@@ -2983,15 +2997,16 @@
isFieldName,
representations,
asFieldName];
- pushInvokeStatic(node, helper, inputs, HType.BOOLEAN);
+ pushInvokeStatic(node, helper, inputs, backend.boolType);
HInstruction call = pop();
- return new HIs.compound(type, expression, call);
+ return new HIs.compound(type, expression, call, backend.boolType);
} else {
if (backend.hasDirectCheckFor(type)) {
- return new HIs.direct(type, expression);
+ return new HIs.direct(type, expression, backend.boolType);
}
// TODO(johnniwinther): Avoid interceptor if unneeded.
- return new HIs.raw(type, expression, invokeInterceptor(expression));
+ return new HIs.raw(
+ type, expression, invokeInterceptor(expression), backend.boolType);
}
}
@@ -3100,7 +3115,9 @@
inputs.add(closureTarget);
addDynamicSendArgumentsToList(node, inputs);
Selector closureSelector = new Selector.callClosureFrom(selector);
- pushWithPosition(new HInvokeClosure(closureSelector, inputs), node);
+ pushWithPosition(
+ new HInvokeClosure(closureSelector, inputs, backend.dynamicType),
+ node);
}
void handleForeignJs(Send node) {
@@ -3136,7 +3153,7 @@
// to fetch the current isolate.
String name = backend.namer.CURRENT_ISOLATE;
push(new HForeign(new js.LiteralString(name),
- HType.UNKNOWN,
+ backend.dynamicType,
<HInstruction>[]));
} else {
// Call a helper method from the isolate library. The isolate
@@ -3147,7 +3164,7 @@
compiler.cancel(
'Isolate library and compiler mismatch', node: node);
}
- pushInvokeStatic(null, element, [], HType.UNKNOWN);
+ pushInvokeStatic(null, element, [], backend.dynamicType);
}
}
@@ -3184,6 +3201,29 @@
argument, string.dartString.slowToString())));
}
+ void handleJsInterceptorConstant(Send node) {
+ // Single argument must be a TypeConstant which is converted into a
+ // InterceptorConstant.
+ if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) {
+ Node argument = node.arguments.head;
+ visit(argument);
+ HInstruction argumentInstruction = pop();
+ if (argumentInstruction is HConstant) {
+ Constant argumentConstant = argumentInstruction.constant;
+ if (argumentConstant is TypeConstant) {
+ Constant constant =
+ new InterceptorConstant(argumentConstant.representedType);
+ HInstruction instruction = graph.addConstant(constant, compiler);
+ stack.add(instruction);
+ return;
+ }
+ }
+ }
+ compiler.reportError(node,
+ MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
+ stack.add(graph.addConstantNull(compiler));
+ }
+
void handleForeignJsCallInIsolate(Send node) {
Link<Node> link = node.arguments;
if (!compiler.hasIsolateSupport()) {
@@ -3191,7 +3231,9 @@
// closure.
visit(link.tail.head);
Selector selector = new Selector.callClosure(0);
- push(new HInvokeClosure(selector, <HInstruction>[pop()]));
+ push(new HInvokeClosure(selector,
+ <HInstruction>[pop()],
+ backend.dynamicType));
} else {
// Call a helper method from the isolate library.
Element element = compiler.isolateHelperLibrary.find('_callInIsolate');
@@ -3201,7 +3243,7 @@
}
List<HInstruction> inputs = <HInstruction>[];
addGenericSendArgumentsToList(link, inputs);
- pushInvokeStatic(node, element, inputs, HType.UNKNOWN);
+ pushInvokeStatic(node, element, inputs, backend.dynamicType);
}
}
@@ -3238,7 +3280,7 @@
String invocationName = backend.namer.invocationName(
new Selector.callClosure(params.requiredParameterCount));
push(new HForeign(js.js('#.$invocationName'),
- HType.UNKNOWN,
+ backend.dynamicType,
inputs));
}
@@ -3252,7 +3294,7 @@
SideEffects sideEffects = new SideEffects.empty();
sideEffects.setAllSideEffects();
push(new HForeign(js.js("$isolateName = #"),
- HType.UNKNOWN,
+ backend.dynamicType,
<HInstruction>[pop()],
effects: sideEffects));
}
@@ -3264,7 +3306,7 @@
}
String constructorName = backend.namer.isolateName;
push(new HForeign(js.js("new $constructorName()"),
- HType.UNKNOWN,
+ backend.dynamicType,
<HInstruction>[]));
}
@@ -3274,7 +3316,7 @@
}
String jsClassReference = backend.namer.isolateAccess(compiler.objectClass);
push(new HForeign(new js.LiteralString(jsClassReference),
- HType.UNKNOWN,
+ backend.dynamicType,
<HInstruction>[]));
}
@@ -3283,7 +3325,7 @@
compiler.cancel('Too many arguments', node: node.argumentsNode);
}
push(new HForeign(new js.LiteralString(backend.namer.CURRENT_ISOLATE),
- HType.UNKNOWN,
+ backend.dynamicType,
<HInstruction>[]));
}
@@ -3351,6 +3393,8 @@
handleForeignJsGetName(node);
} else if (name == 'JS_EFFECT') {
stack.add(graph.addConstantNull(compiler));
+ } else if (name == 'JS_INTERCEPTOR_CONSTANT') {
+ handleJsInterceptorConstant(node);
} else {
throw "Unknown foreign: ${selector}";
}
@@ -3363,12 +3407,13 @@
ClassElement cls = currentNonClosureClass;
Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD);
- if (element.enclosingElement.declaration != compiler.objectClass) {
+ if (compiler.enabledInvokeOn
+ && element.enclosingElement.declaration != compiler.objectClass) {
// Register the call as dynamic if [noSuchMethod] on the super
// class is _not_ the default implementation from [Object], in
// case the [noSuchMethod] implementation calls
// [JSInvocationMirror._invokeOn].
- compiler.enqueuer.codegen.registerSelectorUse(selector);
+ compiler.enqueuer.codegen.registerSelectorUse(selector.asUntyped);
}
String publicName = name;
if (selector.isSetter()) publicName += '=';
@@ -3404,7 +3449,7 @@
graph.addConstant(kindConstant, compiler),
argumentsInstruction,
argumentNamesInstruction],
- HType.UNKNOWN);
+ backend.dynamicType);
var inputs = <HInstruction>[pop()];
push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs));
@@ -3452,7 +3497,7 @@
inputs = <HInstruction>[target];
addDynamicSendArgumentsToList(node, inputs);
Selector closureSelector = new Selector.callClosureFrom(selector);
- push(new HInvokeClosure(closureSelector, inputs));
+ push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType));
}
}
@@ -3478,7 +3523,7 @@
[target,
substitutionName,
graph.addConstantInt(index, compiler)],
- HType.UNKNOWN);
+ backend.dynamicType);
return pop();
}
@@ -3584,7 +3629,7 @@
null,
typeInfoSetterElement,
<HInstruction>[newObject, typeInfo],
- HType.UNKNOWN);
+ backend.dynamicType);
pop();
}
@@ -3600,13 +3645,17 @@
isListConstructor = true;
HType inferred =
new HType.inferredForNode(currentElement, send, compiler);
- return inferred.isUnknown() ? backend.fixedArrayType : inferred;
+ return inferred.containsAll(compiler)
+ ? backend.fixedArrayType
+ : inferred;
} else if (Elements.isGrowableListConstructorCall(
originalElement, send, compiler)) {
isListConstructor = true;
HType inferred =
new HType.inferredForNode(currentElement, send, compiler);
- return inferred.isUnknown() ? backend.extendableArrayType : inferred;
+ return inferred.containsAll(compiler)
+ ? backend.extendableArrayType
+ : inferred;
} else if (element.isGenerativeConstructor()) {
ClassElement cls = element.getEnclosingClass();
return new HType.nonNullExact(cls.thisType.element, compiler);
@@ -3732,7 +3781,8 @@
}
if (element == compiler.identicalFunction) {
- pushWithPosition(new HIdentity(inputs[0], inputs[1]), node);
+ pushWithPosition(
+ new HIdentity(inputs[0], inputs[1], null, backend.boolType), node);
return;
}
@@ -3742,7 +3792,9 @@
List<HInstruction> inputs = <HInstruction>[pop()];
addDynamicSendArgumentsToList(node, inputs);
Selector closureSelector = new Selector.callClosureFrom(selector);
- pushWithPosition(new HInvokeClosure(closureSelector, inputs), node);
+ pushWithPosition(
+ new HInvokeClosure(closureSelector, inputs, backend.dynamicType),
+ node);
}
}
@@ -3786,7 +3838,7 @@
List<HInstruction> inputs = <HInstruction>[target];
addDynamicSendArgumentsToList(node, inputs);
Selector closureSelector = new Selector.callClosureFrom(selector);
- push(new HInvokeClosure(closureSelector, inputs));
+ push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType));
}
}
@@ -3965,19 +4017,20 @@
inputs.add(invokeInterceptor(receiver));
}
inputs.addAll(arguments);
+ HType type = new HType.inferredTypeForSelector(selector, compiler);
if (selector.isGetter()) {
bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
pushWithPosition(
- new HInvokeDynamicGetter(selector, null, inputs, !hasGetter),
+ new HInvokeDynamicGetter(selector, null, inputs, type, !hasGetter),
location);
} else if (selector.isSetter()) {
bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
pushWithPosition(
- new HInvokeDynamicSetter(selector, null, inputs, !hasSetter),
+ new HInvokeDynamicSetter(selector, null, inputs, type, !hasSetter),
location);
} else {
pushWithPosition(
- new HInvokeDynamicMethod(selector, inputs, isIntercepted),
+ new HInvokeDynamicMethod(selector, inputs, type, isIntercepted),
location);
}
}
@@ -4021,19 +4074,19 @@
}
inputs.add(receiver);
inputs.addAll(arguments);
+ HType type;
+ if (!element.isGetter() && selector.isGetter()) {
+ type = new HType.inferredTypeForElement(element, compiler);
+ } else {
+ type = new HType.inferredReturnTypeForElement(element, compiler);
+ }
HInstruction instruction = new HInvokeSuper(
element,
currentNonClosureClass,
selector,
inputs,
+ type,
isSetter: selector.isSetter() || selector.isIndexSet());
- if (!element.isGetter() && selector.isGetter()) {
- instruction.instructionType =
- new HType.inferredTypeForElement(element, compiler);
- } else {
- instruction.instructionType =
- new HType.inferredReturnTypeForElement(element, compiler);
- }
instruction.sideEffects = compiler.world.getSideEffectsOfElement(element);
return instruction;
}
@@ -4384,7 +4437,7 @@
}
HType type = new HType.inferredForNode(currentElement, node, compiler);
- if (!type.isUnknown()) instruction.instructionType = type;
+ if (!type.containsAll(compiler)) instruction.instructionType = type;
stack.add(instruction);
}
@@ -4809,7 +4862,7 @@
void buildCondition() {
js.Expression code = js.js.parseForeignJS('#');
push(createForeign(code,
- HType.BOOLEAN,
+ backend.boolType,
[localsHandler.readLocal(switchTarget)]));
}
handleIf(node, buildCondition, buildLoop, () => {});
@@ -5009,7 +5062,7 @@
Element element = new ElementX('exception',
ElementKind.PARAMETER,
currentElement);
- exception = new HLocalValue(element);
+ exception = new HLocalValue(element, backend.nonNullType);
add(exception);
HInstruction oldRethrowableException = rethrowableException;
rethrowableException = exception;
@@ -5494,7 +5547,7 @@
boolifiedLeft = builder.popBoolified();
builder.stack.add(boolifiedLeft);
if (!isAnd) {
- builder.push(new HNot(builder.pop()));
+ builder.push(new HNot(builder.pop(), builder.backend.boolType));
}
}
@@ -5506,8 +5559,10 @@
handleIf(visitCondition, visitThen, null);
HConstant notIsAnd =
builder.graph.addConstantBool(!isAnd, builder.compiler);
+ JavaScriptBackend backend = builder.backend;
HPhi result = new HPhi.manyInputs(null,
- <HInstruction>[boolifiedRight, notIsAnd]);
+ <HInstruction>[boolifiedRight, notIsAnd],
+ backend.dynamicType);
builder.current.addPhi(result);
builder.stack.add(result);
}
@@ -5566,8 +5621,9 @@
if (isExpression) {
assert(thenValue != null && elseValue != null);
- HPhi phi =
- new HPhi.manyInputs(null, <HInstruction>[thenValue, elseValue]);
+ JavaScriptBackend backend = builder.backend;
+ HPhi phi = new HPhi.manyInputs(
+ null, <HInstruction>[thenValue, elseValue], backend.dynamicType);
joinBranch.block.addPhi(phi);
builder.stack.add(phi);
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 392350c..017889f 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -80,9 +80,9 @@
js.Expression generateMethod(CodegenWorkItem work, HGraph graph) {
return measure(() {
- compiler.tracer.traceGraph("codegen", graph);
SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
codegen.visitGraph(graph);
+ compiler.tracer.traceGraph("codegen", graph);
FunctionElement element = work.element;
return buildJavaScriptFunction(element, codegen.parameters, codegen.body);
});
@@ -278,10 +278,8 @@
return jsNode;
}
- beginGraph(HGraph graph);
- endGraph(HGraph graph);
-
void preGenerateMethod(HGraph graph) {
+ new SsaTypeKnownRemover().visitGraph(graph);
new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph);
new SsaConditionMerger(
generateAtUseSite, controlFlowOperators).visitGraph(graph);
@@ -1543,13 +1541,9 @@
compiler);
return receiverType.refine(selector, compiler);
}
- // If [JSInvocationMirror._invokeOn] has been called, we must not create a
- // typed selector based on the receiver type.
- if (backend.compiler.enabledInvokeOn) {
- return selector.asUntyped;
- }
- HType receiverType = node.getDartReceiver(compiler).instructionType;
- return receiverType.refine(selector, compiler);
+ // If [JSInvocationMirror._invokeOn] is enabled, and this call
+ // might hit a `noSuchMethod`, we register an untyped selector.
+ return selector.extendIfReachesAll(compiler);
}
void registerMethodInvoke(HInvokeDynamic node) {
@@ -1836,15 +1830,13 @@
HInstruction left = relational.left;
HInstruction right = relational.right;
- if (left.instructionType.isUseful() && left.isString(compiler) &&
- right.instructionType.isUseful() && right.isString(compiler)) {
+ if (left.isString(compiler) && right.isString(compiler)) {
return true;
}
// This optimization doesn't work for NaN, so we only do it if the
// type is known to be an integer.
- return left.instructionType.isUseful() && left.isInteger()
- && right.instructionType.isUseful() && right.isInteger();
+ return left.isInteger(compiler) && right.isInteger(compiler);
}
bool handledBySpecialCase = false;
@@ -1964,13 +1956,13 @@
js.Expression over;
if (node.staticChecks != HBoundsCheck.ALWAYS_ABOVE_ZERO) {
use(node.index);
- if (node.index.isInteger()) {
+ if (node.index.isInteger(compiler)) {
under = js.js("# < 0", pop());
} else {
js.Expression jsIndex = pop();
under = js.js("# >>> 0 !== #", [jsIndex, jsIndex]);
}
- } else if (!node.index.isInteger()) {
+ } else if (!node.index.isInteger(compiler)) {
checkInt(node.index, '!==');
under = pop();
}
@@ -2081,7 +2073,7 @@
HInstruction input = node.inputs.first;
if (input.isString(compiler)) {
use(input);
- } else if (input.isInteger() || input.isBoolean()) {
+ } else if (input.isInteger(compiler) || input.isBoolean(compiler)) {
// JavaScript's + operator with a string for the left operand will convert
// the right operand to a string, and the conversion result is correct.
use(input);
@@ -2443,24 +2435,25 @@
// V8 generally prefers 'typeof' checks, but for integers and
// indexable primitives we cannot compile this test into a single
// typeof check so the null check is cheaper.
- bool turnIntoNumCheck = input.isIntegerOrNull() && checkedType.isInteger();
+ bool turnIntoNumCheck = input.isIntegerOrNull(compiler)
+ && checkedType.isInteger(compiler);
bool turnIntoNullCheck = !turnIntoNumCheck
&& (mask.nullable() == receiver)
- && (checkedType.isInteger()
+ && (checkedType.isInteger(compiler)
|| checkedType.isIndexablePrimitive(compiler));
js.Expression test;
if (turnIntoNullCheck) {
use(input);
test = new js.Binary("==", pop(), new js.LiteralNull());
- } else if (checkedType.isInteger() && !turnIntoNumCheck) {
+ } else if (checkedType.isInteger(compiler) && !turnIntoNumCheck) {
// input is !int
checkInt(input, '!==');
test = pop();
- } else if (checkedType.isNumber() || turnIntoNumCheck) {
+ } else if (checkedType.isNumber(compiler) || turnIntoNumCheck) {
// input is !num
checkNum(input, '!==');
test = pop();
- } else if (checkedType.isBoolean()) {
+ } else if (checkedType.isBoolean(compiler)) {
// input is !bool
checkBool(input, '!==');
test = pop();
@@ -2531,8 +2524,8 @@
if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
// An int check if the input is not int or null, is not
// sufficient for doing a argument or receiver check.
- assert(!node.checkedType.isInteger() ||
- node.checkedInput.isIntegerOrNull());
+ assert(!node.checkedType.isInteger(compiler) ||
+ node.checkedInput.isIntegerOrNull(compiler));
js.Expression test = generateTest(node.checkedInput, node.checkedType);
js.Block oldContainer = currentContainer;
js.Statement body = new js.Block.empty();
@@ -2577,7 +2570,8 @@
}
void visitTypeKnown(HTypeKnown node) {
- use(node.checkedInput);
+ // [HTypeKnown] instructions are removed before generating code.
+ assert(false);
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
index a476a1e..8a72f49 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
@@ -5,6 +5,31 @@
part of ssa;
/**
+ * Remove [HTypeKnown] instructions from the graph, to make codegen
+ * analysis easier.
+ */
+class SsaTypeKnownRemover extends HBaseVisitor {
+
+ void visitGraph(HGraph graph) {
+ visitDominatorTree(graph);
+ }
+
+ void visitBasicBlock(HBasicBlock block) {
+ HInstruction instruction = block.first;
+ while (instruction != null) {
+ HInstruction next = instruction.next;
+ instruction.accept(this);
+ instruction = next;
+ }
+ }
+
+ void visitTypeKnown(HTypeKnown instruction) {
+ instruction.block.rewrite(instruction, instruction.checkedInput);
+ instruction.block.remove(instruction);
+ }
+}
+
+/**
* Instead of emitting each SSA instruction with a temporary variable
* mark instructions that can be emitted at their use-site.
* For example, in:
@@ -119,7 +144,8 @@
}
void visitTypeKnown(HTypeKnown instruction) {
- markAsGenerateAtUseSite(instruction);
+ // [HTypeKnown] instructions are removed before code generation.
+ assert(false);
}
void tryGenerateAtUseSite(HInstruction instruction) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
index ae9f7e3..0f89282 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -107,17 +107,17 @@
if (type.isNull()) {
constantInterceptor = backend.jsNullClass;
}
- } else if (type.isInteger()) {
+ } else if (type.isInteger(compiler)) {
constantInterceptor = backend.jsIntClass;
- } else if (type.isDouble()) {
+ } else if (type.isDouble(compiler)) {
constantInterceptor = backend.jsDoubleClass;
- } else if (type.isBoolean()) {
+ } else if (type.isBoolean(compiler)) {
constantInterceptor = backend.jsBoolClass;
} else if (type.isString(compiler)) {
constantInterceptor = backend.jsStringClass;
} else if (type.isArray(compiler)) {
constantInterceptor = backend.jsArrayClass;
- } else if (type.isNumber()
+ } else if (type.isNumber(compiler)
&& !interceptedClasses.contains(backend.jsIntClass)
&& !interceptedClasses.contains(backend.jsDoubleClass)) {
// If the method being intercepted is not defined in [int] or [double] we
@@ -246,10 +246,9 @@
List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
inputs[0] = nullConstant;
HOneShotInterceptor interceptor = new HOneShotInterceptor(
- user.selector, inputs, node.interceptedClasses);
+ user.selector, inputs, user.instructionType, node.interceptedClasses);
interceptor.sourcePosition = user.sourcePosition;
interceptor.sourceElement = user.sourceElement;
- interceptor.instructionType = user.instructionType;
HBasicBlock block = user.block;
block.addAfter(user, interceptor);
@@ -273,17 +272,20 @@
selector,
node.element,
<HInstruction>[constant, node.inputs[1]],
+ node.instructionType,
false);
} else if (node.selector.isSetter()) {
instruction = new HInvokeDynamicSetter(
selector,
node.element,
<HInstruction>[constant, node.inputs[1], node.inputs[2]],
+ node.instructionType,
false);
} else {
List<HInstruction> inputs = new List<HInstruction>.from(node.inputs);
inputs[0] = constant;
- instruction = new HInvokeDynamicMethod(selector, inputs, true);
+ instruction = new HInvokeDynamicMethod(
+ selector, inputs, node.instructionType, true);
}
HBasicBlock block = node.block;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
index 67768a8..d2e54d0 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -15,16 +15,15 @@
HType computeTypeFromInputTypes(HInvokeDynamic instruction,
Compiler compiler) {
- HType receiverType = instruction.getDartReceiver(compiler).instructionType;
- Selector refined = receiverType.refine(instruction.selector, compiler);
- HType type = new HType.inferredTypeForSelector(refined, compiler);
+ Selector selector = instruction.selector;
+ HType type = new HType.inferredTypeForSelector(selector, compiler);
// TODO(ngeoffray): Because we don't know yet the side effects of
// a JS call, we sometimes know more in the compiler about the
// side effects of an element (for example operator% on the int
// class). We should remove this check once we analyze JS calls.
if (!instruction.useGvn()) {
instruction.sideEffects =
- compiler.world.getSideEffectsOfSelector(refined);
+ compiler.world.getSideEffectsOfSelector(selector);
}
return type;
}
@@ -90,7 +89,8 @@
HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
Compiler compiler) {
if (instruction.inputs[1].isMutableIndexable(compiler)) {
- if (!instruction.inputs[2].isInteger() && compiler.enableTypeAssertions) {
+ if (!instruction.inputs[2].isInteger(compiler)
+ && compiler.enableTypeAssertions) {
// We want the right checked mode error.
return null;
}
@@ -109,17 +109,17 @@
HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
Compiler compiler) {
if (!instruction.inputs[1].isIndexable(compiler)) return null;
- if (!instruction.inputs[2].isInteger() && compiler.enableTypeAssertions) {
+ if (!instruction.inputs[2].isInteger(compiler)
+ && compiler.enableTypeAssertions) {
// We want the right checked mode error.
return null;
}
- HInstruction index = new HIndex(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
HType receiverType = instruction.getDartReceiver(compiler).instructionType;
Selector refined = receiverType.refine(instruction.selector, compiler);
HType type = new HType.inferredTypeForSelector(refined, compiler);
- index.instructionType = type;
- return index;
+ return new HIndex(
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, type);
}
}
@@ -134,14 +134,20 @@
Compiler compiler) {
// All bitwise operations on primitive types either produce an
// integer or throw an error.
- if (instruction.inputs[1].isPrimitiveOrNull(compiler)) return HType.INTEGER;
+ JavaScriptBackend backend = compiler.backend;
+ if (instruction.inputs[1].isPrimitiveOrNull(compiler)) {
+ return backend.intType;
+ }
return super.computeTypeFromInputTypes(instruction, compiler);
}
HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
HInstruction input = instruction.inputs[1];
- if (input.isNumber()) return new HBitNot(input, instruction.selector);
+ if (input.isNumber(compiler)) {
+ return new HBitNot(input, instruction.selector, backend.intType);
+ }
return null;
}
}
@@ -156,14 +162,16 @@
HType computeTypeFromInputTypes(HInvokeDynamic instruction,
Compiler compiler) {
HType operandType = instruction.inputs[1].instructionType;
- if (operandType.isNumberOrNull()) return operandType;
+ if (operandType.isNumberOrNull(compiler)) return operandType;
return super.computeTypeFromInputTypes(instruction, compiler);
}
HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
Compiler compiler) {
HInstruction input = instruction.inputs[1];
- if (input.isNumber()) return new HNegate(input, instruction.selector);
+ if (input.isNumber(compiler)) {
+ return new HNegate(input, instruction.selector, input.instructionType);
+ }
return null;
}
}
@@ -175,23 +183,28 @@
Compiler compiler) {
HInstruction left = instruction.inputs[1];
HInstruction right = instruction.inputs[2];
- if (left.isIntegerOrNull() && right.isIntegerOrNull()) return HType.INTEGER;
- if (left.isNumberOrNull()) {
- if (left.isDoubleOrNull() || right.isDoubleOrNull()) return HType.DOUBLE;
- return HType.NUMBER;
+ JavaScriptBackend backend = compiler.backend;
+ if (left.isIntegerOrNull(compiler) && right.isIntegerOrNull(compiler)) {
+ return backend.intType;
+ }
+ if (left.isNumberOrNull(compiler)) {
+ if (left.isDoubleOrNull(compiler) || right.isDoubleOrNull(compiler)) {
+ return backend.doubleType;
+ }
+ return backend.numType;
}
return super.computeTypeFromInputTypes(instruction, compiler);
}
- bool isBuiltin(HInvokeDynamic instruction) {
- return instruction.inputs[1].isNumber()
- && instruction.inputs[2].isNumber();
+ bool isBuiltin(HInvokeDynamic instruction, Compiler compiler) {
+ return instruction.inputs[1].isNumber(compiler)
+ && instruction.inputs[2].isNumber(compiler);
}
HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
Compiler compiler) {
- if (isBuiltin(instruction)) {
- HInstruction builtin = newBuiltinVariant(instruction);
+ if (isBuiltin(instruction, compiler)) {
+ HInstruction builtin = newBuiltinVariant(instruction, compiler);
if (builtin != null) return builtin;
// Even if there is no builtin equivalent instruction, we know
// the instruction does not have any side effect, and that it
@@ -203,7 +216,7 @@
return null;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction);
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler);
}
class AddSpecializer extends BinaryArithmeticSpecializer {
@@ -213,9 +226,11 @@
return constantSystem.add;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
return new HAdd(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, computeTypeFromInputTypes(instruction, compiler));
}
}
@@ -229,13 +244,19 @@
HType computeTypeFromInputTypes(HInstruction instruction,
Compiler compiler) {
HInstruction left = instruction.inputs[1];
- if (left.isNumberOrNull()) return HType.DOUBLE;
+ JavaScriptBackend backend = compiler.backend;
+ if (left.isNumberOrNull(compiler)) {
+ return backend.doubleType;
+ }
return super.computeTypeFromInputTypes(instruction, compiler);
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HDivide(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.doubleType);
}
}
@@ -246,7 +267,8 @@
return constantSystem.modulo;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
// Modulo cannot be mapped to the native operator (different semantics).
return null;
}
@@ -259,9 +281,11 @@
return constantSystem.multiply;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
return new HMultiply(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, computeTypeFromInputTypes(instruction, compiler));
}
}
@@ -272,9 +296,11 @@
return constantSystem.subtract;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
return new HSubtract(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, computeTypeFromInputTypes(instruction, compiler));
}
}
@@ -285,7 +311,8 @@
return constantSystem.truncatingDivide;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
// Truncating divide does not have a JS equivalent.
return null;
}
@@ -299,7 +326,10 @@
// All bitwise operations on primitive types either produce an
// integer or throw an error.
HInstruction left = instruction.inputs[1];
- if (left.isPrimitiveOrNull(compiler)) return HType.INTEGER;
+ JavaScriptBackend backend = compiler.backend;
+ if (left.isPrimitiveOrNull(compiler)) {
+ return backend.intType;
+ }
return super.computeTypeFromInputTypes(instruction, compiler);
}
}
@@ -315,16 +345,19 @@
Compiler compiler) {
HInstruction left = instruction.inputs[1];
HInstruction right = instruction.inputs[2];
- if (!left.isNumber()) return null;
+ if (!left.isNumber(compiler)) return null;
if (argumentLessThan32(right)) {
- return newBuiltinVariant(instruction);
+ return newBuiltinVariant(instruction, compiler);
}
return null;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HShiftLeft(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.intType);
}
bool argumentLessThan32(HInstruction instruction) {
@@ -339,7 +372,8 @@
class ShiftRightSpecializer extends BinaryBitOpSpecializer {
const ShiftRightSpecializer();
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
// Shift right cannot be mapped to the native operator easily.
return null;
}
@@ -356,9 +390,12 @@
return constantSystem.bitOr;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HBitOr(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.intType);
}
}
@@ -369,9 +406,12 @@
return constantSystem.bitAnd;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HBitAnd(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.intType);
}
}
@@ -382,9 +422,12 @@
return constantSystem.bitXor;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HBitXor(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.intType);
}
}
@@ -393,8 +436,9 @@
HType computeTypeFromInputTypes(HInvokeDynamic instruction,
Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
if (instruction.inputs[1].instructionType.isPrimitiveOrNull(compiler)) {
- return HType.BOOLEAN;
+ return backend.boolType;
}
return super.computeTypeFromInputTypes(instruction, compiler);
}
@@ -403,13 +447,13 @@
Compiler compiler) {
HInstruction left = instruction.inputs[1];
HInstruction right = instruction.inputs[2];
- if (left.isNumber() && right.isNumber()) {
- return newBuiltinVariant(instruction);
+ if (left.isNumber(compiler) && right.isNumber(compiler)) {
+ return newBuiltinVariant(instruction, compiler);
}
return null;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction);
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler);
}
class EqualsSpecializer extends RelationalSpecializer {
@@ -421,7 +465,7 @@
HInstruction right = instruction.inputs[2];
HType instructionType = left.instructionType;
if (right.isConstantNull() || instructionType.isPrimitiveOrNull(compiler)) {
- return newBuiltinVariant(instruction);
+ return newBuiltinVariant(instruction, compiler);
}
Selector selector = instructionType.refine(instruction.selector, compiler);
World world = compiler.world;
@@ -431,7 +475,7 @@
// implemented because if the selector matches by subtype, it still will be
// a regular object or an interceptor.
if (matches.every(backend.isDefaultEqualityImplementation)) {
- return newBuiltinVariant(instruction);
+ return newBuiltinVariant(instruction, compiler);
}
return null;
}
@@ -440,9 +484,12 @@
return constantSystem.equal;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HIdentity(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.boolType);
}
}
@@ -453,9 +500,12 @@
return constantSystem.less;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HLess(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.boolType);
}
}
@@ -466,9 +516,12 @@
return constantSystem.greater;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HGreater(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.boolType);
}
}
@@ -479,9 +532,12 @@
return constantSystem.greaterEqual;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HGreaterEqual(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.boolType);
}
}
@@ -492,8 +548,11 @@
return constantSystem.lessEqual;
}
- HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
+ HInstruction newBuiltinVariant(HInvokeDynamic instruction,
+ Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
return new HLessEqual(
- instruction.inputs[1], instruction.inputs[2], instruction.selector);
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, backend.boolType);
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index c72124e..3282eb0 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -163,17 +163,20 @@
static HType mapConstantTypeToSsaType(Constant constant, Compiler compiler) {
JavaScriptBackend backend = compiler.backend;
- if (constant.isNull()) return HType.NULL;
- if (constant.isBool()) return HType.BOOLEAN;
- if (constant.isInt()) return HType.INTEGER;
- if (constant.isDouble()) return HType.DOUBLE;
+ if (constant.isNull()) return backend.nullType;
+ if (constant.isBool()) return backend.boolType;
+ if (constant.isInt()) return backend.intType;
+ if (constant.isDouble()) return backend.doubleType;
if (constant.isString()) return backend.stringType;
if (constant.isList()) return backend.readableArrayType;
- if (constant.isFunction()) return HType.UNKNOWN;
- if (constant.isSentinel()) return HType.UNKNOWN;
+ if (constant.isFunction()) return backend.nonNullType;
+ if (constant.isSentinel()) return backend.nonNullType;
// TODO(sra): What is the type of the prototype of an interceptor?
- if (constant.isInterceptor()) return HType.UNKNOWN;
+ if (constant.isInterceptor()) return backend.nonNullType;
ObjectConstant objectConstant = constant;
+ if (backend.isInterceptorClass(objectConstant.type.element)) {
+ return backend.nonNullType;
+ }
TypeMask mask = new TypeMask.nonNullExact(objectConstant.type.element);
return new HBoundedType(mask);
}
@@ -749,6 +752,7 @@
}
}
+const HType EMPTY_TYPE = const HBoundedType(const TypeMask.nonNullEmpty());
abstract class HInstruction implements Spannable {
Element sourceElement;
@@ -800,7 +804,8 @@
static const int IS_TYPECODE = 28;
static const int INVOKE_DYNAMIC_TYPECODE = 29;
- HInstruction(this.inputs) : id = idCounter++, usedBy = <HInstruction>[] {
+ HInstruction(this.inputs, this.instructionType)
+ : id = idCounter++, usedBy = <HInstruction>[] {
assert(inputs.every((e) => e != null));
}
@@ -852,13 +857,20 @@
instructionType.isPrimitive(compiler);
bool isPrimitiveOrNull(Compiler compiler) =>
instructionType.isPrimitiveOrNull(compiler);
- bool isBoolean() => instructionType.isBoolean();
- bool isInteger() => instructionType.isInteger();
- bool isIntegerOrNull() => instructionType.isIntegerOrNull();
- bool isDouble() => instructionType.isDouble();
- bool isDoubleOrNull() => instructionType.isDoubleOrNull();
- bool isNumber() => instructionType.isNumber();
- bool isNumberOrNull() => instructionType.isNumberOrNull();
+ bool isBoolean(Compiler compiler) =>
+ instructionType.isBoolean(compiler);
+ bool isInteger(Compiler compiler) =>
+ instructionType.isInteger(compiler);
+ bool isIntegerOrNull(Compiler compiler) =>
+ instructionType.isIntegerOrNull(compiler);
+ bool isDouble(Compiler compiler) =>
+ instructionType.isDouble(compiler);
+ bool isDoubleOrNull(Compiler compiler) =>
+ instructionType.isDoubleOrNull(compiler);
+ bool isNumber(Compiler compiler) =>
+ instructionType.isNumber(compiler);
+ bool isNumberOrNull(Compiler compiler) =>
+ instructionType.isNumberOrNull(compiler);
bool isNull() => instructionType.isNull();
bool canBeNull() => instructionType.canBeNull();
bool canBePrimitive(Compiler compiler) =>
@@ -878,7 +890,7 @@
/**
* Type of the unstruction.
*/
- HType instructionType = HType.UNKNOWN;
+ HType instructionType;
Selector get selector => null;
HInstruction getDartReceiver(Compiler compiler) => null;
@@ -1119,11 +1131,12 @@
// The type element is either a class or the void element.
Element element = type.element;
if (identical(element, compiler.objectClass)) return this;
+ JavaScriptBackend backend = compiler.backend;
if (type.kind != TypeKind.INTERFACE) {
- return new HTypeConversion(type, kind, HType.UNKNOWN, this);
+ return new HTypeConversion(type, kind, backend.dynamicType, this);
} else if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) {
// Boolean conversion checks work on non-nullable booleans.
- return new HTypeConversion(type, kind, HType.BOOLEAN, this);
+ return new HTypeConversion(type, kind, backend.boolType, this);
} else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) {
throw 'creating compound check to $type (this = ${this})';
} else {
@@ -1142,9 +1155,9 @@
}
class HBoolify extends HInstruction {
- HBoolify(HInstruction value) : super(<HInstruction>[value]) {
+ HBoolify(HInstruction value, HType type)
+ : super(<HInstruction>[value], type) {
setUseGvn();
- instructionType = HType.BOOLEAN;
}
accept(HVisitor visitor) => visitor.visitBoolify(this);
@@ -1161,7 +1174,7 @@
* instruction itself.
*/
abstract class HCheck extends HInstruction {
- HCheck(inputs) : super(inputs) {
+ HCheck(inputs, type) : super(inputs, type) {
setUseGvn();
}
HInstruction get checkedInput => inputs[0];
@@ -1183,10 +1196,8 @@
*/
int staticChecks = FULL_CHECK;
- HBoundsCheck(length, index, array)
- : super(<HInstruction>[length, index, array]) {
- instructionType = HType.INTEGER;
- }
+ HBoundsCheck(length, index, array, type)
+ : super(<HInstruction>[length, index, array], type);
HInstruction get length => inputs[1];
HInstruction get index => inputs[0];
@@ -1207,7 +1218,7 @@
}
abstract class HControlFlow extends HInstruction {
- HControlFlow(inputs) : super(inputs);
+ HControlFlow(inputs) : super(inputs, EMPTY_TYPE);
bool isControlFlow() => true;
bool isJsStatement() => true;
}
@@ -1218,7 +1229,7 @@
* the receiver of a method-call. The remaining inputs are the arguments
* to the invocation.
*/
- HInvoke(List<HInstruction> inputs) : super(inputs) {
+ HInvoke(List<HInstruction> inputs, type) : super(inputs, type) {
sideEffects.setAllSideEffects();
sideEffects.setDependsOnSomething();
}
@@ -1238,14 +1249,15 @@
abstract class HInvokeDynamic extends HInvoke {
final InvokeDynamicSpecializer specializer;
- final Selector selector;
+ Selector selector;
Element element;
HInvokeDynamic(Selector selector,
this.element,
List<HInstruction> inputs,
+ HType type,
[bool isIntercepted = false])
- : super(inputs),
+ : super(inputs, type),
this.selector = selector,
specializer = isIntercepted
? InvokeDynamicSpecializer.lookupSpecializer(selector)
@@ -1275,8 +1287,8 @@
}
class HInvokeClosure extends HInvokeDynamic {
- HInvokeClosure(Selector selector, List<HInstruction> inputs)
- : super(selector, null, inputs) {
+ HInvokeClosure(Selector selector, List<HInstruction> inputs, HType type)
+ : super(selector, null, inputs, type) {
assert(selector.isClosureCall());
}
accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
@@ -1285,8 +1297,9 @@
class HInvokeDynamicMethod extends HInvokeDynamic {
HInvokeDynamicMethod(Selector selector,
List<HInstruction> inputs,
+ HType type,
[bool isIntercepted = false])
- : super(selector, null, inputs, isIntercepted);
+ : super(selector, null, inputs, type, isIntercepted);
String toString() => 'invoke dynamic method: $selector';
accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
@@ -1303,14 +1316,14 @@
final bool isSideEffectFree;
HInvokeDynamicField(
Selector selector, Element element, List<HInstruction> inputs,
- this.isSideEffectFree)
- : super(selector, element, inputs);
+ HType type, this.isSideEffectFree)
+ : super(selector, element, inputs, type);
toString() => 'invoke dynamic field: $selector';
}
class HInvokeDynamicGetter extends HInvokeDynamicField {
- HInvokeDynamicGetter(selector, element, inputs, isSideEffectFree)
- : super(selector, element, inputs, isSideEffectFree) {
+ HInvokeDynamicGetter(selector, element, inputs, type, isSideEffectFree)
+ : super(selector, element, inputs, type, isSideEffectFree) {
sideEffects.clearAllSideEffects();
if (isSideEffectFree) {
setUseGvn();
@@ -1325,8 +1338,8 @@
}
class HInvokeDynamicSetter extends HInvokeDynamicField {
- HInvokeDynamicSetter(selector, element, inputs, isSideEffectFree)
- : super(selector, element, inputs, isSideEffectFree) {
+ HInvokeDynamicSetter(selector, element, inputs, type, isSideEffectFree)
+ : super(selector, element, inputs, type, isSideEffectFree) {
sideEffects.clearAllSideEffects();
if (isSideEffectFree) {
sideEffects.setChangesInstanceProperty();
@@ -1349,9 +1362,7 @@
List<DartType> instantiatedTypes;
/** The first input must be the target. */
- HInvokeStatic(this.element, inputs, HType type) : super(inputs) {
- instructionType = type;
- }
+ HInvokeStatic(this.element, inputs, HType type) : super(inputs, type);
toString() => 'invoke static: ${element.name}';
accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
@@ -1368,8 +1379,9 @@
this.caller,
this.selector,
inputs,
+ type,
{this.isSetter})
- : super(element, inputs, HType.UNKNOWN);
+ : super(element, inputs, type);
toString() => 'invoke super: ${element.name}';
accept(HVisitor visitor) => visitor.visitInvokeSuper(this);
@@ -1384,8 +1396,8 @@
// The 'inputs' are
// [receiver, arg1, ..., argN] or
// [interceptor, receiver, arg1, ... argN].
- HInvokeConstructorBody(element, inputs)
- : super(element, inputs, HType.UNKNOWN);
+ HInvokeConstructorBody(element, inputs, type)
+ : super(element, inputs, type);
String toString() => 'invoke constructor body: ${element.name}';
accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this);
@@ -1394,8 +1406,8 @@
abstract class HFieldAccess extends HInstruction {
final Element element;
- HFieldAccess(Element element, List<HInstruction> inputs)
- : this.element = element, super(inputs);
+ HFieldAccess(Element element, List<HInstruction> inputs, HType type)
+ : this.element = element, super(inputs, type);
HInstruction get receiver => inputs[0];
}
@@ -1403,11 +1415,14 @@
class HFieldGet extends HFieldAccess {
final bool isAssignable;
- HFieldGet(Element element, HInstruction receiver, {bool isAssignable})
+ HFieldGet(Element element,
+ HInstruction receiver,
+ HType type,
+ {bool isAssignable})
: this.isAssignable = (isAssignable != null)
? isAssignable
: element.isAssignable(),
- super(element, <HInstruction>[receiver]) {
+ super(element, <HInstruction>[receiver], type) {
sideEffects.clearAllSideEffects();
setUseGvn();
if (this.isAssignable) {
@@ -1444,7 +1459,7 @@
HFieldSet(Element element,
HInstruction receiver,
HInstruction value)
- : super(element, <HInstruction>[receiver, value]) {
+ : super(element, <HInstruction>[receiver, value], EMPTY_TYPE) {
sideEffects.clearAllSideEffects();
sideEffects.setChangesInstanceProperty();
}
@@ -1464,8 +1479,8 @@
class HLocalGet extends HFieldAccess {
// No need to use GVN for a [HLocalGet], it is just a local
// access.
- HLocalGet(Element element, HLocalValue local)
- : super(element, <HInstruction>[local]);
+ HLocalGet(Element element, HLocalValue local, HType type)
+ : super(element, <HInstruction>[local], type);
accept(HVisitor visitor) => visitor.visitLocalGet(this);
@@ -1474,7 +1489,7 @@
class HLocalSet extends HFieldAccess {
HLocalSet(Element element, HLocalValue local, HInstruction value)
- : super(element, <HInstruction>[local, value]);
+ : super(element, <HInstruction>[local, value], EMPTY_TYPE);
accept(HVisitor visitor) => visitor.visitLocalSet(this);
@@ -1494,18 +1509,18 @@
{this.isStatement: false,
SideEffects effects,
native.NativeBehavior nativeBehavior})
- : this.nativeBehavior = nativeBehavior, super(inputs) {
+ : this.nativeBehavior = nativeBehavior, super(inputs, type) {
if (effects == null && nativeBehavior != null) {
effects = nativeBehavior.sideEffects;
}
if (effects != null) sideEffects.add(effects);
- instructionType = type;
}
HForeign.statement(codeAst, List<HInstruction> inputs,
SideEffects effects,
- native.NativeBehavior nativeBehavior)
- : this(codeAst, HType.UNKNOWN, inputs, isStatement: true,
+ native.NativeBehavior nativeBehavior,
+ HType type)
+ : this(codeAst, type, inputs, isStatement: true,
effects: effects, nativeBehavior: nativeBehavior);
accept(HVisitor visitor) => visitor.visitForeign(this);
@@ -1534,8 +1549,8 @@
abstract class HInvokeBinary extends HInstruction {
final Selector selector;
- HInvokeBinary(HInstruction left, HInstruction right, this.selector)
- : super(<HInstruction>[left, right]) {
+ HInvokeBinary(HInstruction left, HInstruction right, this.selector, type)
+ : super(<HInstruction>[left, right], type) {
sideEffects.clearAllSideEffects();
setUseGvn();
}
@@ -1547,12 +1562,13 @@
}
abstract class HBinaryArithmetic extends HInvokeBinary {
- HBinaryArithmetic(left, right, selector) : super(left, right, selector);
+ HBinaryArithmetic(left, right, selector, type)
+ : super(left, right, selector, type);
BinaryOperation operation(ConstantSystem constantSystem);
}
class HAdd extends HBinaryArithmetic {
- HAdd(left, right, selector) : super(left, right, selector);
+ HAdd(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitAdd(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1563,9 +1579,7 @@
}
class HDivide extends HBinaryArithmetic {
- HDivide(left, right, selector) : super(left, right, selector) {
- instructionType = HType.DOUBLE;
- }
+ HDivide(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitDivide(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1576,7 +1590,7 @@
}
class HMultiply extends HBinaryArithmetic {
- HMultiply(left, right, selector) : super(left, right, selector);
+ HMultiply(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitMultiply(this);
BinaryOperation operation(ConstantSystem operations)
@@ -1587,7 +1601,7 @@
}
class HSubtract extends HBinaryArithmetic {
- HSubtract(left, right, selector) : super(left, right, selector);
+ HSubtract(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitSubtract(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1621,13 +1635,12 @@
}
abstract class HBinaryBitOp extends HInvokeBinary {
- HBinaryBitOp(left, right, selector) : super(left, right, selector) {
- instructionType = HType.INTEGER;
- }
+ HBinaryBitOp(left, right, selector, type)
+ : super(left, right, selector, type);
}
class HShiftLeft extends HBinaryBitOp {
- HShiftLeft(left, right, selector) : super(left, right, selector);
+ HShiftLeft(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitShiftLeft(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1638,7 +1651,7 @@
}
class HBitOr extends HBinaryBitOp {
- HBitOr(left, right, selector) : super(left, right, selector);
+ HBitOr(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitBitOr(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1649,7 +1662,7 @@
}
class HBitAnd extends HBinaryBitOp {
- HBitAnd(left, right, selector) : super(left, right, selector);
+ HBitAnd(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitBitAnd(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1660,7 +1673,7 @@
}
class HBitXor extends HBinaryBitOp {
- HBitXor(left, right, selector) : super(left, right, selector);
+ HBitXor(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitBitXor(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1672,8 +1685,8 @@
abstract class HInvokeUnary extends HInstruction {
final Selector selector;
- HInvokeUnary(HInstruction input, this.selector)
- : super(<HInstruction>[input]) {
+ HInvokeUnary(HInstruction input, this.selector, type)
+ : super(<HInstruction>[input], type) {
sideEffects.clearAllSideEffects();
setUseGvn();
}
@@ -1684,7 +1697,7 @@
}
class HNegate extends HInvokeUnary {
- HNegate(input, selector) : super(input, selector);
+ HNegate(input, selector, type) : super(input, selector, type);
accept(HVisitor visitor) => visitor.visitNegate(this);
UnaryOperation operation(ConstantSystem constantSystem)
@@ -1695,9 +1708,7 @@
}
class HBitNot extends HInvokeUnary {
- HBitNot(input, selector) : super(input, selector) {
- instructionType = HType.INTEGER;
- }
+ HBitNot(input, selector, type) : super(input, selector, type);
accept(HVisitor visitor) => visitor.visitBitNot(this);
UnaryOperation operation(ConstantSystem constantSystem)
@@ -1825,9 +1836,7 @@
class HConstant extends HInstruction {
final Constant constant;
HConstant.internal(this.constant, HType constantType)
- : super(<HInstruction>[]) {
- instructionType = constantType;
- }
+ : super(<HInstruction>[], constantType);
toString() => 'literal: $constant';
accept(HVisitor visitor) => visitor.visitConstant(this);
@@ -1851,9 +1860,8 @@
}
class HNot extends HInstruction {
- HNot(HInstruction value) : super(<HInstruction>[value]) {
+ HNot(HInstruction value, HType type) : super(<HInstruction>[value], type) {
setUseGvn();
- instructionType = HType.BOOLEAN;
}
accept(HVisitor visitor) => visitor.visitNot(this);
@@ -1868,7 +1876,7 @@
* value from the start, whereas [HLocalValue]s need to be initialized first.
*/
class HLocalValue extends HInstruction {
- HLocalValue(Element element) : super(<HInstruction>[]) {
+ HLocalValue(Element element, HType type) : super(<HInstruction>[], type) {
sourceElement = element;
}
@@ -1877,16 +1885,14 @@
}
class HParameterValue extends HLocalValue {
- HParameterValue(Element element) : super(element);
+ HParameterValue(Element element, type) : super(element, type);
toString() => 'parameter ${sourceElement.name}';
accept(HVisitor visitor) => visitor.visitParameterValue(this);
}
class HThis extends HParameterValue {
- HThis(Element element, [HType type = HType.UNKNOWN]) : super(element) {
- instructionType = type;
- }
+ HThis(Element element, HType type) : super(element, type);
toString() => 'this';
accept(HVisitor visitor) => visitor.visitThis(this);
bool isCodeMotionInvariant() => true;
@@ -1906,14 +1912,16 @@
// The order of the [inputs] must correspond to the order of the
// predecessor-edges. That is if an input comes from the first predecessor
// of the surrounding block, then the input must be the first in the [HPhi].
- HPhi(Element element, List<HInstruction> inputs) : super(inputs) {
+ HPhi(Element element, List<HInstruction> inputs, HType type)
+ : super(inputs, type) {
sourceElement = element;
}
- HPhi.noInputs(Element element) : this(element, <HInstruction>[]);
- HPhi.singleInput(Element element, HInstruction input)
- : this(element, <HInstruction>[input]);
- HPhi.manyInputs(Element element, List<HInstruction> inputs)
- : this(element, inputs);
+ HPhi.noInputs(Element element, HType type)
+ : this(element, <HInstruction>[], type);
+ HPhi.singleInput(Element element, HInstruction input, HType type)
+ : this(element, <HInstruction>[input], type);
+ HPhi.manyInputs(Element element, List<HInstruction> inputs, HType type)
+ : this(element, inputs, type);
void addInput(HInstruction input) {
assert(isInBasicBlock());
@@ -1937,13 +1945,11 @@
abstract class HRelational extends HInvokeBinary {
bool usesBoolifiedInterceptor = false;
- HRelational(left, right, selector) : super(left, right, selector) {
- instructionType = HType.BOOLEAN;
- }
+ HRelational(left, right, selector, type) : super(left, right, selector, type);
}
class HIdentity extends HRelational {
- HIdentity(left, right, [selector]) : super(left, right, selector);
+ HIdentity(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitIdentity(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1954,7 +1960,7 @@
}
class HGreater extends HRelational {
- HGreater(left, right, selector) : super(left, right, selector);
+ HGreater(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitGreater(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1965,7 +1971,8 @@
}
class HGreaterEqual extends HRelational {
- HGreaterEqual(left, right, selector) : super(left, right, selector);
+ HGreaterEqual(left, right, selector, type)
+ : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitGreaterEqual(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1976,7 +1983,7 @@
}
class HLess extends HRelational {
- HLess(left, right, selector) : super(left, right, selector);
+ HLess(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitLess(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -1987,7 +1994,7 @@
}
class HLessEqual extends HRelational {
- HLessEqual(left, right, selector) : super(left, right, selector);
+ HLessEqual(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitLessEqual(this);
BinaryOperation operation(ConstantSystem constantSystem)
@@ -2004,7 +2011,7 @@
}
class HThrowExpression extends HInstruction {
- HThrowExpression(value) : super(<HInstruction>[value]);
+ HThrowExpression(value) : super(<HInstruction>[value], EMPTY_TYPE);
toString() => 'throw expression';
accept(HVisitor visitor) => visitor.visitThrowExpression(this);
bool canThrow() => true;
@@ -2019,7 +2026,7 @@
class HStatic extends HInstruction {
final Element element;
- HStatic(this.element) : super(<HInstruction>[]) {
+ HStatic(this.element, type) : super(<HInstruction>[], type) {
assert(element != null);
assert(invariant(this, element.isDeclaration));
sideEffects.clearAllSideEffects();
@@ -2042,7 +2049,8 @@
// This field should originally be null to allow GVN'ing all
// [HInterceptor] on the same input.
Set<ClassElement> interceptedClasses;
- HInterceptor(HInstruction receiver) : super(<HInstruction>[receiver]) {
+ HInterceptor(HInstruction receiver, HType type)
+ : super(<HInstruction>[receiver], type) {
sideEffects.clearAllSideEffects();
setUseGvn();
}
@@ -2073,10 +2081,11 @@
Set<ClassElement> interceptedClasses;
HOneShotInterceptor(Selector selector,
List<HInstruction> inputs,
+ HType type,
this.interceptedClasses)
- : super(selector, null, inputs, true) {
+ : super(selector, null, inputs, type, true) {
assert(inputs[0] is HConstant);
- assert(inputs[0].instructionType == HType.NULL);
+ assert(inputs[0].instructionType.isNull());
}
bool isCallOnInterceptor(Compiler compiler) => true;
@@ -2087,7 +2096,7 @@
/** An [HLazyStatic] is a static that is initialized lazily at first read. */
class HLazyStatic extends HInstruction {
final Element element;
- HLazyStatic(this.element) : super(<HInstruction>[]) {
+ HLazyStatic(this.element, type) : super(<HInstruction>[], type) {
// TODO(4931): The first access has side-effects, but we afterwards we
// should be able to GVN.
sideEffects.setAllSideEffects();
@@ -2106,7 +2115,7 @@
class HStaticStore extends HInstruction {
Element element;
HStaticStore(this.element, HInstruction value)
- : super(<HInstruction>[value]) {
+ : super(<HInstruction>[value], EMPTY_TYPE) {
sideEffects.clearAllSideEffects();
sideEffects.setChangesStaticProperty();
}
@@ -2120,9 +2129,7 @@
}
class HLiteralList extends HInstruction {
- HLiteralList(List<HInstruction> inputs, HType type) : super(inputs) {
- instructionType = type;
- }
+ HLiteralList(List<HInstruction> inputs, HType type) : super(inputs, type);
toString() => 'literal list';
accept(HVisitor visitor) => visitor.visitLiteralList(this);
}
@@ -2133,8 +2140,8 @@
*/
class HIndex extends HInstruction {
final Selector selector;
- HIndex(HInstruction receiver, HInstruction index, this.selector)
- : super(<HInstruction>[receiver, index]) {
+ HIndex(HInstruction receiver, HInstruction index, this.selector, type)
+ : super(<HInstruction>[receiver, index], type) {
sideEffects.clearAllSideEffects();
sideEffects.setDependsOnIndexStore();
setUseGvn();
@@ -2164,7 +2171,7 @@
HInstruction index,
HInstruction value,
this.selector)
- : super(<HInstruction>[receiver, index, value]) {
+ : super(<HInstruction>[receiver, index, value], EMPTY_TYPE) {
sideEffects.clearAllSideEffects();
sideEffects.setChangesIndex();
}
@@ -2191,29 +2198,33 @@
final int kind;
HIs.direct(DartType typeExpression,
- HInstruction expression)
- : this.internal(typeExpression, [expression], RAW_CHECK);
+ HInstruction expression,
+ HType type)
+ : this.internal(typeExpression, [expression], RAW_CHECK, type);
HIs.raw(DartType typeExpression,
HInstruction expression,
- HInterceptor interceptor)
- : this.internal(typeExpression, [expression, interceptor], RAW_CHECK);
+ HInterceptor interceptor,
+ HType type)
+ : this.internal(
+ typeExpression, [expression, interceptor], RAW_CHECK, type);
HIs.compound(DartType typeExpression,
HInstruction expression,
- HInstruction call)
- : this.internal(typeExpression, [expression, call], COMPOUND_CHECK);
+ HInstruction call,
+ HType type)
+ : this.internal(typeExpression, [expression, call], COMPOUND_CHECK, type);
HIs.variable(DartType typeExpression,
HInstruction expression,
- HInstruction call)
- : this.internal(typeExpression, [expression, call], VARIABLE_CHECK);
+ HInstruction call,
+ HType type)
+ : this.internal(typeExpression, [expression, call], VARIABLE_CHECK, type);
- HIs.internal(this.typeExpression, List<HInstruction> inputs, this.kind)
- : super(inputs) {
+ HIs.internal(this.typeExpression, List<HInstruction> inputs, this.kind, type)
+ : super(inputs, type) {
assert(kind >= RAW_CHECK && kind <= VARIABLE_CHECK);
setUseGvn();
- instructionType = HType.BOOLEAN;
}
HInstruction get expression => inputs[0];
@@ -2264,12 +2275,11 @@
[this.receiverTypeCheckSelector])
: contextIsTypeArguments = false,
checkedType = type,
- super(<HInstruction>[input]) {
+ super(<HInstruction>[input], type) {
assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null);
assert(typeExpression == null ||
typeExpression.kind != TypeKind.TYPEDEF);
sourceElement = input.sourceElement;
- instructionType = type;
}
HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
@@ -2277,23 +2287,21 @@
HInstruction typeRepresentation)
: contextIsTypeArguments = false,
checkedType = type,
- super(<HInstruction>[input, typeRepresentation]),
+ super(<HInstruction>[input, typeRepresentation],type),
receiverTypeCheckSelector = null {
assert(typeExpression.kind != TypeKind.TYPEDEF);
sourceElement = input.sourceElement;
- instructionType = type;
}
HTypeConversion.withContext(this.typeExpression, this.kind,
HType type, HInstruction input,
HInstruction context,
{bool this.contextIsTypeArguments})
- : super(<HInstruction>[input, context]),
+ : super(<HInstruction>[input, context], type),
checkedType = type,
receiverTypeCheckSelector = null {
assert(typeExpression.kind != TypeKind.TYPEDEF);
sourceElement = input.sourceElement;
- instructionType = type;
}
bool get hasTypeRepresentation {
@@ -2339,10 +2347,9 @@
/// The [HTypeKnown] instruction marks a value with a refined type.
class HTypeKnown extends HCheck {
HType knownType;
- HTypeKnown(HType this.knownType, HInstruction input)
- : super(<HInstruction>[input]) {
- instructionType = knownType;
- }
+ HTypeKnown(HType knownType, HInstruction input)
+ : this.knownType = knownType,
+ super(<HInstruction>[input], knownType);
toString() => 'TypeKnown $knownType';
accept(HVisitor visitor) => visitor.visitTypeKnown(this);
@@ -2361,10 +2368,9 @@
}
class HRangeConversion extends HCheck {
- HRangeConversion(HInstruction input) : super(<HInstruction>[input]) {
+ HRangeConversion(HInstruction input, type)
+ : super(<HInstruction>[input], type) {
sourceElement = input.sourceElement;
- // We currently only do range analysis for integers.
- instructionType = HType.INTEGER;
}
accept(HVisitor visitor) => visitor.visitRangeConversion(this);
}
@@ -2372,12 +2378,11 @@
class HStringConcat extends HInstruction {
final Node node;
HStringConcat(HInstruction left, HInstruction right, this.node, HType type)
- : super(<HInstruction>[left, right]) {
+ : super(<HInstruction>[left, right], type) {
// TODO(sra): Until Issue 9293 is fixed, this false dependency keeps the
// concats bunched with stringified inputs for much better looking code with
// fewer temps.
sideEffects.setDependsOnSomething();
- instructionType = type;
}
HInstruction get left => inputs[0];
@@ -2394,10 +2399,9 @@
class HStringify extends HInstruction {
final Node node;
HStringify(HInstruction input, this.node, HType type)
- : super(<HInstruction>[input]) {
+ : super(<HInstruction>[input], type) {
sideEffects.setAllSideEffects();
sideEffects.setDependsOnSomething();
- instructionType = type;
}
accept(HVisitor visitor) => visitor.visitStringify(this);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index d85cc01..d3e21fd 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -39,13 +39,13 @@
// some patterns useful for type conversion.
new SsaInstructionSimplifier(constantSystem, backend, work),
new SsaTypeConversionInserter(compiler),
+ new SsaRedundantPhiEliminator(),
+ new SsaDeadPhiEliminator(),
new SsaTypePropagator(compiler),
// After type propagation, more instructions can be
// simplified.
new SsaInstructionSimplifier(constantSystem, backend, work),
new SsaCheckInserter(backend, work, context.boundsChecked),
- new SsaRedundantPhiEliminator(),
- new SsaDeadPhiEliminator(),
new SsaInstructionSimplifier(constantSystem, backend, work),
new SsaCheckInserter(backend, work, context.boundsChecked),
new SsaTypePropagator(compiler),
@@ -53,6 +53,9 @@
// interceptors are often in the way of LICM'able instructions.
new SsaDeadCodeEliminator(compiler),
new SsaGlobalValueNumberer(compiler),
+ // After GVN, some instructions might need their type to be
+ // updated because they now have different inputs.
+ new SsaTypePropagator(compiler),
new SsaCodeMotion(),
new SsaValueRangeAnalyzer(compiler, constantSystem, work),
// Previous optimizations may have generated new
@@ -108,14 +111,7 @@
// [replacement]'s type can be narrowed.
HType newType = replacement.instructionType.intersection(
instruction.instructionType, compiler);
- if (!newType.isConflicting()) {
- // [HType.intersection] may give up when doing the
- // intersection of two types is too complicated, and return
- // [HType.CONFLICTING]. We do not want instructions to have
- // [HType.CONFLICTING], so we only update the type if the
- // intersection did not give up.
- replacement.instructionType = newType;
- }
+ replacement.instructionType = newType;
// If the replacement instruction does not know its
// source element, use the source element of the
@@ -150,7 +146,7 @@
assert(inputs.length == 1);
HInstruction input = inputs[0];
HType type = input.instructionType;
- if (type.isBoolean()) return input;
+ if (type.isBoolean(compiler)) return input;
// All values that cannot be 'true' are boolified to false.
TypeMask mask = type.computeMask(compiler);
// TODO(kasperl): Get rid of the null check here once all HTypes
@@ -206,8 +202,7 @@
bool isAssignable = !actualReceiver.isFixedArray(compiler) &&
!actualReceiver.isString(compiler);
HFieldGet result = new HFieldGet(
- element, actualReceiver, isAssignable: isAssignable);
- result.instructionType = HType.INTEGER;
+ element, actualReceiver, backend.intType, isAssignable: isAssignable);
return result;
} else if (actualReceiver.isConstantMap()) {
HConstant constantInput = actualReceiver;
@@ -277,7 +272,7 @@
// bounds check will become explicit, so we won't need this
// optimization.
HInvokeDynamicMethod result = new HInvokeDynamicMethod(
- node.selector, node.inputs.sublist(1));
+ node.selector, node.inputs.sublist(1), node.instructionType);
result.element = target;
return result;
}
@@ -373,22 +368,21 @@
if (!canInline) return null;
- HInvokeDynamicMethod result =
- new HInvokeDynamicMethod(node.selector, inputs);
- result.element = method;
// Strengthen instruction type from annotations to help optimize
// dependent instructions.
native.NativeBehavior nativeBehavior =
native.NativeBehavior.ofMethod(method, compiler);
HType returnType = new HType.fromNativeBehavior(nativeBehavior, compiler);
- result.instructionType = returnType;
+ HInvokeDynamicMethod result =
+ new HInvokeDynamicMethod(node.selector, inputs, returnType);
+ result.element = method;
return result;
}
HInstruction visitBoundsCheck(HBoundsCheck node) {
HInstruction index = node.index;
- if (index.isInteger()) return node;
+ if (index.isInteger(compiler)) return node;
if (index.isConstant()) {
HConstant constantInstruction = index;
assert(!constantInstruction.constant.isInt());
@@ -448,7 +442,7 @@
// Intersection of int and double return conflicting, so
// we don't optimize on numbers to preserve the runtime semantics.
- if (!(left.isNumberOrNull() && right.isNumberOrNull()) &&
+ if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler)) &&
leftType.intersection(rightType, compiler).isConflicting()) {
return graph.addConstantBool(false, compiler);
}
@@ -457,21 +451,21 @@
return graph.addConstantBool(true, compiler);
}
- if (left.isConstantBoolean() && right.isBoolean()) {
+ if (left.isConstantBoolean() && right.isBoolean(compiler)) {
HConstant constant = left;
if (constant.constant.isTrue()) {
return right;
} else {
- return new HNot(right);
+ return new HNot(right, backend.boolType);
}
}
- if (right.isConstantBoolean() && left.isBoolean()) {
+ if (right.isConstantBoolean() && left.isBoolean(compiler)) {
HConstant constant = right;
if (constant.constant.isTrue()) {
return left;
} else {
- return new HNot(left);
+ return new HNot(left, backend.boolType);
}
}
@@ -534,7 +528,7 @@
}
HType expressionType = node.expression.instructionType;
- if (expressionType.isInteger()) {
+ if (expressionType.isInteger(compiler)) {
if (identical(element, compiler.intClass)
|| identical(element, compiler.numClass)
|| Elements.isNumberOrStringSupertype(element, compiler)) {
@@ -546,7 +540,7 @@
} else {
return graph.addConstantBool(false, compiler);
}
- } else if (expressionType.isDouble()) {
+ } else if (expressionType.isDouble(compiler)) {
if (identical(element, compiler.doubleClass)
|| identical(element, compiler.numClass)
|| Elements.isNumberOrStringSupertype(element, compiler)) {
@@ -559,7 +553,7 @@
} else {
return graph.addConstantBool(false, compiler);
}
- } else if (expressionType.isNumber()) {
+ } else if (expressionType.isNumber(compiler)) {
if (identical(element, compiler.numClass)) {
return graph.addConstantBool(true, compiler);
} else {
@@ -608,7 +602,7 @@
}
HInstruction removeIfCheckAlwaysSucceeds(HCheck node, HType checkedType) {
- if (checkedType.isUnknown()) return node;
+ if (checkedType.containsAll(compiler)) return node;
HInstruction input = node.checkedInput;
HType inputType = input.instructionType;
HType filteredType = inputType.intersection(checkedType, compiler);
@@ -635,7 +629,7 @@
// that we know takes an int.
if (element == compiler.unnamedListConstructor
&& receiver.inputs.length == 1
- && receiver.inputs[0].isInteger()) {
+ && receiver.inputs[0].isInteger(compiler)) {
return receiver.inputs[0];
}
} else if (receiver.isConstantList() || receiver.isConstantString()) {
@@ -699,18 +693,18 @@
// distinct from ordinary Dart effects.
isAssignable = true;
}
- HFieldGet result = new HFieldGet(
- field, receiver, isAssignable: isAssignable);
+ HType type;
if (field.getEnclosingClass().isNative()) {
- result.instructionType = new HType.fromNativeBehavior(
+ type = new HType.fromNativeBehavior(
native.NativeBehavior.ofFieldLoad(field, compiler),
compiler);
} else {
- result.instructionType =
- new HType.inferredTypeForElement(field, compiler);
+ type = new HType.inferredTypeForElement(field, compiler);
}
- return result;
+
+ return new HFieldGet(
+ field, receiver, type, isAssignable: isAssignable);
}
HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
@@ -836,11 +830,12 @@
bool isAssignable =
!array.isFixedArray(compiler) && !array.isString(compiler);
HFieldGet length = new HFieldGet(
- backend.jsIndexableLength, array, isAssignable: isAssignable);
- length.instructionType = HType.INTEGER;
+ backend.jsIndexableLength, array, backend.intType,
+ isAssignable: isAssignable);
indexNode.block.addBefore(indexNode, length);
- HBoundsCheck check = new HBoundsCheck(indexArgument, length, array);
+ HBoundsCheck check = new HBoundsCheck(
+ indexArgument, length, array, backend.intType);
indexNode.block.addBefore(indexNode, check);
// If the index input to the bounds check was not known to be an integer
// then we replace its uses with the bounds check, which is known to be an
@@ -849,7 +844,7 @@
// the index eg. if it is a constant. The range information from the
// BoundsCheck instruction is attached to the input directly by
// visitBoundsCheck in the SsaValueRangeAnalyzer.
- if (!indexArgument.isInteger()) {
+ if (!indexArgument.isInteger(compiler)) {
indexArgument.replaceAllUsersDominatedBy(indexNode, check);
}
boundsChecked.add(indexNode);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index eea1cc5..f62a343 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -179,9 +179,9 @@
String temporaryId(HInstruction instruction) {
String prefix;
HType type = instruction.instructionType;
- if (type == HType.NULL) {
+ if (type.isNull()) {
prefix = 'u';
- } else if (type == HType.CONFLICTING) {
+ } else if (type.isConflicting()) {
prefix = 'c';
} else if (type.isExtendableArray(compiler)) {
prefix = 'e';
@@ -195,15 +195,15 @@
prefix = 's';
} else if (type.isIndexable(compiler)) {
prefix = 'r';
- } else if (type == HType.BOOLEAN) {
+ } else if (type.isBoolean(compiler)) {
prefix = 'b';
- } else if (type == HType.INTEGER) {
+ } else if (type.isInteger(compiler)) {
prefix = 'i';
- } else if (type == HType.DOUBLE) {
+ } else if (type.isDouble(compiler)) {
prefix = 'd';
- } else if (type == HType.NUMBER) {
+ } else if (type.isNumber(compiler)) {
prefix = 'n';
- } else if (type == HType.UNKNOWN) {
+ } else if (type.containsAll(compiler)) {
prefix = 'v';
} else {
prefix = 'U';
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
index bfdb564..a8e4238 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -14,18 +14,24 @@
*/
factory HType.fromMask(TypeMask mask, Compiler compiler) {
bool isNullable = mask.isNullable;
+ JavaScriptBackend backend = compiler.backend;
if (mask.isEmpty) {
- return isNullable ? HType.NULL : HType.CONFLICTING;
+ return isNullable ? backend.nullType : backend.emptyType;
}
- JavaScriptBackend backend = compiler.backend;
if (mask.containsOnlyInt(compiler)) {
- return isNullable ? HType.INTEGER_OR_NULL : HType.INTEGER;
+ return mask.isNullable
+ ? new HBoundedType(new TypeMask.exact(backend.jsIntClass))
+ : backend.intType;
} else if (mask.containsOnlyDouble(compiler)) {
- return isNullable ? HType.DOUBLE_OR_NULL : HType.DOUBLE;
+ return mask.isNullable
+ ? new HBoundedType(new TypeMask.exact(backend.jsDoubleClass))
+ : backend.doubleType;
} else if (mask.containsOnlyNum(compiler)
|| mask.satisfies(backend.jsNumberClass, compiler)) {
- return isNullable ? HType.NUMBER_OR_NULL : HType.NUMBER;
+ return mask.isNullable
+ ? new HBoundedType(new TypeMask.subclass(backend.jsNumberClass))
+ : backend.numType;
} else if (mask.containsOnlyString(compiler)) {
// TODO(ngeoffray): Avoid creating [TypeMask]s with the string
// class as base.
@@ -33,15 +39,17 @@
? new HBoundedType(new TypeMask.exact(backend.jsStringClass))
: backend.stringType;
} else if (mask.containsOnlyBool(compiler)) {
- return isNullable ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN;
+ return isNullable
+ ? new HBoundedType(new TypeMask.exact(backend.jsBoolClass))
+ : backend.boolType;
} else if (mask.containsOnlyNull(compiler)) {
- return HType.NULL;
+ return backend.nullType;
}
// TODO(kasperl): A lot of the code in the system currently
// expects the top type to be 'unknown'. I'll rework this.
if (mask.containsAll(compiler)) {
- return isNullable ? HType.UNKNOWN : HType.NON_NULL;
+ return isNullable ? backend.dynamicType : backend.nonNullType;
}
return new HBoundedType(mask);
@@ -78,7 +86,8 @@
}
factory HType.fromInferredType(TypeMask mask, Compiler compiler) {
- if (mask == null) return HType.UNKNOWN;
+ JavaScriptBackend backend = compiler.backend;
+ if (mask == null) return backend.dynamicType;
return new HType.fromMask(mask, compiler);
}
@@ -109,7 +118,8 @@
factory HType.fromNativeBehavior(native.NativeBehavior nativeBehavior,
Compiler compiler) {
- if (nativeBehavior.typesReturned.isEmpty) return HType.UNKNOWN;
+ JavaScriptBackend backend = compiler.backend;
+ if (nativeBehavior.typesReturned.isEmpty) return backend.dynamicType;
HType result = nativeBehavior.typesReturned
.map((type) => fromNativeType(type, compiler))
@@ -121,14 +131,15 @@
// [type] is either an instance of [DartType] or special objects
// like [native.SpecialType.JsObject].
static HType fromNativeType(type, Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
if (type == native.SpecialType.JsObject) {
return new HType.nonNullExact(compiler.objectClass, compiler);
} else if (type.isVoid) {
- return HType.NULL;
+ return backend.nullType;
} else if (type.element == compiler.nullClass) {
- return HType.NULL;
+ return backend.nullType;
} else if (type.treatAsDynamic) {
- return HType.UNKNOWN;
+ return backend.dynamicType;
} else if (compiler.world.hasAnySubtype(type.element)) {
return new HType.nonNullSubtype(type.element, compiler);
} else if (compiler.world.hasAnySubclass(type.element)) {
@@ -138,28 +149,13 @@
}
}
- static const HType CONFLICTING = const HConflictingType();
- static const HType UNKNOWN = const HUnknownType();
- static const HType NON_NULL = const HNonNullType();
- static const HType BOOLEAN = const HBooleanType();
- static const HType NUMBER = const HNumberType();
- static const HType INTEGER = const HIntegerType();
- static const HType DOUBLE = const HDoubleType();
- static const HType NULL = const HNullType();
-
- static const HType BOOLEAN_OR_NULL = const HBooleanOrNullType();
- static const HType NUMBER_OR_NULL = const HNumberOrNullType();
- static const HType INTEGER_OR_NULL = const HIntegerOrNullType();
- static const HType DOUBLE_OR_NULL = const HDoubleOrNullType();
-
- bool isConflicting() => identical(this, CONFLICTING);
- bool isUnknown() => identical(this, UNKNOWN);
+ bool isConflicting() => false;
bool isExact() => false;
bool isNull() => false;
- bool isBoolean() => false;
- bool isNumber() => false;
- bool isInteger() => false;
- bool isDouble() => false;
+ bool isBoolean(Compiler compiler) => false;
+ bool isNumber(Compiler compiler) => false;
+ bool isInteger(Compiler compiler) => false;
+ bool isDouble(Compiler compiler) => false;
bool isString(Compiler compiler) => false;
bool isFixedArray(Compiler compiler) => false;
@@ -169,10 +165,10 @@
bool isPrimitive(Compiler compiler) => false;
bool isPrimitiveOrNull(Compiler compiler) => false;
- bool isBooleanOrNull() => false;
- bool isNumberOrNull() => false;
- bool isIntegerOrNull() => false;
- bool isDoubleOrNull() => false;
+ bool isBooleanOrNull(Compiler compiler) => false;
+ bool isNumberOrNull(Compiler compiler) => false;
+ bool isIntegerOrNull(Compiler compiler) => false;
+ bool isDoubleOrNull(Compiler compiler) => false;
// TODO(kasperl): Get rid of this one.
bool isIndexablePrimitive(Compiler compiler) => false;
@@ -199,8 +195,6 @@
bool canBePrimitiveArray(Compiler compiler) => false;
bool canBePrimitiveBoolean(Compiler compiler) => false;
- /** A type is useful it is not unknown, not conflicting, and not null. */
- bool isUseful() => !isUnknown() && !isConflicting() && !isNull();
/** Alias for isReadableArray. */
bool isArray(Compiler compiler) => isReadableArray(compiler);
@@ -258,175 +252,9 @@
HType nonNullable(compiler) {
return new HType.fromMask(computeMask(compiler).nonNullable(), compiler);
}
-}
-/** Used to represent [HType.UNKNOWN] and [HType.CONFLICTING]. */
-abstract class HAnalysisType extends HType {
- final String name;
- const HAnalysisType(this.name);
- String toString() => name;
-}
-
-class HUnknownType extends HAnalysisType {
- const HUnknownType() : super("unknown");
- bool canBePrimitive(Compiler compiler) => true;
- bool canBeNull() => true;
- bool canBePrimitiveNumber(Compiler compiler) => true;
- bool canBePrimitiveString(Compiler compiler) => true;
- bool canBePrimitiveArray(Compiler compiler) => true;
- bool canBePrimitiveBoolean(Compiler compiler) => true;
-
- TypeMask computeMask(Compiler compiler) {
- return new TypeMask.subclass(compiler.objectClass);
- }
-}
-
-class HNonNullType extends HAnalysisType {
- const HNonNullType() : super("non-null");
- bool canBePrimitive(Compiler compiler) => true;
- bool canBeNull() => false;
- bool canBePrimitiveNumber(Compiler compiler) => true;
- bool canBePrimitiveString(Compiler compiler) => true;
- bool canBePrimitiveArray(Compiler compiler) => true;
- bool canBePrimitiveBoolean(Compiler compiler) => true;
-
- TypeMask computeMask(Compiler compiler) {
- return new TypeMask.nonNullSubclass(compiler.objectClass);
- }
-}
-
-class HConflictingType extends HAnalysisType {
- const HConflictingType() : super("conflicting");
- bool canBePrimitive(Compiler compiler) => true;
- bool canBeNull() => false;
-
- TypeMask computeMask(Compiler compiler) {
- return new TypeMask.nonNullEmpty();
- }
-}
-
-abstract class HPrimitiveType extends HType {
- const HPrimitiveType();
- bool isPrimitive(Compiler compiler) => true;
- bool canBePrimitive(Compiler compiler) => true;
- bool isPrimitiveOrNull(Compiler compiler) => true;
-}
-
-class HNullType extends HPrimitiveType {
- const HNullType();
- bool canBeNull() => true;
- bool isNull() => true;
- String toString() => 'null type';
- bool isExact() => true;
-
- TypeMask computeMask(Compiler compiler) {
- return new TypeMask.empty();
- }
-}
-
-abstract class HPrimitiveOrNullType extends HType {
- const HPrimitiveOrNullType();
- bool canBePrimitive(Compiler compiler) => true;
- bool canBeNull() => true;
- bool isPrimitiveOrNull(Compiler compiler) => true;
-}
-
-class HBooleanOrNullType extends HPrimitiveOrNullType {
- const HBooleanOrNullType();
- String toString() => "boolean or null";
- bool isBooleanOrNull() => true;
- bool canBePrimitiveBoolean(Compiler compiler) => true;
-
- TypeMask computeMask(Compiler compiler) {
- JavaScriptBackend backend = compiler.backend;
- return new TypeMask.exact(backend.jsBoolClass);
- }
-}
-
-class HBooleanType extends HPrimitiveType {
- const HBooleanType();
- bool isBoolean() => true;
- bool isBooleanOrNull() => true;
- String toString() => "boolean";
- bool isExact() => true;
- bool canBePrimitiveBoolean(Compiler compiler) => true;
-
- TypeMask computeMask(Compiler compiler) {
- JavaScriptBackend backend = compiler.backend;
- return new TypeMask.nonNullExact(backend.jsBoolClass);
- }
-}
-
-class HNumberOrNullType extends HPrimitiveOrNullType {
- const HNumberOrNullType();
- bool isNumberOrNull() => true;
- String toString() => "number or null";
- bool canBePrimitiveNumber(Compiler compiler) => true;
-
- TypeMask computeMask(Compiler compiler) {
- JavaScriptBackend backend = compiler.backend;
- return new TypeMask.subclass(backend.jsNumberClass);
- }
-}
-
-class HNumberType extends HPrimitiveType {
- const HNumberType();
- bool isNumber() => true;
- bool isNumberOrNull() => true;
- String toString() => "number";
- bool canBePrimitiveNumber(Compiler compiler) => true;
-
- TypeMask computeMask(Compiler compiler) {
- JavaScriptBackend backend = compiler.backend;
- return new TypeMask.nonNullSubclass(backend.jsNumberClass);
- }
-}
-
-class HIntegerOrNullType extends HNumberOrNullType {
- const HIntegerOrNullType();
- bool isIntegerOrNull() => true;
- String toString() => "integer or null";
-
- TypeMask computeMask(Compiler compiler) {
- JavaScriptBackend backend = compiler.backend;
- return new TypeMask.exact(backend.jsIntClass);
- }
-}
-
-class HIntegerType extends HNumberType {
- const HIntegerType();
- bool isInteger() => true;
- bool isIntegerOrNull() => true;
- String toString() => "integer";
- bool isExact() => true;
-
- TypeMask computeMask(Compiler compiler) {
- JavaScriptBackend backend = compiler.backend;
- return new TypeMask.nonNullExact(backend.jsIntClass);
- }
-}
-
-class HDoubleOrNullType extends HNumberOrNullType {
- const HDoubleOrNullType();
- bool isDoubleOrNull() => true;
- String toString() => "double or null";
-
- TypeMask computeMask(Compiler compiler) {
- JavaScriptBackend backend = compiler.backend;
- return new TypeMask.exact(backend.jsDoubleClass);
- }
-}
-
-class HDoubleType extends HNumberType {
- const HDoubleType();
- bool isDouble() => true;
- bool isDoubleOrNull() => true;
- String toString() => "double";
- bool isExact() => true;
-
- TypeMask computeMask(Compiler compiler) {
- JavaScriptBackend backend = compiler.backend;
- return new TypeMask.nonNullExact(backend.jsDoubleClass);
+ bool containsAll(Compiler compiler) {
+ return computeMask(compiler).containsAll(compiler);
}
}
@@ -434,15 +262,19 @@
final TypeMask mask;
const HBoundedType(this.mask);
- bool isExact() => mask.isExact;
+ bool isExact() => mask.isExact || isNull();
bool canBeNull() => mask.isNullable;
+ bool isNull() => mask.isEmpty && mask.isNullable;
+ bool isConflicting() => mask.isEmpty && !mask.isNullable;
+
bool canBePrimitive(Compiler compiler) {
return canBePrimitiveNumber(compiler)
|| canBePrimitiveArray(compiler)
|| canBePrimitiveBoolean(compiler)
- || canBePrimitiveString(compiler);
+ || canBePrimitiveString(compiler)
+ || isNull();
}
bool canBePrimitiveNumber(Compiler compiler) {
@@ -500,16 +332,52 @@
return new HType.fromMask(mask.simplify(compiler), compiler);
}
+ bool isInteger(Compiler compiler) {
+ return mask.containsOnlyInt(compiler) && !mask.isNullable;
+ }
+
+ bool isIntegerOrNull(Compiler compiler) {
+ return mask.containsOnlyInt(compiler);
+ }
+
+ bool isNumber(Compiler compiler) {
+ return mask.containsOnlyNum(compiler) && !mask.isNullable;
+ }
+
+ bool isNumberOrNull(Compiler compiler) {
+ return mask.containsOnlyNum(compiler);
+ }
+
+ bool isDouble(Compiler compiler) {
+ return mask.containsOnlyDouble(compiler) && !mask.isNullable;
+ }
+
+ bool isDoubleOrNull(Compiler compiler) {
+ return mask.containsOnlyDouble(compiler);
+ }
+
+ bool isBoolean(Compiler compiler) {
+ return mask.containsOnlyBool(compiler) && !mask.isNullable;
+ }
+
+ bool isBooleanOrNull(Compiler compiler) {
+ return mask.containsOnlyBool(compiler);
+ }
+
bool isString(Compiler compiler) {
return mask.containsOnlyString(compiler);
}
bool isPrimitive(Compiler compiler) {
- return isIndexablePrimitive(compiler) && !mask.isNullable;
+ return (isPrimitiveOrNull(compiler) && !mask.isNullable)
+ || isNull();
}
bool isPrimitiveOrNull(Compiler compiler) {
- return isIndexablePrimitive(compiler);
+ return isIndexablePrimitive(compiler)
+ || isNumberOrNull(compiler)
+ || isBooleanOrNull(compiler)
+ || isNull();
}
bool operator ==(other) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 4122364..60e6744 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -15,26 +15,6 @@
SsaTypePropagator(this.compiler);
- // Compute the (shared) type of the inputs if any. If all inputs
- // have the same known type return it. If any two inputs have
- // different known types, we'll return a conflict -- otherwise we'll
- // simply return an unknown type.
- HType computeInputsType(HPhi phi, bool ignoreUnknowns) {
- HType candidateType = HType.CONFLICTING;
- for (int i = 0, length = phi.inputs.length; i < length; i++) {
- HType inputType = phi.inputs[i].instructionType;
- if (inputType.isConflicting()) return HType.CONFLICTING;
- if (ignoreUnknowns && inputType.isUnknown()) continue;
- // Phis need to combine the incoming types using the union operation.
- // For example, if one incoming edge has type integer and the other has
- // type double, then the phi is either an integer or double and thus has
- // type number.
- candidateType = candidateType.union(inputType, compiler);
- if (candidateType.isUnknown()) return HType.UNKNOWN;
- }
- return candidateType;
- }
-
HType computeType(HInstruction instruction) {
return instruction.accept(this);
}
@@ -119,9 +99,12 @@
HType visitBinaryArithmetic(HBinaryArithmetic instruction) {
HInstruction left = instruction.left;
HInstruction right = instruction.right;
- if (left.isInteger() && right.isInteger()) return HType.INTEGER;
- if (left.isDouble()) return HType.DOUBLE;
- return HType.NUMBER;
+ JavaScriptBackend backend = compiler.backend;
+ if (left.isInteger(compiler) && right.isInteger(compiler)) {
+ return backend.intType;
+ }
+ if (left.isDouble(compiler)) return backend.doubleType;
+ return backend.numType;
}
HType visitNegate(HNegate instruction) {
@@ -134,24 +117,30 @@
}
HType visitPhi(HPhi phi) {
- HType inputsType = computeInputsType(phi, false);
- if (inputsType.isConflicting()) return HType.UNKNOWN;
- return inputsType;
+ JavaScriptBackend backend = compiler.backend;
+ HType candidateType = backend.emptyType;
+ for (int i = 0, length = phi.inputs.length; i < length; i++) {
+ HType inputType = phi.inputs[i].instructionType;
+ candidateType = candidateType.union(inputType, compiler);
+ }
+ return candidateType;
}
HType visitTypeConversion(HTypeConversion instruction) {
HType inputType = instruction.checkedInput.instructionType;
HType checkedType = instruction.checkedType;
+ JavaScriptBackend backend = compiler.backend;
if (instruction.isArgumentTypeCheck || instruction.isReceiverTypeCheck) {
// We must make sure a type conversion for receiver or argument check
// does not try to do an int check, because an int check is not enough.
// We only do an int check if the input is integer or null.
- if (checkedType.isNumber()
- && !checkedType.isDouble()
- && inputType.isIntegerOrNull()) {
- instruction.checkedType = HType.INTEGER;
- } else if (checkedType.isInteger() && !inputType.isIntegerOrNull()) {
- instruction.checkedType = HType.NUMBER;
+ if (checkedType.isNumber(compiler)
+ && !checkedType.isDouble(compiler)
+ && inputType.isIntegerOrNull(compiler)) {
+ instruction.checkedType = backend.intType;
+ } else if (checkedType.isInteger(compiler)
+ && !inputType.isIntegerOrNull(compiler)) {
+ instruction.checkedType = backend.numType;
}
}
@@ -162,11 +151,13 @@
// can be a literal double '8.0' that is marked as an integer (because 'is
// int' will return 'true'). What we really need to do is make the
// overlap between int and double values explicit in the HType system.
- if (inputType.isIntegerOrNull() && checkedType.isDoubleOrNull()) {
+ if (inputType.isIntegerOrNull(compiler)
+ && checkedType.isDoubleOrNull(compiler)) {
if (inputType.canBeNull() && checkedType.canBeNull()) {
- outputType = HType.DOUBLE_OR_NULL;
+ outputType =
+ new HBoundedType(new TypeMask.exact(backend.jsDoubleClass));
} else {
- outputType = HType.DOUBLE;
+ outputType = backend.doubleType;
}
}
}
@@ -196,11 +187,11 @@
// In some cases, we want the receiver to be an integer,
// but that does not mean we will get a NoSuchMethodError
// if it's not: the receiver could be a double.
- if (type.isInteger()) {
+ if (type.isInteger(compiler)) {
// If the instruction's type is integer or null, the codegen
// will emit a null check, which is enough to know if it will
// hit a noSuchMethod.
- return instruction.instructionType.isIntegerOrNull();
+ return instruction.instructionType.isIntegerOrNull(compiler);
}
return true;
}
@@ -210,8 +201,8 @@
// Return true if the receiver type check was added.
bool checkReceiver(HInvokeDynamic instruction) {
HInstruction receiver = instruction.inputs[1];
- if (receiver.isNumber()) return false;
- if (receiver.isNumberOrNull()) {
+ if (receiver.isNumber(compiler)) return false;
+ if (receiver.isNumberOrNull(compiler)) {
convertInput(instruction,
receiver,
receiver.instructionType.nonNullable(compiler),
@@ -250,9 +241,12 @@
HInstruction right = instruction.inputs[2];
Selector selector = instruction.selector;
- if (selector.isOperator() && receiverType.isNumber()) {
- if (right.isNumber()) return false;
- HType type = right.isIntegerOrNull() ? HType.INTEGER : HType.NUMBER;
+ if (selector.isOperator() && receiverType.isNumber(compiler)) {
+ if (right.isNumber(compiler)) return false;
+ JavaScriptBackend backend = compiler.backend;
+ HType type = right.isIntegerOrNull(compiler)
+ ? backend.intType
+ : backend.numType;
// TODO(ngeoffray): Some number operations don't have a builtin
// variant and will do the check in their method anyway. We
// still add a check because it allows to GVN these operations,
@@ -292,8 +286,7 @@
// of [instruction] might move from number to dynamic.
pendingOptimizations.putIfAbsent(instruction, () => () {
Selector selector = instruction.selector;
- if (selector.isOperator()
- && selector.name != '==') {
+ if (selector.isOperator() && selector.name != '==') {
if (checkReceiver(instruction)) {
addAllUsersBut(instruction, instruction.inputs[1]);
}
@@ -303,6 +296,41 @@
}
});
}
+
+ HInstruction receiver = instruction.getDartReceiver(compiler);
+ HType receiverType = receiver.instructionType;
+ Selector selector = receiverType.refine(instruction.selector, compiler);
+ instruction.selector = selector;
+
+ // Try to specialize the receiver after this call.
+ if (receiver.dominatedUsers(instruction).length != 1
+ && !selector.isClosureCall()) {
+ TypeMask oldMask = receiverType.computeMask(compiler);
+ TypeMask newMask = compiler.world.allFunctions.receiverType(selector);
+ newMask = newMask.intersection(oldMask, compiler);
+
+ if (newMask != oldMask) {
+ HType newType = new HType.fromMask(newMask, compiler);
+ var next = instruction.next;
+ if (next is HTypeKnown && next.checkedInput == receiver) {
+ // We already have refined [receiver].
+ HType nextType = next.instructionType;
+ if (nextType != newType) {
+ next.knownType = next.instructionType = newType;
+ addDependentInstructionsToWorkList(next);
+ }
+ } else {
+ // Insert a refinement node after the call and update all
+ // users dominated by the call to use that node instead of
+ // [receiver].
+ HTypeKnown converted = new HTypeKnown(newType, receiver);
+ instruction.block.addBefore(instruction.next, converted);
+ receiver.replaceAllUsersDominatedBy(converted.next, converted);
+ addDependentInstructionsToWorkList(converted);
+ }
+ }
+ }
+
return instruction.specializer.computeTypeFromInputTypes(
instruction, compiler);
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
index 2f4f70a..829012d 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
@@ -626,7 +626,7 @@
void visit(HInstruction instruction) {
Range range = instruction.accept(this);
- if (instruction.isInteger()) {
+ if (instruction.isInteger(compiler)) {
assert(range != null);
ranges[instruction] = range;
}
@@ -641,20 +641,22 @@
}
Range visitParameterValue(HParameterValue parameter) {
- if (!parameter.isInteger()) return info.newUnboundRange();
+ if (!parameter.isInteger(compiler)) return info.newUnboundRange();
Value value = info.newInstructionValue(parameter);
return info.newNormalizedRange(value, value);
}
Range visitPhi(HPhi phi) {
- if (!phi.isInteger()) return info.newUnboundRange();
+ if (!phi.isInteger(compiler)) return info.newUnboundRange();
// Some phases may replace instructions that change the inputs of
// this phi. Only the [SsaTypesPropagation] phase will update the
// phi type. Play it safe by assuming the [SsaTypesPropagation]
// phase is not necessarily run before the [ValueRangeAnalyzer].
- if (phi.inputs.any((i) => !i.isInteger())) return info.newUnboundRange();
+ if (phi.inputs.any((i) => !i.isInteger(compiler))) {
+ return info.newUnboundRange();
+ }
if (phi.block.isLoopHeader()) {
- Range range = new LoopUpdateRecognizer(ranges, info).run(phi);
+ Range range = new LoopUpdateRecognizer(compiler, ranges, info).run(phi);
if (range == null) return info.newUnboundRange();
return range;
}
@@ -667,14 +669,14 @@
}
Range visitConstant(HConstant constant) {
- if (!constant.isInteger()) return info.newUnboundRange();
+ if (!constant.isInteger(compiler)) return info.newUnboundRange();
IntConstant constantInt = constant.constant;
Value value = info.newIntValue(constantInt.value);
return info.newNormalizedRange(value, value);
}
Range visitFieldGet(HFieldGet fieldGet) {
- if (!fieldGet.isInteger()) return info.newUnboundRange();
+ if (!fieldGet.isInteger(compiler)) return info.newUnboundRange();
if (!fieldGet.receiver.isIndexable(compiler)) {
return visitInstruction(fieldGet);
}
@@ -693,9 +695,9 @@
Range lengthRange = ranges[check.length];
if (indexRange == null) {
indexRange = info.newUnboundRange();
- assert(!check.index.isInteger());
+ assert(!check.index.isInteger(compiler));
}
- assert(check.length.isInteger());
+ assert(check.length.isInteger(compiler));
// Check if the index is strictly below the upper bound of the length
// range.
@@ -749,8 +751,8 @@
Range visitRelational(HRelational relational) {
HInstruction right = relational.right;
HInstruction left = relational.left;
- if (!left.isInteger()) return info.newUnboundRange();
- if (!right.isInteger()) return info.newUnboundRange();
+ if (!left.isInteger(compiler)) return info.newUnboundRange();
+ if (!right.isInteger(compiler)) return info.newUnboundRange();
BinaryOperation operation = relational.operation(constantSystem);
Range rightRange = ranges[relational.right];
Range leftRange = ranges[relational.left];
@@ -780,7 +782,7 @@
}
Range handleBinaryOperation(HBinaryArithmetic instruction) {
- if (!instruction.isInteger()) return info.newUnboundRange();
+ if (!instruction.isInteger(compiler)) return info.newUnboundRange();
return instruction.operation(constantSystem).apply(
ranges[instruction.left], ranges[instruction.right]);
}
@@ -794,10 +796,10 @@
}
Range visitBitAnd(HBitAnd node) {
- if (!node.isInteger()) return info.newUnboundRange();
+ if (!node.isInteger(compiler)) return info.newUnboundRange();
HInstruction right = node.right;
HInstruction left = node.left;
- if (left.isInteger() && right.isInteger()) {
+ if (left.isInteger(compiler) && right.isInteger(compiler)) {
return ranges[left] & ranges[right];
}
@@ -811,9 +813,9 @@
return info.newUnboundRange();
}
- if (left.isInteger()) {
+ if (left.isInteger(compiler)) {
return tryComputeRange(left);
- } else if (right.isInteger()) {
+ } else if (right.isInteger(compiler)) {
return tryComputeRange(right);
}
return info.newUnboundRange();
@@ -828,7 +830,9 @@
HInstruction createRangeConversion(HInstruction cursor,
HInstruction instruction) {
- HRangeConversion newInstruction = new HRangeConversion(instruction);
+ JavaScriptBackend backend = compiler.backend;
+ HRangeConversion newInstruction =
+ new HRangeConversion(instruction, backend.intType);
conversions.add(newInstruction);
cursor.block.addBefore(cursor, newInstruction);
// Update the users of the instruction dominated by [cursor] to
@@ -878,8 +882,8 @@
if (condition is HIdentity) return info.newUnboundRange();
HInstruction right = condition.right;
HInstruction left = condition.left;
- if (!left.isInteger()) return info.newUnboundRange();
- if (!right.isInteger()) return info.newUnboundRange();
+ if (!left.isInteger(compiler)) return info.newUnboundRange();
+ if (!right.isInteger(compiler)) return info.newUnboundRange();
Range rightRange = ranges[right];
Range leftRange = ranges[left];
@@ -939,9 +943,10 @@
* Tries to find a range for the update instruction of a loop phi.
*/
class LoopUpdateRecognizer extends HBaseVisitor {
+ final Compiler compiler;
final Map<HInstruction, Range> ranges;
final ValueRangeInfo info;
- LoopUpdateRecognizer(this.ranges, this.info);
+ LoopUpdateRecognizer(this.compiler, this.ranges, this.info);
Range run(HPhi loopPhi) {
// Create a marker range for the loop phi, so that if the update
@@ -966,7 +971,7 @@
}
Range visit(HInstruction instruction) {
- if (!instruction.isInteger()) return null;
+ if (!instruction.isInteger(compiler)) return null;
if (ranges[instruction] != null) return ranges[instruction];
return instruction.accept(this);
}
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 9aa6409..338258b 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -933,21 +933,13 @@
new TypePromotion(node, variable, shownType);
if (!types.isMoreSpecific(shownType, knownType)) {
String variableName = variable.name;
- if (types.isMoreSpecific(shownType.asRaw(), knownType)) {
- //trace('$node');
- typePromotion.addHint(node,
- MessageKind.NOT_MORE_SPECIFIC_RAW,
- {'variableName': variableName,
- 'shownType': shownType,
- 'knownType': knownType,
- 'shownTypeRaw': shownType.asRaw()});
- } else {
- typePromotion.addHint(node,
- MessageKind.NOT_MORE_SPECIFIC,
- {'variableName': variableName,
- 'shownType': shownType,
- 'knownType': knownType});
- }
+ // TODO(johnniwinther): Provide a how-to-fix in the case one tries
+ // to promote a generic type to a raw type.
+ typePromotion.addHint(node,
+ MessageKind.NOT_MORE_SPECIFIC,
+ {'variableName': variableName,
+ 'shownType': shownType,
+ 'knownType': knownType});
}
showTypePromotion(node, typePromotion);
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
index f65de47..c2e7ada 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
@@ -100,6 +100,6 @@
}
String toString() {
- return 'Container mask: $elementType';
+ return 'Container mask: $elementType $length';
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
index 8848fb9..c58baef 100644
--- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -93,7 +93,9 @@
}
bool containsOnlyNum(Compiler compiler) {
- return base == compiler.numClass
+ return containsOnlyInt(compiler)
+ || containsOnlyDouble(compiler)
+ || base == compiler.numClass
|| base == compiler.backend.numImplementation;
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
index 269b1b5..e6232cc 100644
--- a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
@@ -197,19 +197,36 @@
bool get isContainer => false;
bool get isForwarding => false;
- bool containsOnlyInt(Compiler compiler) => false;
- bool containsOnlyDouble(Compiler compiler) => false;
+ bool containsOnlyInt(Compiler compiler) {
+ return disjointMasks.every((mask) => mask.containsOnlyInt(compiler));
+ }
+
+ bool containsOnlyDouble(Compiler compiler) {
+ return disjointMasks.every((mask) => mask.containsOnlyDouble(compiler));
+ }
+
bool containsOnlyNum(Compiler compiler) {
return disjointMasks.every((mask) {
- return mask.containsOnlyInt(compiler)
- || mask.containsOnlyDouble(compiler)
- || mask.containsOnlyNum(compiler);
+ return mask.containsOnlyNum(compiler);
});
}
- bool containsOnlyNull(Compiler compiler) => false;
- bool containsOnlyBool(Compiler compiler) => false;
- bool containsOnlyString(Compiler compiler) => false;
- bool containsOnly(ClassElement element) => false;
+
+ bool containsOnlyNull(Compiler compiler) {
+ return disjointMasks.every((mask) => mask.containsOnlyNull(compiler));
+ }
+
+ bool containsOnlyBool(Compiler compiler) {
+ return disjointMasks.every((mask) => mask.containsOnlyBool(compiler));
+ }
+
+ bool containsOnlyString(Compiler compiler) {
+ return disjointMasks.every((mask) => mask.containsOnlyString(compiler));
+ }
+
+ bool containsOnly(ClassElement element) {
+ return disjointMasks.every((mask) => mask.containsOnly(element));
+ }
+
bool satisfies(ClassElement cls, Compiler compiler) {
return disjointMasks.every((mask) => mask.satisfies(cls, compiler));
}
@@ -218,7 +235,9 @@
return disjointMasks.any((e) => e.contains(type, compiler));
}
- bool containsAll(Compiler compiler) => false;
+ bool containsAll(Compiler compiler) {
+ return disjointMasks.any((mask) => mask.containsAll(compiler));
+ }
ClassElement singleClass(Compiler compiler) => null;
diff --git a/sdk/lib/_internal/compiler/implementation/universe/function_set.dart b/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
index 522ff2b..c79f826 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
@@ -225,8 +225,8 @@
return const TypeMask.empty();
}
return compiler.world.hasSubclasses(cls)
- ? new TypeMask.nonNullSubclass(cls)
- : new TypeMask.nonNullExact(cls);
+ ? new TypeMask.nonNullSubclass(cls.declaration)
+ : new TypeMask.nonNullExact(cls.declaration);
}),
compiler);
}
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index 8470f83..5c0c9da 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -595,6 +595,10 @@
return 'Selector($kind, $name, '
'arity=$argumentCount$named$type)';
}
+
+ Selector extendIfReachesAll(Compiler compiler) {
+ return new TypedSelector(compiler.typesTask.dynamicType, this);
+ }
}
class TypedSelector extends Selector {
@@ -656,4 +660,12 @@
if (!mask.canHit(element, this, compiler)) return false;
return appliesUntyped(element, compiler);
}
+
+ Selector extendIfReachesAll(Compiler compiler) {
+ bool canReachAll = compiler.enabledInvokeOn
+ && mask.needsNoSuchMethodHandling(this, compiler);
+ return canReachAll
+ ? new TypedSelector(compiler.typesTask.dynamicType, this)
+ : this;
+ }
}
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index fb33d49..4b2d1c7 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -1300,6 +1300,10 @@
static const MessageKind MIRROR_IMPORT = const MessageKind(
"Info: Import of 'dart:mirrors'.");
+ static const MessageKind WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT =
+ const MessageKind(
+ "Error: Argument for 'JS_INTERCEPTOR_CONSTANT' must be a type constant.");
+
static const MessageKind COMPILER_CRASHED = const MessageKind(
"Error: The compiler crashed when compiling this element.");
@@ -1353,12 +1357,6 @@
"'#{shownType}' because '#{shownType}' is not more specific than the "
"known type '#{knownType}' of '#{variableName}'.");
- static const MessageKind NOT_MORE_SPECIFIC_RAW = const MessageKind(
- "Hint: Variable '#{variableName}' is not shown to have type "
- "'#{shownType}' because '#{shownType}' is not more specific than the "
- "known type '#{knownType}' of '#{variableName}'.",
- howToFix: "Try replacing '#{shownType}' with '#{shownTypeRaw}'.");
-
//////////////////////////////////////////////////////////////////////////////
// Patch errors start.
//////////////////////////////////////////////////////////////////////////////
diff --git a/sdk/lib/_internal/compiler/samples/darttags/darttags.dart b/sdk/lib/_internal/compiler/samples/darttags/darttags.dart
index 347b230..4a3cd47 100644
--- a/sdk/lib/_internal/compiler/samples/darttags/darttags.dart
+++ b/sdk/lib/_internal/compiler/samples/darttags/darttags.dart
@@ -51,20 +51,16 @@
RandomAccessFile output;
Uri outputUri;
-main() {
- mainWithOptions(new Options());
-}
-
-mainWithOptions(Options options) {
+main(List<String> arguments) {
handler = new FormattingDiagnosticHandler()
..throwOnError = true;
outputUri =
- handler.provider.cwd.resolve(nativeToUriPath(options.arguments.first));
- output = new File(options.arguments.first).openSync(mode: FileMode.WRITE);
+ handler.provider.cwd.resolve(nativeToUriPath(arguments.first));
+ output = new File(arguments.first).openSync(mode: FileMode.WRITE);
Uri myLocation =
- handler.provider.cwd.resolve(nativeToUriPath(options.script));
+ handler.provider.cwd.resolve(nativeToUriPath(Platform.script));
// Get the names of public dart2js libraries.
Iterable<String> names = LIBRARIES.keys.where(isPublicDart2jsLibrary);
@@ -118,7 +114,7 @@
var lineStart = file.lineStarts[line_number - 1];
// TODO(ahe): Most often an empty string. Try to see if we can
// get the position of the name token instead.
- var tag_definition_text = file.text.substring(lineStart, byte_offset);
+ var tag_definition_text = file.slowText().substring(lineStart, byte_offset);
// One definition.
buffer.write('${tag_definition_text}\x7f${tagname}'
diff --git a/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart b/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
index 931e24b..e58ee6b 100644
--- a/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
+++ b/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
@@ -32,20 +32,16 @@
Uri outputUri;
Uri sdkRoot;
-main() {
- mainWithOptions(new Options());
-}
-
-mainWithOptions(Options options) {
+main(List<String> arguments) {
handler = new FormattingDiagnosticHandler()
..throwOnError = true;
outputUri =
- handler.provider.cwd.resolve(nativeToUriPath(options.arguments.first));
- output = new File(options.arguments.first).openSync(mode: FileMode.WRITE);
+ handler.provider.cwd.resolve(nativeToUriPath(arguments.first));
+ output = new File(arguments.first).openSync(mode: FileMode.WRITE);
Uri myLocation =
- handler.provider.cwd.resolve(nativeToUriPath(options.script));
+ handler.provider.cwd.resolve(nativeToUriPath(Platform.script));
sdkRoot = myLocation.resolve(SDK_ROOT).resolve('../');
diff --git a/sdk/lib/_internal/compiler/samples/leap/leap_server.dart b/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
index 31aaa55..3db4dda 100644
--- a/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
+++ b/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
@@ -94,8 +94,7 @@
}
}
-main() {
- List<String> arguments = new Options().arguments;
+main(List<String> arguments) {
if (arguments.length > 0) {
Conversation.landingPage = arguments[0];
}
diff --git a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
index 72c5c32..6c3ec50 100644
--- a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
@@ -27,20 +27,10 @@
/**
* Run this from the `lib/_internal/dartdoc` directory.
*/
-main() {
- mainWithOptions(new Options());
-}
-
-/**
- * We use this to include dartdoc in a single snapshot with dart2js.
- * (They share 90% of the code)
- */
-mainWithOptions(Options options) {
+main(List<String> arguments) {
// Need this because ArgParser.getUsage doesn't show command invocation.
final USAGE = 'Usage dartdoc [options] <entrypoint(s)>\n[options] include:';
- final args = options.arguments;
-
final dartdoc = new Dartdoc();
final argParser = new ArgParser();
@@ -197,7 +187,7 @@
dartdoc.dartdocPath = path.join(libPath, 'lib', '_internal', 'dartdoc');
- if (args.isEmpty) {
+ if (arguments.isEmpty) {
print('No arguments provided.');
print(USAGE);
print(argParser.getUsage());
@@ -206,7 +196,7 @@
final entrypoints = <Uri>[];
try {
- final option = argParser.parse(args, allowTrailingOptions: true);
+ final option = argParser.parse(arguments, allowTrailingOptions: true);
// This checks to see if the root of all entrypoints is the same.
// If it is not, then we display a warning, as package imports might fail.
diff --git a/sdk/lib/_internal/lib/foreign_helper.dart b/sdk/lib/_internal/lib/foreign_helper.dart
index ae91916..95b5907 100644
--- a/sdk/lib/_internal/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/lib/foreign_helper.dart
@@ -165,6 +165,14 @@
JS_DART_OBJECT_CONSTRUCTOR() {}
/**
+ * Returns the interceptor for class [type]. The interceptor is the type's
+ * constructor's `prototype` property. [type] will typically be the class, not
+ * an interface, e.g. `JS_INTERCEPTOR_CONSTANT(JSInt)`, not
+ * `JS_INTERCEPTOR_CONSTANT(int)`.
+ */
+JS_INTERCEPTOR_CONSTANT(Type type) {}
+
+/**
* Returns the prefix used for generated is checks on classes.
*/
String JS_OPERATOR_IS_PREFIX() {}
diff --git a/sdk/lib/_internal/lib/interceptors.dart b/sdk/lib/_internal/lib/interceptors.dart
index e87ce4f..f56d424 100644
--- a/sdk/lib/_internal/lib/interceptors.dart
+++ b/sdk/lib/_internal/lib/interceptors.dart
@@ -27,7 +27,7 @@
lookupDispatchRecord,
StringMatch,
firstMatchAfter;
-import 'dart:_foreign_helper' show JS, JS_EFFECT;
+import 'dart:_foreign_helper' show JS, JS_EFFECT, JS_INTERCEPTOR_CONSTANT;
import 'dart:math' show Random;
part 'js_array.dart';
@@ -145,7 +145,7 @@
record = lookupDispatchRecord(object);
if (record == null) {
- return const UnknownJavaScriptObject();
+ return JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject);
}
setDispatchProperty(JS('', 'Object.getPrototypeOf(#)', object), record);
return getNativeInterceptor(object);
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index ff0cf49..74c0387 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -8,6 +8,7 @@
import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS,
JS,
JS_CALL_IN_ISOLATE,
+ JS_CONST,
JS_CURRENT_ISOLATE,
JS_CURRENT_ISOLATE_CONTEXT,
JS_DART_OBJECT_CONSTRUCTOR,
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index f6f521d..610af50 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -229,8 +229,8 @@
bool get hasReflectedType => false;
Type get reflectedType => throw new UnsupportedError("This type does not support reflectedTypees");
- List<TypeVariableMirror> get typeVariables => throw new UnimplementedError();
- List<TypeMirror> get typeArguments => throw new UnimplementedError();
+ List<TypeVariableMirror> get typeVariables => const <TypeVariableMirror>[];
+ List<TypeMirror> get typeArguments => const <TypeMirror>[];
bool get isOriginalDeclaration => true;
TypeMirror get originalDeclaration => this;
@@ -689,7 +689,7 @@
throw new UnimplementedError();
}
- List<TypeMirror> get typeArguments => new List();
+ List<TypeMirror> get typeArguments => const <TypeMirror>[];
}
abstract class JsObjectMirror implements ObjectMirror {
@@ -1422,7 +1422,7 @@
return _cachedTypeVariables = new UnmodifiableListView(result);
}
- List<TypeMirror> get typeArguments => new List();
+ List<TypeMirror> get typeArguments => const <TypeMirror>[];
}
class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {
diff --git a/sdk/lib/_internal/lib/mirrors_patch.dart b/sdk/lib/_internal/lib/mirrors_patch.dart
index 1254791..71c1e68 100644
--- a/sdk/lib/_internal/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/lib/mirrors_patch.dart
@@ -16,10 +16,6 @@
patch MirrorSystem currentMirrorSystem() => js.currentJsMirrorSystem;
-patch Future<MirrorSystem> mirrorSystemOf(SendPort port) {
- throw new UnsupportedError("MirrorSystem not implemented");
-}
-
patch InstanceMirror reflect(Object reflectee) => js.reflect(reflectee);
patch ClassMirror reflectClass(Type key) {
@@ -33,4 +29,9 @@
return (tm as ClassMirror).originalDeclaration;
}
-patch TypeMirror reflectType(Type key) => js.reflectType(key);
+patch TypeMirror reflectType(Type key) {
+ if (key == dynamic) {
+ return currentMirrorSystem().dynamicType;
+ }
+ return js.reflectType(key);
+}
diff --git a/sdk/lib/_internal/lib/native_helper.dart b/sdk/lib/_internal/lib/native_helper.dart
index b5f24ff..c85aede 100644
--- a/sdk/lib/_internal/lib/native_helper.dart
+++ b/sdk/lib/_internal/lib/native_helper.dart
@@ -4,102 +4,6 @@
part of _js_helper;
-String typeNameInChrome(obj) {
- String name = JS('String', "#.constructor.name", obj);
- return typeNameInWebKitCommon(name);
-}
-
-String typeNameInSafari(obj) {
- String name = JS('String', '#', constructorNameFallback(obj));
- // Safari is very similar to Chrome.
- return typeNameInWebKitCommon(name);
-}
-
-String typeNameInWebKitCommon(tag) {
- String name = JS('String', '#', tag);
- return name;
-}
-
-String typeNameInOpera(obj) {
- String name = JS('String', '#', constructorNameFallback(obj));
- return name;
-}
-
-String typeNameInFirefox(obj) {
- String name = JS('String', '#', constructorNameFallback(obj));
- if (name == 'BeforeUnloadEvent') return 'Event';
- if (name == 'DataTransfer') return 'Clipboard';
- if (name == 'GeoGeolocation') return 'Geolocation';
- if (name == 'WorkerMessageEvent') return 'MessageEvent';
- if (name == 'XMLDocument') return 'Document';
- return name;
-}
-
-String typeNameInIE(obj) {
- String name = JS('String', '#', constructorNameFallback(obj));
- if (name == 'Document') {
- // IE calls both HTML and XML documents 'Document', so we check for the
- // xmlVersion property, which is the empty string on HTML documents.
- if (JS('bool', '!!#.xmlVersion', obj)) return 'Document';
- return 'HTMLDocument';
- }
- if (name == 'BeforeUnloadEvent') return 'Event';
- if (name == 'DataTransfer') return 'Clipboard';
- if (name == 'HTMLDDElement') return 'HTMLElement';
- if (name == 'HTMLDTElement') return 'HTMLElement';
- if (name == 'HTMLPhraseElement') return 'HTMLElement';
- if (name == 'Position') return 'Geoposition';
-
- // Patches for types which report themselves as Objects.
- if (name == 'Object') {
- if (JS('bool', 'window.DataView && (# instanceof window.DataView)', obj)) {
- return 'DataView';
- }
- }
- return name;
-}
-
-String constructorNameFallback(object) {
- if (object == null) return 'Null';
- var constructor = JS('var', "#.constructor", object);
- if (identical(JS('String', "typeof(#)", constructor), 'function')) {
- var name = JS('var', r'#.builtin$cls', constructor);
- if (name != null) return name;
- // The constructor isn't null or undefined at this point. Try
- // to grab hold of its name.
- name = JS('var', '#.name', constructor);
- // If the name is a non-empty string, we use that as the type
- // name of this object. On Firefox, we often get 'Object' as
- // the constructor name even for more specialized objects so
- // we have to fall through to the toString() based implementation
- // below in that case.
- if (name is String
- && !identical(name, '')
- && !identical(name, 'Object')
- && !identical(name, 'Function.prototype')) { // Can happen in Opera.
- return name;
- }
- }
- String string = JS('String', 'Object.prototype.toString.call(#)', object);
- return JS('String', '#.substring(8, # - 1)', string, string.length);
-}
-
-/**
- * If a lookup on an object [object] that has [tag] fails, this function is
- * called to provide an alternate tag. This allows us to fail gracefully if we
- * can make a good guess, for example, when browsers add novel kinds of
- * HTMLElement that we have never heard of.
- */
-String alternateTag(object, String tag) {
- // Does it smell like some kind of HTML element?
- if (JS('bool', r'!!/^HTML[A-Z].*Element$/.test(#)', tag)) {
- // Check that it is not a simple JavaScript object.
- String string = JS('String', 'Object.prototype.toString.call(#)', object);
- if (string == '[object Object]') return null;
- return 'HTMLElement';
- }
- return null;
-}
// TODO(ngeoffray): stop using this method once our optimizers can
// change str1.contains(str2) into str1.indexOf(str2) != -1.
@@ -139,77 +43,29 @@
return JS('var', '{}');
}
-Function getTypeNameOf = getFunctionForTypeNameOf();
+/**
+ * Returns a String tag identifying the type of the native object, or `null`.
+ * The tag is not the name of the type, but usually the name of the JavaScript
+ * constructor function.
+ */
+Function getTagFunction;
/**
- * Returns the function to use to get the type name (i.e. dispatch tag) of an
- * object.
+ * If a lookup via [getTagFunction] on an object [object] that has [tag] fails,
+ * this function is called to provide an alternate tag. This allows us to fail
+ * gracefully if we can make a good guess, for example, when browsers add novel
+ * kinds of HTMLElement that we have never heard of.
*/
-Function getFunctionForTypeNameOf() {
- var getTagFunction = getBaseFunctionForTypeNameOf();
- if (JS('bool', 'typeof dartExperimentalFixupGetTag == "function"')) {
- return applyExperimentalFixup(
- JS('', 'dartExperimentalFixupGetTag'), getTagFunction);
- }
- return getTagFunction;
-}
-
-/// Don't call directly, use [getFunctionForTypeNameOf] instead.
-Function getBaseFunctionForTypeNameOf() {
- // If we're not in the browser, we're almost certainly running on v8.
- if (!identical(JS('String', 'typeof(navigator)'), 'object')) {
- return typeNameInChrome;
- }
-
- String userAgent = JS('String', "navigator.userAgent");
- // TODO(antonm): remove a reference to DumpRenderTree.
- if (contains(userAgent, 'Chrome') || contains(userAgent, 'DumpRenderTree')) {
- return typeNameInChrome;
- } else if (contains(userAgent, 'Firefox')) {
- return typeNameInFirefox;
- } else if (contains(userAgent, 'Trident/')) {
- return typeNameInIE;
- } else if (contains(userAgent, 'Opera')) {
- return typeNameInOpera;
- } else if (contains(userAgent, 'AppleWebKit')) {
- // Chrome matches 'AppleWebKit' too, but we test for Chrome first, so this
- // is not a problem.
- // Note: Just testing for "Safari" doesn't work when the page is embedded
- // in a UIWebView on iOS 6.
- return typeNameInSafari;
- } else {
- return constructorNameFallback;
- }
-}
-
-Function applyExperimentalFixup(fixupJSFunction,
- Function originalGetTagDartFunction) {
- var originalGetTagJSFunction =
- convertDartClosure1ArgToJSNoDataConversions(
- originalGetTagDartFunction);
-
- var newGetTagJSFunction =
- JS('', '#(#)', fixupJSFunction, originalGetTagJSFunction);
-
- String newGetTagDartFunction(object) =>
- JS('', '#(#)', newGetTagJSFunction, object);
-
- return newGetTagDartFunction;
-}
-
-callDartFunctionWith1Arg(fn, arg) => fn(arg);
-
-convertDartClosure1ArgToJSNoDataConversions(dartClosure) {
- return JS('',
- '(function(invoke, closure){'
- 'return function(arg){ return invoke(closure, arg); };'
- '})(#, #)',
- DART_CLOSURE_TO_JS(callDartFunctionWith1Arg), dartClosure);
-}
+Function alternateTagFunction;
String toStringForNativeObject(var obj) {
- String name = JS('String', '#', getTypeNameOf(obj));
+ // TODO(sra): Is this code dead?
+ // [getTagFunction] might be uninitialized, but in usual usage, toString has
+ // been called via an interceptor and initialized it.
+ String name = getTagFunction == null
+ ? '<Unknown>'
+ : JS('String', '#', getTagFunction(obj));
return 'Instance of $name';
}
@@ -237,16 +93,15 @@
/**
* A JavaScript object mapping tags to the constructors of interceptors.
*
- * Example: 'HTMLImageElement' maps to the ImageElement native class
- * constructor.
+ * Example: 'HTMLImageElement' maps to the ImageElement class constructor.
*/
get interceptorsByTag => JS('=Object', 'init.interceptorsByTag');
/**
* A JavaScript object mapping tags to `true` or `false`.
*
- * Example: 'HTMLImageElement' maps to `true` since, as since there are no
- * subclasses of ImageElement, it is a leaf class in the native class hierarchy.
+ * Example: 'HTMLImageElement' maps to `true` since, as there are no subclasses
+ * of ImageElement, it is a leaf class in the native class hierarchy.
*/
get leafTags => JS('=Object', 'init.leafTags');
@@ -266,11 +121,11 @@
var hasOwnPropertyFunction = JS('var', 'Object.prototype.hasOwnProperty');
var interceptorClass = null;
assert(!isDartObject(obj));
- String tag = getTypeNameOf(obj);
+ String tag = getTagFunction(obj);
interceptorClass = lookupInterceptor(hasOwnPropertyFunction, tag);
if (interceptorClass == null) {
- String secondTag = alternateTag(obj, tag);
+ String secondTag = alternateTagFunction(obj, tag);
if (secondTag != null) {
interceptorClass = lookupInterceptor(hasOwnPropertyFunction, secondTag);
}
@@ -310,11 +165,27 @@
}
}
+/**
+ * [proto] should have no shadowing prototypes that are not also assigned a
+ * dispatch rescord.
+ */
+setNativeSubclassDispatchRecord(proto, interceptor) {
+ setDispatchProperty(proto, makeLeafDispatchRecord(interceptor));
+}
+
+String constructorNameFallback(object) {
+ return JS('String', '#(#)', _constructorNameFallback, object);
+}
+
+
var initNativeDispatchFlag; // null or true
void initNativeDispatch() {
+ if (true == initNativeDispatchFlag) return;
initNativeDispatchFlag = true;
+ initHooks();
+
// Try to pro-actively patch prototypes of DOM objects. For each of our known
// tags `TAG`, if `window.TAG` is a (constructor) function, set the dispatch
// property if the function's prototype to a dispatch record.
@@ -341,9 +212,253 @@
/**
- * [proto] should have no shadowing prototypes that are not also assigned a
- * dispatch rescord.
+ * Initializes [getTagFunction] and [alternateTagFunction].
+ *
+ * These functions are 'hook functions', collectively 'hooks'. They initialized
+ * by applying a series of hooks transformers. Built-in hooks transformers deal
+ * with various known browser behaviours.
+ *
+ * Each hook tranformer takes a 'hooks' input which is a JavaScript object
+ * containing the hook functions, and returns the same or a new object with
+ * replacements. The replacements can wrap the originals to provide alternate
+ * or modified behaviour.
+ *
+ * { getTag: function(obj) {...},
+ * getUnknownTag: function(obj, tag) {...},
+ * discriminator: function(tag) {...},
+ * }
+ *
+ * * getTag(obj) returns the dispatch tag, or `null`.
+ * * getUnknownTag(obj, tag) returns a tag when [getTag] fails.
+ * * discriminator returns a function TBD.
+ *
+ * The web site can adapt a dart2js application by loading code ahead of the
+ * dart2js application that defines hook transformers to be after the built in
+ * ones. Code defining a transformer HT should use the following pattern to
+ * ensure multiple transformers can be composed:
+ *
+ * (dartNativeDispatchHooksTransformer =
+ * window.dartNativeDispatchHooksTransformer || []).push(HT);
+ *
+ *
+ * TODO: Implement and describe dispatch tags and their caching methods.
*/
-setNativeSubclassDispatchRecord(proto, interceptor) {
- setDispatchProperty(proto, makeLeafDispatchRecord(interceptor));
+void initHooks() {
+ // The initial simple hooks:
+ var hooks = JS('', '#()', _baseHooks);
+
+ // Customize for browsers where `object.constructor.name` fails:
+ var _fallbackConstructorHooksTransformer =
+ JS('', '#(#)', _fallbackConstructorHooksTransformerGenerator,
+ _constructorNameFallback);
+ hooks = applyHooksTransformer(_fallbackConstructorHooksTransformer, hooks);
+
+ // Customize for browsers:
+ hooks = applyHooksTransformer(_firefoxHooksTransformer, hooks);
+ hooks = applyHooksTransformer(_ieHooksTransformer, hooks);
+ hooks = applyHooksTransformer(_operaHooksTransformer, hooks);
+ hooks = applyHooksTransformer(_safariHooksTransformer, hooks);
+
+ // TODO(sra): Update ShadowDOM polyfil to use
+ // [dartNativeDispatchHooksTransformer] and remove this hook.
+ hooks = applyHooksTransformer(_dartExperimentalFixupGetTagHooksTransformer,
+ hooks);
+
+ // Apply global hooks.
+ //
+ // If defined, dartNativeDispatchHookdTransformer should be a single function
+ // of a JavaScript Array of functions.
+
+ if (JS('bool', 'typeof dartNativeDispatchHooksTransformer != "undefined"')) {
+ var transformers = JS('', 'dartNativeDispatchHooksTransformer');
+ if (JS('bool', 'typeof # == "function"', transformers)) {
+ transformers = [transformers];
+ }
+ if (JS('bool', '#.constructor == Array', transformers)) {
+ for (int i = 0; i < JS('int', '#.length', transformers); i++) {
+ var transformer = JS('', '#[#]', transformers, i);
+ if (JS('bool', 'typeof # == "function"', transformer)) {
+ hooks = applyHooksTransformer(transformer, hooks);
+ }
+ }
+ }
+ }
+
+ var getTag = JS('', '#.getTag', hooks);
+ var getUnknownTag = JS('', '#.getUnknownTag', hooks);
+
+ getTagFunction = (o) => JS('String|Null', '#(#)', getTag, o);
+ alternateTagFunction =
+ (o, String tag) => JS('String|Null', '#(#, #)', getUnknownTag, o, tag);
}
+
+applyHooksTransformer(transformer, hooks) {
+ var newHooks = JS('=Object|Null', '#(#)', transformer, hooks);
+ return JS('', '# || #', newHooks, hooks);
+}
+
+
+// JavaScript code fragments.
+//
+// This is a temporary place for the JavaScript code.
+//
+// TODO(sra): These code fragments are not minified. They could be generated by
+// the code emitter, or JS_CONST could be improved to parse entire functions and
+// take care of the minification.
+
+const _baseHooks = const JS_CONST(r'''
+function() {
+ function typeNameInChrome(obj) { return obj.constructor.name; }
+ function getUnknownTag(object, tag) {
+ // This code really belongs in [getUnknownTagGenericBrowser] but having it
+ // here allows [getUnknownTag] to be tested on d8.
+ if (/^HTML[A-Z].*Element$/.test(tag)) {
+ // Check that it is not a simple JavaScript object.
+ var name = Object.prototype.toString.call(object);
+ if (name == "[object Object]") return null;
+ return "HTMLElement";
+ }
+ }
+ function getUnknownTagGenericBrowser(object, tag) {
+ if (object instanceof HTMLElement) return "HTMLElement";
+ return getUnknownTag(object, tag);
+ }
+ function discriminator(tag) { return null; }
+
+ var isBrowser = typeof navigator == "object";
+
+ return {
+ getTag: typeNameInChrome,
+ getUnknownTag: isBrowser ? getUnknownTagGenericBrowser : getUnknownTag,
+ discriminator: discriminator };
+}''');
+
+
+/**
+ * Returns the name of the constructor function for browsers where
+ * `object.constructor.name` is not reliable.
+ *
+ * This function is split out of [_fallbackConstructorHooksTransformerGenerator]
+ * as it is called from both the dispatch hooks and via
+ * [constructorNameFallback] from objectToString.
+ */
+const _constructorNameFallback = const JS_CONST(r'''
+function getTagFallback(o) {
+ if (o == null) return "Null";
+ var constructor = o.constructor;
+ if (typeof constructor == "function") {
+ var name = constructor.builtin$cls;
+ if (typeof name == "string") return name;
+ // The constructor is not null or undefined at this point. Try
+ // to grab hold of its name.
+ name = constructor.name;
+ // If the name is a non-empty string, we use that as the type name of this
+ // object. On Firefox, we often get "Object" as the constructor name even
+ // for more specialized objects so we have to fall through to the toString()
+ // based implementation below in that case.
+ if (typeof name == "string"
+ && name !== ""
+ && name !== "Object"
+ && name !== "Function.prototype") { // Can happen in Opera.
+ return name;
+ }
+ }
+ var s = Object.prototype.toString.call(o);
+ return s.substring(8, s.length - 1);
+}''');
+
+
+const _fallbackConstructorHooksTransformerGenerator = const JS_CONST(r'''
+function(getTagFallback) {
+ return function(hooks) {
+ // If we are not in a browser, assume we are in d8.
+ // TODO(sra): Recognize jsshell.
+ if (typeof navigator != "object") return hooks;
+
+ var userAgent = navigator.userAgent;
+ // TODO(antonm): remove a reference to DumpRenderTree.
+ if (userAgent.indexOf("Chrome") >= 0 ||
+ userAgent.indexOf("DumpRenderTree") >= 0) {
+ return hooks;
+ }
+
+ hooks.getTag = getTagFallback;
+ };
+}''');
+
+
+const _ieHooksTransformer = const JS_CONST(r'''
+function(hooks) {
+ var userAgent = typeof navigator == "object" ? navigator.userAgent : "";
+ if (userAgent.indexOf("Trident/") == -1) return hooks;
+
+ var getTag = hooks.getTag;
+
+ var quickMap = {
+ "BeforeUnloadEvent": "Event",
+ "DataTransfer": "Clipboard",
+ "HTMLDDElement": "HTMLElement",
+ "HTMLDTElement": "HTMLElement",
+ "HTMLPhraseElement": "HTMLElement",
+ "Position": "Geoposition"
+ };
+
+ function getTagIE(o) {
+ var tag = getTag(o);
+ var newTag = quickMap[tag];
+ if (newTag) return newTag;
+ if (tag == "Document") {
+ // IE calls both HTML and XML documents "Document", so we check for the
+ // xmlVersion property, which is the empty string on HTML documents.
+ if (!!o.xmlVersion) return "Document";
+ return "HTMLDocument";
+ }
+ // Patches for types which report themselves as Objects.
+ if (tag == "Object") {
+ if (window.DataView && (o instanceof window.DataView)) return "DataView";
+ }
+ return tag;
+ }
+
+ hooks.getTag = getTagIE;
+}''');
+
+
+const _firefoxHooksTransformer = const JS_CONST(r'''
+function(hooks) {
+ var userAgent = typeof navigator == "object" ? navigator.userAgent : "";
+ if (userAgent.indexOf("Firefox") == -1) return hooks;
+
+ var getTag = hooks.getTag;
+
+ var quickMap = {
+ "BeforeUnloadEvent": "Event",
+ "DataTransfer": "Clipboard",
+ "GeoGeolocation": "Geolocation",
+ "WorkerMessageEvent": "MessageEvent",
+ "XMLDocument": "Document"};
+
+ function getTagFirefox(o) {
+ var tag = getTag(o);
+ return quickMap[tag] || tag;
+ }
+
+ hooks.getTag = getTagFirefox;
+}''');
+
+
+const _operaHooksTransformer = const JS_CONST(r'''
+function(hooks) { return hooks; }
+''');
+
+
+const _safariHooksTransformer = const JS_CONST(r'''
+function(hooks) { return hooks; }
+''');
+
+
+const _dartExperimentalFixupGetTagHooksTransformer = const JS_CONST(r'''
+function(hooks) {
+ if (typeof dartExperimentalFixupGetTag != "function") return hooks;
+ hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag);
+}''');
diff --git a/sdk/lib/_internal/lib/platform_patch.dart b/sdk/lib/_internal/lib/platform_patch.dart
deleted file mode 100644
index 13fdeb8..0000000
--- a/sdk/lib/_internal/lib/platform_patch.dart
+++ /dev/null
@@ -1,24 +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.
-
-patch int get numberOfProcessors => null;
-
-patch String get pathSeparator => '/';
-
-patch String get operatingSystem => null;
-
-patch String get localHostname => null;
-
-patch String get version => null;
-
-patch Map<String, String> get environment => null;
-
-patch String get executable => null;
-
-patch Uri get script => null;
-
-// An unmodifiable list.
-patch List<String> get executableArguments => new List<String>(0);
-
-patch String get packageRoot => null;
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index 6aa24dd..0c9925f 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -101,11 +101,6 @@
documented: false,
platforms: VM_PLATFORM),
- "platform": const LibraryInfo(
- "platform/platform.dart",
- maturity: Maturity.UNSTABLE,
- dart2jsPatchPath: "_internal/lib/platform_patch.dart"),
-
"typed_data": const LibraryInfo(
"typed_data/typed_data.dart",
maturity: Maturity.STABLE,
diff --git a/sdk/lib/_internal/pub/bin/pub.dart b/sdk/lib/_internal/pub/bin/pub.dart
index ecd58bd..ca88d38 100644
--- a/sdk/lib/_internal/pub/bin/pub.dart
+++ b/sdk/lib/_internal/pub/bin/pub.dart
@@ -18,11 +18,11 @@
final pubArgParser = initArgParser();
-void main() {
+void main(List<String> arguments) {
ArgResults options;
try {
- options = pubArgParser.parse(new Options().arguments);
+ options = pubArgParser.parse(arguments);
} on FormatException catch (e) {
log.error(e.message);
log.error('Run "pub help" to see available options.');
@@ -84,7 +84,7 @@
}
validatePlatform().then((_) {
- PubCommand.commands[options.command.name].run(cacheDir, options);
+ PubCommand.commands[options.command.name].run(cacheDir, options, arguments);
});
}
diff --git a/sdk/lib/_internal/pub/lib/src/barback.dart b/sdk/lib/_internal/pub/lib/src/barback.dart
index a78f7b8..84a069a 100644
--- a/sdk/lib/_internal/pub/lib/src/barback.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback.dart
@@ -10,10 +10,10 @@
import 'package:path/path.dart' as path;
import 'barback/load_all_transformers.dart';
-import 'barback/pub_barback_logger.dart';
import 'barback/pub_package_provider.dart';
import 'barback/server.dart';
-import 'barback/watch_sources.dart';
+import 'barback/sources.dart';
+import 'log.dart' as log;
import 'package_graph.dart';
import 'utils.dart';
@@ -103,43 +103,54 @@
///
/// If [builtInTransformers] is provided, then a phase is added to the end of
/// each package's cascade including those transformers.
+///
+/// If [watchForUpdates] is true (the default), the server will continually
+/// monitor the app and its dependencies for any updates. Otherwise the state of
+/// the app when the server is started will be maintained.
Future<BarbackServer> createServer(String host, int port, PackageGraph graph,
- {Iterable<Transformer> builtInTransformers}) {
+ {Iterable<Transformer> builtInTransformers, bool watchForUpdates: true}) {
var provider = new PubPackageProvider(graph);
- var logger = new PubBarbackLogger();
- var barback = new Barback(provider, logger: logger);
+ var barback = new Barback(provider);
+
+ barback.log.listen(_log);
return BarbackServer.bind(host, port, barback, graph.entrypoint.root.name)
.then((server) {
- watchSources(graph, barback);
+ return new Future.sync(() {
+ if (watchForUpdates) return watchSources(graph, barback);
+ loadSources(graph, barback);
+ }).then((_) {
+ var completer = new Completer();
- var completer = new Completer();
+ // If any errors get emitted either by barback or by the server, including
+ // non-programmatic barback errors, they should take down the whole
+ // program.
+ var subscriptions = [
+ server.barback.errors.listen((error) {
+ if (error is TransformerException) error = error.error;
+ if (!completer.isCompleted) completer.completeError(error);
+ }),
+ server.barback.results.listen((_) {}, onError: (error, stackTrace) {
+ if (completer.isCompleted) return;
+ completer.completeError(error, stackTrace);
+ }),
+ server.results.listen((_) {}, onError: (error, stackTrace) {
+ if (completer.isCompleted) return;
+ completer.completeError(error, stackTrace);
+ })
+ ];
- // If any errors get emitted either by barback or by the server, including
- // non-programmatic barback errors, they should take down the whole program.
- var subscriptions = [
- server.barback.errors.listen((error) {
- if (error is TransformerException) error = error.error;
- if (!completer.isCompleted) completer.completeError(error);
- }),
- server.barback.results.listen((_) {}, onError: (error, stackTrace) {
+ loadAllTransformers(server, graph, builtInTransformers).then((_) {
+ if (!completer.isCompleted) completer.complete(server);
+ }).catchError((error, stackTrace) {
if (!completer.isCompleted) completer.completeError(error, stackTrace);
- }),
- server.results.listen((_) {}, onError: (error, stackTrace) {
- if (!completer.isCompleted) completer.completeError(error, stackTrace);
- })
- ];
+ });
- loadAllTransformers(server, graph, builtInTransformers).then((_) {
- if (!completer.isCompleted) completer.complete(server);
- }).catchError((error, stackTrace) {
- if (!completer.isCompleted) completer.completeError(error, stackTrace);
- });
-
- return completer.future.whenComplete(() {
- for (var subscription in subscriptions) {
- subscription.cancel();
- }
+ return completer.future.whenComplete(() {
+ for (var subscription in subscriptions) {
+ subscription.cancel();
+ }
+ });
});
});
}
@@ -239,3 +250,56 @@
throw new FormatException('Cannot access assets from "$dir".');
}
}
+
+/// Log [entry] using Pub's logging infrastructure.
+///
+/// Since both [LogEntry] objects and the message itself often redundantly
+/// show the same context like the file where an error occurred, this tries
+/// to avoid showing redundant data in the entry.
+void _log(LogEntry entry) {
+ messageMentions(String text) {
+ return entry.message.toLowerCase().contains(text.toLowerCase());
+ }
+
+ var prefixParts = [];
+
+ // Show the level (unless the message mentions it).
+ if (!messageMentions(entry.level.name)) {
+ prefixParts.add("${entry.level} in");
+ }
+
+ // Show the transformer.
+ prefixParts.add(entry.transform.transformer);
+
+ // Mention the primary input of the transform unless the message seems to.
+ if (!messageMentions(entry.transform.primaryId.path)) {
+ prefixParts.add("on ${entry.transform.primaryId}");
+ }
+
+ // If the relevant asset isn't the primary input, mention it unless the
+ // message already does.
+ if (entry.assetId != entry.transform.primaryId &&
+ !messageMentions(entry.assetId.path)) {
+ prefixParts.add("with input ${entry.assetId}");
+ }
+
+ var prefix = "[${prefixParts.join(' ')}]:";
+ var message = entry.message;
+ if (entry.span != null) {
+ message = entry.span.getLocationMessage(entry.message);
+ }
+
+ switch (entry.level) {
+ case LogLevel.ERROR:
+ log.error("${log.red(prefix)}\n$message");
+ break;
+
+ case LogLevel.WARNING:
+ log.warning("${log.yellow(prefix)}\n$message");
+ break;
+
+ case LogLevel.INFO:
+ log.message("$prefix\n$message");
+ break;
+ }
+}
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
index d79cec7..293ac2f 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
@@ -26,12 +26,16 @@
class Dart2JSTransformer extends Transformer {
final PackageGraph _graph;
+ /// Whether the JavaScript output should be minified.
+ final bool _minify;
+
/// The [AssetId]s the transformer has discovered so far. Used by pub build
/// to determine where to copy the JS bootstrap files.
// TODO(rnystrom): Do something cleaner for this, or eliminate those files.
final entrypoints = new Set<AssetId>();
- Dart2JSTransformer(this._graph);
+ Dart2JSTransformer(this._graph, {bool minify})
+ : _minify = minify == true ? true : false;
/// Only ".dart" files within "web/" are processed.
Future<bool> isPrimary(Asset asset) {
@@ -77,20 +81,20 @@
// path so they can understand them.
return dart.compile(entrypoint,
packageRoot: packageRoot,
+ minify: _minify,
inputProvider: provider.readStringFromUri,
diagnosticHandler: provider.handleDiagnostic).then((js) {
- if (js == null) {
- // The compile failed and errors should have already been reported
- // through the diagnostic handler, so just do nothing here.
- return;
- }
-
var id = transform.primaryInput.id.changeExtension(".dart.js");
transform.addOutput(new Asset.fromString(id, js));
stopwatch.stop();
transform.logger.info("Generated $id (${js.length} characters) in "
"${stopwatch.elapsed}");
+ }).catchError((error) {
+ // The compile failed and errors have been reported through the
+ // diagnostic handler, so just do nothing here.
+ if (error is CompilerException) return;
+ throw error;
});
});
}
diff --git a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
index 3eb02b7..621e85a 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
@@ -32,16 +32,16 @@
import 'http://<<HOST_AND_PORT>>/packages/barback/barback.dart';
/// Sets up the initial communication with the host isolate.
-void main(List<String> args, SendPort replyTo) {
+void main(_, SendPort replyTo) {
var port = new ReceivePort();
- replyTo.send(['success', port.sendPort]);
- port.listen((args) {
- _sendFuture(args['replyTo'], new Future.sync(() {
- var library = Uri.parse(args['library']);
- var configuration = JSON.decode(args['configuration']);
+ replyTo.send(port.sendPort);
+ port.first.then((wrappedMessage) {
+ _respond(wrappedMessage, (message) {
+ var library = Uri.parse(message['library']);
+ var configuration = JSON.decode(message['configuration']);
return initialize(library, configuration).
map(_serializeTransformerOrGroup).toList();
- }));
+ });
});
}
@@ -103,7 +103,7 @@
: _port = transform['port'],
primaryInput = _deserializeAsset(transform['primaryInput']) {
_logger = new TransformLogger((assetId, level, message, span) {
- _port.send({
+ _call(_port, {
'type': 'log',
'level': level.name,
'message': message,
@@ -114,7 +114,7 @@
}
Future<Asset> getInput(AssetId id) {
- return _callAndReceiveFuture(_port, {
+ return _call(_port, {
'type': 'getInput',
'id': _serializeId(id)
}).then(_deserializeAsset);
@@ -129,7 +129,7 @@
_futureStream(getInput(id).then((input) => input.read()));
void addOutput(Asset output) {
- _port.send({
+ _call(_port, {
'type': 'addOutput',
'output': _serializeAsset(output)
});
@@ -183,9 +183,8 @@
/// Converts [transformer] into a serializable map.
Map _serializeTransformer(Transformer transformer) {
var port = new ReceivePort();
- port.listen((message) {
- var replyTo = message['replyTo'];
- _sendFuture(replyTo, new Future.sync(() {
+ port.listen((wrappedMessage) {
+ _respond(wrappedMessage, (message) {
if (message['type'] == 'isPrimary') {
return transformer.isPrimary(_deserializeAsset(message['asset']));
} else {
@@ -193,7 +192,7 @@
return transformer.apply(
new ForeignTransform(message['transform']));
}
- }));
+ });
});
return {
@@ -214,29 +213,45 @@
};
}
-/// When the input receives a 'done' as data-event, transforms it to a
-/// done event and cancels the subscription.
-StreamSubscription doneTransformer(Stream input, bool cancelOnError) {
+/// Converts a serializable map into an [Asset].
+Asset _deserializeAsset(Map asset) {
+ return new Asset.fromStream(
+ _deserializeId(asset['id']),
+ _deserializeStream(asset['stream']));
+}
+
+/// The body of a [StreamTransformer] that deserializes the values in a stream
+/// sent by [_serializeStream].
+StreamSubscription _deserializeTransformer(Stream input, bool cancelOnError) {
var subscription;
var transformed = input.transform(new StreamTransformer.fromHandlers(
handleData: (data, sink) {
- if (data == 'done') {
- sink.close();
- subscription.cancel();
- } else {
- sink.add(data);
- }
- }));
+ if (data['type'] == 'data') {
+ sink.add(data['data']);
+ } else if (data['type'] == 'error') {
+ sink.addError(CrossIsolateException.deserialize(data['error']));
+ } else {
+ assert(data['type'] == 'done');
+ sink.close();
+ subscription.cancel();
+ }
+ }));
subscription = transformed.listen(null, cancelOnError: cancelOnError);
return subscription;
}
-/// Converts a serializable map into an [Asset].
-Asset _deserializeAsset(Map asset) {
- var receivePort = new ReceivePort();
- asset['sendPort'].send(receivePort.sendPort);
- var stream = receivePort.transform(const StreamTransformer(doneTransformer));
- return new Asset.fromStream(_deserializeId(asset['id']), stream);
+/// Convert a [SendPort] whose opposite is waiting to send us a stream into a
+/// [Stream].
+///
+/// No stream data will actually be sent across the isolate boundary until
+/// someone subscribes to the returned stream.
+Stream _deserializeStream(SendPort sendPort) {
+ return callbackStream(() {
+ var receivePort = new ReceivePort();
+ sendPort.send(receivePort.sendPort);
+ return receivePort.transform(
+ const StreamTransformer(_deserializeTransformer));
+ });
}
/// Converts a serializable map into an [AssetId].
@@ -244,23 +259,30 @@
/// Converts [asset] into a serializable map.
Map _serializeAsset(Asset asset) {
- // We can't send IsolateStreams (issue 12437), so instead we send a sink and
- // get the isolate to send us back another sink.
- var receivePort = new ReceivePort();
- receivePort.first.then((sendPort) {
- asset.read().listen(sendPort.send,
- onError: (error, stackTrace) {
- throw new UnimplementedError('Error during asset serialization');
- },
- onDone: () { sendPort.send('done'); });
- });
-
return {
'id': _serializeId(asset.id),
- 'sendPort': receivePort.sendPort
+ 'stream': _serializeStream(asset.read())
};
}
+/// Converts [stream] into a [SendPort] with which another isolate can request
+/// the data from [stream].
+SendPort _serializeStream(Stream stream) {
+ var receivePort = new ReceivePort();
+ receivePort.first.then((sendPort) {
+ stream.listen((data) => sendPort.send({'type': 'data', 'data': data}),
+ onDone: () => sendPort.send({'type': 'done'}),
+ onError: (error, stackTrace) {
+ sendPort.send({
+ 'type': 'error',
+ 'error': CrossIsolateException.serialize(error, stackTrace)
+ });
+ });
+ });
+
+ return receivePort.sendPort;
+}
+
/// Converts [id] into a serializable map.
Map _serializeId(AssetId id) => {'package': id.package, 'path': id.path};
@@ -288,33 +310,42 @@
};
}
-/// Sends the result of [future] through [port].
+/// Responds to a message sent by [_call].
///
-/// This should be received on the other end using [_receiveFuture]. It
-/// re-raises any exceptions on the other side as [CrossIsolateException]s.
-void _sendFuture(SendPort port, Future future) {
- future.then((result) {
- port.send({'success': result});
- }).catchError((error) {
+/// [wrappedMessage] is the raw message sent by [_call]. This unwraps it and
+/// passes the contents of the message to [callback], then sends the return
+/// value of [callback] back to [_call]. If [callback] returns a Future or
+/// throws an error, that will also be sent.
+void _respond(wrappedMessage, callback(message)) {
+ var replyTo = wrappedMessage['replyTo'];
+ new Future.sync(() => callback(wrappedMessage['message']))
+ .then((result) => replyTo.send({'type': 'success', 'value': result}))
+ .catchError((error, stackTrace) {
// TODO(nweiz): at least MissingInputException should be preserved here.
- port.send({'error': CrossIsolateException.serialize(error)});
+ replyTo.send({
+ 'type': 'error',
+ 'error': CrossIsolateException.serialize(error, stackTrace)
+ });
});
}
-/// Receives the result of [_sendFuture] from [portCall], which should be the
-/// return value of [SendPort.call].
+/// Wraps [message] and sends it across [port], then waits for a response which
+/// should be sent using [_respond].
///
-/// The [message] argument is modified to include the [replyTo] port.
-Future _callAndReceiveFuture(SendPort port, Map message) {
- var responsePort = new ReceivePort();
- message['replyTo'] = responsePort.sendPort;
- return new Future.sync(() {
- port.send(message);
- return responsePort.first.then((response) {
- if (response.containsKey('success')) return response['success'];
- return new Future.error(
- new CrossIsolateException.deserialize(response['error']));
- });
+/// The returned Future will complete to the value or error returned by
+/// [_respond].
+Future _call(SendPort port, message) {
+ var receivePort = new ReceivePort();
+ port.send({
+ 'message': message,
+ 'replyTo': receivePort.sendPort
+ });
+
+ return receivePort.first.then((response) {
+ if (response['type'] == 'success') return response['value'];
+ assert(response['type'] == 'error');
+ return new Future.error(
+ new CrossIsolateException.deserialize(response['error']));
});
}
@@ -392,6 +423,21 @@
});
return controller.stream;
}
+
+Stream callbackStream(Stream callback()) {
+ var subscription;
+ var controller;
+ controller = new StreamController(onListen: () {
+ subscription = callback().listen(controller.add,
+ onError: controller.addError,
+ onDone: controller.close);
+ },
+ onCancel: () => subscription.cancel(),
+ onPause: () => subscription.pause(),
+ onResume: () => subscription.resume(),
+ sync: true);
+ return controller.stream;
+}
""";
/// Load and return all transformers and groups from the library identified by
@@ -408,8 +454,11 @@
_TRANSFORMER_ISOLATE.replaceAll('<<HOST_AND_PORT>>', hostAndPort);
log.fine("Loading transformers from $assetId");
- return dart.runInIsolate(code).then((sendPort) {
- return _callAndReceiveFuture(sendPort, {
+ var port = new ReceivePort();
+ return dart.runInIsolate(code, port.sendPort)
+ .then((_) => port.first)
+ .then((sendPort) {
+ return _call(sendPort, {
'library': uri,
// TODO(nweiz): support non-JSON-encodable configuration maps.
'configuration': JSON.encode(id.configuration)
@@ -452,14 +501,14 @@
_toString = map['toString'];
Future<bool> isPrimary(Asset asset) {
- return _callAndReceiveFuture(_port, {
+ return _call(_port, {
'type': 'isPrimary',
'asset': _serializeAsset(asset)
});
}
Future apply(Transform transform) {
- return _callAndReceiveFuture(_port, {
+ return _call(_port, {
'type': 'apply',
'transform': _serializeTransform(transform)
});
@@ -494,16 +543,19 @@
/// Converts [transform] into a serializable map.
Map _serializeTransform(Transform transform) {
var receivePort = new ReceivePort();
- receivePort.listen((message) {
- var replyTo = message['replyTo'];
- if (message['type'] == 'getInput') {
- _sendFuture(replyTo, transform.getInput(_deserializeId(message['id']))
- .then(_serializeAsset));
- } else if (message['type'] == 'addOutput') {
- transform.addOutput(_deserializeAsset(message['output']));
- } else {
- assert(message['type'] == 'log');
+ receivePort.listen((wrappedMessage) {
+ _respond(wrappedMessage, (message) {
+ if (message['type'] == 'getInput') {
+ return transform.getInput(_deserializeId(message['id']))
+ .then(_serializeAsset);
+ }
+ if (message['type'] == 'addOutput') {
+ transform.addOutput(_deserializeAsset(message['output']));
+ return;
+ }
+
+ assert(message['type'] == 'log');
var method;
if (message['level'] == 'Info') {
method = transform.logger.info;
@@ -519,7 +571,7 @@
var span = message['span'] == null ? null :
_deserializeSpan(message['span']);
method(message['message'], asset: assetId, span: span);
- }
+ });
});
return {
@@ -528,29 +580,45 @@
};
}
-/// When the input receives a 'done' as data-event, transforms it to a
-/// done event and cancels the subscription.
-StreamSubscription doneTransformer(Stream input, bool cancelOnError) {
+/// Converts a serializable map into an [Asset].
+Asset _deserializeAsset(Map asset) {
+ return new Asset.fromStream(
+ _deserializeId(asset['id']),
+ _deserializeStream(asset['stream']));
+}
+
+/// A transformer that deserializes the values in a stream sent by
+/// [_serializeStream].
+StreamSubscription _deserializeTransformer(Stream input, bool cancelOnError) {
var subscription;
var transformed = input.transform(new StreamTransformer.fromHandlers(
handleData: (data, sink) {
- if (data == 'done') {
- sink.close();
- subscription.cancel();
- } else {
- sink.add(data);
- }
- }));
+ if (data['type'] == 'data') {
+ sink.add(data['data']);
+ } else if (data['type'] == 'error') {
+ sink.addError(CrossIsolateException.deserialize(data['error']));
+ } else {
+ assert(data['type'] == 'done');
+ sink.close();
+ subscription.cancel();
+ }
+ }));
subscription = transformed.listen(null, cancelOnError: cancelOnError);
return subscription;
}
-/// Converts a serializable map into an [Asset].
-Asset _deserializeAsset(Map asset) {
- var receivePort = new ReceivePort();
- asset['sendPort'].send(receivePort.sendPort);
- var stream = receivePort.transform(const StreamTransformer(doneTransformer));
- return new Asset.fromStream(_deserializeId(asset['id']), stream);
+/// Convert a [SendPort] whose opposite is waiting to send us a stream into a
+/// [Stream].
+///
+/// No stream data will actually be sent across the isolate boundary until
+/// someone subscribes to the returned stream.
+Stream _deserializeStream(SendPort sendPort) {
+ return callbackStream(() {
+ var receivePort = new ReceivePort();
+ sendPort.send(receivePort.sendPort);
+ return receivePort.transform(
+ const StreamTransformer(_deserializeTransformer));
+ });
}
/// Converts a serializable map into an [AssetId].
@@ -575,52 +643,68 @@
// efficiently serialized.
/// Converts [asset] into a serializable map.
Map _serializeAsset(Asset asset) {
- // We can't send IsolateStreams (issue 12437), so instead we send a sink and
- // get the isolate to send us back another sink.
- var receivePort = new ReceivePort();
- receivePort.first.then((sendPort) {
- asset.read().listen(sendPort.send,
- onError: (error, stackTrace) {
- throw new UnimplementedError('Error during asset serialization');
- },
- onDone: () { sendPort.send('done'); });
- });
-
return {
'id': _serializeId(asset.id),
- 'sendPort': receivePort.sendPort
+ 'stream': _serializeStream(asset.read())
};
}
+/// Converts [stream] into a [SendPort] with which another isolate can request
+/// the data from [stream].
+SendPort _serializeStream(Stream stream) {
+ var receivePort = new ReceivePort();
+ receivePort.first.then((sendPort) {
+ stream.listen((data) => sendPort.send({'type': 'data', 'data': data}),
+ onDone: () => sendPort.send({'type': 'done'}),
+ onError: (error, stackTrace) {
+ sendPort.send({
+ 'type': 'error',
+ 'error': CrossIsolateException.serialize(error, stackTrace)
+ });
+ });
+ });
+
+ return receivePort.sendPort;
+}
+
/// Converts [id] into a serializable map.
Map _serializeId(AssetId id) => {'package': id.package, 'path': id.path};
-/// Sends the result of [future] through [port].
+/// Responds to a message sent by [_call].
///
-/// This should be received on the other end using [_callAndReceiveFuture]. It
-/// re-raises any exceptions on the other side as [dart.CrossIsolateException]s.
-void _sendFuture(SendPort port, Future future) {
- future.then((result) {
- port.send({'success': result});
- }).catchError((error) {
+/// [wrappedMessage] is the raw message sent by [_call]. This unwraps it and
+/// passes the contents of the message to [callback], then sends the return
+/// value of [callback] back to [_call]. If [callback] returns a Future or
+/// throws an error, that will also be sent.
+void _respond(wrappedMessage, callback(message)) {
+ var replyTo = wrappedMessage['replyTo'];
+ new Future.sync(() => callback(wrappedMessage['message']))
+ .then((result) => replyTo.send({'type': 'success', 'value': result}))
+ .catchError((error, stackTrace) {
// TODO(nweiz): at least MissingInputException should be preserved here.
- port.send({'error': dart.CrossIsolateException.serialize(error)});
+ replyTo.send({
+ 'type': 'error',
+ 'error': dart.CrossIsolateException.serialize(error, stackTrace)
+ });
});
}
-/// Receives the result of [_sendFuture] from [portCall], which should be the
-/// return value of [SendPort.call].
+/// Wraps [message] and sends it across [port], then waits for a response which
+/// should be sent using [_respond].
///
-/// The [message] argument is modified to include the [replyTo] port.
-Future _callAndReceiveFuture(SendPort port, Map message) {
- var responsePort = new ReceivePort();
- message['replyTo'] = responsePort.sendPort;
- return new Future.sync(() {
- port.send(message);
- return responsePort.first.then((response) {
- if (response.containsKey('success')) return response['success'];
- return new Future.error(
- new dart.CrossIsolateException.deserialize(response['error']));
- });
+/// The returned Future will complete to the value or error returned by
+/// [_respond].
+Future _call(SendPort port, message) {
+ var receivePort = new ReceivePort();
+ port.send({
+ 'message': message,
+ 'replyTo': receivePort.sendPort
+ });
+
+ return receivePort.first.then((response) {
+ if (response['type'] == 'success') return response['value'];
+ assert(response['type'] == 'error');
+ return new Future.error(
+ new dart.CrossIsolateException.deserialize(response['error']));
});
}
diff --git a/sdk/lib/_internal/pub/lib/src/barback/pub_barback_logger.dart b/sdk/lib/_internal/pub/lib/src/barback/pub_barback_logger.dart
deleted file mode 100644
index 374e158..0000000
--- a/sdk/lib/_internal/pub/lib/src/barback/pub_barback_logger.dart
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library pub.pub_barback_logger;
-
-import 'package:barback/barback.dart';
-
-import '../log.dart' as log;
-
-/// A [BarbackLogger] that routes through pub's logging code.
-class PubBarbackLogger implements BarbackLogger {
- /// Since both [LogEntry] objects and the message itself often redundantly
- /// show the same context like the file where an error occurred, this tries
- /// to avoid showing redundant data in the entry.
- void logEntry(LogEntry entry) {
- messageMentions(String text) {
- return entry.message.toLowerCase().contains(text.toLowerCase());
- }
-
- var prefixParts = [];
-
- // Show the level (unless the message mentions it.)
- if (!messageMentions(entry.level.name)) {
- prefixParts.add("${entry.level} in");
- }
-
- // Show the transformer.
- prefixParts.add(entry.transform.transformer);
-
- // Mention the primary input of the transform unless the message seems to.
- if (!messageMentions(entry.transform.primaryId.path)) {
- prefixParts.add("on ${entry.transform.primaryId}");
- }
-
- // If the relevant asset isn't the primary input, mention it unless the
- // message already does.
- if (entry.asset != entry.transform.primaryId &&
- !messageMentions(entry.asset.path)) {
- prefixParts.add("with input ${entry.asset}");
- }
-
- var prefix = "[${prefixParts.join(' ')}]:";
- var message = entry.message;
- if (entry.span != null) {
- message = entry.span.getLocationMessage(entry.message);
- }
-
- switch (entry.level) {
- case LogLevel.ERROR:
- log.error("${log.red(prefix)}\n$message");
- break;
-
- case LogLevel.WARNING:
- log.warning("${log.yellow(prefix)}\n$message");
- break;
-
- case LogLevel.INFO:
- log.message("$prefix\n$message");
- break;
- }
- }
-}
diff --git a/sdk/lib/_internal/pub/lib/src/barback/watch_sources.dart b/sdk/lib/_internal/pub/lib/src/barback/sources.dart
similarity index 79%
rename from sdk/lib/_internal/pub/lib/src/barback/watch_sources.dart
rename to sdk/lib/_internal/pub/lib/src/barback/sources.dart
index 6a176aa..c85044b 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/watch_sources.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/sources.dart
@@ -2,7 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library pub.barback.watch_sources;
+library pub.barback.sources;
+
+import 'dart:async';
import 'package:barback/barback.dart';
import 'package:path/path.dart' as path;
@@ -15,24 +17,26 @@
/// Adds all of the source assets in the provided packages to barback and
/// then watches the public directories for changes.
-void watchSources(PackageGraph graph, Barback barback) {
- for (var package in graph.packages.values) {
- // Add the initial sources.
- barback.updateSources(_listAssets(graph.entrypoint, package));
-
+///
+/// Returns a Future that completes when the sources are loaded and the
+/// watchers are active.
+Future watchSources(PackageGraph graph, Barback barback) {
+ return Future.wait(graph.packages.values.map((package) {
// If this package comes from a cached source, its contents won't change so
// we don't need to monitor it. `packageId` will be null for the application
// package, since that's not locked.
var packageId = graph.lockFile.packages[package.name];
if (packageId != null &&
graph.entrypoint.cache.sources[packageId.source].shouldCache) {
- continue;
+ barback.updateSources(_listAssets(graph.entrypoint, package));
+ return new Future.value();
}
// Watch the visible package directories for changes.
- for (var name in _getPublicDirectories(graph.entrypoint, package)) {
+ return Future.wait(_getPublicDirectories(graph.entrypoint, package)
+ .map((name) {
var subdirectory = path.join(package.dir, name);
- if (!dirExists(subdirectory)) continue;
+ if (!dirExists(subdirectory)) return new Future.value();
// TODO(nweiz): close these watchers when [barback] is closed.
var watcher = new DirectoryWatcher(subdirectory);
@@ -50,7 +54,17 @@
barback.updateSources([id]);
}
});
- }
+ return watcher.ready;
+ })).then((_) {
+ barback.updateSources(_listAssets(graph.entrypoint, package));
+ });
+ }));
+}
+
+/// Adds all of the source assets in the provided packages to barback.
+void loadSources(PackageGraph graph, Barback barback) {
+ for (var package in graph.packages.values) {
+ barback.updateSources(_listAssets(graph.entrypoint, package));
}
}
diff --git a/sdk/lib/_internal/pub/lib/src/command.dart b/sdk/lib/_internal/pub/lib/src/command.dart
index e8b7ed0..167e2d1 100644
--- a/sdk/lib/_internal/pub/lib/src/command.dart
+++ b/sdk/lib/_internal/pub/lib/src/command.dart
@@ -78,7 +78,7 @@
help: 'Print usage information for this command.');
}
- void run(String cacheDir, ArgResults options) {
+ void run(String cacheDir, ArgResults options, List<String> arguments) {
commandOptions = options.command;
if (commandOptions['help']) {
@@ -111,7 +111,7 @@
log.error("""
This is an unexpected error. Please run
- pub --trace ${new Options().arguments.map((arg) => "'$arg'").join(' ')}
+ pub --trace ${arguments.map((arg) => "'$arg'").join(' ')}
and include the results in a bug report on http://dartbug.com/new.
""");
@@ -123,7 +123,8 @@
new Future.sync(() {
// Make sure there aren't unexpected arguments.
if (!takesArguments && commandOptions.rest.isNotEmpty) {
- log.error('Command does not take any arguments.');
+ log.error('Command "${commandOptions.name}" does not take any '
+ 'arguments.');
this.printUsage();
return flushThenExit(exit_codes.USAGE);
}
diff --git a/sdk/lib/_internal/pub/lib/src/command/build.dart b/sdk/lib/_internal/pub/lib/src/command/build.dart
index 04d8ea6..93dee74 100644
--- a/sdk/lib/_internal/pub/lib/src/command/build.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/build.dart
@@ -21,10 +21,10 @@
/// Handles the `build` pub command.
class BuildCommand extends PubCommand {
- final description = "Copy and compile all Dart entrypoints in the 'web' "
- "directory.";
- final usage = "pub build [options]";
- final aliases = const ["deploy", "settle-up"];
+ String get description =>
+ "Copy and compile all Dart entrypoints in the 'web' directory.";
+ String get usage => "pub build [options]";
+ List<String> get aliases => const ["deploy", "settle-up"];
// TODO(nweiz): make these configurable.
/// The path to the source directory of the application.
@@ -33,6 +33,14 @@
/// The path to the application's build output directory.
String get target => path.join(entrypoint.root.dir, 'build');
+ /// `true` if generated JavaScript should be minified.
+ bool get minify => commandOptions['minify'];
+
+ BuildCommand() {
+ commandParser.addFlag('minify', defaultsTo: true,
+ help: 'Minify generated JavaScript.');
+ }
+
Future onRun() {
if (!dirExists(source)) {
throw new ApplicationException("There is no '$source' directory.");
@@ -45,13 +53,14 @@
return entrypoint.ensureLockFileIsUpToDate().then((_) {
return entrypoint.loadPackageGraph();
}).then((graph) {
- dart2jsTransformer = new Dart2JSTransformer(graph);
+ dart2jsTransformer = new Dart2JSTransformer(graph, minify: minify);
// Since this server will only be hit by the transformer loader and isn't
// user-facing, just use an IPv4 address to avoid a weird bug on the
// OS X buildbots.
return barback.createServer("127.0.0.1", 0, graph,
- builtInTransformers: [dart2jsTransformer]);
+ builtInTransformers: [dart2jsTransformer],
+ watchForUpdates: false);
}).then((server) {
// Show in-progress errors, but not results. Those get handled implicitly
// by getAllAssets().
@@ -66,7 +75,7 @@
// in the generated JavaScript.
assets = assets.where((asset) => asset.id.extension != ".dart");
- return Future.forEach(assets, (asset) {
+ return Future.wait(assets.map((asset) {
// Figure out the output directory for the asset, which is the same
// as the path pub serve would use to serve it.
var relativeUrl = barback.idtoUrlPath(entrypoint.root.name, asset.id);
@@ -80,10 +89,11 @@
ensureDir(path.dirname(destPath));
// TODO(rnystrom): Should we display this to the user?
return createFileFromStream(asset.read(), destPath);
- }).then((_) {
+ })).then((_) {
_copyBrowserJsFiles(dart2jsTransformer.entrypoints);
// TODO(rnystrom): Should this count include the JS files?
- log.message("Built ${assets.length} files!");
+ log.message("Built ${assets.length} "
+ "${pluralize('file', assets.length)}!");
});
}).catchError((error) {
// If [getAllAssets()] throws a BarbackException, the error has already
@@ -100,8 +110,8 @@
/// directories next to each entrypoint in [entrypoints].
void _copyBrowserJsFiles(Iterable<AssetId> entrypoints) {
// Must depend on the browser package.
- if (!entrypoint.root.dependencies.any((dep) =>
- dep.name == 'browser' && dep.source == 'hosted')) {
+ if (!entrypoint.root.dependencies.any(
+ (dep) => dep.name == 'browser' && dep.source == 'hosted')) {
return;
}
diff --git a/sdk/lib/_internal/pub/lib/src/command/cache.dart b/sdk/lib/_internal/pub/lib/src/command/cache.dart
index 29ad06b..97e5dbe 100644
--- a/sdk/lib/_internal/pub/lib/src/command/cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/cache.dart
@@ -15,7 +15,7 @@
/// Handles the `cache` pub command.
class CacheCommand extends PubCommand {
String get description => "Inspect the system cache.";
- String get usage => 'pub cache list';
+ String get usage => "pub cache list";
bool get hidden => true;
bool get requiresEntrypoint => false;
bool get takesArguments => true;
diff --git a/sdk/lib/_internal/pub/lib/src/command/get.dart b/sdk/lib/_internal/pub/lib/src/command/get.dart
index 97db6c0..51c5f0a 100644
--- a/sdk/lib/_internal/pub/lib/src/command/get.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/get.dart
@@ -13,9 +13,8 @@
class GetCommand extends PubCommand {
String get description => "Get the current package's dependencies.";
String get usage => "pub get";
- final aliases = const ["install"];
-
- bool get isOffline => commandOptions['offline'];
+ List<String> get aliases => const ["install"];
+ bool get isOffline => commandOptions["offline"];
GetCommand() {
commandParser.addFlag('offline',
diff --git a/sdk/lib/_internal/pub/lib/src/command/help.dart b/sdk/lib/_internal/pub/lib/src/command/help.dart
index a69171d..f02841f 100644
--- a/sdk/lib/_internal/pub/lib/src/command/help.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/help.dart
@@ -14,7 +14,7 @@
/// Handles the `help` pub command.
class HelpCommand extends PubCommand {
String get description => "Display help information for Pub.";
- String get usage => 'pub help [command]';
+ String get usage => "pub help [command]";
bool get requiresEntrypoint => false;
bool get takesArguments => true;
diff --git a/sdk/lib/_internal/pub/lib/src/command/lish.dart b/sdk/lib/_internal/pub/lib/src/command/lish.dart
index b962f24..d5b6b50 100644
--- a/sdk/lib/_internal/pub/lib/src/command/lish.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/lish.dart
@@ -21,9 +21,9 @@
/// Handles the `lish` and `publish` pub commands.
class LishCommand extends PubCommand {
- final description = "Publish the current package to pub.dartlang.org.";
- final usage = "pub publish [options]";
- final aliases = const ["lish", "lush"];
+ String get description => "Publish the current package to pub.dartlang.org.";
+ String get usage => "pub publish [options]";
+ List<String> get aliases => const ["lish", "lush"];
/// The URL of the server to which to upload the package.
Uri get server => Uri.parse(commandOptions['server']);
diff --git a/sdk/lib/_internal/pub/lib/src/command/serve.dart b/sdk/lib/_internal/pub/lib/src/command/serve.dart
index bf2c571..0d7adfc 100644
--- a/sdk/lib/_internal/pub/lib/src/command/serve.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/serve.dart
@@ -22,7 +22,7 @@
/// Handles the `serve` pub command.
class ServeCommand extends PubCommand {
String get description => "Run a local web development server.";
- String get usage => 'pub serve';
+ String get usage => "pub serve";
PubPackageProvider _provider;
@@ -31,6 +31,9 @@
/// `true` if Dart entrypoints should be compiled to JavaScript.
bool get useDart2JS => commandOptions['dart2js'];
+ /// `true` if generated JavaScript should be minified.
+ bool get minify => commandOptions['minify'];
+
ServeCommand() {
commandParser.addOption('port', defaultsTo: '8080',
help: 'The port to listen on.');
@@ -45,6 +48,9 @@
commandParser.addFlag('dart2js', defaultsTo: true,
help: 'Compile Dart to JavaScript.');
+
+ commandParser.addFlag('minify', defaultsTo: false,
+ help: 'Minify generated JavaScript.');
}
Future onRun() {
@@ -64,7 +70,7 @@
var builtInTransformers = null;
if (useDart2JS) {
builtInTransformers = [
- new Dart2JSTransformer(graph),
+ new Dart2JSTransformer(graph, minify: minify),
new DartForwardingTransformer()
];
}
diff --git a/sdk/lib/_internal/pub/lib/src/command/upgrade.dart b/sdk/lib/_internal/pub/lib/src/command/upgrade.dart
index 2f0add7..306e027 100644
--- a/sdk/lib/_internal/pub/lib/src/command/upgrade.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/upgrade.dart
@@ -13,9 +13,9 @@
/// Handles the `upgrade` pub command.
class UpgradeCommand extends PubCommand {
String get description =>
- "Upgrade the current package's dependencies to latest versions.";
- String get usage => 'pub upgrade [dependencies...]';
- final aliases = const ["update"];
+ "Upgrade the current package's dependencies to latest versions.";
+ String get usage => "pub upgrade [dependencies...]";
+ List<String> get aliases => const ["update"];
bool get takesArguments => true;
bool get isOffline => commandOptions['offline'];
diff --git a/sdk/lib/_internal/pub/lib/src/command/uploader.dart b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
index 32e21a8..f9aa11d 100644
--- a/sdk/lib/_internal/pub/lib/src/command/uploader.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
@@ -19,9 +19,10 @@
/// Handles the `uploader` pub command.
class UploaderCommand extends PubCommand {
- final description = "Manage uploaders for a package on pub.dartlang.org.";
- final usage = "pub uploader [options] {add/remove} <email>";
- final requiresEntrypoint = false;
+ String get description =>
+ "Manage uploaders for a package on pub.dartlang.org.";
+ String get usage => "pub uploader [options] {add/remove} <email>";
+ bool get requiresEntrypoint => false;
bool get takesArguments => true;
/// The URL of the package hosting server.
diff --git a/sdk/lib/_internal/pub/lib/src/command/version.dart b/sdk/lib/_internal/pub/lib/src/command/version.dart
index 5fa6026..4855361 100644
--- a/sdk/lib/_internal/pub/lib/src/command/version.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/version.dart
@@ -12,11 +12,11 @@
/// Handles the `version` pub command.
class VersionCommand extends PubCommand {
- String get description => 'Print pub version.';
- String get usage => 'pub version';
+ String get description => "Print pub version.";
+ String get usage => "pub version";
bool get requiresEntrypoint => false;
Future onRun() {
- log.message('Pub ${sdk.version}');
+ log.message("Pub ${sdk.version}");
}
}
diff --git a/sdk/lib/_internal/pub/lib/src/dart.dart b/sdk/lib/_internal/pub/lib/src/dart.dart
index e0701a4..28902cc 100644
--- a/sdk/lib/_internal/pub/lib/src/dart.dart
+++ b/sdk/lib/_internal/pub/lib/src/dart.dart
@@ -30,12 +30,17 @@
/// If [inputProvider] and [diagnosticHandler] are omitted, uses a default
/// [compiler.CompilerInputProvider] that loads directly from the filesystem.
/// If either is provided, both must be.
-Future<String> compile(String entrypoint, {String packageRoot,
- bool toDart: false, compiler.CompilerInputProvider inputProvider,
+Future<String> compile(String entrypoint, {
+ String packageRoot,
+ bool toDart: false,
+ bool minify: true,
+ compiler.CompilerInputProvider inputProvider,
compiler.DiagnosticHandler diagnosticHandler}) {
return new Future.sync(() {
- var options = <String>['--categories=Client,Server', '--minify'];
+ var options = <String>['--categories=Client,Server'];
if (toDart) options.add('--output-type=dart');
+ if (minify) options.add('--minify');
+
if (packageRoot == null) {
packageRoot = path.join(path.dirname(entrypoint), 'packages');
}
@@ -57,7 +62,10 @@
path.toUri(entrypoint),
path.toUri(appendSlash(_libPath)),
path.toUri(appendSlash(packageRoot)),
- inputProvider, diagnosticHandler, options);
+ inputProvider, diagnosticHandler, options).then((js) {
+ if (js == null) throw new CompilerException(entrypoint);
+ return js;
+ });
});
}
@@ -83,27 +91,26 @@
/// Runs [code] in an isolate.
///
/// [code] should be the contents of a Dart entrypoint. It may contain imports;
-/// they will be resolved in the same context as the host isolate.
+/// they will be resolved in the same context as the host isolate. [message] is
+/// passed to the [main] method of the code being run; the caller is responsible
+/// for using this to establish communication with the isolate.
///
-/// Returns a Future that will resolve to a [SendPort] that will communicate to
-/// the spawned isolate once it's spawned. If the isolate fails to spawn, the
-/// Future will complete with an error.
-Future<SendPort> runInIsolate(String code) {
+/// Returns a Future that will fire when the isolate has been spawned. If the
+/// isolate fails to spawn, the Future will complete with an error.
+Future runInIsolate(String code, message) {
return withTempDir((dir) {
var dartPath = path.join(dir, 'runInIsolate.dart');
writeTextFile(dartPath, code, dontLogContents: true);
var port = new ReceivePort();
- var initialMessage = [path.toUri(dartPath).toString(), port.sendPort];
- var isolate = Isolate.spawn(_isolateBuffer, initialMessage);
- return isolate.then((_) {
- return port.first.then((response) {
- if (response.first == 'error') {
- return new Future.error(
- new CrossIsolateException.deserialize(response.last));
- }
-
- return response.last;
- });
+ return Isolate.spawn(_isolateBuffer, {
+ 'replyTo': port.sendPort,
+ 'uri': path.toUri(dartPath).toString(),
+ 'message': message
+ }).then((_) => port.first).then((response) {
+ if (response['type'] == 'success') return;
+ assert(response['type'] == 'error');
+ return new Future.error(
+ new CrossIsolateException.deserialize(response['error']));
});
});
}
@@ -114,18 +121,18 @@
/// [spawnUri] synchronously loads the file and its imports, which can deadlock
/// the host isolate if there's an HTTP import pointing at a server in the host.
/// Adding an additional isolate in the middle works around this.
-void _isolateBuffer(initialMessage) {
- var uri = initialMessage[0];
- var replyTo = initialMessage[1];
- try {
- // TODO(floitsch): If we do it right we shouldn't need to have a try/catch
- // and a catchError.
- Isolate.spawnUri(Uri.parse(uri), [], replyTo).catchError((e, stack) {
- replyTo.send(['error', CrossIsolateException.serialize(e, stack)]);
+void _isolateBuffer(message) {
+ var replyTo = message['replyTo'];
+ // TODO(floitsch): If we do it right we shouldn't need to capture synchronous
+ // errors.
+ new Future.sync(() {
+ return Isolate.spawnUri(Uri.parse(message['uri']), [], message['message']);
+ }).then((_) => replyTo.send({'type': 'success'})).catchError((e, stack) {
+ replyTo.send({
+ 'type': 'error',
+ 'error': CrossIsolateException.serialize(e, stack)
});
- } catch (e, stack) {
- replyTo.send(['error', CrossIsolateException.serialize(e, stack)]);
- }
+ });
}
/// An exception that was originally raised in another isolate.
@@ -175,3 +182,9 @@
String toString() => "$message\n$stackTrace";
}
+
+/// An exception thrown when dart2js generates compiler errors.
+class CompilerException extends ApplicationException {
+ CompilerException(String entrypoint)
+ : super('Failed to compile "$entrypoint".');
+}
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index 8a63d52..c17546e 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -393,6 +393,25 @@
return controller.stream;
}
+/// Returns a [Stream] that will emit the same values as the stream returned by
+/// [callback].
+///
+/// [callback] will only be called when the returned [Stream] gets a subscriber.
+Stream callbackStream(Stream callback()) {
+ var subscription;
+ var controller;
+ controller = new StreamController(onListen: () {
+ subscription = callback().listen(controller.add,
+ onError: controller.addError,
+ onDone: controller.close);
+ },
+ onCancel: () => subscription.cancel(),
+ onPause: () => subscription.pause(),
+ onResume: () => subscription.resume(),
+ sync: true);
+ return controller.stream;
+}
+
/// A regular expression matching a trailing CR character.
final _trailingCR = new RegExp(r"\r$");
diff --git a/sdk/lib/_internal/pub/test/build/compiles_dart_entrypoints_to_dart_and_js_test.dart b/sdk/lib/_internal/pub/test/build/compiles_dart_entrypoints_to_dart_and_js_test.dart
index 5d0b67a..f69676a 100644
--- a/sdk/lib/_internal/pub/test/build/compiles_dart_entrypoints_to_dart_and_js_test.dart
+++ b/sdk/lib/_internal/pub/test/build/compiles_dart_entrypoints_to_dart_and_js_test.dart
@@ -10,7 +10,8 @@
main() {
initConfig();
- // TODO(rnystrom): Should also add tests that other transformers work.
+ // TODO(rnystrom): Should also add tests that other transformers work
+ // (#14556).
integration("compiles Dart entrypoints to Dart and JS", () {
// Dart2js can take a long time to compile dart code, so we increase the
@@ -28,6 +29,8 @@
])
]).create();
+ // TODO(rnystrom): If we flesh out the command-line output, validate that
+ // here.
schedulePub(args: ["build"],
output: new RegExp(r"Built 2 files!"),
exitCode: 0);
diff --git a/sdk/lib/_internal/pub/test/build/minifies_js_by_default_test.dart b/sdk/lib/_internal/pub/test/build/minifies_js_by_default_test.dart
new file mode 100644
index 0000000..73f58dd
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/minifies_js_by_default_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+ initConfig();
+
+ integration("generates minified JavaScript", () {
+ // Dart2js can take a long time to compile dart code, so we increase the
+ // timeout to cope with that.
+ currentSchedule.timeout *= 3;
+
+ d.dir(appPath, [
+ d.appPubspec(),
+ d.dir('web', [
+ d.file('main.dart', 'void main() => print("hello");')
+ ])
+ ]).create();
+
+ schedulePub(args: ["build"],
+ output: new RegExp(r"Built 1 file!"),
+ exitCode: 0);
+
+ d.dir(appPath, [
+ d.dir('build', [
+ d.matcherFile('main.dart.js', isMinifiedDart2JSOutput)
+ ])
+ ]).validate();
+ });
+}
diff --git a/sdk/lib/_internal/pub/test/build/takes_flag_to_disable_minification_test.dart b/sdk/lib/_internal/pub/test/build/takes_flag_to_disable_minification_test.dart
new file mode 100644
index 0000000..fc4bfd0
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/takes_flag_to_disable_minification_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+ initConfig();
+
+ integration("takes a flag to generate unminified JavaScript", () {
+ // Dart2js can take a long time to compile dart code, so we increase the
+ // timeout to cope with that.
+ currentSchedule.timeout *= 3;
+
+ d.dir(appPath, [
+ d.appPubspec(),
+ d.dir('web', [
+ d.file('main.dart', 'void main() => print("hello");')
+ ])
+ ]).create();
+
+ schedulePub(args: ["build", "--no-minify"],
+ output: new RegExp(r"Built 1 file!"),
+ exitCode: 0);
+
+ d.dir(appPath, [
+ d.dir('build', [
+ d.matcherFile('main.dart.js', isUnminifiedDart2JSOutput)
+ ])
+ ]).validate();
+ });
+}
diff --git a/sdk/lib/_internal/pub/test/pub_test.dart b/sdk/lib/_internal/pub/test/pub_test.dart
index ed2507d..cf0749c 100644
--- a/sdk/lib/_internal/pub/test/pub_test.dart
+++ b/sdk/lib/_internal/pub/test/pub_test.dart
@@ -123,7 +123,7 @@
-h, --help Print usage information for this command.
''',
error: '''
- Command does not take any arguments.
+ Command "version" does not take any arguments.
''',
exitCode: 64);
});
diff --git a/sdk/lib/_internal/pub/test/serve/utils.dart b/sdk/lib/_internal/pub/test/serve/utils.dart
index 6ff10c0..1013aec 100644
--- a/sdk/lib/_internal/pub/test/serve/utils.dart
+++ b/sdk/lib/_internal/pub/test/serve/utils.dart
@@ -100,19 +100,17 @@
///
/// Returns the `pub serve` process.
ScheduledProcess startPubServe({bool shouldGetFirst: false,
- bool dart2js: true}) {
+ Iterable<String> args}) {
// Use port 0 to get an ephemeral port.
- var args = ["serve", "--port=0", "--hostname=127.0.0.1"];
+ var pubArgs = ["serve", "--port=0", "--hostname=127.0.0.1"];
- if (!dart2js) args.add("--no-dart2js");
+ if (args != null) pubArgs.addAll(args);
// Dart2js can take a long time to compile dart code, so we increase the
// timeout to cope with that.
- if (dart2js) {
- currentSchedule.timeout = new Duration(seconds: 15);
- }
+ currentSchedule.timeout = new Duration(seconds: 15);
- _pubServer = startPub(args: args);
+ _pubServer = startPub(args: pubArgs);
currentSchedule.onComplete.schedule(() {
if (_webSocket != null) {
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index 2c85e8c..5da6eb6 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -46,10 +46,6 @@
unittestConfiguration.timeout = null;
}
-/// Returns whether we're running on a Dart build bot.
-bool get runningOnBuildbot =>
- Platform.environment.containsKey('BUILDBOT_BUILDERNAME');
-
/// The current [HttpServer] created using [serve].
var _server;
@@ -60,6 +56,16 @@
/// The cached value for [_portCompleter].
Completer<int> _portCompleterCache;
+/// A [Matcher] that matches JavaScript generated by dart2js with minification
+/// enabled.
+Matcher isMinifiedDart2JSOutput =
+ isNot(contains("// The code supports the following hooks"));
+
+/// A [Matcher] that matches JavaScript generated by dart2js with minification
+/// disabled.
+Matcher isUnminifiedDart2JSOutput =
+ contains("// The code supports the following hooks");
+
/// The completer for [port].
Completer<int> get _portCompleter {
if (_portCompleterCache != null) return _portCompleterCache;
@@ -582,14 +588,13 @@
/// The path to the `packages` directory from which pub loads its dependencies.
String get _packageRoot => path.absolute(Platform.packageRoot);
-/// Skips the current test if Git is not installed. This validates that the
-/// current test is running on a buildbot in which case we expect git to be
-/// installed. If we are not running on the buildbot, we will instead see if
-/// git is installed and skip the test if not. This way, users don't need to
-/// have git installed to run the tests locally (unless they actually care
-/// about the pub git tests).
+/// Fails the current test if Git is not installed.
///
-/// This will also increase the [Schedule] timeout to 30 seconds on Windows,
+/// We require machines running these tests to have git installed. This
+/// validation gives an easier-to-understand error when that requirement isn't
+/// met than just failing in the middle of a test when pub invokes git.
+///
+/// This also increases the [Schedule] timeout to 30 seconds on Windows,
/// where Git runs really slowly.
void ensureGit() {
if (Platform.operatingSystem == "windows") {
@@ -598,9 +603,9 @@
schedule(() {
return gitlib.isInstalled.then((installed) {
- if (installed) return;
- if (runningOnBuildbot) return;
- currentSchedule.abort();
+ if (!installed) {
+ throw new Exception("Git must be installed to run this test.");
+ }
});
}, 'ensuring that Git is installed');
}
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_if_disabled_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_if_disabled_test.dart
index fc90667..848ae1b 100644
--- a/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_if_disabled_test.dart
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/does_not_compile_if_disabled_test.dart
@@ -18,7 +18,7 @@
])
]).create();
- startPubServe(dart2js: false);
+ startPubServe(args: ["--no-dart2js"]);
requestShould404("main.dart.js");
endPubServe();
});
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/takes_flag_minify_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/takes_flag_minify_test.dart
new file mode 100644
index 0000000..e385237
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/takes_flag_minify_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS d.file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+import '../../serve/utils.dart';
+
+main() {
+ initConfig();
+ integration("generates minified JS if the flag is set", () {
+ d.dir(appPath, [
+ d.appPubspec(),
+ d.dir("web", [
+ d.file("main.dart", "void main() => print('hello');")
+ ])
+ ]).create();
+
+ startPubServe(args: ["--minify"]);
+ requestShouldSucceed("main.dart.js", isMinifiedDart2JSOutput);
+ endPubServe();
+ });
+}
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/unminified_by_default_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/unminified_by_default_test.dart
new file mode 100644
index 0000000..3f0bb23
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/unminified_by_default_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS d.file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+import '../../serve/utils.dart';
+
+main() {
+ initConfig();
+ integration("generates unminified JS by default", () {
+ d.dir(appPath, [
+ d.appPubspec(),
+ d.dir("web", [
+ d.file("main.dart", "void main() => print('hello');")
+ ])
+ ]).create();
+
+ startPubServe();
+ requestShouldSucceed("main.dart.js", isUnminifiedDart2JSOutput);
+ endPubServe();
+ });
+}
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index f15073f..a565220 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -10,7 +10,7 @@
* [dart:async section of the language tour]
* (https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-asynchronous-programming).
*
- * ## Other Resources
+ * ## Other resources
*
* * [Using Future Based APIs]
* (https://www.dartlang.org/articles/using-future-based-apis/): A first look at
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index 2e43669..59e199c 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -183,9 +183,9 @@
return subscription;
}
- void _recordCancel(_BroadcastSubscription<T> subscription) {
+ Future _recordCancel(_BroadcastSubscription<T> subscription) {
// If already removed by the stream, don't remove it again.
- if (identical(subscription._next, subscription)) return;
+ if (identical(subscription._next, subscription)) return null;
assert(!identical(subscription._next, subscription));
if (subscription._isFiring) {
subscription._setRemoveAfterFiring();
@@ -238,10 +238,10 @@
Future get done => _ensureDoneFuture();
- Future addStream(Stream<T> stream) {
+ Future addStream(Stream<T> stream, {bool cancelOnError: true}) {
if (!_mayAddEvent) throw _addEventError();
_state |= _STATE_ADDSTREAM;
- _addStreamState = new _AddStreamState(this, stream);
+ _addStreamState = new _AddStreamState(this, stream, cancelOnError);
return _addStreamState.addStreamFuture;
}
@@ -472,7 +472,7 @@
void _resume(_) {
if (_pauseCount > 0) _pauseCount--;
}
- void cancel() {}
+ Future cancel() { return new _Future.immediate(null); }
bool get isPaused => _pauseCount > 0;
Future asFuture([Object value]) => new _Future();
}
diff --git a/sdk/lib/async/schedule_microtask.dart b/sdk/lib/async/schedule_microtask.dart
index dca72df..11eb778 100644
--- a/sdk/lib/async/schedule_microtask.dart
+++ b/sdk/lib/async/schedule_microtask.dart
@@ -46,7 +46,7 @@
* callbacks through this method. For example the following program runs
* the callbacks without ever giving the Timer callback a chance to execute:
*
- * Timer.run(() { print("executed"); }); // Will never be executed,
+ * Timer.run(() { print("executed"); }); // Will never be executed.
* foo() {
* scheduleMicrotask(foo); // Schedules [foo] in front of other events.
* }
@@ -54,7 +54,7 @@
* foo();
* }
*
- * ## Other Resources
+ * ## Other resources
*
* * [The Event Loop and Dart](https://www.dartlang.org/articles/event-loop/):
* Learn how Dart handles the event queue and microtask queue, so you can write
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 6672f47..48e70f1 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1030,7 +1030,16 @@
* done.
*/
abstract class StreamConsumer<S> {
+ /**
+ * Consumes the elements of [stream].
+ *
+ * Listens on [stream] and does something for each event.
+ *
+ * The consumer may stop listening after an error, or it may consume
+ * all the errors and only stop at a done event.
+ */
Future addStream(Stream<S> stream);
+
Future close();
}
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index ba3fd61..b40ffb5 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -167,6 +167,26 @@
* allows.
*/
void addError(Object error, [StackTrace stackTrace]);
+
+ /**
+ * Receives events from [source] and puts them into this controller's stream.
+ *
+ * Returns a future which completes when the source stream is done.
+ *
+ * Events must not be added directly to this controller using [add],
+ * [addError], [close] or [addStream], until the returned future
+ * is complete.
+ *
+ * Data and error events are forwarded to this controller's stream. A done
+ * event on the source will end the `addStream` operation and complete the
+ * returned future.
+ *
+ * If [cancelOnError] is true, only the first error on [source] is
+ * forwarded to the controller's stream, and the `addStream` ends
+ * after this. If [cancelOnError] is false, all errors are forwarded
+ * and only a done event will end the `addStream`.
+ */
+ Future addStream(Stream<T> source, {bool cancelOnError: true});
}
@@ -344,11 +364,14 @@
}
// StreamSink interface.
- Future addStream(Stream<T> source) {
+ Future addStream(Stream<T> source, { bool cancelOnError: true }) {
if (!_mayAddEvent) throw _badEventState();
if (_isCanceled) return new _Future.immediate(null);
_StreamControllerAddStreamState addState =
- new _StreamControllerAddStreamState(this, _varData, source);
+ new _StreamControllerAddStreamState(this,
+ _varData,
+ source,
+ cancelOnError);
_varData = addState;
_state |= _STATE_ADDSTREAM;
return addState.addStreamFuture;
@@ -454,6 +477,7 @@
if (_isAddingStream) {
_StreamControllerAddStreamState addState = _varData;
addState.varData = subscription;
+ addState.resume();
} else {
_varData = subscription;
}
@@ -633,7 +657,7 @@
/** A class that exposes only the [StreamSink] interface of an object. */
class _StreamSinkWrapper<T> implements StreamSink<T> {
- final StreamSink _target;
+ final StreamController _target;
_StreamSinkWrapper(this._target);
void add(T data) { _target.add(data); }
void addError(Object error, [StackTrace stackTrace]) {
@@ -649,17 +673,25 @@
*/
class _AddStreamState<T> {
// [_Future] returned by call to addStream.
- _Future addStreamFuture;
+ final _Future addStreamFuture;
// Subscription on stream argument to addStream.
- StreamSubscription addSubscription;
+ final StreamSubscription addSubscription;
- _AddStreamState(_EventSink<T> controller, Stream source)
+ _AddStreamState(_EventSink<T> controller, Stream source, bool cancelOnError)
: addStreamFuture = new _Future(),
addSubscription = source.listen(controller._add,
- onError: controller._addError,
+ onError: cancelOnError
+ ? makeErrorHandler(controller)
+ : controller._addError,
onDone: controller._close,
- cancelOnError: true);
+ cancelOnError: cancelOnError);
+
+ static makeErrorHandler(_EventSink controller) =>
+ (e, StackTrace s) {
+ controller._addError(e, s);
+ controller._close();
+ };
void pause() {
addSubscription.pause();
@@ -687,7 +719,9 @@
_StreamControllerAddStreamState(_StreamController controller,
this.varData,
- Stream source) : super(controller, source) {
+ Stream source,
+ bool cancelOnError)
+ : super(controller, source, cancelOnError) {
if (controller.isPaused) {
addSubscription.pause();
}
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index bf7c8f0..e7ccead 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -488,6 +488,7 @@
/** Stream that generates its own events. */
class _GeneratedStreamImpl<T> extends _StreamImpl<T> {
final _EventGenerator _pending;
+ bool _isUsed = false;
/**
* Initializes the stream to have only the events provided by a
* [_PendingEvents].
@@ -497,6 +498,8 @@
_GeneratedStreamImpl(this._pending);
StreamSubscription _createSubscription(bool cancelOnError) {
+ if (_isUsed) throw new StateError("Stream has already been listened to.");
+ _isUsed = true;
_BufferingStreamSubscription<T> subscription =
new _BufferingStreamSubscription(cancelOnError);
subscription._setPendingEvents(_pending());
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index 5924084..ba286b4 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -147,12 +147,13 @@
_subscription.resume();
}
- void _onCancel() {
+ Future _onCancel() {
if (_subscription != null) {
StreamSubscription subscription = _subscription;
_subscription = null;
subscription.cancel();
}
+ return null;
}
// Methods used as listener on source subscription.
@@ -349,7 +350,7 @@
_remaining--;
return;
}
- return sink._add(inputEvent);
+ sink._add(inputEvent);
}
}
diff --git a/sdk/lib/async/stream_transformers.dart b/sdk/lib/async/stream_transformers.dart
index 1947235..c40ce7d 100644
--- a/sdk/lib/async/stream_transformers.dart
+++ b/sdk/lib/async/stream_transformers.dart
@@ -102,12 +102,13 @@
if (_isSubscribed) _subscription.resume();
}
- void _onCancel() {
+ Future _onCancel() {
if (_isSubscribed) {
StreamSubscription subscription = _subscription;
_subscription = null;
subscription.cancel();
}
+ return null;
}
void _handleData(S data) {
@@ -199,7 +200,7 @@
*
* This way we can reuse the code from [_StreamSinkTransformer].
*/
-class _HandlerEventSink<S, T> implements EventSink<T> {
+class _HandlerEventSink<S, T> implements EventSink<S> {
final _TransformDataHandler<S, T> _handleData;
final _TransformErrorHandler<T> _handleError;
final _TransformDoneHandler<T> _handleDone;
diff --git a/sdk/lib/collection/linked_list.dart b/sdk/lib/collection/linked_list.dart
index cd89e78..fb5ac89 100644
--- a/sdk/lib/collection/linked_list.dart
+++ b/sdk/lib/collection/linked_list.dart
@@ -147,7 +147,7 @@
}
-class _LinkedListIterator<E extends LinkedListEntry>
+class _LinkedListIterator<E extends LinkedListEntry<E>>
implements Iterator<E> {
final LinkedList<E> _list;
final int _modificationCount;
@@ -185,7 +185,7 @@
/**
* Entry element for a [LinkedList]. Any entry must extend this class.
*/
-abstract class LinkedListEntry<E extends LinkedListEntry>
+abstract class LinkedListEntry<E extends LinkedListEntry<E>>
implements _LinkedListLink {
LinkedList<E> _list;
_LinkedListLink _next;
diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart
index ad5afc3..80425fd 100644
--- a/sdk/lib/convert/chunked_conversion.dart
+++ b/sdk/lib/convert/chunked_conversion.dart
@@ -80,7 +80,7 @@
_chunkedSink =
converter.startChunkedConversion(new _EventSinkAdapter(sink));
- void add(T o) => _chunkedSink.add(o);
+ void add(S o) => _chunkedSink.add(o);
void addError(Object error, [StackTrace stackTrace]) {
_eventSink.addError(error, stackTrace);
}
diff --git a/sdk/lib/core/annotations.dart b/sdk/lib/core/annotations.dart
index 7bdc5f5..a0f70a4 100644
--- a/sdk/lib/core/annotations.dart
+++ b/sdk/lib/core/annotations.dart
@@ -89,16 +89,21 @@
* instance fields, where it means that the implicit getter and setter of the
* field is marked as overriding, but the field itself is not.
*
- * A tool may report if no declaration of an annotated member is inherited by
- * the class from either a superclass or an interface.
- *
- * The intent of the "override" notation is to catch situations where a
+ * The intent of the "@override" notation is to catch situations where a
* superclass renames a member, and an independent subclass which used to
* override the member, could silently continue working using the
* superclass implementation.
*
- * The "@override" annotation is intentionally not used in the core libraries.
- * It is intended for the editor, or similar tools, to support user written
- * code.
+ * The editor, or a similar tool aimed at the programmer, may report if no
+ * declaration of an annotated member is inherited by the class from either a
+ * superclass or an interface.
+ *
+ * Use the "@override" annotation judiciously and only for methods where
+ * the superclass is not under the programmer's control, the superclass is in a
+ * different library or package, and it is not considered stable.
+ * In any case, the use of "@override" is optional.
+ *
+ * For example, the annotation is intentionally not used in the Dart platform
+ * libraries, since they only depend on themselves.
*/
const override = const _Override();
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 6ef98dd..2331425 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -38,7 +38,7 @@
import 'dart:web_gl' as gl;
import 'dart:web_sql';
import 'dart:_isolate_helper' show IsolateNatives;
-import 'dart:_foreign_helper' show JS;
+import 'dart:_foreign_helper' show JS, JS_INTERCEPTOR_CONSTANT;
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -57,7 +57,7 @@
import 'dart:_interceptors' show
Interceptor, JSExtendableArray, findInterceptorConstructorForType,
findConstructorForNativeSubclassType, getNativeInterceptor,
- setDispatchProperty, findInterceptorForType;
+ setDispatchProperty;
export 'dart:math' show Rectangle, Point;
@@ -7777,7 +7777,7 @@
@DocsEditable()
@DomName('DOMStringList')
-class DomStringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements JavaScriptIndexingBehavior, List native "DOMStringList" {
+class DomStringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements JavaScriptIndexingBehavior, List<String> native "DOMStringList" {
// To suppress missing implicit constructor warnings.
factory DomStringList._() { throw new UnsupportedError("Not supported"); }
@@ -8372,7 +8372,7 @@
// ElementList as there are valid cases where a NodeList JavaScript object
// contains Node objects that are not Elements.
class _FrozenElementList<T extends Element> extends ListBase<T>
- implements ElementList, NodeListWrapper {
+ implements ElementList<T>, NodeListWrapper {
final List<Node> _nodeList;
// The subset of _nodeList that are Elements.
List<Element> _elementList;
@@ -11241,7 +11241,7 @@
@DocsEditable()
@DomName('FileList')
-class FileList extends Interceptor with ListMixin<File>, ImmutableListMixin<File> implements JavaScriptIndexingBehavior, List native "FileList" {
+class FileList extends Interceptor with ListMixin<File>, ImmutableListMixin<File> implements JavaScriptIndexingBehavior, List<File> native "FileList" {
// To suppress missing implicit constructor warnings.
factory FileList._() { throw new UnsupportedError("Not supported"); }
@@ -12235,7 +12235,7 @@
@DocsEditable()
@DomName('HTMLCollection')
-class HtmlCollection extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List native "HTMLCollection" {
+class HtmlCollection extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "HTMLCollection" {
// To suppress missing implicit constructor warnings.
factory HtmlCollection._() { throw new UnsupportedError("Not supported"); }
@@ -12630,7 +12630,7 @@
* * [Using XMLHttpRequest](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest)
*/
@DomName('XMLHttpRequest')
-class HttpRequest extends XmlHttpRequestEventTarget native "XMLHttpRequest" {
+class HttpRequest extends HttpRequestEventTarget native "XMLHttpRequest" {
/**
* Creates a URL get request for the specified [url].
@@ -13184,10 +13184,100 @@
@DocsEditable()
+@DomName('XMLHttpRequestEventTarget')
+@Experimental() // untriaged
+class HttpRequestEventTarget extends EventTarget native "XMLHttpRequestEventTarget" {
+ // To suppress missing implicit constructor warnings.
+ factory HttpRequestEventTarget._() { throw new UnsupportedError("Not supported"); }
+
+ @DomName('XMLHttpRequestEventTarget.abortEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> abortEvent = const EventStreamProvider<ProgressEvent>('abort');
+
+ @DomName('XMLHttpRequestEventTarget.errorEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> errorEvent = const EventStreamProvider<ProgressEvent>('error');
+
+ @DomName('XMLHttpRequestEventTarget.loadEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> loadEvent = const EventStreamProvider<ProgressEvent>('load');
+
+ @DomName('XMLHttpRequestEventTarget.loadendEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> loadEndEvent = const EventStreamProvider<ProgressEvent>('loadend');
+
+ @DomName('XMLHttpRequestEventTarget.loadstartEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> loadStartEvent = const EventStreamProvider<ProgressEvent>('loadstart');
+
+ @DomName('XMLHttpRequestEventTarget.progressEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
+
+ @DomName('XMLHttpRequestEventTarget.timeoutEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> timeoutEvent = const EventStreamProvider<ProgressEvent>('timeout');
+
+ @DomName('XMLHttpRequestEventTarget.onabort')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onAbort => abortEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onerror')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onError => errorEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onload')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onLoad => loadEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onloadend')
+ @DocsEditable()
+ @SupportedBrowser(SupportedBrowser.CHROME)
+ @SupportedBrowser(SupportedBrowser.FIREFOX)
+ @SupportedBrowser(SupportedBrowser.IE, '10')
+ @SupportedBrowser(SupportedBrowser.SAFARI)
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onLoadEnd => loadEndEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onloadstart')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onLoadStart => loadStartEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onprogress')
+ @DocsEditable()
+ @SupportedBrowser(SupportedBrowser.CHROME)
+ @SupportedBrowser(SupportedBrowser.FIREFOX)
+ @SupportedBrowser(SupportedBrowser.IE, '10')
+ @SupportedBrowser(SupportedBrowser.SAFARI)
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.ontimeout')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onTimeout => timeoutEvent.forTarget(this);
+}
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+@DocsEditable()
@DomName('XMLHttpRequestUpload')
// http://xhr.spec.whatwg.org/#xmlhttprequestupload
@Experimental()
-class HttpRequestUpload extends XmlHttpRequestEventTarget native "XMLHttpRequestUpload,XMLHttpRequestEventTarget" {
+class HttpRequestUpload extends HttpRequestEventTarget native "XMLHttpRequestUpload,XMLHttpRequestEventTarget" {
// To suppress missing implicit constructor warnings.
factory HttpRequestUpload._() { throw new UnsupportedError("Not supported"); }
}
@@ -16512,7 +16602,7 @@
@DocsEditable()
@DomName('MimeTypeArray')
@Experimental() // non-standard
-class MimeTypeArray extends Interceptor with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements JavaScriptIndexingBehavior, List native "MimeTypeArray" {
+class MimeTypeArray extends Interceptor with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements JavaScriptIndexingBehavior, List<MimeType> native "MimeTypeArray" {
// To suppress missing implicit constructor warnings.
factory MimeTypeArray._() { throw new UnsupportedError("Not supported"); }
@@ -17816,7 +17906,7 @@
@DocsEditable()
@DomName('NodeList')
-class NodeList extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List native "NodeList,RadioNodeList" {
+class NodeList extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "NodeList,RadioNodeList" {
// To suppress missing implicit constructor warnings.
factory NodeList._() { throw new UnsupportedError("Not supported"); }
@@ -18898,7 +18988,7 @@
@DocsEditable()
@DomName('PluginArray')
@Experimental() // non-standard
-class PluginArray extends Interceptor with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements JavaScriptIndexingBehavior, List native "PluginArray" {
+class PluginArray extends Interceptor with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements JavaScriptIndexingBehavior, List<Plugin> native "PluginArray" {
// To suppress missing implicit constructor warnings.
factory PluginArray._() { throw new UnsupportedError("Not supported"); }
@@ -20869,7 +20959,7 @@
@DomName('SourceBufferList')
// https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#sourcebufferlist
@Experimental()
-class SourceBufferList extends EventTarget with ListMixin<SourceBuffer>, ImmutableListMixin<SourceBuffer> implements JavaScriptIndexingBehavior, List native "SourceBufferList" {
+class SourceBufferList extends EventTarget with ListMixin<SourceBuffer>, ImmutableListMixin<SourceBuffer> implements JavaScriptIndexingBehavior, List<SourceBuffer> native "SourceBufferList" {
// To suppress missing implicit constructor warnings.
factory SourceBufferList._() { throw new UnsupportedError("Not supported"); }
@@ -21048,7 +21138,7 @@
@DomName('SpeechGrammarList')
// https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#dfn-speechgrammarlist
@Experimental()
-class SpeechGrammarList extends Interceptor with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements JavaScriptIndexingBehavior, List native "SpeechGrammarList" {
+class SpeechGrammarList extends Interceptor with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements JavaScriptIndexingBehavior, List<SpeechGrammar> native "SpeechGrammarList" {
// To suppress missing implicit constructor warnings.
factory SpeechGrammarList._() { throw new UnsupportedError("Not supported"); }
@@ -22792,7 +22882,7 @@
@DomName('TextTrackCueList')
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttrackcuelist
@Experimental()
-class TextTrackCueList extends Interceptor with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements JavaScriptIndexingBehavior, List native "TextTrackCueList" {
+class TextTrackCueList extends Interceptor with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List<TextTrackCue>, JavaScriptIndexingBehavior native "TextTrackCueList" {
// To suppress missing implicit constructor warnings.
factory TextTrackCueList._() { throw new UnsupportedError("Not supported"); }
@@ -22861,7 +22951,7 @@
@DomName('TextTrackList')
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttracklist
@Experimental()
-class TextTrackList extends EventTarget with ListMixin<TextTrack>, ImmutableListMixin<TextTrack> implements JavaScriptIndexingBehavior, List native "TextTrackList" {
+class TextTrackList extends EventTarget with ListMixin<TextTrack>, ImmutableListMixin<TextTrack> implements JavaScriptIndexingBehavior, List<TextTrack> native "TextTrackList" {
// To suppress missing implicit constructor warnings.
factory TextTrackList._() { throw new UnsupportedError("Not supported"); }
@@ -23165,7 +23255,7 @@
@DomName('TouchList')
// http://www.w3.org/TR/touch-events/, http://www.chromestatus.com/features
@Experimental()
-class TouchList extends Interceptor with ListMixin<Touch>, ImmutableListMixin<Touch> implements JavaScriptIndexingBehavior, List native "TouchList" {
+class TouchList extends Interceptor with ListMixin<Touch>, ImmutableListMixin<Touch> implements JavaScriptIndexingBehavior, List<Touch> native "TouchList" {
/// NB: This constructor likely does not work as you might expect it to! This
/// constructor will simply fail (returning null) if you are not on a device
/// with touch enabled. See dartbug.com/8314.
@@ -24182,6 +24272,33 @@
@DocsEditable()
+/**
+ * Top-level container for the current browser tab or window.
+ *
+ * In a web browser, each window has a [Window] object, but within the context
+ * of a script, a [Window] object represents only the current window. In
+ * addition to the open window, each window, tab, and iframe has its own
+ * [Window] object. A [Window] contains a [Document] object, which contains this
+ * web page's content.
+ *
+ * Use `window` to access properties of the current window. For example:
+ *
+ * // Draw a scene when the window repaints.
+ * drawScene(num delta) {...}
+ * window.animationFrame.then(drawScene);.
+ *
+ * // Write to the console.
+ * window.console.log('Jinkies!');
+ * window.console.error('Jeepers!');
+ *
+ * **Note:** This class represents the current window, whereas [WindowBase] is
+ * a representation of any window, including other tabs, windows, and frames.
+ *
+ * ## Other resources
+ *
+ * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
+ * * [Window](http://www.w3.org/TR/Window/) from the W3C.
+ */
@DomName('Window')
class Window extends EventTarget implements WindowBase, _WindowTimers, WindowBase64 native "Window,DOMWindow" {
@@ -25699,96 +25816,6 @@
@DocsEditable()
-@DomName('XMLHttpRequestEventTarget')
-@Experimental() // untriaged
-class XmlHttpRequestEventTarget extends EventTarget native "XMLHttpRequestEventTarget" {
- // To suppress missing implicit constructor warnings.
- factory XmlHttpRequestEventTarget._() { throw new UnsupportedError("Not supported"); }
-
- @DomName('XMLHttpRequestEventTarget.abortEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> abortEvent = const EventStreamProvider<ProgressEvent>('abort');
-
- @DomName('XMLHttpRequestEventTarget.errorEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> errorEvent = const EventStreamProvider<ProgressEvent>('error');
-
- @DomName('XMLHttpRequestEventTarget.loadEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> loadEvent = const EventStreamProvider<ProgressEvent>('load');
-
- @DomName('XMLHttpRequestEventTarget.loadendEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> loadEndEvent = const EventStreamProvider<ProgressEvent>('loadend');
-
- @DomName('XMLHttpRequestEventTarget.loadstartEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> loadStartEvent = const EventStreamProvider<ProgressEvent>('loadstart');
-
- @DomName('XMLHttpRequestEventTarget.progressEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
-
- @DomName('XMLHttpRequestEventTarget.timeoutEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> timeoutEvent = const EventStreamProvider<ProgressEvent>('timeout');
-
- @DomName('XMLHttpRequestEventTarget.onabort')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onAbort => abortEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onerror')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onError => errorEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onload')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onLoad => loadEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onloadend')
- @DocsEditable()
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.FIREFOX)
- @SupportedBrowser(SupportedBrowser.IE, '10')
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental() // untriaged
- Stream<ProgressEvent> get onLoadEnd => loadEndEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onloadstart')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onLoadStart => loadStartEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onprogress')
- @DocsEditable()
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.FIREFOX)
- @SupportedBrowser(SupportedBrowser.IE, '10')
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental() // untriaged
- Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.ontimeout')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onTimeout => timeoutEvent.forTarget(this);
-}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-
-@DocsEditable()
@DomName('XMLSerializer')
// http://domparsing.spec.whatwg.org/#the-xmlserializer-interface
@deprecated // stable
@@ -26101,7 +26128,7 @@
@DocsEditable()
@DomName('ClientRectList')
-class _ClientRectList extends Interceptor with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements JavaScriptIndexingBehavior, List native "ClientRectList" {
+class _ClientRectList extends Interceptor with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements List<Rectangle>, JavaScriptIndexingBehavior native "ClientRectList" {
// To suppress missing implicit constructor warnings.
factory _ClientRectList._() { throw new UnsupportedError("Not supported"); }
@@ -26177,7 +26204,7 @@
@DocsEditable()
@DomName('CSSRuleList')
-class _CssRuleList extends Interceptor with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements JavaScriptIndexingBehavior, List native "CSSRuleList" {
+class _CssRuleList extends Interceptor with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements JavaScriptIndexingBehavior, List<CssRule> native "CSSRuleList" {
// To suppress missing implicit constructor warnings.
factory _CssRuleList._() { throw new UnsupportedError("Not supported"); }
@@ -26242,7 +26269,7 @@
@DomName('CSSValueList')
// http://dev.w3.org/csswg/cssom/
@deprecated // deprecated
-class _CssValueList extends _CSSValue with ListMixin<_CSSValue>, ImmutableListMixin<_CSSValue> implements JavaScriptIndexingBehavior, List native "CSSValueList" {
+class _CssValueList extends _CSSValue with ListMixin<_CSSValue>, ImmutableListMixin<_CSSValue> implements JavaScriptIndexingBehavior, List<_CSSValue> native "CSSValueList" {
// To suppress missing implicit constructor warnings.
factory _CssValueList._() { throw new UnsupportedError("Not supported"); }
@@ -26468,7 +26495,7 @@
@DomName('GamepadList')
// https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html
@Experimental()
-class _GamepadList extends Interceptor with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements JavaScriptIndexingBehavior, List native "GamepadList" {
+class _GamepadList extends Interceptor with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements JavaScriptIndexingBehavior, List<Gamepad> native "GamepadList" {
// To suppress missing implicit constructor warnings.
factory _GamepadList._() { throw new UnsupportedError("Not supported"); }
@@ -26709,7 +26736,7 @@
@DomName('NamedNodeMap')
// http://dom.spec.whatwg.org/#namednodemap
@deprecated // deprecated
-class _NamedNodeMap extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List native "NamedNodeMap,MozNamedAttrMap" {
+class _NamedNodeMap extends Interceptor with ListMixin<Node>, ImmutableListMixin<Node> implements JavaScriptIndexingBehavior, List<Node> native "NamedNodeMap,MozNamedAttrMap" {
// To suppress missing implicit constructor warnings.
factory _NamedNodeMap._() { throw new UnsupportedError("Not supported"); }
@@ -26905,7 +26932,7 @@
@DomName('SpeechInputResultList')
// http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#speech_input_result_list_interface
@Experimental()
-class _SpeechInputResultList extends Interceptor with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements JavaScriptIndexingBehavior, List native "SpeechInputResultList" {
+class _SpeechInputResultList extends Interceptor with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements JavaScriptIndexingBehavior, List<SpeechInputResult> native "SpeechInputResultList" {
// To suppress missing implicit constructor warnings.
factory _SpeechInputResultList._() { throw new UnsupportedError("Not supported"); }
@@ -26970,7 +26997,7 @@
@DomName('SpeechRecognitionResultList')
// https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#speechrecognitionresultlist
@Experimental()
-class _SpeechRecognitionResultList extends Interceptor with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements JavaScriptIndexingBehavior, List native "SpeechRecognitionResultList" {
+class _SpeechRecognitionResultList extends Interceptor with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements JavaScriptIndexingBehavior, List<SpeechRecognitionResult> native "SpeechRecognitionResultList" {
// To suppress missing implicit constructor warnings.
factory _SpeechRecognitionResultList._() { throw new UnsupportedError("Not supported"); }
@@ -27033,7 +27060,7 @@
@DocsEditable()
@DomName('StyleSheetList')
-class _StyleSheetList extends Interceptor with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements JavaScriptIndexingBehavior, List native "StyleSheetList" {
+class _StyleSheetList extends Interceptor with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements JavaScriptIndexingBehavior, List<StyleSheet> native "StyleSheetList" {
// To suppress missing implicit constructor warnings.
factory _StyleSheetList._() { throw new UnsupportedError("Not supported"); }
@@ -27580,17 +27607,16 @@
/**
- * An object representing the top-level context object for web scripting.
+ * Top-level container for a browser tab or window.
*
- * In a web browser, a [Window] object represents the actual browser window.
- * In a multi-tabbed browser, each tab has its own [Window] object. A [Window]
- * is the container that displays a [Document]'s content. All web scripting
- * happens within the context of a [Window] object.
+ * In a web browser, a [WindowBase] object represents any browser window. This
+ * abstract class contains the state of the window and its relation to other
+ * windows, such as which window opened it.
*
* **Note:** This class represents any window, whereas [Window] is
- * used to access the properties and content of the current window.
+ * used to access the properties and content of the current window or tab.
*
- * See also:
+ * ## Other resources
*
* * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
* * [Window](http://www.w3.org/TR/Window/) from the W3C.
@@ -28222,6 +28248,121 @@
/**
+ * A factory to expose DOM events as Streams.
+ */
+class EventStreamProvider<T extends Event> {
+ final String _eventType;
+
+ const EventStreamProvider(this._eventType);
+
+ /**
+ * Gets a [Stream] for this event type, on the specified target.
+ *
+ * This will always return a broadcast stream so multiple listeners can be
+ * used simultaneously.
+ *
+ * This may be used to capture DOM events:
+ *
+ * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
+ *
+ * // Alternate method:
+ * Element.keyDownEvent.forTarget(element).capture(...);
+ *
+ * Or for listening to an event which will bubble through the DOM tree:
+ *
+ * MediaElement.pauseEvent.forTarget(document.body).listen(...);
+ *
+ * See also:
+ *
+ * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+ */
+ Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
+ new _EventStream(e, _eventType, useCapture);
+
+ /**
+ * Gets an [ElementEventStream] for this event type, on the specified element.
+ *
+ * This will always return a broadcast stream so multiple listeners can be
+ * used simultaneously.
+ *
+ * This may be used to capture DOM events:
+ *
+ * Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
+ *
+ * // Alternate method:
+ * Element.keyDownEvent.forElement(element).capture(...);
+ *
+ * Or for listening to an event which will bubble through the DOM tree:
+ *
+ * MediaElement.pauseEvent.forElement(document.body).listen(...);
+ *
+ * See also:
+ *
+ * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+ */
+ ElementStream<T> forElement(Element e, {bool useCapture: false}) {
+ return new _ElementEventStreamImpl(e, _eventType, useCapture);
+ }
+
+ /**
+ * Gets an [ElementEventStream] for this event type, on the list of elements.
+ *
+ * This will always return a broadcast stream so multiple listeners can be
+ * used simultaneously.
+ *
+ * This may be used to capture DOM events:
+ *
+ * Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
+ *
+ * See also:
+ *
+ * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+ */
+ ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
+ return new _ElementListEventStreamImpl(e, _eventType, useCapture);
+ }
+
+ /**
+ * Gets the type of the event which this would listen for on the specified
+ * event target.
+ *
+ * The target is necessary because some browsers may use different event names
+ * for the same purpose and the target allows differentiating browser support.
+ */
+ String getEventType(EventTarget target) {
+ return _eventType;
+ }
+}
+
+/** A specialized Stream available to [Element]s to enable event delegation. */
+abstract class ElementStream<T extends Event> implements Stream<T> {
+ /**
+ * Return a stream that only fires when the particular event fires for
+ * elements matching the specified CSS selector.
+ *
+ * This is the Dart equivalent to jQuery's
+ * [delegate](http://api.jquery.com/delegate/).
+ */
+ Stream<T> matches(String selector);
+
+ /**
+ * Adds a capturing subscription to this stream.
+ *
+ * If the target of the event is a descendant of the element from which this
+ * stream derives then [onData] is called before the event propagates down to
+ * the target. This is the opposite of bubbling behavior, where the event
+ * is first processed for the event target and then bubbles upward.
+ *
+ * ## Other resources
+ *
+ * * [Event Capture]
+ * (http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture)
+ * from the W3C DOM Events specification.
+ */
+ StreamSubscription<T> capture(void onData(T event));
+}
+
+/**
* Adapter for exposing DOM events as Dart streams.
*/
class _EventStream<T extends Event> extends Stream<T> {
@@ -28247,20 +28388,6 @@
}
}
-/** A specialized Stream available to [Element]s to enable event delegation. */
-abstract class ElementStream<T extends Event> implements Stream<T> {
- /**
- * Return a stream that only fires when the particular event fires for
- * elements matching the specified CSS selector.
- *
- * This is the Dart equivalent to jQuery's
- * [delegate](http://api.jquery.com/delegate/).
- */
- Stream<T> matches(String selector);
-
- StreamSubscription<T> capture(void onData(T event));
-}
-
/**
* Adapter for exposing DOM Element events as streams, while also allowing
* event delegation.
@@ -28327,6 +28454,83 @@
bool get isBroadcast => true;
}
+class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
+ int _pauseCount = 0;
+ EventTarget _target;
+ final String _eventType;
+ var _onData;
+ final bool _useCapture;
+
+ _EventStreamSubscription(this._target, this._eventType, onData,
+ this._useCapture) : _onData = _wrapZone(onData) {
+ _tryResume();
+ }
+
+ void cancel() {
+ if (_canceled) return;
+
+ _unlisten();
+ // Clear out the target to indicate this is complete.
+ _target = null;
+ _onData = null;
+ }
+
+ bool get _canceled => _target == null;
+
+ void onData(void handleData(T event)) {
+ if (_canceled) {
+ throw new StateError("Subscription has been canceled.");
+ }
+ // Remove current event listener.
+ _unlisten();
+
+ _onData = _wrapZone(handleData);
+ _tryResume();
+ }
+
+ /// Has no effect.
+ void onError(Function handleError) {}
+
+ /// Has no effect.
+ void onDone(void handleDone()) {}
+
+ void pause([Future resumeSignal]) {
+ if (_canceled) return;
+ ++_pauseCount;
+ _unlisten();
+
+ if (resumeSignal != null) {
+ resumeSignal.whenComplete(resume);
+ }
+ }
+
+ bool get isPaused => _pauseCount > 0;
+
+ void resume() {
+ if (_canceled || !isPaused) return;
+ --_pauseCount;
+ _tryResume();
+ }
+
+ void _tryResume() {
+ if (_onData != null && !isPaused) {
+ _target.addEventListener(_eventType, _onData, _useCapture);
+ }
+ }
+
+ void _unlisten() {
+ if (_onData != null) {
+ _target.removeEventListener(_eventType, _onData, _useCapture);
+ }
+ }
+
+ Future asFuture([var futureValue]) {
+ // We just need a future that will never succeed or fail.
+ Completer completer = new Completer();
+ return completer.future;
+ }
+}
+
/**
* A stream of custom events, which enables the user to "fire" (add) their own
* custom events to a stream.
@@ -28440,160 +28644,6 @@
}
}
-class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
- int _pauseCount = 0;
- EventTarget _target;
- final String _eventType;
- var _onData;
- final bool _useCapture;
-
- _EventStreamSubscription(this._target, this._eventType, onData,
- this._useCapture) : _onData = _wrapZone(onData) {
- _tryResume();
- }
-
- void cancel() {
- if (_canceled) return;
-
- _unlisten();
- // Clear out the target to indicate this is complete.
- _target = null;
- _onData = null;
- }
-
- bool get _canceled => _target == null;
-
- void onData(void handleData(T event)) {
- if (_canceled) {
- throw new StateError("Subscription has been canceled.");
- }
- // Remove current event listener.
- _unlisten();
-
- _onData = _wrapZone(handleData);
- _tryResume();
- }
-
- /// Has no effect.
- void onError(Function handleError) {}
-
- /// Has no effect.
- void onDone(void handleDone()) {}
-
- void pause([Future resumeSignal]) {
- if (_canceled) return;
- ++_pauseCount;
- _unlisten();
-
- if (resumeSignal != null) {
- resumeSignal.whenComplete(resume);
- }
- }
-
- bool get isPaused => _pauseCount > 0;
-
- void resume() {
- if (_canceled || !isPaused) return;
- --_pauseCount;
- _tryResume();
- }
-
- void _tryResume() {
- if (_onData != null && !isPaused) {
- _target.addEventListener(_eventType, _onData, _useCapture);
- }
- }
-
- void _unlisten() {
- if (_onData != null) {
- _target.removeEventListener(_eventType, _onData, _useCapture);
- }
- }
-
- Future asFuture([var futureValue]) {
- // We just need a future that will never succeed or fail.
- Completer completer = new Completer();
- return completer.future;
- }
-}
-
-/**
- * A factory to expose DOM events as Streams.
- */
-class EventStreamProvider<T extends Event> {
- final String _eventType;
-
- const EventStreamProvider(this._eventType);
-
- /**
- * Gets a [Stream] for this event type, on the specified target.
- *
- * This will always return a broadcast stream so multiple listeners can be
- * used simultaneously.
- *
- * This may be used to capture DOM events:
- *
- * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
- *
- * Or for listening to an event which will bubble through the DOM tree:
- *
- * MediaElement.pauseEvent.forTarget(document.body).listen(...);
- *
- * See also:
- *
- * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
- */
- Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
- new _EventStream(e, _eventType, useCapture);
-
- /**
- * Gets an [ElementEventStream] for this event type, on the specified element.
- *
- * This will always return a broadcast stream so multiple listeners can be
- * used simultaneously.
- *
- * This may be used to capture DOM events:
- *
- * Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
- *
- * See also:
- *
- * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
- */
- ElementStream<T> forElement(Element e, {bool useCapture: false}) {
- return new _ElementEventStreamImpl(e, _eventType, useCapture);
- }
-
- /**
- * Gets an [ElementEventStream] for this event type, on the list of elements.
- *
- * This will always return a broadcast stream so multiple listeners can be
- * used simultaneously.
- *
- * This may be used to capture DOM events:
- *
- * Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
- *
- * See also:
- *
- * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
- */
- ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
- return new _ElementListEventStreamImpl(e, _eventType, useCapture);
- }
-
- /**
- * Gets the type of the event which this would listen for on the specified
- * event target.
- *
- * The target is necessary because some browsers may use different event names
- * for the same purpose and the target allows differentiating browser support.
- */
- String getEventType(EventTarget target) {
- return _eventType;
- }
-}
-
/**
* A factory to expose DOM events as streams, where the DOM event name has to
* be determined on the fly (for example, mouse wheel events).
@@ -31788,7 +31838,7 @@
/** Helper to statically create the dispatch record. */
static _makeRecord() {
- var interceptor = findInterceptorForType(KeyboardEvent);
+ var interceptor = JS_INTERCEPTOR_CONSTANT(KeyboardEvent);
return makeLeafDispatchRecord(interceptor);
}
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 3af252e..7d5d233 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -8149,7 +8149,7 @@
@DocsEditable()
@DomName('DOMStringList')
-class DomStringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List {
+class DomStringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List<String> {
// To suppress missing implicit constructor warnings.
factory DomStringList._() { throw new UnsupportedError("Not supported"); }
@@ -8765,7 +8765,7 @@
// ElementList as there are valid cases where a NodeList JavaScript object
// contains Node objects that are not Elements.
class _FrozenElementList<T extends Element> extends ListBase<T>
- implements ElementList, NodeListWrapper {
+ implements ElementList<T>, NodeListWrapper {
final List<Node> _nodeList;
// The subset of _nodeList that are Elements.
List<Element> _elementList;
@@ -11490,7 +11490,7 @@
@DocsEditable()
@DomName('FileList')
-class FileList extends NativeFieldWrapperClass2 with ListMixin<File>, ImmutableListMixin<File> implements List {
+class FileList extends NativeFieldWrapperClass2 with ListMixin<File>, ImmutableListMixin<File> implements List<File> {
// To suppress missing implicit constructor warnings.
factory FileList._() { throw new UnsupportedError("Not supported"); }
@@ -12619,7 +12619,7 @@
@DocsEditable()
@DomName('HTMLCollection')
-class HtmlCollection extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class HtmlCollection extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List<Node> {
// To suppress missing implicit constructor warnings.
factory HtmlCollection._() { throw new UnsupportedError("Not supported"); }
@@ -13171,7 +13171,7 @@
* * [Using XMLHttpRequest](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest)
*/
@DomName('XMLHttpRequest')
-class HttpRequest extends XmlHttpRequestEventTarget {
+class HttpRequest extends HttpRequestEventTarget {
/**
* Creates a URL get request for the specified [url].
@@ -13707,10 +13707,118 @@
@DocsEditable()
+@DomName('XMLHttpRequestEventTarget')
+@Experimental() // untriaged
+class HttpRequestEventTarget extends EventTarget {
+ // To suppress missing implicit constructor warnings.
+ factory HttpRequestEventTarget._() { throw new UnsupportedError("Not supported"); }
+
+ @DomName('XMLHttpRequestEventTarget.abortEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> abortEvent = const EventStreamProvider<ProgressEvent>('abort');
+
+ @DomName('XMLHttpRequestEventTarget.errorEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> errorEvent = const EventStreamProvider<ProgressEvent>('error');
+
+ @DomName('XMLHttpRequestEventTarget.loadEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> loadEvent = const EventStreamProvider<ProgressEvent>('load');
+
+ @DomName('XMLHttpRequestEventTarget.loadendEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> loadEndEvent = const EventStreamProvider<ProgressEvent>('loadend');
+
+ @DomName('XMLHttpRequestEventTarget.loadstartEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> loadStartEvent = const EventStreamProvider<ProgressEvent>('loadstart');
+
+ @DomName('XMLHttpRequestEventTarget.progressEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
+
+ @DomName('XMLHttpRequestEventTarget.timeoutEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ static const EventStreamProvider<ProgressEvent> timeoutEvent = const EventStreamProvider<ProgressEvent>('timeout');
+
+ @DomName('XMLHttpRequestEventTarget.addEventListener')
+ @DocsEditable()
+ @Experimental() // untriaged
+ void addEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_addEventListener_Callback";
+
+ @DomName('XMLHttpRequestEventTarget.dispatchEvent')
+ @DocsEditable()
+ @Experimental() // untriaged
+ bool dispatchEvent(Event event) native "XMLHttpRequestEventTarget_dispatchEvent_Callback";
+
+ @DomName('XMLHttpRequestEventTarget.removeEventListener')
+ @DocsEditable()
+ @Experimental() // untriaged
+ void removeEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_removeEventListener_Callback";
+
+ @DomName('XMLHttpRequestEventTarget.onabort')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onAbort => abortEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onerror')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onError => errorEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onload')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onLoad => loadEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onloadend')
+ @DocsEditable()
+ @SupportedBrowser(SupportedBrowser.CHROME)
+ @SupportedBrowser(SupportedBrowser.FIREFOX)
+ @SupportedBrowser(SupportedBrowser.IE, '10')
+ @SupportedBrowser(SupportedBrowser.SAFARI)
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onLoadEnd => loadEndEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onloadstart')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onLoadStart => loadStartEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.onprogress')
+ @DocsEditable()
+ @SupportedBrowser(SupportedBrowser.CHROME)
+ @SupportedBrowser(SupportedBrowser.FIREFOX)
+ @SupportedBrowser(SupportedBrowser.IE, '10')
+ @SupportedBrowser(SupportedBrowser.SAFARI)
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
+
+ @DomName('XMLHttpRequestEventTarget.ontimeout')
+ @DocsEditable()
+ @Experimental() // untriaged
+ Stream<ProgressEvent> get onTimeout => timeoutEvent.forTarget(this);
+
+}
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable()
@DomName('XMLHttpRequestUpload')
// http://xhr.spec.whatwg.org/#xmlhttprequestupload
@Experimental()
-class HttpRequestUpload extends XmlHttpRequestEventTarget {
+class HttpRequestUpload extends HttpRequestEventTarget {
// To suppress missing implicit constructor warnings.
factory HttpRequestUpload._() { throw new UnsupportedError("Not supported"); }
@@ -17692,7 +17800,7 @@
@DocsEditable()
@DomName('MimeTypeArray')
@Experimental() // non-standard
-class MimeTypeArray extends NativeFieldWrapperClass2 with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements List {
+class MimeTypeArray extends NativeFieldWrapperClass2 with ListMixin<MimeType>, ImmutableListMixin<MimeType> implements List<MimeType> {
// To suppress missing implicit constructor warnings.
factory MimeTypeArray._() { throw new UnsupportedError("Not supported"); }
@@ -19012,7 +19120,7 @@
@DocsEditable()
@DomName('NodeList')
-class NodeList extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class NodeList extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List<Node> {
// To suppress missing implicit constructor warnings.
factory NodeList._() { throw new UnsupportedError("Not supported"); }
@@ -20271,7 +20379,7 @@
@DocsEditable()
@DomName('PluginArray')
@Experimental() // non-standard
-class PluginArray extends NativeFieldWrapperClass2 with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements List {
+class PluginArray extends NativeFieldWrapperClass2 with ListMixin<Plugin>, ImmutableListMixin<Plugin> implements List<Plugin> {
// To suppress missing implicit constructor warnings.
factory PluginArray._() { throw new UnsupportedError("Not supported"); }
@@ -22395,7 +22503,7 @@
@DomName('SourceBufferList')
// https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#sourcebufferlist
@Experimental()
-class SourceBufferList extends EventTarget with ListMixin<SourceBuffer>, ImmutableListMixin<SourceBuffer> implements List {
+class SourceBufferList extends EventTarget with ListMixin<SourceBuffer>, ImmutableListMixin<SourceBuffer> implements List<SourceBuffer> {
// To suppress missing implicit constructor warnings.
factory SourceBufferList._() { throw new UnsupportedError("Not supported"); }
@@ -22624,7 +22732,7 @@
@DomName('SpeechGrammarList')
// https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#dfn-speechgrammarlist
@Experimental()
-class SpeechGrammarList extends NativeFieldWrapperClass2 with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements List {
+class SpeechGrammarList extends NativeFieldWrapperClass2 with ListMixin<SpeechGrammar>, ImmutableListMixin<SpeechGrammar> implements List<SpeechGrammar> {
// To suppress missing implicit constructor warnings.
factory SpeechGrammarList._() { throw new UnsupportedError("Not supported"); }
@@ -24695,7 +24803,7 @@
@DomName('TextTrackCueList')
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttrackcuelist
@Experimental()
-class TextTrackCueList extends NativeFieldWrapperClass2 with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List {
+class TextTrackCueList extends NativeFieldWrapperClass2 with ListMixin<TextTrackCue>, ImmutableListMixin<TextTrackCue> implements List<TextTrackCue> {
// To suppress missing implicit constructor warnings.
factory TextTrackCueList._() { throw new UnsupportedError("Not supported"); }
@@ -24768,7 +24876,7 @@
@DomName('TextTrackList')
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttracklist
@Experimental()
-class TextTrackList extends EventTarget with ListMixin<TextTrack>, ImmutableListMixin<TextTrack> implements List {
+class TextTrackList extends EventTarget with ListMixin<TextTrack>, ImmutableListMixin<TextTrack> implements List<TextTrack> {
// To suppress missing implicit constructor warnings.
factory TextTrackList._() { throw new UnsupportedError("Not supported"); }
@@ -25075,7 +25183,7 @@
@DomName('TouchList')
// http://www.w3.org/TR/touch-events/, http://www.chromestatus.com/features
@Experimental()
-class TouchList extends NativeFieldWrapperClass2 with ListMixin<Touch>, ImmutableListMixin<Touch> implements List {
+class TouchList extends NativeFieldWrapperClass2 with ListMixin<Touch>, ImmutableListMixin<Touch> implements List<Touch> {
/// NB: This constructor likely does not work as you might expect it to! This
/// constructor will simply fail (returning null) if you are not on a device
/// with touch enabled. See dartbug.com/8314.
@@ -25499,13 +25607,13 @@
if ((blob_OR_source_OR_stream is Blob || blob_OR_source_OR_stream == null)) {
return _createObjectURL_1(blob_OR_source_OR_stream);
}
- if ((blob_OR_source_OR_stream is MediaStream || blob_OR_source_OR_stream == null)) {
+ if ((blob_OR_source_OR_stream is MediaSource || blob_OR_source_OR_stream == null)) {
return _createObjectURL_2(blob_OR_source_OR_stream);
}
- if ((blob_OR_source_OR_stream is MediaSource || blob_OR_source_OR_stream == null)) {
+ if ((blob_OR_source_OR_stream is _WebKitMediaSource || blob_OR_source_OR_stream == null)) {
return _createObjectURL_3(blob_OR_source_OR_stream);
}
- if ((blob_OR_source_OR_stream is _WebKitMediaSource || blob_OR_source_OR_stream == null)) {
+ if ((blob_OR_source_OR_stream is MediaStream || blob_OR_source_OR_stream == null)) {
return _createObjectURL_4(blob_OR_source_OR_stream);
}
throw new ArgumentError("Incorrect number or type of arguments");
@@ -26022,6 +26130,33 @@
@DocsEditable()
+/**
+ * Top-level container for the current browser tab or window.
+ *
+ * In a web browser, each window has a [Window] object, but within the context
+ * of a script, a [Window] object represents only the current window. In
+ * addition to the open window, each window, tab, and iframe has its own
+ * [Window] object. A [Window] contains a [Document] object, which contains this
+ * web page's content.
+ *
+ * Use `window` to access properties of the current window. For example:
+ *
+ * // Draw a scene when the window repaints.
+ * drawScene(num delta) {...}
+ * window.animationFrame.then(drawScene);.
+ *
+ * // Write to the console.
+ * window.console.log('Jinkies!');
+ * window.console.error('Jeepers!');
+ *
+ * **Note:** This class represents the current window, whereas [WindowBase] is
+ * a representation of any window, including other tabs, windows, and frames.
+ *
+ * ## Other resources
+ *
+ * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
+ * * [Window](http://www.w3.org/TR/Window/) from the W3C.
+ */
@DomName('Window')
class Window extends EventTarget implements WindowBase, _WindowTimers, WindowBase64 {
@@ -27439,114 +27574,6 @@
@DocsEditable()
-@DomName('XMLHttpRequestEventTarget')
-@Experimental() // untriaged
-class XmlHttpRequestEventTarget extends EventTarget {
- // To suppress missing implicit constructor warnings.
- factory XmlHttpRequestEventTarget._() { throw new UnsupportedError("Not supported"); }
-
- @DomName('XMLHttpRequestEventTarget.abortEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> abortEvent = const EventStreamProvider<ProgressEvent>('abort');
-
- @DomName('XMLHttpRequestEventTarget.errorEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> errorEvent = const EventStreamProvider<ProgressEvent>('error');
-
- @DomName('XMLHttpRequestEventTarget.loadEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> loadEvent = const EventStreamProvider<ProgressEvent>('load');
-
- @DomName('XMLHttpRequestEventTarget.loadendEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> loadEndEvent = const EventStreamProvider<ProgressEvent>('loadend');
-
- @DomName('XMLHttpRequestEventTarget.loadstartEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> loadStartEvent = const EventStreamProvider<ProgressEvent>('loadstart');
-
- @DomName('XMLHttpRequestEventTarget.progressEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
-
- @DomName('XMLHttpRequestEventTarget.timeoutEvent')
- @DocsEditable()
- @Experimental() // untriaged
- static const EventStreamProvider<ProgressEvent> timeoutEvent = const EventStreamProvider<ProgressEvent>('timeout');
-
- @DomName('XMLHttpRequestEventTarget.addEventListener')
- @DocsEditable()
- @Experimental() // untriaged
- void addEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_addEventListener_Callback";
-
- @DomName('XMLHttpRequestEventTarget.dispatchEvent')
- @DocsEditable()
- @Experimental() // untriaged
- bool dispatchEvent(Event event) native "XMLHttpRequestEventTarget_dispatchEvent_Callback";
-
- @DomName('XMLHttpRequestEventTarget.removeEventListener')
- @DocsEditable()
- @Experimental() // untriaged
- void removeEventListener(String type, EventListener listener, [bool useCapture]) native "XMLHttpRequestEventTarget_removeEventListener_Callback";
-
- @DomName('XMLHttpRequestEventTarget.onabort')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onAbort => abortEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onerror')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onError => errorEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onload')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onLoad => loadEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onloadend')
- @DocsEditable()
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.FIREFOX)
- @SupportedBrowser(SupportedBrowser.IE, '10')
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental() // untriaged
- Stream<ProgressEvent> get onLoadEnd => loadEndEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onloadstart')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onLoadStart => loadStartEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.onprogress')
- @DocsEditable()
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.FIREFOX)
- @SupportedBrowser(SupportedBrowser.IE, '10')
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental() // untriaged
- Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
-
- @DomName('XMLHttpRequestEventTarget.ontimeout')
- @DocsEditable()
- @Experimental() // untriaged
- Stream<ProgressEvent> get onTimeout => timeoutEvent.forTarget(this);
-
-}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable()
@DomName('XMLSerializer')
// http://domparsing.spec.whatwg.org/#the-xmlserializer-interface
@deprecated // stable
@@ -27889,7 +27916,7 @@
@DocsEditable()
@DomName('ClientRectList')
-class _ClientRectList extends NativeFieldWrapperClass2 with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements List {
+class _ClientRectList extends NativeFieldWrapperClass2 with ListMixin<Rectangle>, ImmutableListMixin<Rectangle> implements List<Rectangle> {
// To suppress missing implicit constructor warnings.
factory _ClientRectList._() { throw new UnsupportedError("Not supported"); }
@@ -27972,7 +27999,7 @@
@DocsEditable()
@DomName('CSSRuleList')
-class _CssRuleList extends NativeFieldWrapperClass2 with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements List {
+class _CssRuleList extends NativeFieldWrapperClass2 with ListMixin<CssRule>, ImmutableListMixin<CssRule> implements List<CssRule> {
// To suppress missing implicit constructor warnings.
factory _CssRuleList._() { throw new UnsupportedError("Not supported"); }
@@ -28041,7 +28068,7 @@
@DomName('CSSValueList')
// http://dev.w3.org/csswg/cssom/
@deprecated // deprecated
-class _CssValueList extends _CSSValue with ListMixin<_CSSValue>, ImmutableListMixin<_CSSValue> implements List {
+class _CssValueList extends _CSSValue with ListMixin<_CSSValue>, ImmutableListMixin<_CSSValue> implements List<_CSSValue> {
// To suppress missing implicit constructor warnings.
factory _CssValueList._() { throw new UnsupportedError("Not supported"); }
@@ -28311,7 +28338,7 @@
@DomName('GamepadList')
// https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html
@Experimental()
-class _GamepadList extends NativeFieldWrapperClass2 with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements List {
+class _GamepadList extends NativeFieldWrapperClass2 with ListMixin<Gamepad>, ImmutableListMixin<Gamepad> implements List<Gamepad> {
// To suppress missing implicit constructor warnings.
factory _GamepadList._() { throw new UnsupportedError("Not supported"); }
@@ -28579,7 +28606,7 @@
@DomName('NamedNodeMap')
// http://dom.spec.whatwg.org/#namednodemap
@deprecated // deprecated
-class _NamedNodeMap extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List {
+class _NamedNodeMap extends NativeFieldWrapperClass2 with ListMixin<Node>, ImmutableListMixin<Node> implements List<Node> {
// To suppress missing implicit constructor warnings.
factory _NamedNodeMap._() { throw new UnsupportedError("Not supported"); }
@@ -28797,7 +28824,7 @@
@DomName('SpeechInputResultList')
// http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#speech_input_result_list_interface
@Experimental()
-class _SpeechInputResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements List {
+class _SpeechInputResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechInputResult>, ImmutableListMixin<SpeechInputResult> implements List<SpeechInputResult> {
// To suppress missing implicit constructor warnings.
factory _SpeechInputResultList._() { throw new UnsupportedError("Not supported"); }
@@ -28866,7 +28893,7 @@
@DomName('SpeechRecognitionResultList')
// https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#speechrecognitionresultlist
@Experimental()
-class _SpeechRecognitionResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements List {
+class _SpeechRecognitionResultList extends NativeFieldWrapperClass2 with ListMixin<SpeechRecognitionResult>, ImmutableListMixin<SpeechRecognitionResult> implements List<SpeechRecognitionResult> {
// To suppress missing implicit constructor warnings.
factory _SpeechRecognitionResultList._() { throw new UnsupportedError("Not supported"); }
@@ -28933,7 +28960,7 @@
@DocsEditable()
@DomName('StyleSheetList')
-class _StyleSheetList extends NativeFieldWrapperClass2 with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements List {
+class _StyleSheetList extends NativeFieldWrapperClass2 with ListMixin<StyleSheet>, ImmutableListMixin<StyleSheet> implements List<StyleSheet> {
// To suppress missing implicit constructor warnings.
factory _StyleSheetList._() { throw new UnsupportedError("Not supported"); }
@@ -29525,17 +29552,16 @@
/**
- * An object representing the top-level context object for web scripting.
+ * Top-level container for a browser tab or window.
*
- * In a web browser, a [Window] object represents the actual browser window.
- * In a multi-tabbed browser, each tab has its own [Window] object. A [Window]
- * is the container that displays a [Document]'s content. All web scripting
- * happens within the context of a [Window] object.
+ * In a web browser, a [WindowBase] object represents any browser window. This
+ * abstract class contains the state of the window and its relation to other
+ * windows, such as which window opened it.
*
* **Note:** This class represents any window, whereas [Window] is
- * used to access the properties and content of the current window.
+ * used to access the properties and content of the current window or tab.
*
- * See also:
+ * ## Other resources
*
* * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
* * [Window](http://www.w3.org/TR/Window/) from the W3C.
@@ -30167,6 +30193,121 @@
/**
+ * A factory to expose DOM events as Streams.
+ */
+class EventStreamProvider<T extends Event> {
+ final String _eventType;
+
+ const EventStreamProvider(this._eventType);
+
+ /**
+ * Gets a [Stream] for this event type, on the specified target.
+ *
+ * This will always return a broadcast stream so multiple listeners can be
+ * used simultaneously.
+ *
+ * This may be used to capture DOM events:
+ *
+ * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
+ *
+ * // Alternate method:
+ * Element.keyDownEvent.forTarget(element).capture(...);
+ *
+ * Or for listening to an event which will bubble through the DOM tree:
+ *
+ * MediaElement.pauseEvent.forTarget(document.body).listen(...);
+ *
+ * See also:
+ *
+ * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+ */
+ Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
+ new _EventStream(e, _eventType, useCapture);
+
+ /**
+ * Gets an [ElementEventStream] for this event type, on the specified element.
+ *
+ * This will always return a broadcast stream so multiple listeners can be
+ * used simultaneously.
+ *
+ * This may be used to capture DOM events:
+ *
+ * Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
+ *
+ * // Alternate method:
+ * Element.keyDownEvent.forElement(element).capture(...);
+ *
+ * Or for listening to an event which will bubble through the DOM tree:
+ *
+ * MediaElement.pauseEvent.forElement(document.body).listen(...);
+ *
+ * See also:
+ *
+ * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+ */
+ ElementStream<T> forElement(Element e, {bool useCapture: false}) {
+ return new _ElementEventStreamImpl(e, _eventType, useCapture);
+ }
+
+ /**
+ * Gets an [ElementEventStream] for this event type, on the list of elements.
+ *
+ * This will always return a broadcast stream so multiple listeners can be
+ * used simultaneously.
+ *
+ * This may be used to capture DOM events:
+ *
+ * Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
+ *
+ * See also:
+ *
+ * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+ */
+ ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
+ return new _ElementListEventStreamImpl(e, _eventType, useCapture);
+ }
+
+ /**
+ * Gets the type of the event which this would listen for on the specified
+ * event target.
+ *
+ * The target is necessary because some browsers may use different event names
+ * for the same purpose and the target allows differentiating browser support.
+ */
+ String getEventType(EventTarget target) {
+ return _eventType;
+ }
+}
+
+/** A specialized Stream available to [Element]s to enable event delegation. */
+abstract class ElementStream<T extends Event> implements Stream<T> {
+ /**
+ * Return a stream that only fires when the particular event fires for
+ * elements matching the specified CSS selector.
+ *
+ * This is the Dart equivalent to jQuery's
+ * [delegate](http://api.jquery.com/delegate/).
+ */
+ Stream<T> matches(String selector);
+
+ /**
+ * Adds a capturing subscription to this stream.
+ *
+ * If the target of the event is a descendant of the element from which this
+ * stream derives then [onData] is called before the event propagates down to
+ * the target. This is the opposite of bubbling behavior, where the event
+ * is first processed for the event target and then bubbles upward.
+ *
+ * ## Other resources
+ *
+ * * [Event Capture]
+ * (http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture)
+ * from the W3C DOM Events specification.
+ */
+ StreamSubscription<T> capture(void onData(T event));
+}
+
+/**
* Adapter for exposing DOM events as Dart streams.
*/
class _EventStream<T extends Event> extends Stream<T> {
@@ -30192,20 +30333,6 @@
}
}
-/** A specialized Stream available to [Element]s to enable event delegation. */
-abstract class ElementStream<T extends Event> implements Stream<T> {
- /**
- * Return a stream that only fires when the particular event fires for
- * elements matching the specified CSS selector.
- *
- * This is the Dart equivalent to jQuery's
- * [delegate](http://api.jquery.com/delegate/).
- */
- Stream<T> matches(String selector);
-
- StreamSubscription<T> capture(void onData(T event));
-}
-
/**
* Adapter for exposing DOM Element events as streams, while also allowing
* event delegation.
@@ -30272,6 +30399,83 @@
bool get isBroadcast => true;
}
+class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
+ int _pauseCount = 0;
+ EventTarget _target;
+ final String _eventType;
+ var _onData;
+ final bool _useCapture;
+
+ _EventStreamSubscription(this._target, this._eventType, onData,
+ this._useCapture) : _onData = _wrapZone(onData) {
+ _tryResume();
+ }
+
+ void cancel() {
+ if (_canceled) return;
+
+ _unlisten();
+ // Clear out the target to indicate this is complete.
+ _target = null;
+ _onData = null;
+ }
+
+ bool get _canceled => _target == null;
+
+ void onData(void handleData(T event)) {
+ if (_canceled) {
+ throw new StateError("Subscription has been canceled.");
+ }
+ // Remove current event listener.
+ _unlisten();
+
+ _onData = _wrapZone(handleData);
+ _tryResume();
+ }
+
+ /// Has no effect.
+ void onError(Function handleError) {}
+
+ /// Has no effect.
+ void onDone(void handleDone()) {}
+
+ void pause([Future resumeSignal]) {
+ if (_canceled) return;
+ ++_pauseCount;
+ _unlisten();
+
+ if (resumeSignal != null) {
+ resumeSignal.whenComplete(resume);
+ }
+ }
+
+ bool get isPaused => _pauseCount > 0;
+
+ void resume() {
+ if (_canceled || !isPaused) return;
+ --_pauseCount;
+ _tryResume();
+ }
+
+ void _tryResume() {
+ if (_onData != null && !isPaused) {
+ _target.addEventListener(_eventType, _onData, _useCapture);
+ }
+ }
+
+ void _unlisten() {
+ if (_onData != null) {
+ _target.removeEventListener(_eventType, _onData, _useCapture);
+ }
+ }
+
+ Future asFuture([var futureValue]) {
+ // We just need a future that will never succeed or fail.
+ Completer completer = new Completer();
+ return completer.future;
+ }
+}
+
/**
* A stream of custom events, which enables the user to "fire" (add) their own
* custom events to a stream.
@@ -30385,160 +30589,6 @@
}
}
-class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
- int _pauseCount = 0;
- EventTarget _target;
- final String _eventType;
- var _onData;
- final bool _useCapture;
-
- _EventStreamSubscription(this._target, this._eventType, onData,
- this._useCapture) : _onData = _wrapZone(onData) {
- _tryResume();
- }
-
- void cancel() {
- if (_canceled) return;
-
- _unlisten();
- // Clear out the target to indicate this is complete.
- _target = null;
- _onData = null;
- }
-
- bool get _canceled => _target == null;
-
- void onData(void handleData(T event)) {
- if (_canceled) {
- throw new StateError("Subscription has been canceled.");
- }
- // Remove current event listener.
- _unlisten();
-
- _onData = _wrapZone(handleData);
- _tryResume();
- }
-
- /// Has no effect.
- void onError(Function handleError) {}
-
- /// Has no effect.
- void onDone(void handleDone()) {}
-
- void pause([Future resumeSignal]) {
- if (_canceled) return;
- ++_pauseCount;
- _unlisten();
-
- if (resumeSignal != null) {
- resumeSignal.whenComplete(resume);
- }
- }
-
- bool get isPaused => _pauseCount > 0;
-
- void resume() {
- if (_canceled || !isPaused) return;
- --_pauseCount;
- _tryResume();
- }
-
- void _tryResume() {
- if (_onData != null && !isPaused) {
- _target.addEventListener(_eventType, _onData, _useCapture);
- }
- }
-
- void _unlisten() {
- if (_onData != null) {
- _target.removeEventListener(_eventType, _onData, _useCapture);
- }
- }
-
- Future asFuture([var futureValue]) {
- // We just need a future that will never succeed or fail.
- Completer completer = new Completer();
- return completer.future;
- }
-}
-
-/**
- * A factory to expose DOM events as Streams.
- */
-class EventStreamProvider<T extends Event> {
- final String _eventType;
-
- const EventStreamProvider(this._eventType);
-
- /**
- * Gets a [Stream] for this event type, on the specified target.
- *
- * This will always return a broadcast stream so multiple listeners can be
- * used simultaneously.
- *
- * This may be used to capture DOM events:
- *
- * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
- *
- * Or for listening to an event which will bubble through the DOM tree:
- *
- * MediaElement.pauseEvent.forTarget(document.body).listen(...);
- *
- * See also:
- *
- * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
- */
- Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
- new _EventStream(e, _eventType, useCapture);
-
- /**
- * Gets an [ElementEventStream] for this event type, on the specified element.
- *
- * This will always return a broadcast stream so multiple listeners can be
- * used simultaneously.
- *
- * This may be used to capture DOM events:
- *
- * Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
- *
- * See also:
- *
- * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
- */
- ElementStream<T> forElement(Element e, {bool useCapture: false}) {
- return new _ElementEventStreamImpl(e, _eventType, useCapture);
- }
-
- /**
- * Gets an [ElementEventStream] for this event type, on the list of elements.
- *
- * This will always return a broadcast stream so multiple listeners can be
- * used simultaneously.
- *
- * This may be used to capture DOM events:
- *
- * Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
- *
- * See also:
- *
- * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
- */
- ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
- return new _ElementListEventStreamImpl(e, _eventType, useCapture);
- }
-
- /**
- * Gets the type of the event which this would listen for on the specified
- * event target.
- *
- * The target is necessary because some browsers may use different event names
- * for the same purpose and the target allows differentiating browser support.
- */
- String getEventType(EventTarget target) {
- return _eventType;
- }
-}
-
/**
* A factory to expose DOM events as streams, where the DOM event name has to
* be determined on the fly (for example, mouse wheel events).
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index af7fe54..10b6068 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -292,6 +292,7 @@
bool canceled = false;
bool nextRunning = false;
bool closed = false;
+ Completer closeCompleter = new Completer();
_AsyncDirectoryLister(String this.path,
bool this.recursive,
@@ -312,7 +313,7 @@
next();
} else {
error(response);
- controller.close();
+ close();
}
});
}
@@ -321,12 +322,14 @@
if (!nextRunning) next();
}
- void onCancel() {
+ Future onCancel() {
canceled = true;
// If we are active, but not requesting, close.
if (!nextRunning) {
close();
}
+
+ return closeCompleter.future;
}
void next() {
@@ -336,10 +339,12 @@
}
if (id == null) return;
if (controller.isPaused) return;
- assert(!nextRunning);
+ if (nextRunning) return;
nextRunning = true;
_IOService.dispatch(_DIRECTORY_LIST_NEXT, [id]).then((result) {
+ nextRunning = false;
if (result is List) {
+ next();
assert(result.length % 2 == 0);
for (int i = 0; i < result.length; i++) {
assert(i % 2 == 0);
@@ -357,25 +362,29 @@
error(result[i]);
break;
case LIST_DONE:
- close();
+ canceled = true;
return;
}
}
} else {
controller.addError(new FileSystemException("Internal error"));
}
- nextRunning = false;
- next();
});
}
void close() {
if (closed) return;
- if (id == null) return;
- closed = true;
- _IOService.dispatch(_DIRECTORY_LIST_STOP, [id]).then((_) {
+ if (nextRunning) return;
+ void cleanup() {
controller.close();
- });
+ closeCompleter.complete();
+ }
+ closed = true;
+ if (id != null) {
+ _IOService.dispatch(_DIRECTORY_LIST_STOP, [id]).whenComplete(cleanup);
+ } else {
+ cleanup();
+ }
}
void error(message) {
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 16fb764..81d406d 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -349,6 +349,8 @@
* supports watching directories. Recursive watching is supported.
* * `Linux`: Uses `inotify`. The implementation supports watching both
* files and directories. Recursive watching is not supported.
+ * Note: When watching files directly, delete events might not happen
+ * as expected.
* * `Mac OS`: Uses `FSEvents`. The implementation supports watching both
* files and directories. Recursive watching is supported.
* Note: events happened slightly before calling [watch], may be part of
@@ -656,6 +658,7 @@
static const int _MODIFY_ATTRIBUTES = 1 << 4;
static const int _DELETE_SELF = 1 << 5;
+ static const int _IS_DIR = 1 << 6;
/**
* The type of event. See [FileSystemEvent] for a list of events.
@@ -668,7 +671,12 @@
*/
final String path;
- FileSystemEvent._(this.type, this.path);
+ /**
+ * Is `true` if the event target was a directory.
+ */
+ final bool isDirectory;
+
+ FileSystemEvent._(this.type, this.path, this.isDirectory);
}
@@ -676,8 +684,8 @@
* File system event for newly created file system objects.
*/
class FileSystemCreateEvent extends FileSystemEvent {
- FileSystemCreateEvent._(path)
- : super._(FileSystemEvent.CREATE, path);
+ FileSystemCreateEvent._(path, isDirectory)
+ : super._(FileSystemEvent.CREATE, path, isDirectory);
String toString() => "FileSystemCreateEvent('$path')";
}
@@ -693,8 +701,8 @@
*/
final bool contentChanged;
- FileSystemModifyEvent._(path, this.contentChanged)
- : super._(FileSystemEvent.MODIFY, path);
+ FileSystemModifyEvent._(path, isDirectory, this.contentChanged)
+ : super._(FileSystemEvent.MODIFY, path, isDirectory);
String toString() =>
"FileSystemModifyEvent('$path', contentChanged=$contentChanged)";
@@ -705,8 +713,8 @@
* File system event for deletion of file system objects.
*/
class FileSystemDeleteEvent extends FileSystemEvent {
- FileSystemDeleteEvent._(path)
- : super._(FileSystemEvent.DELETE, path);
+ FileSystemDeleteEvent._(path, isDirectory)
+ : super._(FileSystemEvent.DELETE, path, isDirectory);
String toString() => "FileSystemDeleteEvent('$path')";
}
@@ -722,8 +730,8 @@
*/
final String destination;
- FileSystemMoveEvent._(path, this.destination)
- : super._(FileSystemEvent.MOVE, path);
+ FileSystemMoveEvent._(path, isDirectory, this.destination)
+ : super._(FileSystemEvent.MOVE, path, isDirectory);
String toString() {
var buffer = new StringBuffer();
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 42b8d6f..c1ec1bf 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -460,8 +460,8 @@
_dataSink.add(data);
}
- void addError(error) {
- _dataSink.addError(error);
+ void addError(error, [StackTrace stackTrace]) {
+ _dataSink.addError(error, stackTrace);
}
Future<T> addStream(Stream<List<int>> stream) {
@@ -697,7 +697,7 @@
class _HttpResponse extends _HttpOutboundMessage<HttpResponse>
implements HttpResponse {
- int statusCode = 200;
+ int _statusCode = 200;
String _reasonPhrase;
List<Cookie> _cookies;
_HttpRequest _httpRequest;
@@ -717,6 +717,12 @@
return _cookies;
}
+ int get statusCode => _statusCode;
+ void set statusCode(int statusCode) {
+ if (_headersWritten) throw new StateError("Header already sent");
+ _statusCode = statusCode;
+ }
+
String get reasonPhrase => _findReasonPhrase(statusCode);
void set reasonPhrase(String reasonPhrase) {
if (_headersWritten) throw new StateError("Header already sent");
@@ -2094,8 +2100,9 @@
// Indicated if the http server has been closed.
bool closed = false;
- // The server listen socket.
- final ServerSocket _serverSocket;
+ // The server listen socket. Untyped as it can be both ServerSocket and
+ // SecureServerSocket.
+ final _serverSocket;
final bool _closeServer;
// Set of currently connected clients.
@@ -2238,7 +2245,8 @@
void add(List<int> bytes) => _socket.add(bytes);
- void addError(error) => _socket.addError(error);
+ void addError(error, [StackTrace stackTrace]) =>
+ _socket.addError(error, stackTrace);
Future<Socket> addStream(Stream<List<int>> stream) {
return _socket.addStream(stream);
diff --git a/sdk/lib/io/io_sink.dart b/sdk/lib/io/io_sink.dart
index ac4ce0a..042a469 100644
--- a/sdk/lib/io/io_sink.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -38,7 +38,7 @@
/**
* Writes an error to the consumer.
*/
- void addError(error);
+ void addError(error, [StackTrace stackTrace]);
/**
* Adds all elements of the given [stream] to `this`.
@@ -76,8 +76,8 @@
_controller.add(data);
}
- void addError(error) {
- _controller.addError(error);
+ void addError(error, [StackTrace stackTrace]) {
+ _controller.addError(error, stackTrace);
}
Future addStream(Stream<T> stream) {
diff --git a/sdk/lib/io/platform.dart b/sdk/lib/io/platform.dart
index 1053d37..11dee79 100644
--- a/sdk/lib/io/platform.dart
+++ b/sdk/lib/io/platform.dart
@@ -5,19 +5,8 @@
part of dart.io;
/**
- * Deprecated: the [Platform] class exposes details of the machine and operating
+ * The [Platform] class exposes details of the machine and operating
* system.
- *
- * This class has been replaced by adding the dart:platform library to Dart.
- * dart:platform is available on all browser and standalone platforms,
- * including Dart code that has been compiled to javascript.
- *
- * The dart:platform class has
- * the same top-level getters as the members of [Platform], except that the
- * [isWindows], [isLinux], [isAndroid], and [isMacOS] getters
- * have been removed. On platforms supporting dart:io, the getters of
- * dart:platform have the same values as the Platform class members, except
- * that [script] has been changed from a [String] to a file [Uri].
*/
@deprecated
class Platform {
diff --git a/sdk/lib/io/secure_server_socket.dart b/sdk/lib/io/secure_server_socket.dart
index eca89d3..affa57c 100644
--- a/sdk/lib/io/secure_server_socket.dart
+++ b/sdk/lib/io/secure_server_socket.dart
@@ -10,7 +10,7 @@
*
* See [SecureSocket] for more info.
*/
-class SecureServerSocket extends Stream<SecureSocket> implements ServerSocket {
+class SecureServerSocket extends Stream<SecureSocket> {
final RawSecureServerSocket _socket;
SecureServerSocket._(RawSecureServerSocket this._socket);
@@ -95,6 +95,11 @@
int get port => _socket.port;
/**
+ * Returns the address used by this socket.
+ */
+ InternetAddress get address => _socket.address;
+
+ /**
* Closes the socket. The returned future completes when the socket
* is fully closed and is no longer bound.
*/
@@ -205,6 +210,11 @@
int get port => _socket.port;
/**
+ * Returns the address used by this socket.
+ */
+ InternetAddress get address => _socket.address;
+
+ /**
* Closes the socket. The returned future completes when the socket
* is fully closed and is no longer bound.
*/
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index 073903d..76abe05 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.dart
@@ -162,7 +162,8 @@
void writeln([object = "" ]) => _sink.writeln(object);
void writeAll(objects, [sep = ""]) => _sink.writeAll(objects, sep);
void add(List<int> data) => _sink.add(data);
- void addError(error) => _sink.addError(error);
+ void addError(error, [StackTrace stackTrace]) =>
+ _sink.addError(error, stackTrace);
void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
Future addStream(Stream<List<int>> stream) => _sink.addStream(stream);
Future close() => _sink.close();
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index 9178757..dafd2bd 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.dart
@@ -13,6 +13,8 @@
class SystemEncoding extends Encoding {
const SystemEncoding();
+ String get name => 'system';
+
List<int> encode(String input) => encoder.convert(input);
String decode(List<int> encoded) => decoder.convert(encoded);
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index cb6d099..6a62609 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -898,7 +898,8 @@
String get closeReason => _closeReason;
void add(data) => _sink.add(data);
- void addError(error) => _sink.addError(error);
+ void addError(error, [StackTrace stackTrace]) =>
+ _sink.addError(error, stackTrace);
Future addStream(Stream stream) => _sink.addStream(stream);
Future get done => _sink.done;
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 9dbc193..b5b13c8 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -43,7 +43,7 @@
* context['console'].callMethod('log', [message]);
* }
*
- * ## Proxying and Automatic Conversion
+ * ## Proxying and automatic conversion
*
* When setting properties on a JsObject or passing arguments to a Javascript
* method or function, Dart objects are automatically converted or proxied to
@@ -84,7 +84,7 @@
library dart.js;
import 'dart:html' show Blob, ImageData, Node;
-import 'dart:collection' show HashMap;
+import 'dart:collection' show HashMap, ListMixin;
import 'dart:indexed_db' show KeyRange;
import 'dart:typed_data' show TypedData;
@@ -92,7 +92,7 @@
import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject;
import 'dart:_js_helper' show Primitives, convertDartClosureToJS;
-final JsObject context = new JsObject._fromJs(Primitives.computeGlobalThis());
+final JsObject context = _wrapToDart(Primitives.computeGlobalThis());
_convertDartFunction(Function f, {bool captureThis: false}) {
return JS('',
@@ -108,7 +108,7 @@
if (captureThis) {
arguments = [self]..addAll(arguments);
}
- var dartArgs = arguments.map(_convertToDart).toList();
+ var dartArgs = new List.from(arguments.map(_convertToDart));
return _convertToJS(Function.apply(callback, dartArgs));
}
@@ -122,10 +122,9 @@
// The wrapped JS object.
final dynamic _jsObject;
+ // This shoud only be called from _wrapToDart
JsObject._fromJs(this._jsObject) {
assert(_jsObject != null);
- // Remember this proxy for the JS object
- _getDartProxy(_jsObject, _DART_OBJECT_PROPERTY_NAME, (o) => this);
}
/**
@@ -135,7 +134,7 @@
factory JsObject(JsFunction constructor, [List arguments]) {
var constr = _convertToJS(constructor);
if (arguments == null) {
- return new JsObject._fromJs(JS('', 'new #()', constr));
+ return _wrapToDart(JS('', 'new #()', constr));
}
// The following code solves the problem of invoking a JavaScript
// constructor with an unknown number arguments.
@@ -151,7 +150,8 @@
// This could return an UnknownJavaScriptObject, or a native
// object for which there is an interceptor
var jsObj = JS('JavaScriptObject', 'new #()', factoryFunction);
- return new JsObject._fromJs(jsObj);
+
+ return _wrapToDart(jsObj);
}
/**
@@ -170,7 +170,7 @@
throw new ArgumentError(
"object cannot be a num, string, bool, or null");
}
- return new JsObject._fromJs(_convertToJS(object));
+ return _wrapToDart(_convertToJS(object));
}
/**
@@ -186,7 +186,7 @@
if ((object is! Map) && (object is! Iterable)) {
throw new ArgumentError("object must be a Map or Iterable");
}
- return new JsObject._fromJs(_convertDataTree(object));
+ return _wrapToDart(_convertDataTree(object));
}
static _convertDataTree(data) {
@@ -304,7 +304,7 @@
}
return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, method,
_jsObject,
- args == null ? null : args.map(_convertToJS).toList()));
+ args == null ? null : new List.from(args.map(_convertToJS))));
}
}
@@ -331,7 +331,119 @@
dynamic apply(List args, { thisArg }) =>
_convertToDart(JS('', '#.apply(#, #)', _jsObject,
_convertToJS(thisArg),
- args == null ? null : args.map(_convertToJS).toList()));
+ args == null ? null : new List.from(args.map(_convertToJS))));
+}
+
+/**
+ * A [List] that proxies a JavaScript array.
+ */
+class JsArray<E> extends JsObject with ListMixin<E> {
+
+ /**
+ * Creates a new JavaScript array.
+ */
+ JsArray() : super._fromJs([]);
+
+ /**
+ * Creates a new JavaScript array and initializes it to the contents of
+ * [other].
+ */
+ JsArray.from(Iterable<E> other)
+ : super._fromJs([]..addAll(other.map(_convertToJS)));
+
+ JsArray._fromJs(jsObject) : super._fromJs(jsObject);
+
+ _checkIndex(int index) {
+ if (index is int && (index < 0 || index >= length)) {
+ throw new RangeError.range(index, 0, length);
+ }
+ }
+
+ _checkInsertIndex(int index) {
+ if (index is int && (index < 0 || index >= length + 1)) {
+ throw new RangeError.range(index, 0, length);
+ }
+ }
+
+ _checkRange(int start, int end) {
+ if (start < 0 || start > this.length) {
+ throw new RangeError.range(start, 0, this.length);
+ }
+ if (end < start || end > this.length) {
+ throw new RangeError.range(end, start, this.length);
+ }
+ }
+
+ // Methods required by ListMixin
+
+ E operator [](index) {
+ // TODO(justinfagnani): fix the semantics for non-ints
+ // dartbug.com/14605
+ if (index is num && index == index.toInt()) {
+ _checkIndex(index);
+ }
+ return super[index];
+ }
+
+ void operator []=(index, E value) {
+ // TODO(justinfagnani): fix the semantics for non-ints
+ // dartbug.com/14605
+ if (index is num && index == index.toInt()) {
+ _checkIndex(index);
+ }
+ super[index] = value;
+ }
+
+ int get length => super['length'];
+
+ void set length(int length) { super['length'] = length; }
+
+
+ // Methods overriden for better performance
+
+ void add(E value) {
+ callMethod('push', [value]);
+ }
+
+ void addAll(Iterable<E> iterable) {
+ var list = (JS('bool', '# instanceof Array', iterable))
+ ? iterable
+ : new List.from(iterable);
+ callMethod('push', list);
+ }
+
+ void insert(int index, E element) {
+ _checkInsertIndex(index);
+ callMethod('splice', [index, 0, element]);
+ }
+
+ E removeAt(int index) {
+ _checkIndex(index);
+ return callMethod('splice', [index, 1])[0];
+ }
+
+ E removeLast() {
+ if (length == 0) throw new RangeError(-1);
+ return callMethod('pop');
+ }
+
+ void removeRange(int start, int end) {
+ _checkRange(start, end);
+ callMethod('splice', [start, end - start]);
+ }
+
+ void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
+ _checkRange(start, end);
+ int length = end - start;
+ if (length == 0) return;
+ if (skipCount < 0) throw new ArgumentError(skipCount);
+ var args = [start, length]..addAll(iterable.skip(skipCount).take(length));
+ callMethod('splice', args);
+ }
+
+ void sort([int compare(E a, E b)]) {
+ callMethod('sort', [compare]);
+ }
}
// property added to a Dart object referencing its JS-side DartObject proxy
@@ -359,8 +471,8 @@
if (o == null) {
return null;
} else if (o is String || o is num || o is bool
- || o is Blob || o is KeyRange || o is ImageData || o is Node
- || o is TypedData) {
+ || o is Blob || o is KeyRange || o is ImageData || o is Node
+ || o is TypedData) {
return o;
} else if (o is DateTime) {
return Primitives.lazyAsJsDate(o);
@@ -391,23 +503,33 @@
// converts a Dart object to a reference to a native JS object
// which might be a DartObject JS->Dart proxy
Object _convertToDart(o) {
+ var isArray = JS('bool', '# instanceof Array', o);
if (JS('bool', '# == null', o) ||
JS('bool', 'typeof # == "string"', o) ||
JS('bool', 'typeof # == "number"', o) ||
JS('bool', 'typeof # == "boolean"', o)) {
return o;
} else if (o is Blob || o is KeyRange || o is ImageData || o is Node
- || o is TypedData) {
+ || o is TypedData) {
return JS('Blob|KeyRange|ImageData|Node|TypedData', '#', o);
} else if (JS('bool', '# instanceof Date', o)) {
var ms = JS('num', '#.getMilliseconds()', o);
return new DateTime.fromMillisecondsSinceEpoch(ms);
- } else if (JS('bool', 'typeof # == "function"', o)) {
- return _getDartProxy(o, _DART_CLOSURE_PROPERTY_NAME,
- (o) => new JsFunction._fromJs(o));
} else if (JS('bool', '#.constructor === DartObject', o)) {
return JS('', '#.o', o);
} else {
+ return _wrapToDart(o);
+ }
+}
+
+JsObject _wrapToDart(o) {
+ if (JS('bool', 'typeof # == "function"', o)) {
+ return _getDartProxy(o, _DART_CLOSURE_PROPERTY_NAME,
+ (o) => new JsFunction._fromJs(o));
+ } else if (JS('bool', '# instanceof Array', o)) {
+ return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME,
+ (o) => new JsArray._fromJs(o));
+ } else {
return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME,
(o) => new JsObject._fromJs(o));
}
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart
index af3df6c..03df4a4 100644
--- a/sdk/lib/js/dartium/js_dartium.dart
+++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -43,7 +43,7 @@
* context['console'].callMethod('log', [message]);
* }
*
- * ## Proxying and Automatic Conversion
+ * ## Proxying and automatic conversion
*
* When setting properties on a JsObject or passing arguments to a Javascript
* method or function, Dart objects are automatically converted or proxied to
@@ -83,6 +83,7 @@
*/
library dart.js;
+import 'dart:collection' show ListMixin;
import 'dart:nativewrappers';
JsObject _cachedContext;
@@ -260,6 +261,101 @@
}
/**
+ * A [List] proxying a JavaScript Array.
+ */
+class JsArray<E> extends JsObject with ListMixin<E> {
+
+ factory JsArray() => _newJsArray();
+
+ static JsArray _newJsArray() native "JsArray_newJsArray";
+
+ factory JsArray.from(Iterable<E> other) => _newJsArrayFromSafeList(new List.from(other));
+
+ static JsArray _newJsArrayFromSafeList(List list) native "JsArray_newJsArrayFromSafeList";
+
+ _checkIndex(int index, {bool insert: false}) {
+ int length = insert ? this.length + 1 : this.length;
+ if (index is int && (index < 0 || index >= length)) {
+ throw new RangeError.range(index, 0, length);
+ }
+ }
+
+ _checkRange(int start, int end) {
+ int cachedLength = this.length;
+ if (start < 0 || start > cachedLength) {
+ throw new RangeError.range(start, 0, cachedLength);
+ }
+ if (end < start || end > cachedLength) {
+ throw new RangeError.range(end, start, cachedLength);
+ }
+ }
+
+ // Methods required by ListMixin
+
+ E operator [](index) {
+ if (index is int) {
+ _checkIndex(index);
+ }
+ return super[index];
+ }
+
+ void operator []=(index, E value) {
+ if(index is int) {
+ _checkIndex(index);
+ }
+ super[index] = value;
+ }
+
+ int get length native "JsArray_length";
+
+ void set length(int length) { super['length'] = length; }
+
+ // Methods overriden for better performance
+
+ void add(E value) {
+ callMethod('push', [value]);
+ }
+
+ void addAll(Iterable<E> iterable) {
+ // TODO(jacobr): this can be optimized slightly.
+ callMethod('push', new List.from(iterable));
+ }
+
+ void insert(int index, E element) {
+ _checkIndex(index, insert:true);
+ callMethod('splice', [index, 0, element]);
+ }
+
+ E removeAt(int index) {
+ _checkIndex(index);
+ return callMethod('splice', [index, 1])[0];
+ }
+
+ E removeLast() {
+ if (length == 0) throw new RangeError(-1);
+ return callMethod('pop');
+ }
+
+ void removeRange(int start, int end) {
+ _checkRange(start, end);
+ callMethod('splice', [start, end - start]);
+ }
+
+ void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
+ _checkRange(start, end);
+ int length = end - start;
+ if (length == 0) return;
+ if (skipCount < 0) throw new ArgumentError(skipCount);
+ var args = [start, length]..addAll(iterable.skip(skipCount).take(length));
+ callMethod('splice', args);
+ }
+
+ void sort([int compare(E a, E b)]) {
+ callMethod('sort', [compare]);
+ }
+}
+
+/**
* Placeholder object for cases where we need to determine exactly how many
* args were passed to a function.
*/
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 109f832..678348d 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -125,12 +125,6 @@
external MirrorSystem currentMirrorSystem();
/**
- * Creates a [MirrorSystem] for the isolate which is listening on
- * the [SendPort].
- */
-external Future<MirrorSystem> mirrorSystemOf(SendPort port);
-
-/**
* Reflects an instance.
* Returns an [InstanceMirror] reflecting [reflectee].
* If [reflectee] is a function or an instance of a class
@@ -177,12 +171,7 @@
*
* Every [Mirror] originates from some [MirrorSystem].
*/
-abstract class Mirror {
- /**
- * The [MirrorSystem] that contains this mirror.
- */
- MirrorSystem get mirrors;
-}
+abstract class Mirror {}
/**
* An [IsolateMirror] reflects an isolate.
@@ -419,106 +408,6 @@
*/
/* TODO(turnidge): Handle ambiguous names.*/
InstanceMirror setField(Symbol fieldName, Object value);
-
- /**
- * Invokes the named function and returns a mirror on the result.
- * The arguments must be instances of [InstanceMirror], or of
- * a type that is serializable across isolates (currently [num],
- * [String], or [bool]).
- *
- * Let *o* be the object reflected by this mirror, let
- * *f* be the simple name of the member denoted by [memberName],
- * let *a1, ..., an* be the elements of [positionalArguments]
- * let *k1, ..., km* be the identifiers denoted by the elements of
- * [namedArguments.keys]
- * and let *v1, ..., vm* be the elements of [namedArguments.values].
- * For each *ai*, if *ai* is an instance of [InstanceMirror], let *pi*
- * be the object reflected by *ai*; otherwise let *pi = ai, i in 1 ...n*.
- * Likewise, for each *vj*, if *vj* is an instance of [InstanceMirror], let *qj*
- * be the object reflected by *vj*; otherwise let *qj = vj, j in 1 ...m*.
- * If any of the *pi, qj* is not an instance of [InstanceMirror] and
- * is not serializable across isolates, an exception is thrown.
- * Then this method will perform the method invocation
- * *o.f(p1, ..., pn, k1: q1, ..., km: qm)*
- * in a scope that has access to the private members
- * of *o* (if *o* is a class or library) or the private members of the
- * class of *o*(otherwise).
- * The method returns a future *k*.
- * If the invocation returns a result *r*, *k* will be completed
- * with the result of calling [reflect](*r*).
- * If the invocation throws an exception *e* (that it does not catch)
- * then *k* is completed with a [MirrorError] wrapping *e*.
- */
- /*
- * TODO(turnidge): Handle ambiguous names.
- * TODO(turnidge): Handle optional & named arguments.
- */
- Future<InstanceMirror> invokeAsync(Symbol memberName,
- List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]);
-
- /**
- * Invokes a getter and returns a mirror on the result. The getter
- * can be the implicit getter for a field or a user-defined getter
- * method.
- *
- * Let *o* be the object reflected by this mirror, let
- * *f* be the simple name of the getter denoted by [fieldName],
- * Then this method will perform the getter invocation
- * *o.f*
- * in a scope that has access to the private members
- * of *o* (if *o* is a class or library) or the private members of the
- * class of *o*(otherwise).
- *
- * If this mirror is an [InstanceMirror], and [fieldName] denotes an instance
- * method on its reflectee, the result of the invocation is an instance
- * mirror on a closure corresponding to that method.
- *
- * If this mirror is a [LibraryMirror], and [fieldName] denotes a top-level
- * method in the corresponding library, the result of the invocation is an
- * instance mirror on a closure corresponding to that method.
- *
- * If this mirror is a [ClassMirror], and [fieldName] denotes a static method
- * in the corresponding class, the result of the invocation is an instance
- * mirror on a closure corresponding to that method.
- *
- * The method returns a future *k*.
- * If the invocation returns a result *r*, *k* will be completed
- * with the result of calling [reflect](*r*).
- * If the invocation throws an exception *e* (that it does not catch)
- * then *k* is completed with a [MirrorError] wrapping *e*.
- */
- /* TODO(turnidge): Handle ambiguous names.*/
- Future<InstanceMirror> getFieldAsync(Symbol fieldName);
-
- /**
- * Invokes a setter and returns a mirror on the result. The setter
- * may be either the implicit setter for a non-final field or a
- * user-defined setter method.
- * The second argument must be an instance of [InstanceMirror], or of
- * a type that is serializable across isolates (currently [num],
- * [String], or [bool]).
- *
- * Let *o* be the object reflected by this mirror, let
- * *f* be the simple name of the getter denoted by [fieldName],
- * and let a be the object bound to [value]. If *a* is an instance of
- * [InstanceMirror] let *p* be the object
- * reflected by *a*, otherwise let *p =a*.
- * If *p* is not an instance of [InstanceMirror], *p* must be
- * serializable across isolates or an exception is thrown.
- * Then this method will perform the setter invocation
- * *o.f = a*
- * in a scope that has access to the private members
- * of *o* (if *o* is a class or library) or the private members of the
- * class of *o*(otherwise).
- * The method returns a future *k*.
- * If the invocation returns a result *r*, *k* will be completed
- * with the result of calling [reflect](*r*).
- * If the invocation throws an exception *e* (that it does not catch)
- * then *k* is completed with a [MirrorError} wrapping *e*.
- */
- /* TODO(turnidge): Handle ambiguous names.*/
- Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value);
}
/**
@@ -616,36 +505,6 @@
[Map<Symbol, dynamic> namedArguments]);
/**
- * Executes the closure and returns a mirror on the result.
- *
- * Let *f* be the closure reflected by this mirror,
- * let *a1, ..., an* be the elements of [positionalArguments]
- * let *k1, ..., km* be the identifiers denoted by the elements of
- * [namedArguments.keys]
- * and let *v1, ..., vm* be the elements of [namedArguments.values].
- * For each *ai*, if *ai* is an instance of [InstanceMirror], let *pi*
- * be the object reflected by *ai*; otherwise let *pi = ai, i in 1 ...n*.
- * Likewise, for each *vj*, if *vj* is an instance of [InstanceMirror], let
- * *qj*
- * be the object reflected by *vj*; otherwise let *qj = vj, j in 1 ...m*.
- * If any of the *pi, qj* is not an instance of [InstanceMirror] and
- * is not serializable across isolates, an exception is thrown.
- * Then this method will perform the function invocation
- * *f(p1, ..., pn, k1: q1, ..., km: qm)*
- * The method returns a future *k*.
- * If the invocation returns a result *r*, *k* will be completed
- * with the result of calling [reflect](*r*).
- * If the invocation throws an exception *e* (that it does not catch)
- * then *k* is completed with a [MirrorError] wrapping *e*.
- *
- * The arguments must be instances of [InstanceMirror], or of
- * a type that is serializable across isolates (currently [num],
- * [String], or [bool]).
- */
- Future<InstanceMirror> applyAsync(List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]);
-
- /**
* Looks up the value of a name in the scope of the closure. The
* result is a mirror on that value.
*
@@ -921,45 +780,6 @@
List positionalArguments,
[Map<Symbol,dynamic> namedArguments]);
- /**
- * Invokes the named function and returns a mirror on the result.
- * The arguments must be instances of [InstanceMirror], or of
- * a type that is serializable across isolates (currently [num],
- * [String], or [bool]).
- *
- * Let *c* be the class reflected by this mirror,
- * let *a1, ..., an* be the elements of [positionalArguments]
- * let *k1, ..., km* be the identifiers denoted by the elements of
- * [namedArguments.keys]
- * and let *v1, ..., vm* be the elements of [namedArguments.values].
- * For each *ai*, if *ai* is an instance of [InstanceMirror], let *pi*
- * be the object reflected by *ai*; otherwise let *pi = ai, i in 1 ...n*.
- * Likewise, for each *vj*, if *vj* is an instance of [InstanceMirror], let
- * *qj*
- * be the object reflected by *vj*; otherwise let *qj = vj, j in 1 ...m*.
- * If any of the *pi, qj* is not an instance of [InstanceMirror] and
- * is not serializable across isolates, an exception is thrown.
- * If [constructorName] was created from the empty string
- * Then this method will execute the instance creation expression
- * *new c(a1, ..., an, k1: v1, ..., km: vm)*
- * in a scope that has access to the private members
- * of *c*. Otherwise, let
- * *f* be the simple name of the constructor denoted by [constructorName]
- * Then this method will execute the instance creation expression
- * *new c.f(a1, ..., an, k1: v1, ..., km: vm)*
- * in a scope that has access to the private members
- * of *c*.
- * In either case:
- * The method returns a future *k*.
- * If the invocation returns a result *r*, *k* will be completed
- * with the result of calling [reflect](*r*).
- * If the invocation throws an exception *e* (that it does not catch)
- * then *k* is completed with a [MirrorError] wrapping *e*.
-*/
- Future<InstanceMirror> newInstanceAsync(Symbol constructorName,
- List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]);
-
/**
* Returns [:true:] if this mirror is equal to [other].
* Otherwise returns [:false:].
@@ -1029,7 +849,7 @@
*
* For instance [:void f(int):] is the referent for [:typedef void f(int):].
*/
- TypeMirror get referent;
+ FunctionTypeMirror get referent;
}
/**
diff --git a/sdk/lib/platform/platform.dart b/sdk/lib/platform/platform.dart
deleted file mode 100644
index ee8658e..0000000
--- a/sdk/lib/platform/platform.dart
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/**
- * Runtime information about the current platform.
- */
-library dart.platform;
-
-/**
- * The number of processors of the platform.
- *
- * Returns null if no information is available.
- *
- * Supported on the standalone Dart executable.
- */
-external int get numberOfProcessors;
-
-/**
- * The path separator used on the platform to separate
- * components in file paths.
- *
- * Returns null if the path separator is unknown or not valid.
- *
- * Supported on the standalone Dart executable and on dart2js.
- */
-external String get pathSeparator;
-
-/**
- * A string (`linux`, `macos`, `windows` or `android`)
- * representing the operating system.
- *
- * Returns null if the operating system could not be determined.
- */
-external String get operatingSystem;
-
-/**
- * The local hostname for the system.
- *
- * Returns null if the local hostname is not available.
- *
- * Supported on the standalone Dart executable.
- */
-external String get localHostname;
-
-/**
- * The version of the current Dart runtime.
- *
- * Returns null if not running a Dart runtime.
- *
- * Supported on the standalone Dart executable.
- */
-external String get version;
-
-/**
- * The environment for this instance of the platform.
- *
- * If environment variables are not supported on this platform, or not
- * available, null is returned.
- *
- * Environment variables on Windows are case-insensitive. The map
- * returned on Windows is therefore case-insensitive and converts
- * all keys and key arguments to its methods to upper case.
- * On other platforms the returned map is
- * a standard case-sensitive map.
- *
- * Supported on the standalone Dart executable.
- */
-external Map<String, String> get environment;
-
-/**
- * The path of the executable this Dart isolate is running on.
- *
- * Returns null if the execution environment does not make the information
- * available.
- *
- * Supported on the standalone Dart executable.
- */
-external String get executable;
-
-/**
- * The URI of the script being run in this isolate.
- *
- * If the URI is relative it is relative to the file URI of
- * the working directory of the VM when it was started.
- *
- * Returns null if the executable environment does not make the information
- * available.
- *
- * Supported on the standalone Dart executable.
- */
-external Uri get script;
-
-/**
- * The flags passed to the executable used to run the script in this
- * isolate. These are the command-line flags between the executable name
- * and the script name.
- *
- * Returns the empty list if [executableArguments] is not supported.
- *
- * Supported on the standalone Dart executable.
- */
-external List<String> get executableArguments;
-
-/**
- * The value of the --package-root flag passed to the executable
- * used to run the script in this isolate. This is the directory in which
- * Dart packages are looked up.
- *
- * If there is no --package-root flag, then the empty string is returned.
- *
- * Returns null if the information is not available on this platform.
- *
- * Supported on the standalone Dart executable.
- */
-external String get packageRoot;
diff --git a/sdk/lib/platform/platform_sources.gypi b/sdk/lib/platform/platform_sources.gypi
deleted file mode 100644
index 6bca2b3..0000000
--- a/sdk/lib/platform/platform_sources.gypi
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# This file contains all sources for the dart:platform library.
-{
- 'sources': [
- 'platform.dart',
- # The above file needs to be first as it lists the parts below.
- ],
-}
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index c837f1f..1d51c92 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -3041,7 +3041,7 @@
@DocsEditable()
@DomName('SVGLengthList')
@Unstable()
-class LengthList extends Interceptor with ListMixin<Length>, ImmutableListMixin<Length> implements List native "SVGLengthList" {
+class LengthList extends Interceptor with ListMixin<Length>, ImmutableListMixin<Length> implements List<Length> native "SVGLengthList" {
// To suppress missing implicit constructor warnings.
factory LengthList._() { throw new UnsupportedError("Not supported"); }
@@ -3495,7 +3495,7 @@
@DocsEditable()
@DomName('SVGNumberList')
@Unstable()
-class NumberList extends Interceptor with ListMixin<Number>, ImmutableListMixin<Number> implements List native "SVGNumberList" {
+class NumberList extends Interceptor with ListMixin<Number>, ImmutableListMixin<Number> implements List<Number> native "SVGNumberList" {
// To suppress missing implicit constructor warnings.
factory NumberList._() { throw new UnsupportedError("Not supported"); }
@@ -4260,7 +4260,7 @@
@DocsEditable()
@DomName('SVGPathSegList')
@Unstable()
-class PathSegList extends Interceptor with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List native "SVGPathSegList" {
+class PathSegList extends Interceptor with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List<PathSeg> native "SVGPathSegList" {
// To suppress missing implicit constructor warnings.
factory PathSegList._() { throw new UnsupportedError("Not supported"); }
@@ -4951,7 +4951,7 @@
@DocsEditable()
@DomName('SVGStringList')
@Unstable()
-class StringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements List native "SVGStringList" {
+class StringList extends Interceptor with ListMixin<String>, ImmutableListMixin<String> implements List<String> native "SVGStringList" {
// To suppress missing implicit constructor warnings.
factory StringList._() { throw new UnsupportedError("Not supported"); }
@@ -5906,7 +5906,7 @@
@DocsEditable()
@DomName('SVGTransformList')
@Unstable()
-class TransformList extends Interceptor with ListMixin<Transform>, ImmutableListMixin<Transform> implements List native "SVGTransformList" {
+class TransformList extends Interceptor with ListMixin<Transform>, ImmutableListMixin<Transform> implements List<Transform> native "SVGTransformList" {
// To suppress missing implicit constructor warnings.
factory TransformList._() { throw new UnsupportedError("Not supported"); }
@@ -6278,7 +6278,7 @@
@DocsEditable()
@DomName('SVGElementInstanceList')
@Unstable()
-class _ElementInstanceList extends Interceptor with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List native "SVGElementInstanceList" {
+class _ElementInstanceList extends Interceptor with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List<ElementInstance> native "SVGElementInstanceList" {
// To suppress missing implicit constructor warnings.
factory _ElementInstanceList._() { throw new UnsupportedError("Not supported"); }
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index f25ee0a..7e348f0 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -3217,7 +3217,7 @@
@DocsEditable()
@DomName('SVGLengthList')
@Unstable()
-class LengthList extends NativeFieldWrapperClass2 with ListMixin<Length>, ImmutableListMixin<Length> implements List {
+class LengthList extends NativeFieldWrapperClass2 with ListMixin<Length>, ImmutableListMixin<Length> implements List<Length> {
// To suppress missing implicit constructor warnings.
factory LengthList._() { throw new UnsupportedError("Not supported"); }
@@ -3713,7 +3713,7 @@
@DocsEditable()
@DomName('SVGNumberList')
@Unstable()
-class NumberList extends NativeFieldWrapperClass2 with ListMixin<Number>, ImmutableListMixin<Number> implements List {
+class NumberList extends NativeFieldWrapperClass2 with ListMixin<Number>, ImmutableListMixin<Number> implements List<Number> {
// To suppress missing implicit constructor warnings.
factory NumberList._() { throw new UnsupportedError("Not supported"); }
@@ -4733,7 +4733,7 @@
@DocsEditable()
@DomName('SVGPathSegList')
@Unstable()
-class PathSegList extends NativeFieldWrapperClass2 with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List {
+class PathSegList extends NativeFieldWrapperClass2 with ListMixin<PathSeg>, ImmutableListMixin<PathSeg> implements List<PathSeg> {
// To suppress missing implicit constructor warnings.
factory PathSegList._() { throw new UnsupportedError("Not supported"); }
@@ -5505,7 +5505,7 @@
@DocsEditable()
@DomName('SVGStringList')
@Unstable()
-class StringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List {
+class StringList extends NativeFieldWrapperClass2 with ListMixin<String>, ImmutableListMixin<String> implements List<String> {
// To suppress missing implicit constructor warnings.
factory StringList._() { throw new UnsupportedError("Not supported"); }
@@ -6529,7 +6529,7 @@
@DocsEditable()
@DomName('SVGTransformList')
@Unstable()
-class TransformList extends NativeFieldWrapperClass2 with ListMixin<Transform>, ImmutableListMixin<Transform> implements List {
+class TransformList extends NativeFieldWrapperClass2 with ListMixin<Transform>, ImmutableListMixin<Transform> implements List<Transform> {
// To suppress missing implicit constructor warnings.
factory TransformList._() { throw new UnsupportedError("Not supported"); }
@@ -6927,7 +6927,7 @@
@DocsEditable()
@DomName('SVGElementInstanceList')
@Unstable()
-class _ElementInstanceList extends NativeFieldWrapperClass2 with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List {
+class _ElementInstanceList extends NativeFieldWrapperClass2 with ListMixin<ElementInstance>, ImmutableListMixin<ElementInstance> implements List<ElementInstance> {
// To suppress missing implicit constructor warnings.
factory _ElementInstanceList._() { throw new UnsupportedError("Not supported"); }
diff --git a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
index f43139e..668bdef 100644
--- a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -203,7 +203,7 @@
@DomName('SQLResultSetRowList')
// http://www.w3.org/TR/webdatabase/#sqlresultsetrowlist
@Experimental() // deprecated
-class SqlResultSetRowList extends Interceptor with ListMixin<Map>, ImmutableListMixin<Map> implements List native "SQLResultSetRowList" {
+class SqlResultSetRowList extends Interceptor with ListMixin<Map>, ImmutableListMixin<Map> implements List<Map> native "SQLResultSetRowList" {
// To suppress missing implicit constructor warnings.
factory SqlResultSetRowList._() { throw new UnsupportedError("Not supported"); }
diff --git a/sdk/lib/web_sql/dartium/web_sql_dartium.dart b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
index 81f384d..62f2497 100644
--- a/sdk/lib/web_sql/dartium/web_sql_dartium.dart
+++ b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
@@ -212,7 +212,7 @@
@DomName('SQLResultSetRowList')
// http://www.w3.org/TR/webdatabase/#sqlresultsetrowlist
@Experimental() // deprecated
-class SqlResultSetRowList extends NativeFieldWrapperClass2 with ListMixin<Map>, ImmutableListMixin<Map> implements List {
+class SqlResultSetRowList extends NativeFieldWrapperClass2 with ListMixin<Map>, ImmutableListMixin<Map> implements List<Map> {
// To suppress missing implicit constructor warnings.
factory SqlResultSetRowList._() { throw new UnsupportedError("Not supported"); }
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 426e16e..267d3d0 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -15,6 +15,22 @@
# TBF: malformed or malbounded type in "conts" is static warning
Language/12_Expressions/12_Instance_Creation_A01_t08: Fail
+# TBF: it seems that "12.15.3 Unqualied Invocation" was changed, so it may be not an error anymore to call unknown function from top-level
+Language/13_Statements/04_Local_Function_Declaration_A04_t02: Fail # co19-roll r641: Please triage this failure
+
+# TBF: when we override "foo([x = 0]) {}" with "foo([x]) {}" we should report warning - different default value
+Language/07_Classes/1_Instance_Methods_A04_t02: MissingStaticWarning
+Language/07_Classes/4_Abstract_Instance_Members_A07_t04: MissingStaticWarning
+
+# TBF: It is a static warning if a class C declares an instance method named n and has a setter named n=.
+Language/07_Classes/1_Instance_Methods_A07_t01: MissingStaticWarning
+Language/07_Classes/1_Instance_Methods_A07_t02: MissingStaticWarning
+
+# TBF: Static members should not be accessible via subclasses.
+Language/07_Classes/7_Static_Methods_A01_t03: MissingStaticWarning
+Language/07_Classes/9_Superclasses/1_Inheritance_and_Overriding_A01_t05: MissingStaticWarning
+Language/08_Interfaces/5_Superinterfaces/1_Inheritance_and_Overriding_A01_t02: MissingStaticWarning
+
# co19 issue #442, undefined name "Expect"
@@ -227,15 +243,53 @@
Language/13_Statements/09_Switch_A02_t04: Fail # Issue 629
-Language/12_Expressions/05_Strings_A20_t01: Fail # co19-roll r623: Please triage this failure
-LibTest/collection/DoubleLinkedQueue/DoubleLinkedQueue_class_A01_t01: Fail # co19-roll r623: Please triage this failure
-LibTest/collection/ListQueue/ListQueue_class_A01_t01: Fail # co19-roll r623: Please triage this failure
-LibTest/collection/Queue/Queue_class_A01_t01: Fail # co19-roll r623: Please triage this failure
-LibTest/core/Iterable/Iterable.generate_A01_t01: Fail # co19-roll r623: Please triage this failure
-Language/13_Statements/04_Local_Function_Declaration_A04_t02: Fail # co19-roll r641: Please triage this failure
-LibTest/collection/HashMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/collection/LinkedHashMap/LinkedHashMap_class_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/collection/LinkedHashMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/collection/SplayTreeMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/core/Map/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
+
+
+# co19 issue 642, The argument type 'int' cannot be assigned to the parameter type 'Iterable'
+LibTest/collection/DoubleLinkedQueue/DoubleLinkedQueue_class_A01_t01: Fail, OK
+LibTest/collection/ListQueue/ListQueue_class_A01_t01: Fail, OK
+LibTest/collection/Queue/Queue_class_A01_t01: Fail, OK
+
+# co19 issue 643, A value of type 'Iterable' cannot be assigned to a variable of type 'Iterator'
+LibTest/core/Iterable/Iterable.generate_A01_t01: Fail, OK
+
+# co19 issue 644, The argument type 'int' cannot be assigned to the parameter type '(String, Object) -> void'
+LibTest/collection/HashMap/allTests_A01_t01: Fail, OK
+LibTest/collection/LinkedHashMap/LinkedHashMap_class_A01_t01: Fail, OK
+LibTest/collection/LinkedHashMap/allTests_A01_t01: Fail, OK
+LibTest/collection/SplayTreeMap/allTests_A01_t01: Fail, OK
+LibTest/core/Map/allTests_A01_t01: Fail, OK
+
+# co19 issue 645, "15.7 Type Void". Likewise, passing the result of a void method as a parameter or assigning it to a variable will cause a warning unless the variable/formal parameter has type dynamic.
+Language/06_Functions/06_Functions_A04_t01: Fail, OK
+
+# co19 issue 646, I don't see where Spec requires any warning for boolean conversion
+Language/12_Expressions/04_Booleans/1_Boolean_Conversion_A01_t02: MissingStaticWarning
+
+Language/12_Expressions/15_Method_Invocation/2_Cascaded_Invocation_A01_t19: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t02: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t09: MissingStaticWarning
+Language/12_Expressions/19_Conditional_A01_t14: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t10: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t11: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t12: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t13: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t14: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t15: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A02_t02: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A03_t01: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A03_t02: MissingStaticWarning
+Language/12_Expressions/21_Bitwise_Expressions_A01_t17: MissingStaticWarning
+Language/12_Expressions/23_Relational_Expressions_A01_t23: MissingStaticWarning
+Language/12_Expressions/24_Shift_A01_t14: MissingStaticWarning
+Language/12_Expressions/25_Additive_Expressions_A01_t14: MissingStaticWarning
+Language/12_Expressions/26_Multiplicative_Expressions_A01_t17: MissingStaticWarning
+Language/12_Expressions/27_Unary_Expressions_A01_t21: MissingStaticWarning
+Language/12_Expressions/29_Assignable_Expressions_A01_t09: MissingStaticWarning
+Language/12_Expressions/30_Identifier_Reference_A07_t01: MissingStaticWarning
+Language/13_Statements/06_For/1_For_Loop_A01_t07: MissingStaticWarning
+Language/13_Statements/06_For/1_For_Loop_A01_t08: MissingStaticWarning
+Language/13_Statements/09_Switch_A10_t03: MissingStaticWarning
+Language/13_Statements/15_Assert_A04_t04: MissingStaticWarning
+LibTest/collection/IterableMixin/IterableMixin_class_A01_t01: MissingStaticWarning
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 4a4cb2a..db7d1f1 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -146,6 +146,80 @@
LibTest/async/StreamEventTransformer/handleDone_A01_t01: Fail
LibTest/async/StreamEventTransformer/handleError_A01_t01: Fail
+# co19 issue 639.
+Language/12_Expressions/12_Spawning_an_Isolate_A01_t01: Fail
+LibTest/isolate/IsolateSink/add_A01_t01: Fail
+LibTest/isolate/IsolateSink/add_A01_t02: Fail
+LibTest/isolate/IsolateSink/add_A02_t01: Fail
+LibTest/isolate/IsolateSink/close_A01_t01: Fail
+LibTest/isolate/IsolateSink/close_A01_t02: Fail
+LibTest/isolate/IsolateSink/close_A01_t03: Fail
+LibTest/isolate/IsolateSink/close_A01_t04: Fail
+LibTest/isolate/IsolateSink/operator_equality_A01_t01: Fail
+LibTest/isolate/IsolateStream/any_A01_t01: Fail
+LibTest/isolate/IsolateStream/asBroadcastStream_A01_t01: Fail
+LibTest/isolate/IsolateStream/contains_A01_t01: Fail
+LibTest/isolate/IsolateStream/first_A01_t01: Fail
+LibTest/isolate/IsolateStream/first_A02_t01: Fail
+LibTest/isolate/IsolateStream/first_A02_t02: Fail
+LibTest/isolate/IsolateStream/isBroadcast_A01_t01: Fail
+LibTest/isolate/IsolateStream/isBroadcast_A01_t02: Fail
+LibTest/isolate/IsolateStream/isEmpty_A01_t01: Fail
+LibTest/isolate/IsolateStream/last_A01_t01: Fail
+LibTest/isolate/IsolateStream/last_A02_t01: Fail
+LibTest/isolate/IsolateStream/length_A01_t01: Fail
+LibTest/isolate/IsolateStream/single_A01_t01: Fail
+LibTest/isolate/IsolateStream/single_A02_t01: Fail
+LibTest/isolate/ReceivePort/close_A01_t01: Fail
+LibTest/isolate/ReceivePort/close_A02_t01: Fail
+LibTest/isolate/ReceivePort/receive_A01_t01: Fail
+LibTest/isolate/ReceivePort/receive_A01_t03: Fail
+LibTest/isolate/ReceivePort/toSendPort_A01_t01: Fail
+LibTest/isolate/ReceivePort/toSendPort_A01_t03: Fail
+LibTest/isolate/SendPort/call_A01_t01: Fail
+LibTest/isolate/SendPort/hashCode_A01_t01: Fail
+LibTest/isolate/SendPort/operator_equality_A01_t01: Fail
+LibTest/isolate/SendPort/send_A01_t01: Pass
+LibTest/isolate/SendPort/send_A02_t01: Fail
+LibTest/isolate/SendPort/send_A02_t04: Fail
+LibTest/isolate/SendPort/send_A02_t05: Fail
+LibTest/isolate/SendPort/send_A02_t06: Fail
+LibTest/isolate/SendPort/send_A03_t01: Fail
+LibTest/isolate/SendPort/send_A03_t02: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t01: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t02: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t03: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t04: Fail
+LibTest/isolate/isolate_api/spawnFunction_A01_t05: Fail
+LibTest/isolate/isolate_api/spawnFunction_A02_t01: Fail
+LibTest/isolate/isolate_api/spawnFunction_A03_t01: Fail
+LibTest/isolate/isolate_api/spawnFunction_A04_t02: Fail
+LibTest/isolate/isolate_api/spawnFunction_A04_t03: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t01: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t02: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t03: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t04: Fail
+LibTest/isolate/isolate_api/spawnUri_A01_t05: Fail
+LibTest/isolate/isolate_api/streamSpawnFunction_A01_t01: Fail
+LibTest/isolate/isolate_api/stream_A01_t01: Fail
+LibTest/isolate/isolate_api/port_A01_t01: Fail
+LibTest/isolate/IsolateSink/addError_A01_t01: Fail
+LibTest/isolate/IsolateSink/addError_A01_t02: Fail
+LibTest/isolate/IsolateStream/any_A02_t01: Fail
+LibTest/isolate/IsolateStream/contains_A02_t01: Fail
+LibTest/isolate/ReceivePort/receive_A01_t02: Fail
+LibTest/isolate/ReceivePort/toSendPort_A01_t02: Fail
+LibTest/isolate/SendPort/send_A01_t01: Fail
+LibTest/isolate/SendPort/send_A02_t02: Fail
+LibTest/isolate/SendPort/send_A02_t03: Fail
+LibTest/isolate/isolate_api/spawnFunction_A02_t02: Fail
+LibTest/isolate/isolate_api/spawnFunction_A04_t01: Fail
+LibTest/isolate/isolate_api/spawnUri_A02_t01: Fail
+LibTest/isolate/isolate_api/spawnUri_A02_t02: Fail
+LibTest/isolate/isolate_api/spawnUri_A02_t03: Fail
+LibTest/isolate/isolate_api/streamSpawnFunction_A02_t01: Fail
+LibTest/isolate/isolate_api/streamSpawnFunction_A02_t02: Fail
+
#co19 issue 631
Language/12_Expressions/30_Identifier_Reference_A02_t01: Fail
Language/13_Statements/03_Variable_Declaration_A01_t09: Fail
@@ -165,3 +239,45 @@
LibTest/collection/LinkedHashMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
LibTest/collection/SplayTreeMap/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
LibTest/core/Map/allTests_A01_t01: Fail # co19-roll r641: Please triage this failure
+
+Language/06_Functions/06_Functions_A04_t01: MissingStaticWarning
+Language/07_Classes/1_Instance_Methods_A04_t02: MissingStaticWarning
+Language/07_Classes/1_Instance_Methods_A07_t01: MissingStaticWarning
+Language/07_Classes/1_Instance_Methods_A07_t02: MissingStaticWarning
+Language/07_Classes/4_Abstract_Instance_Members_A07_t04: MissingStaticWarning
+Language/07_Classes/7_Static_Methods_A01_t03: MissingStaticWarning
+Language/07_Classes/9_Superclasses/1_Inheritance_and_Overriding_A01_t05: MissingStaticWarning
+Language/08_Interfaces/5_Superinterfaces/1_Inheritance_and_Overriding_A01_t02: MissingStaticWarning
+Language/12_Expressions/04_Booleans/1_Boolean_Conversion_A01_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A05_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A06_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A06_t06: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A07_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A08_t02: MissingStaticWarning
+Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A04_t02: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/2_Cascaded_Invocation_A01_t19: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t02: MissingStaticWarning
+Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t09: MissingStaticWarning
+Language/12_Expressions/19_Conditional_A01_t14: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t10: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t11: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t12: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t13: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t14: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A01_t15: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A02_t02: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A03_t01: MissingStaticWarning
+Language/12_Expressions/20_Logical_Boolean_Expressions_A03_t02: MissingStaticWarning
+Language/12_Expressions/21_Bitwise_Expressions_A01_t17: MissingStaticWarning
+Language/12_Expressions/23_Relational_Expressions_A01_t23: MissingStaticWarning
+Language/12_Expressions/24_Shift_A01_t14: MissingStaticWarning
+Language/12_Expressions/25_Additive_Expressions_A01_t14: MissingStaticWarning
+Language/12_Expressions/26_Multiplicative_Expressions_A01_t17: MissingStaticWarning
+Language/12_Expressions/27_Unary_Expressions_A01_t21: MissingStaticWarning
+Language/12_Expressions/29_Assignable_Expressions_A01_t09: MissingStaticWarning
+Language/12_Expressions/30_Identifier_Reference_A07_t01: MissingStaticWarning
+Language/13_Statements/06_For/1_For_Loop_A01_t07: MissingStaticWarning
+Language/13_Statements/06_For/1_For_Loop_A01_t08: MissingStaticWarning
+Language/13_Statements/09_Switch_A10_t03: MissingStaticWarning
+Language/13_Statements/15_Assert_A04_t04: MissingStaticWarning
+LibTest/collection/IterableMixin/IterableMixin_class_A01_t01: MissingStaticWarning
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 09b02e0..a998592 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -93,8 +93,7 @@
LibTest/async/Stream/handleError_A04_t02: Fail # co19-roll r641: Please triage this failure
LibTest/async/Stream/listen_A05_t02: Fail # co19-roll r641: Please triage this failure
LibTest/async/StreamSink/addError_A01_t01: Fail # co19-roll r641: Please triage this failure
-LibTest/async/StreamSink/addStream_A01_t01: Timeout, Fail # co19-roll r641: Please triage this failure
-LibTest/async/StreamSink/addStream_A01_t02: Timeout, Fail # co19-roll r641: Please triage this failure
+LibTest/async/StreamSink/addStream_A01_t02: Timeout, Fail, OK # Dart issue 14334 - test is also incorrect.
LibTest/collection/ListBase/ListBase_class_A01_t01: Fail, Timeout # co19-roll r641: Please triage this failure
LibTest/collection/ListMixin/ListMixin_class_A01_t01: Fail, Timeout # co19-roll r641: Please triage this failure
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index f539402..7134716 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -31,8 +31,6 @@
Language/03_Overview/1_Scoping_A02_t05: Fail # Inherited from dart2js
Language/03_Overview/1_Scoping_A02_t06: Fail # inherited from dart2js
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Fail # Inherited from VM (circular initialization?).
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t05: Fail # Inherited from dart2js
Language/06_Functions/4_External_Functions_A01_t01: Fail # inherited from VM
Language/07_Classes/3_Setters_A04_t01: Fail # inherited from VM
Language/07_Classes/3_Setters_A04_t02: Fail # inherited from VM
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 357e7b6..862e381 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -14,9 +14,6 @@
Language/13_Statements/03_Variable_Declaration_A04_t07: Fail # co19 issue 535
Language/13_Statements/03_Variable_Declaration_A04_t08: Fail # co19 issue 535
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Fail # Dart issue 5802
-Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t05: Fail # Dart issue 5894
-
LibTest/core/RegExp/Pattern_semantics/firstMatch_Term_A03_t01: Fail # Issue 12508
LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A02_t01: Fail # Issue 12508
LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # Issue 12508
@@ -55,13 +52,11 @@
LibTest/isolate/ReceivePort/receive_A01_t02: Fail # VM triage, check spec.
LibTest/isolate/SendPort/send_A01_t01: fail # co19-roll r546: Please triage this failure
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: Fail # co19-roll r607: Please triage this failure
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: Fail # co19-roll r607: Please triage this failure
LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: RuntimeError # co19-roll r607: Please triage this failure
LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # co19-roll r607: Please triage this failure
LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # co19-roll r607: Please triage this failure
-LibTest/typed_data/Float32x4/clamp_A01_t01: Pass, Fail # Issue 13106
+LibTest/typed_data/Float32x4/clamp_A01_t01: Pass, Fail # co19 issue 636
[ $compiler == none && $runtime == vm ]
LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # Issue 13398
diff --git a/tests/compiler/dart2js/array_static_intercept_test.dart b/tests/compiler/dart2js/array_static_intercept_test.dart
index ca50ccf..23e88eb 100644
--- a/tests/compiler/dart2js/array_static_intercept_test.dart
+++ b/tests/compiler/dart2js/array_static_intercept_test.dart
@@ -17,5 +17,5 @@
String generated = compile(TEST_ONE, entry: 'foo');
Expect.isTrue(generated.contains(r'.add$1('));
Expect.isTrue(generated.contains(r'.removeLast$0('));
- Expect.isTrue(generated.contains(r'.get$length('));
+ Expect.isTrue(generated.contains(r'.length'));
}
diff --git a/tests/compiler/dart2js/list_tracer_length_test.dart b/tests/compiler/dart2js/list_tracer_length_test.dart
index 6b039d8..89d3405 100644
--- a/tests/compiler/dart2js/list_tracer_length_test.dart
+++ b/tests/compiler/dart2js/list_tracer_length_test.dart
@@ -63,6 +63,14 @@
}
""";
+const String TEST7 = r"""
+var a = [42, 54];
+main() {
+ a[0]++;
+ return a[1];
+}
+""";
+
void checkRangeError(String test, {bool hasRangeError}) {
asyncTest(() => compileAll(test).then((generated) {
Expect.equals(hasRangeError, generated.contains('ioore'));
@@ -79,4 +87,5 @@
checkRangeError(TEST4, hasRangeError: true);
checkRangeError(TEST5, hasRangeError: true);
checkRangeError(TEST6, hasRangeError: true);
+ checkRangeError(TEST7, hasRangeError: false);
}
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index 27e412d..0099dc9 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -58,7 +58,7 @@
// 2. Some code was refactored, and there are more methods.
// Either situation could be problematic, but in situation 2, it is often
// acceptable to increase [expectedMethodCount] a little.
- int expectedMethodCount = 337;
+ int expectedMethodCount = 341;
Expect.isTrue(
generatedCode.length <= expectedMethodCount,
'Too many compiled methods: '
diff --git a/tests/compiler/dart2js/subtype_test.dart b/tests/compiler/dart2js/subtype_test.dart
index 585659e..f755503 100644
--- a/tests/compiler/dart2js/subtype_test.dart
+++ b/tests/compiler/dart2js/subtype_test.dart
@@ -67,30 +67,30 @@
expect(true, num_, Object_);
expect(true, int_, Object_);
expect(true, String_, Object_);
- expect(true, dynamic_, Object_);
+ expect(true, dynamic_, Object_, expectMoreSpecific: false);
expect(false, Object_, num_);
expect(true, num_, num_);
expect(true, int_, num_);
expect(false, String_, num_);
- expect(true, dynamic_, num_);
+ expect(true, dynamic_, num_, expectMoreSpecific: false);
expect(false, Object_, int_);
expect(false, num_, int_);
expect(true, int_, int_);
expect(false, String_, int_);
- expect(true, dynamic_, int_);
+ expect(true, dynamic_, int_, expectMoreSpecific: false);
expect(false, Object_, String_);
expect(false, num_, String_);
expect(false, int_, String_);
expect(true, String_, String_);
- expect(true, dynamic_, String_);
+ expect(true, dynamic_, String_, expectMoreSpecific: false);
- expect(true, Object_, dynamic_, expectMoreSpecific: false);
- expect(true, num_, dynamic_, expectMoreSpecific: false);
- expect(true, int_, dynamic_, expectMoreSpecific: false);
- expect(true, String_, dynamic_, expectMoreSpecific: false);
+ expect(true, Object_, dynamic_);
+ expect(true, num_, dynamic_);
+ expect(true, int_, dynamic_);
+ expect(true, String_, dynamic_);
expect(true, dynamic_, dynamic_);
DartType A_Object = instantiate(A, [Object_]);
@@ -103,36 +103,36 @@
expect(false, A_Object, num_);
expect(false, A_Object, int_);
expect(false, A_Object, String_);
- expect(true, A_Object, dynamic_, expectMoreSpecific: false);
+ expect(true, A_Object, dynamic_);
expect(true, A_Object, A_Object);
expect(true, A_num, A_Object);
expect(true, A_int, A_Object);
expect(true, A_String, A_Object);
- expect(true, A_dynamic, A_Object);
+ expect(true, A_dynamic, A_Object, expectMoreSpecific: false);
expect(false, A_Object, A_num);
expect(true, A_num, A_num);
expect(true, A_int, A_num);
expect(false, A_String, A_num);
- expect(true, A_dynamic, A_num);
+ expect(true, A_dynamic, A_num, expectMoreSpecific: false);
expect(false, A_Object, A_int);
expect(false, A_num, A_int);
expect(true, A_int, A_int);
expect(false, A_String, A_int);
- expect(true, A_dynamic, A_int);
+ expect(true, A_dynamic, A_int, expectMoreSpecific: false);
expect(false, A_Object, A_String);
expect(false, A_num, A_String);
expect(false, A_int, A_String);
expect(true, A_String, A_String);
- expect(true, A_dynamic, A_String);
+ expect(true, A_dynamic, A_String, expectMoreSpecific: false);
- expect(true, A_Object, A_dynamic, expectMoreSpecific: false);
- expect(true, A_num, A_dynamic, expectMoreSpecific: false);
- expect(true, A_int, A_dynamic, expectMoreSpecific: false);
- expect(true, A_String, A_dynamic, expectMoreSpecific: false);
+ expect(true, A_Object, A_dynamic);
+ expect(true, A_num, A_dynamic);
+ expect(true, A_int, A_dynamic);
+ expect(true, A_String, A_dynamic);
expect(true, A_dynamic, A_dynamic);
DartType B_Object_Object = instantiate(B, [Object_, Object_]);
@@ -146,27 +146,27 @@
expect(false, B_Object_Object, A_num);
expect(false, B_Object_Object, A_int);
expect(false, B_Object_Object, A_String);
- expect(true, B_Object_Object, A_dynamic, expectMoreSpecific: false);
+ expect(true, B_Object_Object, A_dynamic);
expect(true, B_num_num, Object_);
expect(true, B_num_num, A_Object);
expect(true, B_num_num, A_num);
expect(false, B_num_num, A_int);
expect(false, B_num_num, A_String);
- expect(true, B_num_num, A_dynamic, expectMoreSpecific: false);
+ expect(true, B_num_num, A_dynamic);
expect(true, B_int_num, Object_);
expect(true, B_int_num, A_Object);
expect(true, B_int_num, A_num);
expect(true, B_int_num, A_int);
expect(false, B_int_num, A_String);
- expect(true, B_int_num, A_dynamic, expectMoreSpecific: false);
+ expect(true, B_int_num, A_dynamic);
expect(true, B_dynamic_dynamic, Object_);
- expect(true, B_dynamic_dynamic, A_Object);
- expect(true, B_dynamic_dynamic, A_num);
- expect(true, B_dynamic_dynamic, A_int);
- expect(true, B_dynamic_dynamic, A_String);
+ expect(true, B_dynamic_dynamic, A_Object, expectMoreSpecific: false);
+ expect(true, B_dynamic_dynamic, A_num, expectMoreSpecific: false);
+ expect(true, B_dynamic_dynamic, A_int, expectMoreSpecific: false);
+ expect(true, B_dynamic_dynamic, A_String, expectMoreSpecific: false);
expect(true, B_dynamic_dynamic, A_dynamic);
expect(true, B_String_dynamic, Object_);
@@ -174,37 +174,37 @@
expect(false, B_String_dynamic, A_num);
expect(false, B_String_dynamic, A_int);
expect(true, B_String_dynamic, A_String);
- expect(true, B_String_dynamic, A_dynamic, expectMoreSpecific: false);
+ expect(true, B_String_dynamic, A_dynamic);
expect(true, B_Object_Object, B_Object_Object);
expect(true, B_num_num, B_Object_Object);
expect(true, B_int_num, B_Object_Object);
- expect(true, B_dynamic_dynamic, B_Object_Object);
- expect(true, B_String_dynamic, B_Object_Object);
+ expect(true, B_dynamic_dynamic, B_Object_Object, expectMoreSpecific: false);
+ expect(true, B_String_dynamic, B_Object_Object, expectMoreSpecific: false);
expect(false, B_Object_Object, B_num_num);
expect(true, B_num_num, B_num_num);
expect(true, B_int_num, B_num_num);
- expect(true, B_dynamic_dynamic, B_num_num);
+ expect(true, B_dynamic_dynamic, B_num_num, expectMoreSpecific: false);
expect(false, B_String_dynamic, B_num_num);
expect(false, B_Object_Object, B_int_num);
expect(false, B_num_num, B_int_num);
expect(true, B_int_num, B_int_num);
- expect(true, B_dynamic_dynamic, B_int_num);
+ expect(true, B_dynamic_dynamic, B_int_num, expectMoreSpecific: false);
expect(false, B_String_dynamic, B_int_num);
- expect(true, B_Object_Object, B_dynamic_dynamic, expectMoreSpecific: false);
- expect(true, B_num_num, B_dynamic_dynamic, expectMoreSpecific: false);
- expect(true, B_int_num, B_dynamic_dynamic, expectMoreSpecific: false);
+ expect(true, B_Object_Object, B_dynamic_dynamic);
+ expect(true, B_num_num, B_dynamic_dynamic);
+ expect(true, B_int_num, B_dynamic_dynamic);
expect(true, B_dynamic_dynamic, B_dynamic_dynamic);
- expect(true, B_String_dynamic, B_dynamic_dynamic,
- expectMoreSpecific: false);
+ expect(true, B_String_dynamic, B_dynamic_dynamic);
expect(false, B_Object_Object, B_String_dynamic);
expect(false, B_num_num, B_String_dynamic);
expect(false, B_int_num, B_String_dynamic);
- expect(true, B_dynamic_dynamic, B_String_dynamic);
+ expect(true, B_dynamic_dynamic, B_String_dynamic,
+ expectMoreSpecific: false);
expect(true, B_String_dynamic, B_String_dynamic);
DartType C_Object_Object = instantiate(C, [Object_, Object_]);
@@ -215,26 +215,27 @@
expect(true, C_Object_Object, B_Object_Object);
expect(false, C_Object_Object, B_num_num);
expect(false, C_Object_Object, B_int_num);
- expect(true, C_Object_Object, B_dynamic_dynamic, expectMoreSpecific: false);
+ expect(true, C_Object_Object, B_dynamic_dynamic);
expect(false, C_Object_Object, B_String_dynamic);
expect(true, C_num_num, B_Object_Object);
expect(true, C_num_num, B_num_num);
expect(false, C_num_num, B_int_num);
- expect(true, C_num_num, B_dynamic_dynamic, expectMoreSpecific: false);
+ expect(true, C_num_num, B_dynamic_dynamic);
expect(false, C_num_num, B_String_dynamic);
expect(true, C_int_String, B_Object_Object);
expect(false, C_int_String, B_num_num);
expect(false, C_int_String, B_int_num);
- expect(true, C_int_String, B_dynamic_dynamic, expectMoreSpecific: false);
- expect(true, C_int_String, B_String_dynamic, expectMoreSpecific: false);
+ expect(true, C_int_String, B_dynamic_dynamic);
+ expect(true, C_int_String, B_String_dynamic);
- expect(true, C_dynamic_dynamic, B_Object_Object);
- expect(true, C_dynamic_dynamic, B_num_num);
- expect(true, C_dynamic_dynamic, B_int_num);
+ expect(true, C_dynamic_dynamic, B_Object_Object, expectMoreSpecific: false);
+ expect(true, C_dynamic_dynamic, B_num_num, expectMoreSpecific: false);
+ expect(true, C_dynamic_dynamic, B_int_num, expectMoreSpecific: false);
expect(true, C_dynamic_dynamic, B_dynamic_dynamic);
- expect(true, C_dynamic_dynamic, B_String_dynamic);
+ expect(true, C_dynamic_dynamic, B_String_dynamic,
+ expectMoreSpecific: false);
expect(false, C_int_String, A_int);
expect(true, C_int_String, A_String);
@@ -586,7 +587,7 @@
expect(false, A_T, num_);
expect(false, A_T, int_);
expect(false, A_T, String_);
- expect(true, A_T, dynamic_, expectMoreSpecific: false);
+ expect(true, A_T, dynamic_);
expect(true, A_T, A_T);
expect(false, A_T, B_T);
@@ -595,7 +596,7 @@
expect(false, B_T, num_);
expect(false, B_T, int_);
expect(false, B_T, String_);
- expect(true, B_T, dynamic_, expectMoreSpecific: false);
+ expect(true, B_T, dynamic_);
expect(true, B_T, B_T);
expect(false, B_T, A_T);
@@ -604,7 +605,7 @@
expect(true, C_T, num_);
expect(false, C_T, int_);
expect(false, C_T, String_);
- expect(true, C_T, dynamic_, expectMoreSpecific: false);
+ expect(true, C_T, dynamic_);
expect(true, C_T, C_T);
expect(false, C_T, A_T);
@@ -613,7 +614,7 @@
expect(true, D_T, num_);
expect(true, D_T, int_);
expect(false, D_T, String_);
- expect(true, D_T, dynamic_, expectMoreSpecific: false);
+ expect(true, D_T, dynamic_);
expect(true, D_T, D_T);
expect(false, D_T, A_T);
@@ -622,7 +623,7 @@
expect(true, E_T, num_);
expect(false, E_T, int_);
expect(false, E_T, String_);
- expect(true, E_T, dynamic_, expectMoreSpecific: false);
+ expect(true, E_T, dynamic_);
expect(true, E_T, E_T);
expect(true, E_T, E_S);
expect(false, E_T, A_T);
@@ -631,7 +632,7 @@
expect(true, E_S, num_);
expect(false, E_S, int_);
expect(false, E_S, String_);
- expect(true, E_S, dynamic_, expectMoreSpecific: false);
+ expect(true, E_S, dynamic_);
expect(false, E_S, E_T);
expect(true, E_S, E_S);
expect(false, E_S, A_T);
@@ -641,7 +642,7 @@
expect(true, F_T, num_);
expect(false, F_T, int_);
expect(false, F_T, String_);
- expect(true, F_T, dynamic_, expectMoreSpecific: false);
+ expect(true, F_T, dynamic_);
expect(false, F_T, F_S);
expect(true, F_T, F_T);
expect(false, F_T, A_T);
@@ -650,7 +651,7 @@
expect(true, F_S, num_);
expect(false, F_S, int_);
expect(false, F_S, String_);
- expect(true, F_S, dynamic_, expectMoreSpecific: false);
+ expect(true, F_S, dynamic_);
expect(true, F_S, F_S);
expect(true, F_S, F_T);
expect(false, F_S, A_T);
@@ -660,7 +661,7 @@
expect(false, G_T, num_);
expect(false, G_T, int_);
expect(false, G_T, String_);
- expect(true, G_T, dynamic_, expectMoreSpecific: false);
+ expect(true, G_T, dynamic_);
expect(true, G_T, G_T);
expect(false, G_T, A_T);
@@ -669,7 +670,7 @@
expect(false, H_T, num_);
expect(false, H_T, int_);
expect(false, H_T, String_);
- expect(true, H_T, dynamic_, expectMoreSpecific: false);
+ expect(true, H_T, dynamic_);
expect(true, H_T, H_T);
expect(true, H_T, H_S);
expect(false, H_T, A_T);
@@ -678,7 +679,7 @@
expect(false, H_S, num_);
expect(false, H_S, int_);
expect(false, H_S, String_);
- expect(true, H_S, dynamic_, expectMoreSpecific: false);
+ expect(true, H_S, dynamic_);
expect(true, H_S, H_T);
expect(true, H_S, H_S);
expect(false, H_S, A_T);
@@ -688,7 +689,7 @@
expect(false, I_T, num_);
expect(false, I_T, int_);
expect(false, I_T, String_);
- expect(true, I_T, dynamic_, expectMoreSpecific: false);
+ expect(true, I_T, dynamic_);
expect(true, I_T, I_T);
expect(true, I_T, I_S);
expect(true, I_T, I_U);
@@ -698,7 +699,7 @@
expect(false, I_S, num_);
expect(false, I_S, int_);
expect(false, I_S, String_);
- expect(true, I_S, dynamic_, expectMoreSpecific: false);
+ expect(true, I_S, dynamic_);
expect(true, I_S, I_T);
expect(true, I_S, I_S);
expect(true, I_S, I_U);
@@ -708,7 +709,7 @@
expect(false, I_U, num_);
expect(false, I_U, int_);
expect(false, I_U, String_);
- expect(true, I_U, dynamic_, expectMoreSpecific: false);
+ expect(true, I_U, dynamic_);
expect(true, I_U, I_T);
expect(true, I_U, I_S);
expect(true, I_U, I_U);
@@ -719,7 +720,7 @@
expect(false, J_T, num_);
expect(false, J_T, int_);
expect(false, J_T, String_);
- expect(true, J_T, dynamic_, expectMoreSpecific: false);
+ expect(true, J_T, dynamic_);
expect(true, J_T, J_T);
expect(true, J_T, J_S);
expect(true, J_T, J_U);
@@ -729,7 +730,7 @@
expect(false, J_S, num_);
expect(false, J_S, int_);
expect(false, J_S, String_);
- expect(true, J_S, dynamic_, expectMoreSpecific: false);
+ expect(true, J_S, dynamic_);
expect(false, J_S, J_T);
expect(true, J_S, J_S);
expect(true, J_S, J_U);
@@ -739,7 +740,7 @@
expect(false, J_U, num_);
expect(false, J_U, int_);
expect(false, J_U, String_);
- expect(true, J_U, dynamic_, expectMoreSpecific: false);
+ expect(true, J_U, dynamic_);
expect(false, J_U, J_T);
expect(true, J_U, J_S);
expect(true, J_U, J_U);
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 19539ae..8ca53a8 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -1554,17 +1554,17 @@
infos: []);
check('''
- D d = new E();
- if (d is E<int>) {
+ D<int> d = new E();
+ if (d is E) {
var x = d.e;
}''',
warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
- hints: [MessageKind.NOT_MORE_SPECIFIC_RAW],
+ hints: [MessageKind.NOT_MORE_SPECIFIC],
infos: []);
check('''
- D d = new E();
- if (d is E<int>) {
+ D<int> d = new E();
+ if (d is E) {
var x = d.f; // Type promotion wouldn't help.
}''',
warnings: [MessageKind.MEMBER_NOT_FOUND.warning],
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index fd7cbf4..2d1a4d5 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -8,18 +8,18 @@
import "../../../sdk/lib/_internal/compiler/implementation/ssa/ssa.dart";
import "../../../sdk/lib/_internal/compiler/implementation/types/types.dart";
-const CONFLICTING = HType.CONFLICTING;
-const UNKNOWN = HType.UNKNOWN;
-const BOOLEAN = HType.BOOLEAN;
-const NUMBER = HType.NUMBER;
-const INTEGER = HType.INTEGER;
-const DOUBLE = HType.DOUBLE;
-const BOOLEAN_OR_NULL = HType.BOOLEAN_OR_NULL;
-const NUMBER_OR_NULL = HType.NUMBER_OR_NULL;
-const INTEGER_OR_NULL = HType.INTEGER_OR_NULL;
-const DOUBLE_OR_NULL = HType.DOUBLE_OR_NULL;
-const NULL = HType.NULL;
-const NON_NULL = HType.NON_NULL;
+HType nullType;
+HType objectType;
+HType jsBoolean;
+HType jsNumber;
+HType jsInteger;
+HType jsDouble;
+HType jsBooleanOrNull;
+HType jsNumberOrNull;
+HType jsIntegerOrNull;
+HType jsDoubleOrNull;
+HType emptyType;
+HType dynamicType;
var patternClass;
HType nonPrimitive1;
@@ -101,283 +101,283 @@
rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
check(type1, type2, predicate) => ruleSet.check(type1, type2, predicate);
- rule(CONFLICTING, CONFLICTING, CONFLICTING);
- rule(CONFLICTING, UNKNOWN, UNKNOWN);
- rule(CONFLICTING, BOOLEAN, BOOLEAN);
- rule(CONFLICTING, NUMBER, NUMBER);
- rule(CONFLICTING, INTEGER, INTEGER);
- rule(CONFLICTING, DOUBLE, DOUBLE);
- rule(CONFLICTING, jsIndexable, jsIndexable);
- rule(CONFLICTING, jsString, jsString);
- rule(CONFLICTING, jsReadableArray, jsReadableArray);
- rule(CONFLICTING, jsMutableArray, jsMutableArray);
- rule(CONFLICTING, jsExtendableArray, jsExtendableArray);
- rule(CONFLICTING, nonPrimitive1, nonPrimitive1);
- rule(CONFLICTING, nonPrimitive2, nonPrimitive2);
- rule(CONFLICTING, potentialArray, potentialArray);
- rule(CONFLICTING, potentialString, potentialString);
- rule(CONFLICTING, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
- rule(CONFLICTING, NUMBER_OR_NULL, NUMBER_OR_NULL);
- rule(CONFLICTING, INTEGER_OR_NULL, INTEGER_OR_NULL);
- rule(CONFLICTING, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
- rule(CONFLICTING, jsStringOrNull, jsStringOrNull);
- rule(CONFLICTING, NULL, NULL);
- rule(CONFLICTING, jsFixedArray, jsFixedArray);
+ rule(emptyType, emptyType, emptyType);
+ rule(emptyType, dynamicType, dynamicType);
+ rule(emptyType, jsBoolean, jsBoolean);
+ rule(emptyType, jsNumber, jsNumber);
+ rule(emptyType, jsInteger, jsInteger);
+ rule(emptyType, jsDouble, jsDouble);
+ rule(emptyType, jsIndexable, jsIndexable);
+ rule(emptyType, jsString, jsString);
+ rule(emptyType, jsReadableArray, jsReadableArray);
+ rule(emptyType, jsMutableArray, jsMutableArray);
+ rule(emptyType, jsExtendableArray, jsExtendableArray);
+ rule(emptyType, nonPrimitive1, nonPrimitive1);
+ rule(emptyType, nonPrimitive2, nonPrimitive2);
+ rule(emptyType, potentialArray, potentialArray);
+ rule(emptyType, potentialString, potentialString);
+ rule(emptyType, jsBooleanOrNull, jsBooleanOrNull);
+ rule(emptyType, jsNumberOrNull, jsNumberOrNull);
+ rule(emptyType, jsIntegerOrNull, jsIntegerOrNull);
+ rule(emptyType, jsDoubleOrNull, jsDoubleOrNull);
+ rule(emptyType, jsStringOrNull, jsStringOrNull);
+ rule(emptyType, nullType, nullType);
+ rule(emptyType, jsFixedArray, jsFixedArray);
- rule(UNKNOWN, UNKNOWN, UNKNOWN);
- rule(UNKNOWN, BOOLEAN, UNKNOWN);
- rule(UNKNOWN, NUMBER, UNKNOWN);
- rule(UNKNOWN, INTEGER, UNKNOWN);
- rule(UNKNOWN, DOUBLE, UNKNOWN);
- rule(UNKNOWN, jsIndexable, UNKNOWN);
- rule(UNKNOWN, jsString, UNKNOWN);
- rule(UNKNOWN, jsReadableArray, UNKNOWN);
- rule(UNKNOWN, jsMutableArray, UNKNOWN);
- rule(UNKNOWN, jsExtendableArray, UNKNOWN);
- rule(UNKNOWN, nonPrimitive1, UNKNOWN);
- rule(UNKNOWN, nonPrimitive2, UNKNOWN);
- rule(UNKNOWN, potentialArray, UNKNOWN);
- rule(UNKNOWN, potentialString, UNKNOWN);
- rule(UNKNOWN, BOOLEAN_OR_NULL, UNKNOWN);
- rule(UNKNOWN, NUMBER_OR_NULL, UNKNOWN);
- rule(UNKNOWN, INTEGER_OR_NULL, UNKNOWN);
- rule(UNKNOWN, DOUBLE_OR_NULL, UNKNOWN);
- rule(UNKNOWN, jsStringOrNull, UNKNOWN);
- rule(UNKNOWN, NULL, UNKNOWN);
- rule(UNKNOWN, jsFixedArray, UNKNOWN);
+ rule(dynamicType, dynamicType, dynamicType);
+ rule(dynamicType, jsBoolean, dynamicType);
+ rule(dynamicType, jsNumber, dynamicType);
+ rule(dynamicType, jsInteger, dynamicType);
+ rule(dynamicType, jsDouble, dynamicType);
+ rule(dynamicType, jsIndexable, dynamicType);
+ rule(dynamicType, jsString, dynamicType);
+ rule(dynamicType, jsReadableArray, dynamicType);
+ rule(dynamicType, jsMutableArray, dynamicType);
+ rule(dynamicType, jsExtendableArray, dynamicType);
+ rule(dynamicType, nonPrimitive1, dynamicType);
+ rule(dynamicType, nonPrimitive2, dynamicType);
+ rule(dynamicType, potentialArray, dynamicType);
+ rule(dynamicType, potentialString, dynamicType);
+ rule(dynamicType, jsBooleanOrNull, dynamicType);
+ rule(dynamicType, jsNumberOrNull, dynamicType);
+ rule(dynamicType, jsIntegerOrNull, dynamicType);
+ rule(dynamicType, jsDoubleOrNull, dynamicType);
+ rule(dynamicType, jsStringOrNull, dynamicType);
+ rule(dynamicType, nullType, dynamicType);
+ rule(dynamicType, jsFixedArray, dynamicType);
- rule(BOOLEAN, BOOLEAN, BOOLEAN);
- rule(BOOLEAN, NUMBER, jsInterceptor);
- rule(BOOLEAN, INTEGER, jsInterceptor);
- rule(BOOLEAN, DOUBLE, jsInterceptor);
- rule(BOOLEAN, jsIndexable, NON_NULL);
- rule(BOOLEAN, jsString, jsInterceptor);
- rule(BOOLEAN, jsReadableArray, jsInterceptor);
- rule(BOOLEAN, jsMutableArray, jsInterceptor);
- rule(BOOLEAN, jsExtendableArray, jsInterceptor);
- rule(BOOLEAN, nonPrimitive1, NON_NULL);
- rule(BOOLEAN, nonPrimitive2, NON_NULL);
- rule(BOOLEAN, potentialArray, UNKNOWN);
- rule(BOOLEAN, potentialString, UNKNOWN);
- rule(BOOLEAN, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
- rule(BOOLEAN, NUMBER_OR_NULL, jsInterceptorOrNull);
- rule(BOOLEAN, INTEGER_OR_NULL, jsInterceptorOrNull);
- rule(BOOLEAN, DOUBLE_OR_NULL, jsInterceptorOrNull);
- rule(BOOLEAN, jsStringOrNull, jsInterceptorOrNull);
- rule(BOOLEAN, NULL, BOOLEAN_OR_NULL);
- rule(BOOLEAN, jsFixedArray, jsInterceptor);
+ rule(jsBoolean, jsBoolean, jsBoolean);
+ rule(jsBoolean, jsNumber, jsInterceptor);
+ rule(jsBoolean, jsInteger, jsInterceptor);
+ rule(jsBoolean, jsDouble, jsInterceptor);
+ rule(jsBoolean, jsIndexable, objectType);
+ rule(jsBoolean, jsString, jsInterceptor);
+ rule(jsBoolean, jsReadableArray, jsInterceptor);
+ rule(jsBoolean, jsMutableArray, jsInterceptor);
+ rule(jsBoolean, jsExtendableArray, jsInterceptor);
+ rule(jsBoolean, nonPrimitive1, objectType);
+ rule(jsBoolean, nonPrimitive2, objectType);
+ rule(jsBoolean, potentialArray, dynamicType);
+ rule(jsBoolean, potentialString, dynamicType);
+ rule(jsBoolean, jsBooleanOrNull, jsBooleanOrNull);
+ rule(jsBoolean, jsNumberOrNull, jsInterceptorOrNull);
+ rule(jsBoolean, jsIntegerOrNull, jsInterceptorOrNull);
+ rule(jsBoolean, jsDoubleOrNull, jsInterceptorOrNull);
+ rule(jsBoolean, jsStringOrNull, jsInterceptorOrNull);
+ rule(jsBoolean, nullType, jsBooleanOrNull);
+ rule(jsBoolean, jsFixedArray, jsInterceptor);
- rule(NUMBER, NUMBER, NUMBER);
- rule(NUMBER, INTEGER, NUMBER);
- rule(NUMBER, DOUBLE, NUMBER);
- rule(NUMBER, jsIndexable, NON_NULL);
- rule(NUMBER, jsString, jsInterceptor);
- rule(NUMBER, jsReadableArray, jsInterceptor);
- rule(NUMBER, jsMutableArray, jsInterceptor);
- rule(NUMBER, jsExtendableArray, jsInterceptor);
- rule(NUMBER, nonPrimitive1, NON_NULL);
- rule(NUMBER, nonPrimitive2, NON_NULL);
- rule(NUMBER, potentialArray, UNKNOWN);
- rule(NUMBER, potentialString, UNKNOWN);
- rule(NUMBER, BOOLEAN_OR_NULL, jsInterceptorOrNull);
- rule(NUMBER, NUMBER_OR_NULL, NUMBER_OR_NULL);
- rule(NUMBER, INTEGER_OR_NULL, NUMBER_OR_NULL);
- rule(NUMBER, DOUBLE_OR_NULL, NUMBER_OR_NULL);
- rule(NUMBER, jsStringOrNull, jsInterceptorOrNull);
- rule(NUMBER, NULL, NUMBER_OR_NULL);
- rule(NUMBER, jsFixedArray, jsInterceptor);
+ rule(jsNumber, jsNumber, jsNumber);
+ rule(jsNumber, jsInteger, jsNumber);
+ rule(jsNumber, jsDouble, jsNumber);
+ rule(jsNumber, jsIndexable, objectType);
+ rule(jsNumber, jsString, jsInterceptor);
+ rule(jsNumber, jsReadableArray, jsInterceptor);
+ rule(jsNumber, jsMutableArray, jsInterceptor);
+ rule(jsNumber, jsExtendableArray, jsInterceptor);
+ rule(jsNumber, nonPrimitive1, objectType);
+ rule(jsNumber, nonPrimitive2, objectType);
+ rule(jsNumber, potentialArray, dynamicType);
+ rule(jsNumber, potentialString, dynamicType);
+ rule(jsNumber, jsBooleanOrNull, jsInterceptorOrNull);
+ rule(jsNumber, jsNumberOrNull, jsNumberOrNull);
+ rule(jsNumber, jsIntegerOrNull, jsNumberOrNull);
+ rule(jsNumber, jsDoubleOrNull, jsNumberOrNull);
+ rule(jsNumber, jsStringOrNull, jsInterceptorOrNull);
+ rule(jsNumber, nullType, jsNumberOrNull);
+ rule(jsNumber, jsFixedArray, jsInterceptor);
- rule(INTEGER, INTEGER, INTEGER);
- rule(INTEGER, DOUBLE, NUMBER);
- rule(INTEGER, jsIndexable, NON_NULL);
- rule(INTEGER, jsString, jsInterceptor);
- rule(INTEGER, jsReadableArray, jsInterceptor);
- rule(INTEGER, jsMutableArray, jsInterceptor);
- rule(INTEGER, jsExtendableArray, jsInterceptor);
- rule(INTEGER, nonPrimitive1, NON_NULL);
- rule(INTEGER, nonPrimitive2, NON_NULL);
- rule(INTEGER, potentialArray, UNKNOWN);
- rule(INTEGER, potentialString, UNKNOWN);
- rule(INTEGER, BOOLEAN_OR_NULL, jsInterceptorOrNull);
- rule(INTEGER, NUMBER_OR_NULL, NUMBER_OR_NULL);
- rule(INTEGER, INTEGER_OR_NULL, INTEGER_OR_NULL);
- rule(INTEGER, DOUBLE_OR_NULL, NUMBER_OR_NULL);
- rule(INTEGER, jsStringOrNull, jsInterceptorOrNull);
- rule(INTEGER, NULL, INTEGER_OR_NULL);
- rule(INTEGER, jsFixedArray, jsInterceptor);
+ rule(jsInteger, jsInteger, jsInteger);
+ rule(jsInteger, jsDouble, jsNumber);
+ rule(jsInteger, jsIndexable, objectType);
+ rule(jsInteger, jsString, jsInterceptor);
+ rule(jsInteger, jsReadableArray, jsInterceptor);
+ rule(jsInteger, jsMutableArray, jsInterceptor);
+ rule(jsInteger, jsExtendableArray, jsInterceptor);
+ rule(jsInteger, nonPrimitive1, objectType);
+ rule(jsInteger, nonPrimitive2, objectType);
+ rule(jsInteger, potentialArray, dynamicType);
+ rule(jsInteger, potentialString, dynamicType);
+ rule(jsInteger, jsBooleanOrNull, jsInterceptorOrNull);
+ rule(jsInteger, jsNumberOrNull, jsNumberOrNull);
+ rule(jsInteger, jsIntegerOrNull, jsIntegerOrNull);
+ rule(jsInteger, jsDoubleOrNull, jsNumberOrNull);
+ rule(jsInteger, jsStringOrNull, jsInterceptorOrNull);
+ rule(jsInteger, nullType, jsIntegerOrNull);
+ rule(jsInteger, jsFixedArray, jsInterceptor);
- rule(DOUBLE, DOUBLE, DOUBLE);
- rule(DOUBLE, jsIndexable, NON_NULL);
- rule(DOUBLE, jsString, jsInterceptor);
- rule(DOUBLE, jsReadableArray, jsInterceptor);
- rule(DOUBLE, jsMutableArray, jsInterceptor);
- rule(DOUBLE, jsExtendableArray, jsInterceptor);
- rule(DOUBLE, nonPrimitive1, NON_NULL);
- rule(DOUBLE, nonPrimitive2, NON_NULL);
- rule(DOUBLE, potentialArray, UNKNOWN);
- rule(DOUBLE, potentialString, UNKNOWN);
- rule(DOUBLE, BOOLEAN_OR_NULL, jsInterceptorOrNull);
- rule(DOUBLE, NUMBER_OR_NULL, NUMBER_OR_NULL);
- rule(DOUBLE, INTEGER_OR_NULL, NUMBER_OR_NULL);
- rule(DOUBLE, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
- rule(DOUBLE, jsStringOrNull, jsInterceptorOrNull);
- rule(DOUBLE, NULL, DOUBLE_OR_NULL);
- rule(DOUBLE, jsFixedArray, jsInterceptor);
+ rule(jsDouble, jsDouble, jsDouble);
+ rule(jsDouble, jsIndexable, objectType);
+ rule(jsDouble, jsString, jsInterceptor);
+ rule(jsDouble, jsReadableArray, jsInterceptor);
+ rule(jsDouble, jsMutableArray, jsInterceptor);
+ rule(jsDouble, jsExtendableArray, jsInterceptor);
+ rule(jsDouble, nonPrimitive1, objectType);
+ rule(jsDouble, nonPrimitive2, objectType);
+ rule(jsDouble, potentialArray, dynamicType);
+ rule(jsDouble, potentialString, dynamicType);
+ rule(jsDouble, jsBooleanOrNull, jsInterceptorOrNull);
+ rule(jsDouble, jsNumberOrNull, jsNumberOrNull);
+ rule(jsDouble, jsIntegerOrNull, jsNumberOrNull);
+ rule(jsDouble, jsDoubleOrNull, jsDoubleOrNull);
+ rule(jsDouble, jsStringOrNull, jsInterceptorOrNull);
+ rule(jsDouble, nullType, jsDoubleOrNull);
+ rule(jsDouble, jsFixedArray, jsInterceptor);
rule(jsIndexable, jsIndexable, jsIndexable);
rule(jsIndexable, jsString, jsIndexable);
rule(jsIndexable, jsReadableArray, jsIndexable);
rule(jsIndexable, jsMutableArray, jsIndexable);
rule(jsIndexable, jsExtendableArray, jsIndexable);
- rule(jsIndexable, nonPrimitive1, NON_NULL);
- rule(jsIndexable, nonPrimitive2, NON_NULL);
- rule(jsIndexable, potentialArray, UNKNOWN);
- rule(jsIndexable, potentialString, UNKNOWN);
- rule(jsIndexable, BOOLEAN_OR_NULL, UNKNOWN);
- rule(jsIndexable, NUMBER_OR_NULL, UNKNOWN);
- rule(jsIndexable, INTEGER_OR_NULL, UNKNOWN);
- rule(jsIndexable, DOUBLE_OR_NULL, UNKNOWN);
+ rule(jsIndexable, nonPrimitive1, objectType);
+ rule(jsIndexable, nonPrimitive2, objectType);
+ rule(jsIndexable, potentialArray, dynamicType);
+ rule(jsIndexable, potentialString, dynamicType);
+ rule(jsIndexable, jsBooleanOrNull, dynamicType);
+ rule(jsIndexable, jsNumberOrNull, dynamicType);
+ rule(jsIndexable, jsIntegerOrNull, dynamicType);
+ rule(jsIndexable, jsDoubleOrNull, dynamicType);
rule(jsIndexable, jsStringOrNull, jsIndexableOrNull);
- rule(jsIndexable, NULL, jsIndexableOrNull);
+ rule(jsIndexable, nullType, jsIndexableOrNull);
rule(jsIndexable, jsFixedArray, jsIndexable);
rule(jsString, jsString, jsString);
rule(jsString, jsReadableArray, jsIndexable);
rule(jsString, jsMutableArray, jsIndexable);
rule(jsString, jsExtendableArray, jsIndexable);
- rule(jsString, nonPrimitive1, NON_NULL);
- rule(jsString, nonPrimitive2, NON_NULL);
- rule(jsString, potentialArray, UNKNOWN);
+ rule(jsString, nonPrimitive1, objectType);
+ rule(jsString, nonPrimitive2, objectType);
+ rule(jsString, potentialArray, dynamicType);
rule(jsString, potentialString, potentialString);
- rule(jsString, BOOLEAN_OR_NULL, jsInterceptorOrNull);
- rule(jsString, NUMBER_OR_NULL, jsInterceptorOrNull);
- rule(jsString, INTEGER_OR_NULL, jsInterceptorOrNull);
- rule(jsString, DOUBLE_OR_NULL, jsInterceptorOrNull);
+ rule(jsString, jsBooleanOrNull, jsInterceptorOrNull);
+ rule(jsString, jsNumberOrNull, jsInterceptorOrNull);
+ rule(jsString, jsIntegerOrNull, jsInterceptorOrNull);
+ rule(jsString, jsDoubleOrNull, jsInterceptorOrNull);
rule(jsString, jsStringOrNull, jsStringOrNull);
- rule(jsString, NULL, jsStringOrNull);
+ rule(jsString, nullType, jsStringOrNull);
rule(jsString, jsFixedArray, jsIndexable);
rule(jsReadableArray, jsReadableArray, jsReadableArray);
rule(jsReadableArray, jsMutableArray, jsReadableArray);
rule(jsReadableArray, jsExtendableArray, jsReadableArray);
- rule(jsReadableArray, nonPrimitive1, NON_NULL);
- rule(jsReadableArray, nonPrimitive2, NON_NULL);
+ rule(jsReadableArray, nonPrimitive1, objectType);
+ rule(jsReadableArray, nonPrimitive2, objectType);
rule(jsReadableArray, potentialArray, potentialArray);
- rule(jsReadableArray, potentialString, UNKNOWN);
- rule(jsReadableArray, BOOLEAN_OR_NULL, jsInterceptorOrNull);
- rule(jsReadableArray, NUMBER_OR_NULL, jsInterceptorOrNull);
- rule(jsReadableArray, INTEGER_OR_NULL, jsInterceptorOrNull);
- rule(jsReadableArray, DOUBLE_OR_NULL, jsInterceptorOrNull);
+ rule(jsReadableArray, potentialString, dynamicType);
+ rule(jsReadableArray, jsBooleanOrNull, jsInterceptorOrNull);
+ rule(jsReadableArray, jsNumberOrNull, jsInterceptorOrNull);
+ rule(jsReadableArray, jsIntegerOrNull, jsInterceptorOrNull);
+ rule(jsReadableArray, jsDoubleOrNull, jsInterceptorOrNull);
rule(jsReadableArray, jsStringOrNull, jsIndexableOrNull);
- rule(jsReadableArray, NULL, jsArrayOrNull);
+ rule(jsReadableArray, nullType, jsArrayOrNull);
rule(jsReadableArray, jsFixedArray, jsReadableArray);
rule(jsMutableArray, jsMutableArray, jsMutableArray);
rule(jsMutableArray, jsExtendableArray, jsMutableArray);
- rule(jsMutableArray, nonPrimitive1, NON_NULL);
- rule(jsMutableArray, nonPrimitive2, NON_NULL);
+ rule(jsMutableArray, nonPrimitive1, objectType);
+ rule(jsMutableArray, nonPrimitive2, objectType);
rule(jsMutableArray, potentialArray, potentialArray);
- rule(jsMutableArray, potentialString, UNKNOWN);
- rule(jsMutableArray, BOOLEAN_OR_NULL, jsInterceptorOrNull);
- rule(jsMutableArray, NUMBER_OR_NULL, jsInterceptorOrNull);
- rule(jsMutableArray, INTEGER_OR_NULL, jsInterceptorOrNull);
- rule(jsMutableArray, DOUBLE_OR_NULL, jsInterceptorOrNull);
+ rule(jsMutableArray, potentialString, dynamicType);
+ rule(jsMutableArray, jsBooleanOrNull, jsInterceptorOrNull);
+ rule(jsMutableArray, jsNumberOrNull, jsInterceptorOrNull);
+ rule(jsMutableArray, jsIntegerOrNull, jsInterceptorOrNull);
+ rule(jsMutableArray, jsDoubleOrNull, jsInterceptorOrNull);
rule(jsMutableArray, jsStringOrNull, jsIndexableOrNull);
- rule(jsMutableArray, NULL, jsMutableArrayOrNull);
+ rule(jsMutableArray, nullType, jsMutableArrayOrNull);
rule(jsMutableArray, jsFixedArray, jsMutableArray);
rule(jsExtendableArray, jsExtendableArray, jsExtendableArray);
- rule(jsExtendableArray, nonPrimitive1, NON_NULL);
- rule(jsExtendableArray, nonPrimitive2, NON_NULL);
+ rule(jsExtendableArray, nonPrimitive1, objectType);
+ rule(jsExtendableArray, nonPrimitive2, objectType);
rule(jsExtendableArray, potentialArray, potentialArray);
- rule(jsExtendableArray, potentialString, UNKNOWN);
- rule(jsExtendableArray, BOOLEAN_OR_NULL, jsInterceptorOrNull);
- rule(jsExtendableArray, NUMBER_OR_NULL, jsInterceptorOrNull);
- rule(jsExtendableArray, INTEGER_OR_NULL, jsInterceptorOrNull);
- rule(jsExtendableArray, DOUBLE_OR_NULL, jsInterceptorOrNull);
+ rule(jsExtendableArray, potentialString, dynamicType);
+ rule(jsExtendableArray, jsBooleanOrNull, jsInterceptorOrNull);
+ rule(jsExtendableArray, jsNumberOrNull, jsInterceptorOrNull);
+ rule(jsExtendableArray, jsIntegerOrNull, jsInterceptorOrNull);
+ rule(jsExtendableArray, jsDoubleOrNull, jsInterceptorOrNull);
rule(jsExtendableArray, jsStringOrNull, jsIndexableOrNull);
- rule(jsExtendableArray, NULL, jsExtendableArrayOrNull);
+ rule(jsExtendableArray, nullType, jsExtendableArrayOrNull);
rule(jsExtendableArray, jsFixedArray, jsMutableArray);
rule(nonPrimitive1, nonPrimitive1, nonPrimitive1);
- rule(nonPrimitive1, nonPrimitive2, NON_NULL);
- rule(nonPrimitive1, potentialArray, UNKNOWN);
- rule(nonPrimitive1, potentialString, UNKNOWN);
- rule(nonPrimitive1, BOOLEAN_OR_NULL, UNKNOWN);
- rule(nonPrimitive1, NUMBER_OR_NULL, UNKNOWN);
- rule(nonPrimitive1, INTEGER_OR_NULL, UNKNOWN);
- rule(nonPrimitive1, DOUBLE_OR_NULL, UNKNOWN);
- rule(nonPrimitive1, jsStringOrNull, UNKNOWN);
- rule(nonPrimitive1, jsFixedArray, NON_NULL);
+ rule(nonPrimitive1, nonPrimitive2, objectType);
+ rule(nonPrimitive1, potentialArray, dynamicType);
+ rule(nonPrimitive1, potentialString, dynamicType);
+ rule(nonPrimitive1, jsBooleanOrNull, dynamicType);
+ rule(nonPrimitive1, jsNumberOrNull, dynamicType);
+ rule(nonPrimitive1, jsIntegerOrNull, dynamicType);
+ rule(nonPrimitive1, jsDoubleOrNull, dynamicType);
+ rule(nonPrimitive1, jsStringOrNull, dynamicType);
+ rule(nonPrimitive1, jsFixedArray, objectType);
rule(nonPrimitive2, nonPrimitive2, nonPrimitive2);
- rule(nonPrimitive2, potentialArray, UNKNOWN);
- rule(nonPrimitive2, potentialString, UNKNOWN);
- rule(nonPrimitive2, BOOLEAN_OR_NULL, UNKNOWN);
- rule(nonPrimitive2, NUMBER_OR_NULL, UNKNOWN);
- rule(nonPrimitive2, INTEGER_OR_NULL, UNKNOWN);
- rule(nonPrimitive2, DOUBLE_OR_NULL, UNKNOWN);
- rule(nonPrimitive2, jsStringOrNull, UNKNOWN);
- rule(nonPrimitive2, jsFixedArray, NON_NULL);
+ rule(nonPrimitive2, potentialArray, dynamicType);
+ rule(nonPrimitive2, potentialString, dynamicType);
+ rule(nonPrimitive2, jsBooleanOrNull, dynamicType);
+ rule(nonPrimitive2, jsNumberOrNull, dynamicType);
+ rule(nonPrimitive2, jsIntegerOrNull, dynamicType);
+ rule(nonPrimitive2, jsDoubleOrNull, dynamicType);
+ rule(nonPrimitive2, jsStringOrNull, dynamicType);
+ rule(nonPrimitive2, jsFixedArray, objectType);
rule(potentialArray, potentialArray, potentialArray);
- rule(potentialArray, potentialString, UNKNOWN);
- rule(potentialArray, BOOLEAN_OR_NULL, UNKNOWN);
- rule(potentialArray, NUMBER_OR_NULL, UNKNOWN);
- rule(potentialArray, INTEGER_OR_NULL, UNKNOWN);
- rule(potentialArray, DOUBLE_OR_NULL, UNKNOWN);
- rule(potentialArray, jsStringOrNull, UNKNOWN);
- rule(potentialArray, NULL, potentialArray);
+ rule(potentialArray, potentialString, dynamicType);
+ rule(potentialArray, jsBooleanOrNull, dynamicType);
+ rule(potentialArray, jsNumberOrNull, dynamicType);
+ rule(potentialArray, jsIntegerOrNull, dynamicType);
+ rule(potentialArray, jsDoubleOrNull, dynamicType);
+ rule(potentialArray, jsStringOrNull, dynamicType);
+ rule(potentialArray, nullType, potentialArray);
rule(potentialArray, jsFixedArray, potentialArray);
rule(potentialString, potentialString, potentialString);
- rule(potentialString, BOOLEAN_OR_NULL, UNKNOWN);
- rule(potentialString, NUMBER_OR_NULL, UNKNOWN);
- rule(potentialString, INTEGER_OR_NULL, UNKNOWN);
- rule(potentialString, DOUBLE_OR_NULL, UNKNOWN);
+ rule(potentialString, jsBooleanOrNull, dynamicType);
+ rule(potentialString, jsNumberOrNull, dynamicType);
+ rule(potentialString, jsIntegerOrNull, dynamicType);
+ rule(potentialString, jsDoubleOrNull, dynamicType);
rule(potentialString, jsStringOrNull, potentialString);
- rule(potentialString, NULL, potentialString);
- rule(potentialString, jsFixedArray, UNKNOWN);
+ rule(potentialString, nullType, potentialString);
+ rule(potentialString, jsFixedArray, dynamicType);
- rule(BOOLEAN_OR_NULL, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
- rule(BOOLEAN_OR_NULL, NUMBER_OR_NULL, jsInterceptorOrNull);
- rule(BOOLEAN_OR_NULL, INTEGER_OR_NULL, jsInterceptorOrNull);
- rule(BOOLEAN_OR_NULL, DOUBLE_OR_NULL, jsInterceptorOrNull);
- rule(BOOLEAN_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
- rule(BOOLEAN_OR_NULL, NULL, BOOLEAN_OR_NULL);
- rule(BOOLEAN_OR_NULL, jsFixedArray, jsInterceptorOrNull);
+ rule(jsBooleanOrNull, jsBooleanOrNull, jsBooleanOrNull);
+ rule(jsBooleanOrNull, jsNumberOrNull, jsInterceptorOrNull);
+ rule(jsBooleanOrNull, jsIntegerOrNull, jsInterceptorOrNull);
+ rule(jsBooleanOrNull, jsDoubleOrNull, jsInterceptorOrNull);
+ rule(jsBooleanOrNull, jsStringOrNull, jsInterceptorOrNull);
+ rule(jsBooleanOrNull, nullType, jsBooleanOrNull);
+ rule(jsBooleanOrNull, jsFixedArray, jsInterceptorOrNull);
- rule(NUMBER_OR_NULL, NUMBER_OR_NULL, NUMBER_OR_NULL);
- rule(NUMBER_OR_NULL, INTEGER_OR_NULL, NUMBER_OR_NULL);
- rule(NUMBER_OR_NULL, DOUBLE_OR_NULL, NUMBER_OR_NULL);
- rule(NUMBER_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
- rule(NUMBER_OR_NULL, NULL, NUMBER_OR_NULL);
- rule(NUMBER_OR_NULL, jsFixedArray, jsInterceptorOrNull);
+ rule(jsNumberOrNull, jsNumberOrNull, jsNumberOrNull);
+ rule(jsNumberOrNull, jsIntegerOrNull, jsNumberOrNull);
+ rule(jsNumberOrNull, jsDoubleOrNull, jsNumberOrNull);
+ rule(jsNumberOrNull, jsStringOrNull, jsInterceptorOrNull);
+ rule(jsNumberOrNull, nullType, jsNumberOrNull);
+ rule(jsNumberOrNull, jsFixedArray, jsInterceptorOrNull);
- rule(INTEGER_OR_NULL, INTEGER_OR_NULL, INTEGER_OR_NULL);
- rule(INTEGER_OR_NULL, DOUBLE_OR_NULL, NUMBER_OR_NULL);
- rule(INTEGER_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
- rule(INTEGER_OR_NULL, NULL, INTEGER_OR_NULL);
- rule(INTEGER_OR_NULL, jsFixedArray, jsInterceptorOrNull);
+ rule(jsIntegerOrNull, jsIntegerOrNull, jsIntegerOrNull);
+ rule(jsIntegerOrNull, jsDoubleOrNull, jsNumberOrNull);
+ rule(jsIntegerOrNull, jsStringOrNull, jsInterceptorOrNull);
+ rule(jsIntegerOrNull, nullType, jsIntegerOrNull);
+ rule(jsIntegerOrNull, jsFixedArray, jsInterceptorOrNull);
- rule(DOUBLE_OR_NULL, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
- rule(DOUBLE_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
- rule(DOUBLE_OR_NULL, NULL, DOUBLE_OR_NULL);
- rule(DOUBLE_OR_NULL, jsFixedArray, jsInterceptorOrNull);
+ rule(jsDoubleOrNull, jsDoubleOrNull, jsDoubleOrNull);
+ rule(jsDoubleOrNull, jsStringOrNull, jsInterceptorOrNull);
+ rule(jsDoubleOrNull, nullType, jsDoubleOrNull);
+ rule(jsDoubleOrNull, jsFixedArray, jsInterceptorOrNull);
rule(jsStringOrNull, jsStringOrNull, jsStringOrNull);
- rule(jsStringOrNull, NULL, jsStringOrNull);
+ rule(jsStringOrNull, nullType, jsStringOrNull);
rule(jsStringOrNull, jsFixedArray, jsIndexableOrNull);
- rule(NULL, NULL, NULL);
- rule(NULL, jsFixedArray, jsFixedArrayOrNull);
+ rule(nullType, nullType, nullType);
+ rule(nullType, jsFixedArray, jsFixedArrayOrNull);
rule(jsFixedArray, jsFixedArray, jsFixedArray);
- check(nonPrimitive1, NULL, (type) => type is HBoundedType);
- check(nonPrimitive2, NULL, (type) => type is HBoundedType);
- check(NULL, nonPrimitive1, (type) => type.canBeNull());
- check(NULL, nonPrimitive2, (type) => type.canBeNull());
+ check(nonPrimitive1, nullType, (type) => type is HBoundedType);
+ check(nonPrimitive2, nullType, (type) => type is HBoundedType);
+ check(nullType, nonPrimitive1, (type) => type.canBeNull());
+ check(nullType, nonPrimitive2, (type) => type.canBeNull());
ruleSet.validateCoverage();
}
@@ -387,279 +387,279 @@
(t1, t2) => t1.intersection(t2, compiler));
rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
- rule(CONFLICTING, CONFLICTING, CONFLICTING);
- rule(CONFLICTING, UNKNOWN, CONFLICTING);
- rule(CONFLICTING, BOOLEAN, CONFLICTING);
- rule(CONFLICTING, NUMBER, CONFLICTING);
- rule(CONFLICTING, INTEGER, CONFLICTING);
- rule(CONFLICTING, DOUBLE, CONFLICTING);
- rule(CONFLICTING, jsIndexable, CONFLICTING);
- rule(CONFLICTING, jsString, CONFLICTING);
- rule(CONFLICTING, jsReadableArray, CONFLICTING);
- rule(CONFLICTING, jsMutableArray, CONFLICTING);
- rule(CONFLICTING, jsExtendableArray, CONFLICTING);
- rule(CONFLICTING, nonPrimitive1, CONFLICTING);
- rule(CONFLICTING, nonPrimitive2, CONFLICTING);
- rule(CONFLICTING, potentialArray, CONFLICTING);
- rule(CONFLICTING, potentialString, CONFLICTING);
- rule(CONFLICTING, BOOLEAN_OR_NULL, CONFLICTING);
- rule(CONFLICTING, NUMBER_OR_NULL, CONFLICTING);
- rule(CONFLICTING, INTEGER_OR_NULL, CONFLICTING);
- rule(CONFLICTING, DOUBLE_OR_NULL, CONFLICTING);
- rule(CONFLICTING, jsStringOrNull, CONFLICTING);
- rule(CONFLICTING, NULL, CONFLICTING);
- rule(CONFLICTING, jsFixedArray, CONFLICTING);
+ rule(emptyType, emptyType, emptyType);
+ rule(emptyType, dynamicType, emptyType);
+ rule(emptyType, jsBoolean, emptyType);
+ rule(emptyType, jsNumber, emptyType);
+ rule(emptyType, jsInteger, emptyType);
+ rule(emptyType, jsDouble, emptyType);
+ rule(emptyType, jsIndexable, emptyType);
+ rule(emptyType, jsString, emptyType);
+ rule(emptyType, jsReadableArray, emptyType);
+ rule(emptyType, jsMutableArray, emptyType);
+ rule(emptyType, jsExtendableArray, emptyType);
+ rule(emptyType, nonPrimitive1, emptyType);
+ rule(emptyType, nonPrimitive2, emptyType);
+ rule(emptyType, potentialArray, emptyType);
+ rule(emptyType, potentialString, emptyType);
+ rule(emptyType, jsBooleanOrNull, emptyType);
+ rule(emptyType, jsNumberOrNull, emptyType);
+ rule(emptyType, jsIntegerOrNull, emptyType);
+ rule(emptyType, jsDoubleOrNull, emptyType);
+ rule(emptyType, jsStringOrNull, emptyType);
+ rule(emptyType, nullType, emptyType);
+ rule(emptyType, jsFixedArray, emptyType);
- rule(UNKNOWN, UNKNOWN, UNKNOWN);
- rule(UNKNOWN, BOOLEAN, BOOLEAN);
- rule(UNKNOWN, NUMBER, NUMBER);
- rule(UNKNOWN, INTEGER, INTEGER);
- rule(UNKNOWN, DOUBLE, DOUBLE);
- rule(UNKNOWN, jsIndexable, jsIndexable);
- rule(UNKNOWN, jsString, jsString);
- rule(UNKNOWN, jsReadableArray, jsReadableArray);
- rule(UNKNOWN, jsMutableArray, jsMutableArray);
- rule(UNKNOWN, jsExtendableArray, jsExtendableArray);
- rule(UNKNOWN, nonPrimitive1, nonPrimitive1);
- rule(UNKNOWN, nonPrimitive2, nonPrimitive2);
- rule(UNKNOWN, potentialArray, potentialArray);
- rule(UNKNOWN, potentialString, potentialString);
- rule(UNKNOWN, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
- rule(UNKNOWN, NUMBER_OR_NULL, NUMBER_OR_NULL);
- rule(UNKNOWN, INTEGER_OR_NULL, INTEGER_OR_NULL);
- rule(UNKNOWN, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
- rule(UNKNOWN, jsStringOrNull, jsStringOrNull);
- rule(UNKNOWN, NULL, NULL);
- rule(UNKNOWN, jsFixedArray, jsFixedArray);
+ rule(dynamicType, dynamicType, dynamicType);
+ rule(dynamicType, jsBoolean, jsBoolean);
+ rule(dynamicType, jsNumber, jsNumber);
+ rule(dynamicType, jsInteger, jsInteger);
+ rule(dynamicType, jsDouble, jsDouble);
+ rule(dynamicType, jsIndexable, jsIndexable);
+ rule(dynamicType, jsString, jsString);
+ rule(dynamicType, jsReadableArray, jsReadableArray);
+ rule(dynamicType, jsMutableArray, jsMutableArray);
+ rule(dynamicType, jsExtendableArray, jsExtendableArray);
+ rule(dynamicType, nonPrimitive1, nonPrimitive1);
+ rule(dynamicType, nonPrimitive2, nonPrimitive2);
+ rule(dynamicType, potentialArray, potentialArray);
+ rule(dynamicType, potentialString, potentialString);
+ rule(dynamicType, jsBooleanOrNull, jsBooleanOrNull);
+ rule(dynamicType, jsNumberOrNull, jsNumberOrNull);
+ rule(dynamicType, jsIntegerOrNull, jsIntegerOrNull);
+ rule(dynamicType, jsDoubleOrNull, jsDoubleOrNull);
+ rule(dynamicType, jsStringOrNull, jsStringOrNull);
+ rule(dynamicType, nullType, nullType);
+ rule(dynamicType, jsFixedArray, jsFixedArray);
- rule(BOOLEAN, BOOLEAN, BOOLEAN);
- rule(BOOLEAN, NUMBER, CONFLICTING);
- rule(BOOLEAN, INTEGER, CONFLICTING);
- rule(BOOLEAN, DOUBLE, CONFLICTING);
- rule(BOOLEAN, jsIndexable, CONFLICTING);
- rule(BOOLEAN, jsString, CONFLICTING);
- rule(BOOLEAN, jsReadableArray, CONFLICTING);
- rule(BOOLEAN, jsMutableArray, CONFLICTING);
- rule(BOOLEAN, jsExtendableArray, CONFLICTING);
- rule(BOOLEAN, nonPrimitive1, CONFLICTING);
- rule(BOOLEAN, nonPrimitive2, CONFLICTING);
- rule(BOOLEAN, potentialArray, CONFLICTING);
- rule(BOOLEAN, potentialString, CONFLICTING);
- rule(BOOLEAN, BOOLEAN_OR_NULL, BOOLEAN);
- rule(BOOLEAN, NUMBER_OR_NULL, CONFLICTING);
- rule(BOOLEAN, INTEGER_OR_NULL, CONFLICTING);
- rule(BOOLEAN, DOUBLE_OR_NULL, CONFLICTING);
- rule(BOOLEAN, jsStringOrNull, CONFLICTING);
- rule(BOOLEAN, NULL, CONFLICTING);
- rule(BOOLEAN, jsFixedArray, CONFLICTING);
+ rule(jsBoolean, jsBoolean, jsBoolean);
+ rule(jsBoolean, jsNumber, emptyType);
+ rule(jsBoolean, jsInteger, emptyType);
+ rule(jsBoolean, jsDouble, emptyType);
+ rule(jsBoolean, jsIndexable, emptyType);
+ rule(jsBoolean, jsString, emptyType);
+ rule(jsBoolean, jsReadableArray, emptyType);
+ rule(jsBoolean, jsMutableArray, emptyType);
+ rule(jsBoolean, jsExtendableArray, emptyType);
+ rule(jsBoolean, nonPrimitive1, emptyType);
+ rule(jsBoolean, nonPrimitive2, emptyType);
+ rule(jsBoolean, potentialArray, emptyType);
+ rule(jsBoolean, potentialString, emptyType);
+ rule(jsBoolean, jsBooleanOrNull, jsBoolean);
+ rule(jsBoolean, jsNumberOrNull, emptyType);
+ rule(jsBoolean, jsIntegerOrNull, emptyType);
+ rule(jsBoolean, jsDoubleOrNull, emptyType);
+ rule(jsBoolean, jsStringOrNull, emptyType);
+ rule(jsBoolean, nullType, emptyType);
+ rule(jsBoolean, jsFixedArray, emptyType);
- rule(NUMBER, NUMBER, NUMBER);
- rule(NUMBER, INTEGER, INTEGER);
- rule(NUMBER, DOUBLE, DOUBLE);
- rule(NUMBER, jsIndexable, CONFLICTING);
- rule(NUMBER, jsString, CONFLICTING);
- rule(NUMBER, jsReadableArray, CONFLICTING);
- rule(NUMBER, jsMutableArray, CONFLICTING);
- rule(NUMBER, jsExtendableArray, CONFLICTING);
- rule(NUMBER, nonPrimitive1, CONFLICTING);
- rule(NUMBER, nonPrimitive2, CONFLICTING);
- rule(NUMBER, potentialArray, CONFLICTING);
- rule(NUMBER, potentialString, CONFLICTING);
- rule(NUMBER, BOOLEAN_OR_NULL, CONFLICTING);
- rule(NUMBER, NUMBER_OR_NULL, NUMBER);
- rule(NUMBER, INTEGER_OR_NULL, INTEGER);
- rule(NUMBER, DOUBLE_OR_NULL, DOUBLE);
- rule(NUMBER, jsStringOrNull, CONFLICTING);
- rule(NUMBER, NULL, CONFLICTING);
- rule(NUMBER, jsFixedArray, CONFLICTING);
+ rule(jsNumber, jsNumber, jsNumber);
+ rule(jsNumber, jsInteger, jsInteger);
+ rule(jsNumber, jsDouble, jsDouble);
+ rule(jsNumber, jsIndexable, emptyType);
+ rule(jsNumber, jsString, emptyType);
+ rule(jsNumber, jsReadableArray, emptyType);
+ rule(jsNumber, jsMutableArray, emptyType);
+ rule(jsNumber, jsExtendableArray, emptyType);
+ rule(jsNumber, nonPrimitive1, emptyType);
+ rule(jsNumber, nonPrimitive2, emptyType);
+ rule(jsNumber, potentialArray, emptyType);
+ rule(jsNumber, potentialString, emptyType);
+ rule(jsNumber, jsBooleanOrNull, emptyType);
+ rule(jsNumber, jsNumberOrNull, jsNumber);
+ rule(jsNumber, jsIntegerOrNull, jsInteger);
+ rule(jsNumber, jsDoubleOrNull, jsDouble);
+ rule(jsNumber, jsStringOrNull, emptyType);
+ rule(jsNumber, nullType, emptyType);
+ rule(jsNumber, jsFixedArray, emptyType);
- rule(INTEGER, INTEGER, INTEGER);
- rule(INTEGER, DOUBLE, CONFLICTING);
- rule(INTEGER, jsIndexable, CONFLICTING);
- rule(INTEGER, jsString, CONFLICTING);
- rule(INTEGER, jsReadableArray, CONFLICTING);
- rule(INTEGER, jsMutableArray, CONFLICTING);
- rule(INTEGER, jsExtendableArray, CONFLICTING);
- rule(INTEGER, nonPrimitive1, CONFLICTING);
- rule(INTEGER, nonPrimitive2, CONFLICTING);
- rule(INTEGER, potentialArray, CONFLICTING);
- rule(INTEGER, potentialString, CONFLICTING);
- rule(INTEGER, BOOLEAN_OR_NULL, CONFLICTING);
- rule(INTEGER, NUMBER_OR_NULL, INTEGER);
- rule(INTEGER, INTEGER_OR_NULL, INTEGER);
- rule(INTEGER, DOUBLE_OR_NULL, CONFLICTING);
- rule(INTEGER, jsStringOrNull, CONFLICTING);
- rule(INTEGER, NULL, CONFLICTING);
- rule(INTEGER, jsFixedArray, CONFLICTING);
+ rule(jsInteger, jsInteger, jsInteger);
+ rule(jsInteger, jsDouble, emptyType);
+ rule(jsInteger, jsIndexable, emptyType);
+ rule(jsInteger, jsString, emptyType);
+ rule(jsInteger, jsReadableArray, emptyType);
+ rule(jsInteger, jsMutableArray, emptyType);
+ rule(jsInteger, jsExtendableArray, emptyType);
+ rule(jsInteger, nonPrimitive1, emptyType);
+ rule(jsInteger, nonPrimitive2, emptyType);
+ rule(jsInteger, potentialArray, emptyType);
+ rule(jsInteger, potentialString, emptyType);
+ rule(jsInteger, jsBooleanOrNull, emptyType);
+ rule(jsInteger, jsNumberOrNull, jsInteger);
+ rule(jsInteger, jsIntegerOrNull, jsInteger);
+ rule(jsInteger, jsDoubleOrNull, emptyType);
+ rule(jsInteger, jsStringOrNull, emptyType);
+ rule(jsInteger, nullType, emptyType);
+ rule(jsInteger, jsFixedArray, emptyType);
- rule(DOUBLE, DOUBLE, DOUBLE);
- rule(DOUBLE, jsIndexable, CONFLICTING);
- rule(DOUBLE, jsString, CONFLICTING);
- rule(DOUBLE, jsReadableArray, CONFLICTING);
- rule(DOUBLE, jsMutableArray, CONFLICTING);
- rule(DOUBLE, jsExtendableArray, CONFLICTING);
- rule(DOUBLE, nonPrimitive1, CONFLICTING);
- rule(DOUBLE, nonPrimitive2, CONFLICTING);
- rule(DOUBLE, potentialArray, CONFLICTING);
- rule(DOUBLE, potentialString, CONFLICTING);
- rule(DOUBLE, BOOLEAN_OR_NULL, CONFLICTING);
- rule(DOUBLE, NUMBER_OR_NULL, DOUBLE);
- rule(DOUBLE, INTEGER_OR_NULL, CONFLICTING);
- rule(DOUBLE, DOUBLE_OR_NULL, DOUBLE);
- rule(DOUBLE, jsStringOrNull, CONFLICTING);
- rule(DOUBLE, NULL, CONFLICTING);
- rule(DOUBLE, jsFixedArray, CONFLICTING);
+ rule(jsDouble, jsDouble, jsDouble);
+ rule(jsDouble, jsIndexable, emptyType);
+ rule(jsDouble, jsString, emptyType);
+ rule(jsDouble, jsReadableArray, emptyType);
+ rule(jsDouble, jsMutableArray, emptyType);
+ rule(jsDouble, jsExtendableArray, emptyType);
+ rule(jsDouble, nonPrimitive1, emptyType);
+ rule(jsDouble, nonPrimitive2, emptyType);
+ rule(jsDouble, potentialArray, emptyType);
+ rule(jsDouble, potentialString, emptyType);
+ rule(jsDouble, jsBooleanOrNull, emptyType);
+ rule(jsDouble, jsNumberOrNull, jsDouble);
+ rule(jsDouble, jsIntegerOrNull, emptyType);
+ rule(jsDouble, jsDoubleOrNull, jsDouble);
+ rule(jsDouble, jsStringOrNull, emptyType);
+ rule(jsDouble, nullType, emptyType);
+ rule(jsDouble, jsFixedArray, emptyType);
rule(jsIndexable, jsIndexable, jsIndexable);
rule(jsIndexable, jsString, jsString);
rule(jsIndexable, jsReadableArray, jsReadableArray);
rule(jsIndexable, jsMutableArray, jsMutableArray);
rule(jsIndexable, jsExtendableArray, jsExtendableArray);
- rule(jsIndexable, nonPrimitive1, CONFLICTING);
- rule(jsIndexable, nonPrimitive2, CONFLICTING);
+ rule(jsIndexable, nonPrimitive1, emptyType);
+ rule(jsIndexable, nonPrimitive2, emptyType);
rule(jsIndexable, potentialArray, new HType.nonNullSubtype(
compiler.backend.jsArrayClass, compiler));
rule(jsIndexable, potentialString, jsString);
- rule(jsIndexable, BOOLEAN_OR_NULL, CONFLICTING);
- rule(jsIndexable, NUMBER_OR_NULL, CONFLICTING);
- rule(jsIndexable, INTEGER_OR_NULL, CONFLICTING);
- rule(jsIndexable, DOUBLE_OR_NULL, CONFLICTING);
+ rule(jsIndexable, jsBooleanOrNull, emptyType);
+ rule(jsIndexable, jsNumberOrNull, emptyType);
+ rule(jsIndexable, jsIntegerOrNull, emptyType);
+ rule(jsIndexable, jsDoubleOrNull, emptyType);
rule(jsIndexable, jsStringOrNull, jsString);
- rule(jsIndexable, NULL, CONFLICTING);
+ rule(jsIndexable, nullType, emptyType);
rule(jsIndexable, jsFixedArray, jsFixedArray);
rule(jsString, jsString, jsString);
- rule(jsString, jsReadableArray, CONFLICTING);
- rule(jsString, jsMutableArray, CONFLICTING);
- rule(jsString, jsExtendableArray, CONFLICTING);
- rule(jsString, nonPrimitive1, CONFLICTING);
- rule(jsString, nonPrimitive2, CONFLICTING);
- rule(jsString, potentialArray, CONFLICTING);
+ rule(jsString, jsReadableArray, emptyType);
+ rule(jsString, jsMutableArray, emptyType);
+ rule(jsString, jsExtendableArray, emptyType);
+ rule(jsString, nonPrimitive1, emptyType);
+ rule(jsString, nonPrimitive2, emptyType);
+ rule(jsString, potentialArray, emptyType);
rule(jsString, potentialString, jsString);
- rule(jsString, BOOLEAN_OR_NULL, CONFLICTING);
- rule(jsString, NUMBER_OR_NULL, CONFLICTING);
- rule(jsString, INTEGER_OR_NULL, CONFLICTING);
- rule(jsString, DOUBLE_OR_NULL, CONFLICTING);
+ rule(jsString, jsBooleanOrNull, emptyType);
+ rule(jsString, jsNumberOrNull, emptyType);
+ rule(jsString, jsIntegerOrNull, emptyType);
+ rule(jsString, jsDoubleOrNull, emptyType);
rule(jsString, jsStringOrNull, jsString);
- rule(jsString, NULL, CONFLICTING);
- rule(jsString, jsFixedArray, CONFLICTING);
+ rule(jsString, nullType, emptyType);
+ rule(jsString, jsFixedArray, emptyType);
rule(jsReadableArray, jsReadableArray, jsReadableArray);
rule(jsReadableArray, jsMutableArray, jsMutableArray);
rule(jsReadableArray, jsExtendableArray, jsExtendableArray);
- rule(jsReadableArray, nonPrimitive1, CONFLICTING);
- rule(jsReadableArray, nonPrimitive2, CONFLICTING);
+ rule(jsReadableArray, nonPrimitive1, emptyType);
+ rule(jsReadableArray, nonPrimitive2, emptyType);
rule(jsReadableArray, potentialArray, jsReadableArray);
- rule(jsReadableArray, potentialString, CONFLICTING);
- rule(jsReadableArray, BOOLEAN_OR_NULL, CONFLICTING);
- rule(jsReadableArray, NUMBER_OR_NULL, CONFLICTING);
- rule(jsReadableArray, INTEGER_OR_NULL, CONFLICTING);
- rule(jsReadableArray, DOUBLE_OR_NULL, CONFLICTING);
- rule(jsReadableArray, jsStringOrNull, CONFLICTING);
- rule(jsReadableArray, NULL, CONFLICTING);
+ rule(jsReadableArray, potentialString, emptyType);
+ rule(jsReadableArray, jsBooleanOrNull, emptyType);
+ rule(jsReadableArray, jsNumberOrNull, emptyType);
+ rule(jsReadableArray, jsIntegerOrNull, emptyType);
+ rule(jsReadableArray, jsDoubleOrNull, emptyType);
+ rule(jsReadableArray, jsStringOrNull, emptyType);
+ rule(jsReadableArray, nullType, emptyType);
rule(jsReadableArray, jsFixedArray, jsFixedArray);
rule(jsMutableArray, jsMutableArray, jsMutableArray);
rule(jsMutableArray, jsExtendableArray, jsExtendableArray);
- rule(jsMutableArray, nonPrimitive1, CONFLICTING);
- rule(jsMutableArray, nonPrimitive2, CONFLICTING);
+ rule(jsMutableArray, nonPrimitive1, emptyType);
+ rule(jsMutableArray, nonPrimitive2, emptyType);
rule(jsMutableArray, potentialArray, jsMutableArray);
- rule(jsMutableArray, potentialString, CONFLICTING);
- rule(jsMutableArray, BOOLEAN_OR_NULL, CONFLICTING);
- rule(jsMutableArray, NUMBER_OR_NULL, CONFLICTING);
- rule(jsMutableArray, INTEGER_OR_NULL, CONFLICTING);
- rule(jsMutableArray, DOUBLE_OR_NULL, CONFLICTING);
- rule(jsMutableArray, jsStringOrNull, CONFLICTING);
- rule(jsMutableArray, NULL, CONFLICTING);
+ rule(jsMutableArray, potentialString, emptyType);
+ rule(jsMutableArray, jsBooleanOrNull, emptyType);
+ rule(jsMutableArray, jsNumberOrNull, emptyType);
+ rule(jsMutableArray, jsIntegerOrNull, emptyType);
+ rule(jsMutableArray, jsDoubleOrNull, emptyType);
+ rule(jsMutableArray, jsStringOrNull, emptyType);
+ rule(jsMutableArray, nullType, emptyType);
rule(jsMutableArray, jsFixedArray, jsFixedArray);
rule(jsExtendableArray, jsExtendableArray, jsExtendableArray);
- rule(jsExtendableArray, nonPrimitive1, CONFLICTING);
- rule(jsExtendableArray, nonPrimitive2, CONFLICTING);
+ rule(jsExtendableArray, nonPrimitive1, emptyType);
+ rule(jsExtendableArray, nonPrimitive2, emptyType);
rule(jsExtendableArray, potentialArray, jsExtendableArray);
- rule(jsExtendableArray, potentialString, CONFLICTING);
- rule(jsExtendableArray, BOOLEAN_OR_NULL, CONFLICTING);
- rule(jsExtendableArray, NUMBER_OR_NULL, CONFLICTING);
- rule(jsExtendableArray, INTEGER_OR_NULL, CONFLICTING);
- rule(jsExtendableArray, DOUBLE_OR_NULL, CONFLICTING);
- rule(jsExtendableArray, jsStringOrNull, CONFLICTING);
- rule(jsExtendableArray, NULL, CONFLICTING);
- rule(jsExtendableArray, jsFixedArray, CONFLICTING);
+ rule(jsExtendableArray, potentialString, emptyType);
+ rule(jsExtendableArray, jsBooleanOrNull, emptyType);
+ rule(jsExtendableArray, jsNumberOrNull, emptyType);
+ rule(jsExtendableArray, jsIntegerOrNull, emptyType);
+ rule(jsExtendableArray, jsDoubleOrNull, emptyType);
+ rule(jsExtendableArray, jsStringOrNull, emptyType);
+ rule(jsExtendableArray, nullType, emptyType);
+ rule(jsExtendableArray, jsFixedArray, emptyType);
rule(nonPrimitive1, nonPrimitive1, nonPrimitive1);
- rule(nonPrimitive1, nonPrimitive2, CONFLICTING);
- rule(nonPrimitive1, potentialArray, CONFLICTING);
- rule(nonPrimitive1, potentialString, CONFLICTING);
- rule(nonPrimitive1, BOOLEAN_OR_NULL, CONFLICTING);
- rule(nonPrimitive1, NUMBER_OR_NULL, CONFLICTING);
- rule(nonPrimitive1, INTEGER_OR_NULL, CONFLICTING);
- rule(nonPrimitive1, DOUBLE_OR_NULL, CONFLICTING);
- rule(nonPrimitive1, jsStringOrNull, CONFLICTING);
- rule(nonPrimitive1, NULL, CONFLICTING);
- rule(nonPrimitive1, jsFixedArray, CONFLICTING);
+ rule(nonPrimitive1, nonPrimitive2, emptyType);
+ rule(nonPrimitive1, potentialArray, emptyType);
+ rule(nonPrimitive1, potentialString, emptyType);
+ rule(nonPrimitive1, jsBooleanOrNull, emptyType);
+ rule(nonPrimitive1, jsNumberOrNull, emptyType);
+ rule(nonPrimitive1, jsIntegerOrNull, emptyType);
+ rule(nonPrimitive1, jsDoubleOrNull, emptyType);
+ rule(nonPrimitive1, jsStringOrNull, emptyType);
+ rule(nonPrimitive1, nullType, emptyType);
+ rule(nonPrimitive1, jsFixedArray, emptyType);
rule(nonPrimitive2, nonPrimitive2, nonPrimitive2);
- rule(nonPrimitive2, potentialArray, CONFLICTING);
- rule(nonPrimitive2, potentialString, CONFLICTING);
- rule(nonPrimitive2, BOOLEAN_OR_NULL, CONFLICTING);
- rule(nonPrimitive2, NUMBER_OR_NULL, CONFLICTING);
- rule(nonPrimitive2, INTEGER_OR_NULL, CONFLICTING);
- rule(nonPrimitive2, DOUBLE_OR_NULL, CONFLICTING);
- rule(nonPrimitive2, jsStringOrNull, CONFLICTING);
- rule(nonPrimitive2, NULL, CONFLICTING);
- rule(nonPrimitive2, jsFixedArray, CONFLICTING);
+ rule(nonPrimitive2, potentialArray, emptyType);
+ rule(nonPrimitive2, potentialString, emptyType);
+ rule(nonPrimitive2, jsBooleanOrNull, emptyType);
+ rule(nonPrimitive2, jsNumberOrNull, emptyType);
+ rule(nonPrimitive2, jsIntegerOrNull, emptyType);
+ rule(nonPrimitive2, jsDoubleOrNull, emptyType);
+ rule(nonPrimitive2, jsStringOrNull, emptyType);
+ rule(nonPrimitive2, nullType, emptyType);
+ rule(nonPrimitive2, jsFixedArray, emptyType);
rule(potentialArray, potentialArray, potentialArray);
- rule(potentialArray, potentialString, NULL);
- rule(potentialArray, BOOLEAN_OR_NULL, NULL);
- rule(potentialArray, NUMBER_OR_NULL, NULL);
- rule(potentialArray, INTEGER_OR_NULL, NULL);
- rule(potentialArray, DOUBLE_OR_NULL, NULL);
- rule(potentialArray, jsStringOrNull, NULL);
- rule(potentialArray, NULL, NULL);
+ rule(potentialArray, potentialString, nullType);
+ rule(potentialArray, jsBooleanOrNull, nullType);
+ rule(potentialArray, jsNumberOrNull, nullType);
+ rule(potentialArray, jsIntegerOrNull, nullType);
+ rule(potentialArray, jsDoubleOrNull, nullType);
+ rule(potentialArray, jsStringOrNull, nullType);
+ rule(potentialArray, nullType, nullType);
rule(potentialArray, jsFixedArray, jsFixedArray);
rule(potentialString, potentialString, potentialString);
- rule(potentialString, BOOLEAN_OR_NULL, NULL);
- rule(potentialString, NUMBER_OR_NULL, NULL);
- rule(potentialString, INTEGER_OR_NULL, NULL);
- rule(potentialString, DOUBLE_OR_NULL, NULL);
+ rule(potentialString, jsBooleanOrNull, nullType);
+ rule(potentialString, jsNumberOrNull, nullType);
+ rule(potentialString, jsIntegerOrNull, nullType);
+ rule(potentialString, jsDoubleOrNull, nullType);
rule(potentialString, jsStringOrNull, jsStringOrNull);
- rule(potentialString, NULL, NULL);
- rule(potentialString, jsFixedArray, CONFLICTING);
+ rule(potentialString, nullType, nullType);
+ rule(potentialString, jsFixedArray, emptyType);
- rule(BOOLEAN_OR_NULL, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
- rule(BOOLEAN_OR_NULL, NUMBER_OR_NULL, NULL);
- rule(BOOLEAN_OR_NULL, INTEGER_OR_NULL, NULL);
- rule(BOOLEAN_OR_NULL, DOUBLE_OR_NULL, NULL);
- rule(BOOLEAN_OR_NULL, jsStringOrNull, NULL);
- rule(BOOLEAN_OR_NULL, NULL, NULL);
- rule(BOOLEAN_OR_NULL, jsFixedArray, CONFLICTING);
+ rule(jsBooleanOrNull, jsBooleanOrNull, jsBooleanOrNull);
+ rule(jsBooleanOrNull, jsNumberOrNull, nullType);
+ rule(jsBooleanOrNull, jsIntegerOrNull, nullType);
+ rule(jsBooleanOrNull, jsDoubleOrNull, nullType);
+ rule(jsBooleanOrNull, jsStringOrNull, nullType);
+ rule(jsBooleanOrNull, nullType, nullType);
+ rule(jsBooleanOrNull, jsFixedArray, emptyType);
- rule(NUMBER_OR_NULL, NUMBER_OR_NULL, NUMBER_OR_NULL);
- rule(NUMBER_OR_NULL, INTEGER_OR_NULL, INTEGER_OR_NULL);
- rule(NUMBER_OR_NULL, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
- rule(NUMBER_OR_NULL, jsStringOrNull, NULL);
- rule(NUMBER_OR_NULL, NULL, NULL);
- rule(NUMBER_OR_NULL, jsFixedArray, CONFLICTING);
+ rule(jsNumberOrNull, jsNumberOrNull, jsNumberOrNull);
+ rule(jsNumberOrNull, jsIntegerOrNull, jsIntegerOrNull);
+ rule(jsNumberOrNull, jsDoubleOrNull, jsDoubleOrNull);
+ rule(jsNumberOrNull, jsStringOrNull, nullType);
+ rule(jsNumberOrNull, nullType, nullType);
+ rule(jsNumberOrNull, jsFixedArray, emptyType);
- rule(INTEGER_OR_NULL, INTEGER_OR_NULL, INTEGER_OR_NULL);
- rule(INTEGER_OR_NULL, DOUBLE_OR_NULL, NULL);
- rule(INTEGER_OR_NULL, jsStringOrNull, NULL);
- rule(INTEGER_OR_NULL, NULL, NULL);
- rule(INTEGER_OR_NULL, jsFixedArray, CONFLICTING);
+ rule(jsIntegerOrNull, jsIntegerOrNull, jsIntegerOrNull);
+ rule(jsIntegerOrNull, jsDoubleOrNull, nullType);
+ rule(jsIntegerOrNull, jsStringOrNull, nullType);
+ rule(jsIntegerOrNull, nullType, nullType);
+ rule(jsIntegerOrNull, jsFixedArray, emptyType);
- rule(DOUBLE_OR_NULL, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
- rule(DOUBLE_OR_NULL, jsStringOrNull, NULL);
- rule(DOUBLE_OR_NULL, NULL, NULL);
- rule(DOUBLE_OR_NULL, jsFixedArray, CONFLICTING);
+ rule(jsDoubleOrNull, jsDoubleOrNull, jsDoubleOrNull);
+ rule(jsDoubleOrNull, jsStringOrNull, nullType);
+ rule(jsDoubleOrNull, nullType, nullType);
+ rule(jsDoubleOrNull, jsFixedArray, emptyType);
rule(jsStringOrNull, jsStringOrNull, jsStringOrNull);
- rule(jsStringOrNull, NULL, NULL);
- rule(jsStringOrNull, jsFixedArray, CONFLICTING);
+ rule(jsStringOrNull, nullType, nullType);
+ rule(jsStringOrNull, jsFixedArray, emptyType);
- rule(NULL, NULL, NULL);
- rule(NULL, jsFixedArray, CONFLICTING);
+ rule(nullType, nullType, nullType);
+ rule(nullType, jsFixedArray, emptyType);
rule(jsFixedArray, jsFixedArray, jsFixedArray);
@@ -725,6 +725,30 @@
compiler.backend.jsStringClass, compiler);
jsString = new HType.nonNullExact(
compiler.backend.jsStringClass, compiler);
+ jsBoolean = new HType.nonNullExact(
+ compiler.backend.jsBoolClass, compiler);
+ jsNumber = new HType.nonNullSubclass(
+ compiler.backend.jsNumberClass, compiler);
+ jsInteger = new HType.nonNullExact(
+ compiler.backend.jsIntClass, compiler);
+ jsDouble = new HType.nonNullExact(
+ compiler.backend.jsDoubleClass, compiler);
+ jsBooleanOrNull = new HType.exact(
+ compiler.backend.jsBoolClass, compiler);
+ jsNumberOrNull = new HType.subclass(
+ compiler.backend.jsNumberClass, compiler);
+ jsIntegerOrNull = new HType.exact(
+ compiler.backend.jsIntClass, compiler);
+ jsDoubleOrNull = new HType.exact(
+ compiler.backend.jsDoubleClass, compiler);
+ nullType = new HBoundedType(
+ const TypeMask.empty());
+ objectType = new HType.nonNullSubclass(
+ compiler.objectClass, compiler);
+ emptyType = new HBoundedType(
+ const TypeMask.nonNullEmpty());
+ dynamicType = new HType.subclass(
+ compiler.objectClass, compiler);
testUnion(compiler);
testIntersection(compiler);
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index c3db052..5055a89 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -12,7 +12,6 @@
[ $compiler == none || $compiler == dart2dart ]
symbol_test/none: Fail # bug 11669
-error_stack_trace2_test: Fail # Bug 5802
[ $compiler == none && $runtime == drt ]
main_test: Fail # Dartium needs to check for both main() and main(args).
@@ -41,7 +40,6 @@
[ $compiler == dart2js ]
error_stack_trace1_test: RuntimeError # Issue 12399
hash_set_test/01: RuntimeError # Issue 11551
-main_test: Fail # Issue 14200
big_integer_vm_test: RuntimeError, OK # VM specific test.
bit_twiddling_bigint_test: RuntimeError # Requires bigint support.
@@ -113,3 +111,14 @@
[ $arch == simmips && $mode == debug ]
collection_to_string_test: Pass, Crash # Issue: 11207
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+collection_to_string_test: StaticWarning
+error_stack_trace_test: StaticWarning
+iterable_element_at_test: StaticWarning
+iterable_test: StaticWarning
+list_map_test: StaticWarning
+num_clamp_test: StaticWarning
+queue_test: StaticWarning
+string_codeunits_test: StaticWarning
+string_test: StaticWarning
diff --git a/tests/html/html.status b/tests/html/html.status
index cb34ece..0a46d3b 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -5,6 +5,7 @@
async_window_test: Skip #TODO(gram): investigating
event_test: Skip # Issue 1996
interactive_test: Skip # Must be run manually.
+dromaeo_smoke_test: Fail, Pass # Issue 14521
[ $compiler == dart2js && $browser ]
element_offset_test/offset: Pass, Fail # Issue 13296
@@ -29,10 +30,10 @@
postmessage_structured_test/typed_arrays: Fail
xhr_test: Pass, Fail # Issue 12648
xhr_test/json: Fail # Issue 13069
-uri_test: Fail Issue 13581
async_test: Fail # Background timers not implemented.
keyboard_event_test: Fail # Issue 13902
isolates_test: Fail # Issue 13921
+js_interop_2_test: Fail # Issue 14604
[ $compiler == none && $runtime == drt && $system == windows ]
worker_test/functional: Pass, Crash # Issue 9929.
@@ -70,9 +71,9 @@
worker_api_test: Fail # IE does not support URL.createObjectURL in web workers.
[ $compiler == dart2js && $runtime == safari ]
-url_test: Pass, Fail # Issue 14506 Passes only on certain versions of Safari
audiobuffersourcenode_test/supported: Pass, Timeout # Issue 12772
+
[ $compiler == dart2js && $browser && $checked ]
postmessage_structured_test/typed_arrays: Fail # Issue 10097
postmessage_structured_test/primitives: Fail # Issue 10097
@@ -273,11 +274,10 @@
input_element_test/supported_time: Fail, Crash
input_element_test/supported_week: Fail, Crash
webgl_1_test: Pass, Fail # Issue 8219
-wheelevent_test: Pass, Fail # Issue: 14506 Passes only on certain versions of Safari
-xhr_test/xhr_requestBlob: Pass, Fail # Issue: 14506 Passes only on certain versions of Safari
canvasrenderingcontext2d_test/drawImage_video_element: Fail # Safari does not support drawImage w/ video element
canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # Safari does not support drawImage w/ video element
audiocontext_test/functional: Fail # Issue 14354
+websql_test/functional: Pass, Fail # Issue 14523
# Safari Feature support statuses-
@@ -350,8 +350,8 @@
# FireFox Feature support statuses-
# All changes should be accompanied by platform support annotation changes.
-audiobuffersourcenode_test/supported: Fail
-audiocontext_test/supported: Fail
+audiobuffersourcenode_test: Pass, Fail # Issue 14602
+audiocontext_test: Pass, Fail # Issue 14602
css_test/supportsPointConversions: Fail
document_test/supports_cssCanvasContext: Fail
element_types_test/supported_content: Fail
@@ -402,3 +402,23 @@
dromaeo_smoke_test: Fail # Issue 13719: Please triage this failure.
element_offset_test/offset: Pass, Fail # Issue 13719, 13296
touchevent_test/supported: Fail # Issue 13719: Please triage this failure.
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+audiocontext_test: StaticWarning
+custom/created_callback_test: StaticWarning
+custom/document_register_basic_test: StaticWarning
+datalistelement_test: StaticWarning
+documentfragment_test: StaticWarning
+element_add_test: StaticWarning
+element_test: StaticWarning
+events_test: StaticWarning
+htmlelement_test: StaticWarning
+isolates_test: StaticWarning
+localstorage_test: StaticWarning
+mutationobserver_test: StaticWarning
+track_element_constructor_test: StaticWarning
+transferables_test: StaticWarning
+typed_arrays_range_checks_test: StaticWarning
+typing_test: StaticWarning
+webgl_1_test: StaticWarning
+window_nosuchmethod_test: StaticWarning
diff --git a/tests/html/js_test.dart b/tests/html/js_test.dart
index 633ed89..e1aafae 100644
--- a/tests/html/js_test.dart
+++ b/tests/html/js_test.dart
@@ -269,7 +269,6 @@
context.deleteProperty('foo2');
});
-
test('retrieve same dart Object', () {
final obj = new Object();
context['obj'] = obj;
@@ -315,16 +314,19 @@
});
test('new Array()', () {
- final a = new JsObject(context['Array']);
- expect(a, isNotNull);
- expect(a['length'], equals(0));
+ var a = new JsObject(context['Array']);
+ expect(a, new isInstanceOf<JsArray>());
+
+ // Test that the object still behaves via the base JsObject interface.
+ // JsArray specific tests are below.
+ expect(a['length'], 0);
a.callMethod('push', ["value 1"]);
- expect(a['length'], equals(1));
- expect(a[0], equals("value 1"));
+ expect(a['length'], 1);
+ expect(a[0], "value 1");
a.callMethod('pop');
- expect(a['length'], equals(0));
+ expect(a['length'], 0);
});
test('new Date()', () {
@@ -337,10 +339,9 @@
expect(a.callMethod('getTime'), equals(12345678));
});
- test('new Date("December 17, 1995 03:24:00 GMT")',
- () {
+ test('new Date("December 17, 1995 03:24:00 GMT")', () {
final a = new JsObject(context['Date'],
- ["December 17, 1995 03:24:00 GMT"]);
+ ["December 17, 1995 03:24:00 GMT"]);
expect(a.callMethod('getTime'), equals(819170640000));
});
@@ -354,7 +355,7 @@
test('new Date(1995,11,17,3,24,0)', () {
// Note: JS Date counts months from 0 while Dart counts from 1.
final a = new JsObject(context['Date'],
- [1995, 11, 17, 3, 24, 0]);
+ [1995, 11, 17, 3, 24, 0]);
final b = new DateTime(1995, 12, 17, 3, 24, 0);
expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
});
@@ -419,6 +420,11 @@
group('JsFunction and callMethod', () {
+ test('new JsObject can return a JsFunction', () {
+ var f = new JsObject(context['Function']);
+ expect(f, new isInstanceOf<JsFunction>());
+ });
+
test('JsFunction.apply on a function defined in JS', () {
expect(context['razzle'].apply([]), equals(42));
});
@@ -454,6 +460,150 @@
*/
});
+ group('JsArray', () {
+
+ test('new JsArray()', () {
+ var array = new JsArray();
+ var arrayType = context['Array'];
+ expect(array.instanceof(arrayType), true);
+ expect(array, []);
+ // basic check that it behaves like a List
+ array.addAll([1, 2, 3]);
+ expect(array, [1, 2, 3]);
+ });
+
+ test('new JsArray.from()', () {
+ var array = new JsArray.from([1, 2, 3]);
+ var arrayType = context['Array'];
+ expect(array.instanceof(arrayType), true);
+ expect(array, [1, 2, 3]);
+ });
+
+ test('get Array from JS', () {
+ context['a'] = new JsObject(context['Array'], [1, 2, 3]);
+ expect(context.callMethod('isPropertyInstanceOf',
+ ['a', context['Array']]), isTrue);
+ var a = context['a'];
+ expect(a, new isInstanceOf<JsArray>());
+ expect(a, [1, 2, 3]);
+ context.deleteProperty('a');
+ });
+
+ test('pass Array to JS', () {
+ context['a'] = [1, 2, 3];
+ expect(context.callMethod('isPropertyInstanceOf',
+ ['a', context['Array']]), isFalse);
+ var a = context['a'];
+ expect(a, new isInstanceOf<List>());
+ expect(a, isNot(new isInstanceOf<JsArray>()));
+ expect(a, [1, 2, 3]);
+ context.deleteProperty('a');
+ });
+
+ test('[]', () {
+ var array = new JsArray.from([1, 2]);
+ expect(array[0], 1);
+ expect(array[1], 2);
+ expect(() => array[-1], throwsA(isRangeError));
+ expect(() => array[2], throwsA(isRangeError));
+ });
+
+ test('[]=', () {
+ var array = new JsArray.from([1, 2]);
+ array[0] = 'd';
+ array[1] = 'e';
+ expect(array, ['d', 'e']);
+ expect(() => array[-1] = 3, throwsA(isRangeError));
+ expect(() => array[2] = 3, throwsA(isRangeError));
+ });
+
+ test('length', () {
+ var array = new JsArray.from([1, 2, 3]);
+ expect(array.length, 3);
+ array.add(4);
+ expect(array.length, 4);
+ array.length = 2;
+ expect(array, [1, 2]);
+ array.length = 3;
+ expect(array, [1, 2, null]);
+ });
+
+ test('add', () {
+ var array = new JsArray();
+ array.add('a');
+ expect(array, ['a']);
+ array.add('b');
+ expect(array, ['a', 'b']);
+ });
+
+ test('addAll', () {
+ var array = new JsArray();
+ array.addAll(['a', 'b']);
+ expect(array, ['a', 'b']);
+ // make sure addAll can handle Iterables
+ array.addAll(new Set.from(['c']));
+ expect(array, ['a', 'b', 'c']);
+ });
+
+ test('insert', () {
+ var array = new JsArray.from([]);
+ array.insert(0, 'b');
+ expect(array, ['b']);
+ array.insert(0, 'a');
+ expect(array, ['a', 'b']);
+ array.insert(2, 'c');
+ expect(array, ['a', 'b', 'c']);
+ expect(() => array.insert(4, 'e'), throwsA(isRangeError));
+ expect(() => array.insert(-1, 'e'), throwsA(isRangeError));
+ });
+
+ test('removeAt', () {
+ var array = new JsArray.from(['a', 'b', 'c']);
+ expect(array.removeAt(1), 'b');
+ expect(array, ['a', 'c']);
+ expect(() => array.removeAt(2), throwsA(isRangeError));
+ expect(() => array.removeAt(-1), throwsA(isRangeError));
+ });
+
+ test('removeLast', () {
+ var array = new JsArray.from(['a', 'b', 'c']);
+ expect(array.removeLast(), 'c');
+ expect(array, ['a', 'b']);
+ array.length = 0;
+ expect(() => array.removeLast(), throwsA(isRangeError));
+ });
+
+ test('removeRange', () {
+ var array = new JsArray.from(['a', 'b', 'c', 'd']);
+ array.removeRange(1, 3);
+ expect(array, ['a', 'd']);
+ expect(() => array.removeRange(-1, 2), throwsA(isRangeError));
+ expect(() => array.removeRange(0, 3), throwsA(isRangeError));
+ expect(() => array.removeRange(2, 1), throwsA(isRangeError));
+ });
+
+ test('setRange', () {
+ var array = new JsArray.from(['a', 'b', 'c', 'd']);
+ array.setRange(1, 3, ['e', 'f']);
+ expect(array, ['a', 'e', 'f', 'd']);
+ array.setRange(3, 4, ['g', 'h', 'i'], 1);
+ expect(array, ['a', 'e', 'f', 'h']);
+ });
+
+ test('sort', () {
+ var array = new JsArray.from(['c', 'a', 'b']);
+ array.sort();
+ expect(array, ['a', 'b', 'c']);
+ });
+
+ test('sort with a Comparator', () {
+ var array = new JsArray.from(['c', 'a', 'b']);
+ array.sort((a, b) => -(a.compareTo(b)));
+ expect(array, ['c', 'b', 'a']);
+ });
+
+ });
+
group('JsObject.fromBrowserObject()', () {
test('Nodes are proxied', () {
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index d7e85a6..58e6cd7 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -13,10 +13,7 @@
[ $analyzer ]
isolate2_negative_test: Fail
-isolate_negative_test: Fail
isolate_import_negative_test: Fail
-spawn_function_negative_test: Fail
-spawn_uri_vm_negative_test: Fail
unresolved_ports_negative_test: Fail
mandel_isolate_test: Fail # issue 14452
@@ -119,3 +116,18 @@
spawn_function_test: Fail
stacktrace_message_test: Fail
unresolved_ports_test: Fail
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+browser/typed_data_message_test: StaticWarning
+illegal_msg_test: StaticWarning
+isolate3_negative_test: CompileTimeError
+isolate/illegal_msg_test: StaticWarning
+isolate_import_negative_test: CompileTimeError
+isolate/mint_maker_test: StaticWarning
+isolate/unresolved_ports_test: StaticWarning
+mandel_isolate_stream_test: StaticWarning
+mandel_isolate_test: StaticWarning
+mint_maker_test: StaticWarning
+serialization_test: StaticWarning
+unresolved_ports_test: StaticWarning
+
diff --git a/tests/language/arithmetic2_test.dart b/tests/language/arithmetic2_test.dart
index 0952f2b..65655da 100644
--- a/tests/language/arithmetic2_test.dart
+++ b/tests/language/arithmetic2_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Dart test program to test arithmetic operations.
-// @static-clean
import "package:expect/expect.dart";
diff --git a/tests/language/bool_test.dart b/tests/language/bool_test.dart
index 4015c18..efe8a7a 100644
--- a/tests/language/bool_test.dart
+++ b/tests/language/bool_test.dart
@@ -4,9 +4,6 @@
import "package:expect/expect.dart";
-// Dart test program for testing basic boolean properties.
-// @static-clean
-
class BoolTest {
static void testEquality() {
Expect.equals(true, true);
diff --git a/tests/language/context2_test.dart b/tests/language/context2_test.dart
index 1b4d683..f3358ed 100644
--- a/tests/language/context2_test.dart
+++ b/tests/language/context2_test.dart
@@ -6,7 +6,6 @@
import "package:expect/expect.dart";
// Regression test for issue 5991015.
-// @static-clean
class V {
diff --git a/tests/language/default_implementation_test.dart b/tests/language/default_implementation_test.dart
index 74a797d..51a2210 100644
--- a/tests/language/default_implementation_test.dart
+++ b/tests/language/default_implementation_test.dart
@@ -5,8 +5,6 @@
import "package:expect/expect.dart";
-// @static-clean
-
abstract class Point {
factory Point(int x, int y) = PointImplementation;
diff --git a/tests/language/dynamic_test.dart b/tests/language/dynamic_test.dart
index b871001..8813b23 100644
--- a/tests/language/dynamic_test.dart
+++ b/tests/language/dynamic_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
//
// Dart test program testing the use of 'dynamic' in generic types.
-// @static-clean
import "package:expect/expect.dart";
diff --git a/tests/language/getters_setters_type2_test.dart b/tests/language/getters_setters_type2_test.dart
index 22a3264..0e19f80 100644
--- a/tests/language/getters_setters_type2_test.dart
+++ b/tests/language/getters_setters_type2_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// Getters and setters can have different types, and it is not a warning if the
// two types are assignable.
-// @static-clean
import "package:expect/expect.dart";
diff --git a/tests/language/getters_setters_type3_test.dart b/tests/language/getters_setters_type3_test.dart
index aaa8b35..a41f59f 100644
--- a/tests/language/getters_setters_type3_test.dart
+++ b/tests/language/getters_setters_type3_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// Getters and setters can have different types, and it is not a warning if the
// two types are assignable.
-// @static-clean
import "package:expect/expect.dart";
diff --git a/tests/language/language.status b/tests/language/language.status
index 120f90f..d5bb2ff 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -5,9 +5,6 @@
# This directory contains tests that are intended to show the
# current state of the language.
-[ $compiler == none && $runtime == drt && $mode == debug ]
-source_self_negative_test: Crash # Issue 14003
-
[ $compiler == none ]
mixin_super_constructor_named_test: Fail # Issue 12631
mixin_super_constructor_positionals_test: Fail # Issue 12631
@@ -27,9 +24,6 @@
mixin_forwarding_constructor2_test: Fail # Issue 13641
implicit_setter_test: Fail # Issue 13917
-cyclic_typedef_test/10: Fail # Issue 13675
-cyclic_typedef_test/11: Fail # Issue 13675
-
[ $compiler == none && $runtime == vm ]
class_keyword_test/02: MissingCompileTimeError # Issue 13627
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 8bdaf61..5fb3de7 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -13,9 +13,6 @@
class_literal_test: fail
constructor_call_as_function_test/01: fail
-# TBF: It is a static warning if the function type of k' is not a subtype of the type of k.
-default_implementation2_test: fail
-
function_type_alias9_test/00: crash # Issue 11987
# TBF: we should check conflicts not only for methods, but for accessors too
@@ -24,9 +21,6 @@
method_override7_test/03: Fail # Issue 11496
method_override8_test/03: Fail # Issue 11496
-# TBF: prefix T hidden by type variable T in 'new T.Class()'
-prefix10_negative_test: fail
-
built_in_identifier_test/none: Fail # Issue 13023
@@ -36,10 +30,6 @@
#
-# test issue 10683, It is a compile-time error if e refers to the name v or the name v=.
-block_scope_test: fail
-lazy_static3_test: fail
-
# test issue 11124, It is warning, not error to don't initialize final field
field3a_negative_test: Fail # Issue 11124
final_syntax_test/01: Fail # Issue 11124
@@ -72,9 +62,6 @@
# test issue 11579, assignment, no setter
getter_no_setter_test/none: fail
-# test issue 11581, it is not warning to call dynamic
-call_through_getter_test: fail
-
# test issue 11584, positional arguments cannot be used for named parameters
compile_time_constant_e_test: fail
@@ -96,16 +83,10 @@
import_combinators_negative_test: fail
interface_static_non_final_fields_negative_test: fail
-# test issue 11698, no setter, so warning, not error
-assign_instance_method_negative_test: fail
-
# test issue 11918: mixin and const constructor
const_constructor_mixin_test/01: fail
const_constructor_mixin3_test/01: fail
-# test issue 11958, fails only at runtime
-no_such_method_negative_test: fail
-
# test issue 11962, it is warning, not error to reference undeclared identifier
prefix1_negative_test: fail
prefix2_negative_test: fail
@@ -113,9 +94,6 @@
prefix5_negative_test: fail
prefix12_negative_test: fail
-# test issue 11963, it is fine to access any property of the dynamic variable
-prefix6_negative_test: fail
-
# test issue 11964, Any use of a malformed type gives rise to a static warning.
prefix8_negative_test: fail
prefix11_negative_test: fail
@@ -180,17 +158,13 @@
bailout3_test: fail # test issue 14289
prefix9_test: fail # test issue 14289
-# test issue 14358, E does not implement inherited A.+
-type_promotion_closure_test/none: Fail
-
-# test issue 14362, wrong assumption that dynamic << A
-type_promotion_functions_test/none: Fail
-
# test issue 14363, "if ((a is B))" has the same effect as "if (a is B)", so no static warning expected
type_promotion_parameter_test/53: Fail
# test issue 14364, "E<A> << D"
-type_promotion_more_specific_test/08: fail
+type_promotion_more_specific_test/09: Fail
+type_promotion_more_specific_test/10: Fail
+type_promotion_more_specific_test/11: Fail
# test issue 14406, setter for final field was removed from spec
implicit_setter_test/01: fail
@@ -199,24 +173,292 @@
# test issue 14410, "typedef C = " is now really illegal syntax
mixin_illegal_syntax_test/none: fail
-#
-# Please don't add new items here.
-# This is section for invalid tests.
-#
-[ $compiler == dartanalyzer && $checked ]
-factory1_test/00: fail
-factory1_test/01: fail
-field_type_check2_test/01: fail
-factory_implementation_test/00: fail
-factory_redirection_test/08: fail
-factory_redirection_test/09: fail
-factory_redirection_test/10: fail
-factory_redirection_test/11: fail
-factory_redirection_test/12: fail
-factory_redirection_test/13: fail
-factory_redirection_test/14: fail
-getters_setters2_test/03: fail
-type_variable_bounds3_test/00: fail
-type_variable_bounds2_test/05: fail
+abstract_exact_selector_test: StaticWarning
+abstract_getter_test: StaticWarning
+abstract_object_method_test: StaticWarning
+abstract_runtime_error_test: StaticWarning
+application_negative_test: CompileTimeError
+bad_constructor_test/05: CompileTimeError
+bad_initializer1_negative_test: CompileTimeError
+bad_named_constructor_negative_test: CompileTimeError
+bad_named_parameters2_test: StaticWarning
+bad_named_parameters_test: StaticWarning
+bit_operations_test: StaticWarning
+body_less_constructor_wrong_arg_negative_test: CompileTimeError
+built_in_identifier_test/01: CompileTimeError
+call_constructor_on_unresolvable_class_test/04: StaticWarning
+call_constructor_on_unresolvable_class_test/05: StaticWarning
+call_constructor_on_unresolvable_class_test/06: StaticWarning
+call_nonexistent_constructor_test: StaticWarning
+checked_null_test: StaticWarning
+checked_setter2_test: StaticWarning
+checked_setter_test: StaticWarning
+closure_type_test: StaticWarning
+compile_time_constant_checked2_test/02: MissingCompileTimeError
+compile_time_constant_checked2_test/03: MissingCompileTimeError
+compile_time_constant_checked2_test/04: MissingCompileTimeError
+compile_time_constant_checked2_test/06: MissingCompileTimeError
+compile_time_constant_checked3_test/02: MissingCompileTimeError
+compile_time_constant_checked3_test/03: MissingCompileTimeError
+compile_time_constant_checked3_test/04: MissingCompileTimeError
+compile_time_constant_checked3_test/06: MissingCompileTimeError
+compile_time_constant_checked_test/02: MissingCompileTimeError
+compile_time_constant_k_test: StaticWarning
+compile_time_constant_o_test: StaticWarning
+const_counter_negative_test: CompileTimeError
+const_objects_are_immutable_test: StaticWarning
+const_optional_args_negative_test: CompileTimeError
+constructor_named_arguments_test/01: StaticWarning
+constructor_redirect1_negative_test: CompileTimeError
+constructor_redirect2_negative_test: CompileTimeError
+constructor_setter_negative_test: CompileTimeError
+constructor_test: StaticWarning
+core_type_check_test: StaticWarning
+crash_6725_test: StaticWarning
+default_factory_library_test: StaticWarning
+default_factory_test: StaticWarning
+div_with_power_of_two2_test: StaticWarning
+double_to_string_as_exponential2_test: StaticWarning
+double_to_string_as_fixed2_test: StaticWarning
+double_to_string_as_precision2_test: StaticWarning
+duplicate_export_negative_test: CompileTimeError
+duplicate_interface_negative_test: CompileTimeError
+dynamic_field_test: StaticWarning
+dynamic_prefix_core_test: StaticWarning
+empty_block_case_test: StaticWarning
+error_stacktrace_test: StaticWarning
+extend_type_parameter2_negative_test: CompileTimeError
+extend_type_parameter_negative_test: CompileTimeError
+external_test/20: StaticWarning
+factory2_negative_test: CompileTimeError
+factory2_test: StaticWarning
+factory3_negative_test: CompileTimeError
+factory3_test: StaticWarning
+factory4_test: StaticWarning
+factory_implementation_test/00: StaticWarning
+factory_negative_test: CompileTimeError
+factory_redirection_test/01: StaticWarning
+factory_redirection_test/03: StaticWarning
+factory_redirection_test/05: StaticWarning
+factory_redirection_test/06: StaticWarning
+factory_return_type_checked_test: StaticWarning
+f_bounded_quantification4_test: StaticWarning
+f_bounded_quantification5_test: StaticWarning
+field1_negative_test: CompileTimeError
+field2_negative_test: CompileTimeError
+field3_negative_test: CompileTimeError
+field4_negative_test: CompileTimeError
+field5_negative_test: CompileTimeError
+field6a_negative_test: CompileTimeError
+field6_negative_test: CompileTimeError
+first_class_types_literals_test: StaticWarning
+function_malformed_result_type_test: StaticWarning
+function_subtype_bound_closure7_test: StaticWarning
+function_subtype_checked0_test: StaticWarning
+function_subtype_closure0_test: StaticWarning
+function_subtype_closure1_test: StaticWarning
+function_subtype_factory1_test: StaticWarning
+function_subtype_inline1_test: StaticWarning
+function_type2_test: StaticWarning
+function_type_parameter2_negative_test: CompileTimeError
+function_type_parameter_negative_test: CompileTimeError
+generic_list_checked_test: StaticWarning
+generics_test: StaticWarning
+generic_test: StaticWarning
+getter_declaration_negative_test: CompileTimeError
+getter_no_setter2_test/01: StaticWarning
+getter_no_setter_test/01: StaticWarning
+illegal_invocation_test/01: CompileTimeError
+implicit_this_test/02: StaticWarning
+implied_interface_test: StaticWarning
+import_combinators_test: StaticWarning
+import_core_prefix_test: StaticWarning
+inferrer_this_access_test: StaticWarning
+inlined_throw_test: StaticWarning
+instance_method2_negative_test: CompileTimeError
+instance_method_negative_test: CompileTimeError
+instanceof3_test: StaticWarning
+instantiate_type_variable_test/01: StaticWarning
+inst_field_initializer1_negative_test: CompileTimeError
+interceptor6_test: StaticWarning
+interface2_negative_test: CompileTimeError
+interface_inherit_field_test: StaticWarning
+interface_injection1_negative_test: CompileTimeError
+interface_injection2_negative_test: CompileTimeError
+interface_static_method_negative_test: CompileTimeError
+invocation_mirror_test: StaticWarning
+is_not_class1_negative_test: CompileTimeError
+is_not_class2_test: StaticWarning
+is_not_class4_negative_test: CompileTimeError
+isnot_malformed_type_test: StaticWarning
+issue1363_test: StaticWarning
+issue1578_negative_test: CompileTimeError
+label2_negative_test: CompileTimeError
+label3_negative_test: CompileTimeError
+label5_negative_test: CompileTimeError
+label6_negative_test: CompileTimeError
+label8_negative_test: CompileTimeError
+label_test: StaticWarning
+library_ambiguous_test/00: StaticWarning
+library_ambiguous_test/01: CompileTimeError
+library_ambiguous_test/02: CompileTimeError
+library_ambiguous_test/03: CompileTimeError
+library_negative_test: CompileTimeError
+list_literal2_negative_test: CompileTimeError
+list_literal4_test: StaticWarning
+list_literal_negative_test: CompileTimeError
+list_test: StaticWarning
+malbounded_type_cast_test: StaticWarning
+malbounded_type_literal_test: StaticWarning
+malformed_type_test: StaticWarning
+map_literal11_test: StaticWarning
+map_literal2_negative_test: CompileTimeError
+map_literal3_test: StaticWarning
+map_literal4_test: StaticWarning
+map_literal6_test: StaticWarning
+map_literal8_test: StaticWarning
+map_literal_negative_test: CompileTimeError
+method_override4_test: StaticWarning
+method_override5_test: StaticWarning
+method_override6_test: StaticWarning
+method_override_test: StaticWarning
+mixin_illegal_syntax_test/13: CompileTimeError
+mixin_typedef_constructor_test: StaticWarning
+mixin_type_parameter2_test: StaticWarning
+mixin_type_parameters_mixin_extends_test: StaticWarning
+mixin_type_parameters_mixin_test: StaticWarning
+mixin_type_parameters_super_extends_test: StaticWarning
+mixin_type_parameters_super_test: StaticWarning
+mixin_with_two_implicit_constructors_test: StaticWarning
+named_constructor_test/01: StaticWarning
+named_constructor_test/03: StaticWarning
+named_parameters2_test: StaticWarning
+named_parameters3_test: StaticWarning
+named_parameters4_test: StaticWarning
+named_parameters_test/01: StaticWarning
+named_parameters_test/02: StaticWarning
+named_parameters_test/03: StaticWarning
+named_parameters_test/04: StaticWarning
+named_parameters_test/05: StaticWarning
+named_parameters_test/06: StaticWarning
+named_parameters_test/07: StaticWarning
+named_parameters_test/08: StaticWarning
+named_parameters_test/09: StaticWarning
+named_parameters_test/10: StaticWarning
+named_parameters_type_test/01: StaticWarning
+new_expression1_negative_test: CompileTimeError
+new_expression2_negative_test: CompileTimeError
+new_expression3_negative_test: CompileTimeError
+non_const_super_negative_test: CompileTimeError
+non_parameterized_factory2_test: StaticWarning
+non_parameterized_factory_test: StaticWarning
+no_such_constructor2_test: StaticWarning
+no_such_method2_test: StaticWarning
+no_such_method_dispatcher_test: StaticWarning
+not_enough_positional_arguments_test/00: StaticWarning
+not_enough_positional_arguments_test/01: CompileTimeError
+not_enough_positional_arguments_test/02: StaticWarning
+not_enough_positional_arguments_test/03: StaticWarning
+not_enough_positional_arguments_test/05: StaticWarning
+not_enough_positional_arguments_test/06: StaticWarning
+not_enough_positional_arguments_test/07: StaticWarning
+number_identifier_test/08: StaticWarning
+number_identifier_test/09: StaticWarning
+on_catch_malformed_type_test: StaticWarning
+operator1_negative_test: CompileTimeError
+operator2_negative_test: CompileTimeError
+operator_equals_test: StaticWarning
+optional_named_parameters_test/01: StaticWarning
+optional_named_parameters_test/02: StaticWarning
+optional_named_parameters_test/03: StaticWarning
+optional_named_parameters_test/04: StaticWarning
+optional_named_parameters_test/05: StaticWarning
+optional_named_parameters_test/06: StaticWarning
+optional_named_parameters_test/07: StaticWarning
+optional_named_parameters_test/08: StaticWarning
+optional_named_parameters_test/09: StaticWarning
+override_field_method1_negative_test: CompileTimeError
+override_field_method2_negative_test: CompileTimeError
+override_field_method4_negative_test: CompileTimeError
+override_field_method5_negative_test: CompileTimeError
+parameter_initializer1_negative_test: CompileTimeError
+parameter_initializer2_negative_test: CompileTimeError
+parameter_initializer3_negative_test: CompileTimeError
+parameter_initializer4_negative_test: CompileTimeError
+parameter_initializer5_negative_test: CompileTimeError
+parameter_initializer6_negative_test: CompileTimeError
+parser_quirks_test: StaticWarning
+part2_test: StaticWarning
+positional_parameters_type_test/01: StaticWarning
+prefix13_negative_test: CompileTimeError
+prefix14_test: StaticWarning
+prefix15_negative_test: CompileTimeError
+prefix15_test: StaticWarning
+prefix16_test: StaticWarning
+prefix17_test: StaticWarning
+prefix18_negative_test: CompileTimeError
+prefix22_test: StaticWarning
+prefix23_test: StaticWarning
+prefix7_negative_test: CompileTimeError
+property_field_override_test: StaticWarning
+redirecting_factory_default_values_test/none: StaticWarning
+redirecting_factory_incompatible_signature_test: StaticWarning
+regress_13494_test: StaticWarning
+return_type_test: StaticWarning
+script1_negative_test: CompileTimeError
+script2_negative_test: CompileTimeError
+setter_declaration2_negative_test: CompileTimeError
+setter_declaration_negative_test: CompileTimeError
+setter_no_getter_call_test/01: CompileTimeError
+source_self_negative_test: CompileTimeError
+static_initializer_type_error_test: StaticWarning
+string_escape4_negative_test: CompileTimeError
+string_interpolate1_negative_test: CompileTimeError
+string_interpolate2_negative_test: CompileTimeError
+string_interpolate_test: StaticWarning
+string_interpolation1_negative_test: CompileTimeError
+string_interpolation2_negative_test: CompileTimeError
+string_interpolation3_negative_test: CompileTimeError
+string_interpolation4_negative_test: CompileTimeError
+string_interpolation5_negative_test: CompileTimeError
+string_interpolation6_negative_test: CompileTimeError
+string_test: StaticWarning
+string_unicode1_negative_test: CompileTimeError
+string_unicode2_negative_test: CompileTimeError
+string_unicode3_negative_test: CompileTimeError
+string_unicode4_negative_test: CompileTimeError
+super_assign_test: StaticWarning
+super_call4_test: StaticWarning
+super_getter_setter_test: StaticWarning
+super_operator_index5_test: StaticWarning
+super_operator_index6_test: StaticWarning
+super_operator_index7_test: StaticWarning
+super_operator_index8_test: StaticWarning
+super_operator_test: StaticWarning
+super_setter_test: StaticWarning
+switch1_negative_test: CompileTimeError
+switch3_negative_test: CompileTimeError
+switch4_negative_test: CompileTimeError
+switch5_negative_test: CompileTimeError
+switch6_test: StaticWarning
+switch7_negative_test: CompileTimeError
+switch_fallthru_test: StaticWarning
+test_negative_test: CompileTimeError
+top_level_non_prefixed_library_test: StaticWarning
+try_catch4_test: StaticWarning
+try_catch5_test: StaticWarning
+type_argument_in_super_type_test: StaticWarning
+typed_selector2_test: StaticWarning
+type_variable_bounds2_test/05: StaticWarning
+type_variable_bounds3_test/00: StaticWarning
+type_variable_identifier_expression_test: StaticWarning
+type_variable_scope2_test: StaticWarning
+unary_plus_negative_test: CompileTimeError
+unbound_getter_test: StaticWarning
+unhandled_exception_negative_test: CompileTimeError
+unresolved_top_level_method_negative_test: CompileTimeError
+vm/type_cast_vm_test: StaticWarning
+vm/type_vm_test: StaticWarning
+void_type_test: StaticWarning
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index 5d6dc93..a8ebdfd 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -13,9 +13,6 @@
class_literal_test: fail
constructor_call_as_function_test/01: fail
-# TBF: It is a static warning if the function type of k' is not a subtype of the type of k.
-default_implementation2_test: fail
-
function_type_alias9_test/00: crash # Issue 11987
# TBF: we should check conflicts not only for methods, but for accessors too
@@ -24,21 +21,8 @@
method_override7_test/03: Fail # Issue 11496
method_override8_test/03: Fail # Issue 11496
-# TBF: prefix T hidden by type variable T in 'new T.Class()'
-prefix10_negative_test: fail
-
built_in_identifier_test/none: Fail # Issue 13023
-# Invalid constant redirecting factories should cause compile-time error.
-const_types_test/23: Fail # Issue 14306
-const_types_test/24: Fail # Issue 14306
-const_types_test/25: Fail # Issue 14306
-const_types_test/26: Fail # Issue 14306
-const_types_test/27: Fail # Issue 14306
-const_types_test/28: Fail # Issue 14306
-const_types_test/29: Fail # Issue 14306
-const_types_test/30: Fail # Issue 14306
-const_types_test/41: Fail # Issue 14306
# Please add new failing tests before this line.
# Section below is for invalid tests.
@@ -82,9 +66,6 @@
# test issue 11579, assignment, no setter
getter_no_setter_test/none: fail
-# test issue 11581, it is not warning to call dynamic
-call_through_getter_test: fail
-
# test issue 11584, positional arguments cannot be used for named parameters
compile_time_constant_e_test: fail
@@ -106,16 +87,10 @@
import_combinators_negative_test: fail
interface_static_non_final_fields_negative_test: fail
-# test issue 11698, no setter, so warning, not error
-assign_instance_method_negative_test: fail
-
# test issue 11918: mixin and const constructor
const_constructor_mixin_test/01: fail
const_constructor_mixin3_test/01: fail
-# test issue 11958, fails only at runtime
-no_such_method_negative_test: fail
-
# test issue 11962, it is warning, not error to reference undeclared identifier
prefix1_negative_test: fail
prefix2_negative_test: fail
@@ -123,9 +98,6 @@
prefix5_negative_test: fail
prefix12_negative_test: fail
-# test issue 11963, it is fine to access any property of the dynamic variable
-prefix6_negative_test: fail
-
# test issue 11964, Any use of a malformed type gives rise to a static warning.
prefix8_negative_test: fail
prefix11_negative_test: fail
@@ -167,6 +139,9 @@
# test issue 13916, Looks as no warning should be in this redirecting factory
redirecting_factory_infinite_steps_test/01: fail
+# test issue , disallow default values in redirecting factories
+redirecting_factory_default_values_test/none: fail # Issue 14471
+
# test issue 13956, It is a static type warning if any of the type arguments to k' are not subtypes of the bounds of the corresponding formal type parameters of type.
default_factory2_test/none: fail
@@ -188,16 +163,16 @@
prefix9_test: fail # test issue 14289
# test issue 14358, E does not implement inherited A.+
-type_promotion_closure_test/none: Fail
-
-# test issue 14362, wrong assumption that dynamic << A
-type_promotion_functions_test/none: Fail
+type_promotion_closure_test/01: Fail
+type_promotion_closure_test/02: Fail
# test issue 14363, "if ((a is B))" has the same effect as "if (a is B)", so no static warning expected
type_promotion_parameter_test/53: Fail
# test issue 14364, "E<A> << D"
-type_promotion_more_specific_test/08: fail
+type_promotion_more_specific_test/09: Fail
+type_promotion_more_specific_test/10: Fail
+type_promotion_more_specific_test/11: Fail
# test issue 14406, setter for final field was removed from spec
implicit_setter_test/01: fail
@@ -206,24 +181,293 @@
# test issue 14410, "typedef C = " is now really illegal syntax
mixin_illegal_syntax_test/none: fail
-#
-# Please don't add new items here.
-# This is section for invalid tests.
-#
-[ $compiler == dart2analyzer && $checked ]
-factory1_test/00: fail
-factory1_test/01: fail
-field_type_check2_test/01: fail
-factory_implementation_test/00: fail
-factory_redirection_test/08: fail
-factory_redirection_test/09: fail
-factory_redirection_test/10: fail
-factory_redirection_test/11: fail
-factory_redirection_test/12: fail
-factory_redirection_test/13: fail
-factory_redirection_test/14: fail
-getters_setters2_test/03: fail
-type_variable_bounds3_test/00: fail
-type_variable_bounds2_test/05: fail
+abstract_exact_selector_test: StaticWarning
+abstract_getter_test: StaticWarning
+abstract_object_method_test: StaticWarning
+abstract_runtime_error_test: StaticWarning
+application_negative_test: CompileTimeError
+bad_constructor_test/05: CompileTimeError
+bad_initializer1_negative_test: CompileTimeError
+bad_initializer2_negative_test: CompileTimeError
+bad_named_constructor_negative_test: CompileTimeError
+bad_named_parameters2_test: StaticWarning
+bad_named_parameters_test: StaticWarning
+bit_operations_test: StaticWarning
+body_less_constructor_wrong_arg_negative_test: CompileTimeError
+built_in_identifier_test/01: CompileTimeError
+call_constructor_on_unresolvable_class_test/04: StaticWarning
+call_constructor_on_unresolvable_class_test/05: StaticWarning
+call_constructor_on_unresolvable_class_test/06: StaticWarning
+call_nonexistent_constructor_test: StaticWarning
+checked_null_test: StaticWarning
+checked_setter2_test: StaticWarning
+checked_setter_test: StaticWarning
+closure_type_test: StaticWarning
+compile_time_constant_checked2_test/02: MissingCompileTimeError
+compile_time_constant_checked2_test/03: MissingCompileTimeError
+compile_time_constant_checked2_test/04: MissingCompileTimeError
+compile_time_constant_checked2_test/06: MissingCompileTimeError
+compile_time_constant_checked3_test/02: MissingCompileTimeError
+compile_time_constant_checked3_test/03: MissingCompileTimeError
+compile_time_constant_checked3_test/04: MissingCompileTimeError
+compile_time_constant_checked3_test/06: MissingCompileTimeError
+compile_time_constant_checked_test/02: MissingCompileTimeError
+compile_time_constant_k_test: StaticWarning
+compile_time_constant_o_test: StaticWarning
+const_counter_negative_test: CompileTimeError
+const_objects_are_immutable_test: StaticWarning
+const_optional_args_negative_test: CompileTimeError
+constructor_named_arguments_test/01: StaticWarning
+constructor_redirect1_negative_test: CompileTimeError
+constructor_redirect2_negative_test: CompileTimeError
+constructor_setter_negative_test: CompileTimeError
+constructor_test: StaticWarning
+core_type_check_test: StaticWarning
+crash_6725_test: StaticWarning
+default_factory_library_test: StaticWarning
+default_factory_test: StaticWarning
+div_with_power_of_two2_test: StaticWarning
+double_to_string_as_exponential2_test: StaticWarning
+double_to_string_as_fixed2_test: StaticWarning
+double_to_string_as_precision2_test: StaticWarning
+duplicate_export_negative_test: CompileTimeError
+duplicate_interface_negative_test: CompileTimeError
+dynamic_field_test: StaticWarning
+dynamic_prefix_core_test: StaticWarning
+empty_block_case_test: StaticWarning
+error_stacktrace_test: StaticWarning
+extend_type_parameter2_negative_test: CompileTimeError
+extend_type_parameter_negative_test: CompileTimeError
+external_test/20: StaticWarning
+factory2_negative_test: CompileTimeError
+factory2_test: StaticWarning
+factory3_negative_test: CompileTimeError
+factory3_test: StaticWarning
+factory4_test: StaticWarning
+factory_implementation_test/00: StaticWarning
+factory_negative_test: CompileTimeError
+factory_redirection_test/01: StaticWarning
+factory_redirection_test/03: StaticWarning
+factory_redirection_test/05: StaticWarning
+factory_redirection_test/06: StaticWarning
+factory_return_type_checked_test: StaticWarning
+f_bounded_quantification4_test: StaticWarning
+f_bounded_quantification5_test: StaticWarning
+field1_negative_test: CompileTimeError
+field2_negative_test: CompileTimeError
+field3_negative_test: CompileTimeError
+field4_negative_test: CompileTimeError
+field5_negative_test: CompileTimeError
+field6a_negative_test: CompileTimeError
+field6_negative_test: CompileTimeError
+first_class_types_literals_test: StaticWarning
+function_malformed_result_type_test: StaticWarning
+function_subtype_bound_closure7_test: StaticWarning
+function_subtype_checked0_test: StaticWarning
+function_subtype_closure0_test: StaticWarning
+function_subtype_closure1_test: StaticWarning
+function_subtype_factory1_test: StaticWarning
+function_subtype_inline1_test: StaticWarning
+function_type2_test: StaticWarning
+function_type_parameter2_negative_test: CompileTimeError
+function_type_parameter_negative_test: CompileTimeError
+generic_list_checked_test: StaticWarning
+generics_test: StaticWarning
+generic_test: StaticWarning
+getter_declaration_negative_test: CompileTimeError
+getter_no_setter2_test/01: StaticWarning
+getter_no_setter_test/01: StaticWarning
+illegal_invocation_test/01: CompileTimeError
+implicit_this_test/02: StaticWarning
+implied_interface_test: StaticWarning
+import_combinators_test: StaticWarning
+import_core_prefix_test: StaticWarning
+inferrer_this_access_test: StaticWarning
+inlined_throw_test: StaticWarning
+instance_method2_negative_test: CompileTimeError
+instance_method_negative_test: CompileTimeError
+instanceof3_test: StaticWarning
+instantiate_type_variable_test/01: StaticWarning
+inst_field_initializer1_negative_test: CompileTimeError
+interceptor6_test: StaticWarning
+interface2_negative_test: CompileTimeError
+interface_inherit_field_test: StaticWarning
+interface_injection1_negative_test: CompileTimeError
+interface_injection2_negative_test: CompileTimeError
+interface_static_method_negative_test: CompileTimeError
+invocation_mirror_test: StaticWarning
+is_not_class1_negative_test: CompileTimeError
+is_not_class2_test: StaticWarning
+is_not_class4_negative_test: CompileTimeError
+isnot_malformed_type_test: StaticWarning
+issue1363_test: StaticWarning
+issue1578_negative_test: CompileTimeError
+label2_negative_test: CompileTimeError
+label3_negative_test: CompileTimeError
+label5_negative_test: CompileTimeError
+label6_negative_test: CompileTimeError
+label8_negative_test: CompileTimeError
+label_test: StaticWarning
+library_ambiguous_test/00: StaticWarning
+library_ambiguous_test/01: CompileTimeError
+library_ambiguous_test/02: CompileTimeError
+library_ambiguous_test/03: CompileTimeError
+library_negative_test: CompileTimeError
+list_literal2_negative_test: CompileTimeError
+list_literal4_test: StaticWarning
+list_literal_negative_test: CompileTimeError
+list_test: StaticWarning
+malbounded_type_cast_test: StaticWarning
+malbounded_type_literal_test: StaticWarning
+malformed_type_test: StaticWarning
+map_literal11_test: StaticWarning
+map_literal2_negative_test: CompileTimeError
+map_literal3_test: StaticWarning
+map_literal4_test: StaticWarning
+map_literal6_test: StaticWarning
+map_literal8_test: StaticWarning
+map_literal_negative_test: CompileTimeError
+method_override4_test: StaticWarning
+method_override5_test: StaticWarning
+method_override6_test: StaticWarning
+method_override_test: StaticWarning
+mixin_illegal_syntax_test/13: CompileTimeError
+mixin_typedef_constructor_test: StaticWarning
+mixin_type_parameter2_test: StaticWarning
+mixin_type_parameters_mixin_extends_test: StaticWarning
+mixin_type_parameters_mixin_test: StaticWarning
+mixin_type_parameters_super_extends_test: StaticWarning
+mixin_type_parameters_super_test: StaticWarning
+mixin_with_two_implicit_constructors_test: StaticWarning
+named_constructor_test/01: StaticWarning
+named_constructor_test/03: StaticWarning
+named_parameters2_test: StaticWarning
+named_parameters3_test: StaticWarning
+named_parameters4_test: StaticWarning
+named_parameters_test/01: StaticWarning
+named_parameters_test/02: StaticWarning
+named_parameters_test/03: StaticWarning
+named_parameters_test/04: StaticWarning
+named_parameters_test/05: StaticWarning
+named_parameters_test/06: StaticWarning
+named_parameters_test/07: StaticWarning
+named_parameters_test/08: StaticWarning
+named_parameters_test/09: StaticWarning
+named_parameters_test/10: StaticWarning
+named_parameters_type_test/01: StaticWarning
+new_expression1_negative_test: CompileTimeError
+new_expression2_negative_test: CompileTimeError
+new_expression3_negative_test: CompileTimeError
+non_const_super_negative_test: CompileTimeError
+non_parameterized_factory2_test: StaticWarning
+non_parameterized_factory_test: StaticWarning
+no_such_constructor2_test: StaticWarning
+no_such_method2_test: StaticWarning
+no_such_method_dispatcher_test: StaticWarning
+not_enough_positional_arguments_test/00: StaticWarning
+not_enough_positional_arguments_test/01: CompileTimeError
+not_enough_positional_arguments_test/02: StaticWarning
+not_enough_positional_arguments_test/03: StaticWarning
+not_enough_positional_arguments_test/05: StaticWarning
+not_enough_positional_arguments_test/06: StaticWarning
+not_enough_positional_arguments_test/07: StaticWarning
+number_identifier_test/08: StaticWarning
+number_identifier_test/09: StaticWarning
+on_catch_malformed_type_test: StaticWarning
+operator1_negative_test: CompileTimeError
+operator2_negative_test: CompileTimeError
+operator_equals_test: StaticWarning
+optional_named_parameters_test/01: StaticWarning
+optional_named_parameters_test/02: StaticWarning
+optional_named_parameters_test/03: StaticWarning
+optional_named_parameters_test/04: StaticWarning
+optional_named_parameters_test/05: StaticWarning
+optional_named_parameters_test/06: StaticWarning
+optional_named_parameters_test/07: StaticWarning
+optional_named_parameters_test/08: StaticWarning
+optional_named_parameters_test/09: StaticWarning
+override_field_method1_negative_test: CompileTimeError
+override_field_method2_negative_test: CompileTimeError
+override_field_method4_negative_test: CompileTimeError
+override_field_method5_negative_test: CompileTimeError
+parameter_initializer1_negative_test: CompileTimeError
+parameter_initializer2_negative_test: CompileTimeError
+parameter_initializer3_negative_test: CompileTimeError
+parameter_initializer4_negative_test: CompileTimeError
+parameter_initializer5_negative_test: CompileTimeError
+parameter_initializer6_negative_test: CompileTimeError
+parser_quirks_test: StaticWarning
+part2_test: StaticWarning
+positional_parameters_type_test/01: StaticWarning
+prefix13_negative_test: CompileTimeError
+prefix14_test: StaticWarning
+prefix15_negative_test: CompileTimeError
+prefix15_test: StaticWarning
+prefix16_test: StaticWarning
+prefix17_test: StaticWarning
+prefix18_negative_test: CompileTimeError
+prefix22_test: StaticWarning
+prefix23_test: StaticWarning
+prefix7_negative_test: CompileTimeError
+property_field_override_test: StaticWarning
+redirecting_factory_default_values_test/none: StaticWarning
+redirecting_factory_incompatible_signature_test: StaticWarning
+regress_13494_test: StaticWarning
+return_type_test: StaticWarning
+script1_negative_test: CompileTimeError
+script2_negative_test: CompileTimeError
+setter_declaration2_negative_test: CompileTimeError
+setter_declaration_negative_test: CompileTimeError
+setter_no_getter_call_test/01: CompileTimeError
+source_self_negative_test: CompileTimeError
+static_initializer_type_error_test: StaticWarning
+string_escape4_negative_test: CompileTimeError
+string_interpolate1_negative_test: CompileTimeError
+string_interpolate2_negative_test: CompileTimeError
+string_interpolate_test: StaticWarning
+string_interpolation1_negative_test: CompileTimeError
+string_interpolation2_negative_test: CompileTimeError
+string_interpolation3_negative_test: CompileTimeError
+string_interpolation4_negative_test: CompileTimeError
+string_interpolation5_negative_test: CompileTimeError
+string_interpolation6_negative_test: CompileTimeError
+string_test: StaticWarning
+string_unicode1_negative_test: CompileTimeError
+string_unicode2_negative_test: CompileTimeError
+string_unicode3_negative_test: CompileTimeError
+string_unicode4_negative_test: CompileTimeError
+super_assign_test: StaticWarning
+super_call4_test: StaticWarning
+super_getter_setter_test: StaticWarning
+super_operator_index5_test: StaticWarning
+super_operator_index6_test: StaticWarning
+super_operator_index7_test: StaticWarning
+super_operator_index8_test: StaticWarning
+super_operator_test: StaticWarning
+super_setter_test: StaticWarning
+switch1_negative_test: CompileTimeError
+switch3_negative_test: CompileTimeError
+switch4_negative_test: CompileTimeError
+switch5_negative_test: CompileTimeError
+switch6_test: StaticWarning
+switch7_negative_test: CompileTimeError
+switch_fallthru_test: StaticWarning
+test_negative_test: CompileTimeError
+top_level_non_prefixed_library_test: StaticWarning
+try_catch4_test: StaticWarning
+try_catch5_test: StaticWarning
+type_argument_in_super_type_test: StaticWarning
+typed_selector2_test: StaticWarning
+type_variable_bounds2_test/05: StaticWarning
+type_variable_bounds3_test/00: StaticWarning
+type_variable_identifier_expression_test: StaticWarning
+type_variable_scope2_test: StaticWarning
+unary_plus_negative_test: CompileTimeError
+unbound_getter_test: StaticWarning
+unhandled_exception_negative_test: CompileTimeError
+unresolved_top_level_method_negative_test: CompileTimeError
+vm/type_cast_vm_test: StaticWarning
+vm/type_vm_test: StaticWarning
+void_type_test: StaticWarning
diff --git a/tests/language/part_test.dart b/tests/language/part_test.dart
index 740e17c..38d84d8 100644
--- a/tests/language/part_test.dart
+++ b/tests/language/part_test.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.
-// @static-clean
-
library org.dartlang.test.part_test;
part "part_part.dart";
diff --git a/tests/language/third_test.dart b/tests/language/third_test.dart
index 04fc19a..28c1b0f 100644
--- a/tests/language/third_test.dart
+++ b/tests/language/third_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Third dart test program.
-// @static-clean
import "package:expect/expect.dart";
diff --git a/tests/language/type_promotion_closure_test.dart b/tests/language/type_promotion_closure_test.dart
index 5c32a77..bb514da 100644
--- a/tests/language/type_promotion_closure_test.dart
+++ b/tests/language/type_promotion_closure_test.dart
@@ -17,7 +17,7 @@
class D extends A {
var d = "d";
}
-class E implements C, D {
+class E extends D implements C {
var a = "";
var b = "";
var c = "";
diff --git a/tests/language/type_promotion_functions_test.dart b/tests/language/type_promotion_functions_test.dart
index e6cc0c4..daa317d 100644
--- a/tests/language/type_promotion_functions_test.dart
+++ b/tests/language/type_promotion_functions_test.dart
@@ -37,10 +37,11 @@
b = funcAtoDyn(new B());
c = funcAtoDyn(new C()); /// 01: static type warning
- if (funcAtoDyn is FuncDynToDyn) { // Promotion: FuncDynToDyn << FuncAtoDyn.
+ if (funcAtoDyn is FuncDynToDyn) {
+ // No promotion: FuncDynToDyn !<< FuncAtoDyn.
a = funcAtoDyn(new A());
b = funcAtoDyn(new B());
- c = funcAtoDyn(new C());
+ c = funcAtoDyn(new C()); /// 11: static type warning
}
}
@@ -50,11 +51,10 @@
b = funcDynToDyn(new B());
c = funcDynToDyn(new C());
- if (funcDynToDyn is FuncAtoDyn) {
- // No promotion: FuncAtoDyn !<< FuncDynToDyn.
+ if (funcDynToDyn is FuncAtoDyn) { // Promotion: FuncAtoDyn << FuncDynToDyn.
a = funcDynToDyn(new A());
b = funcDynToDyn(new B());
- c = funcDynToDyn(new C());
+ c = funcDynToDyn(new C()); /// 09: static type warning
}
if (funcDynToDyn is FuncDynToVoid) {
@@ -64,11 +64,10 @@
c = funcDynToDyn(new C());
}
- if (funcDynToDyn is FuncDynToA) {
- // No promotion: FuncDynToA !<< FuncDynToDyn.
+ if (funcDynToDyn is FuncDynToA) { // Promotion: FuncDynToA << FuncDynToDyn.
a = funcDynToDyn(new A());
b = funcDynToDyn(new B());
- c = funcDynToDyn(new C());
+ c = funcDynToDyn(new C()); /// 10: static type warning
}
}
@@ -98,10 +97,11 @@
b = funcDynToA(new B());
c = funcDynToA(new C()); /// 06: static type warning
- if (funcDynToA is FuncDynToDyn) { // Promotion: FuncDynToDyn << FuncDynToA.
+ if (funcDynToA is FuncDynToDyn) {
+ // No promotion: FuncDynToDyn !<< FuncDynToA.
a = funcDynToA(new A());
b = funcDynToA(new B());
- c = funcDynToA(new C());
+ c = funcDynToA(new C()); /// 08: static type warning
}
if (funcDynToA is FuncDynToVoid) {
diff --git a/tests/language/type_promotion_more_specific_test.dart b/tests/language/type_promotion_more_specific_test.dart
index b672e4b..eb843b6 100644
--- a/tests/language/type_promotion_more_specific_test.dart
+++ b/tests/language/type_promotion_more_specific_test.dart
@@ -61,17 +61,17 @@
if (d1 is E) { // Promotion: E << D.
x = d1.e; /// 05: ok
}
- if (d1 is E<A>) { // No promotion E<A> << D.
- int a = d1.d; /// 06: ok
- String b = d1.d; /// 07: ok
- x = d1.e; /// 08: static type warning
+ if (d1 is E<A>) { // Promotion: E<A> << D.
+ int a = d1.d; /// 06: static type warning
+ String b = d1.d; /// 07: static type warning
+ x = d1.e; /// 08: ok
}
D<A> d2 = new E<B>(null);
- if (d2 is E) { // Promotion: E << D<A>
- x = d2.e; /// 09: ok
- int a = d2.e; /// 10: ok
- String b = d2.e; /// 11: ok
+ if (d2 is E) { // No promotion: E !<< D<A>
+ x = d2.e; /// 09: static type warning
+ int a = d2.e; /// 10: static type warning
+ String b = d2.e; /// 11: static type warning
}
D<A> d3 = new E<B>(new B());
diff --git a/tests/language/vm/optimized_polymorphic_list_access_test.dart b/tests/language/vm/optimized_polymorphic_list_access_test.dart
new file mode 100644
index 0000000..6ab48f9
--- /dev/null
+++ b/tests/language/vm/optimized_polymorphic_list_access_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--optimization_counter_threshold=10
+
+import "package:expect/expect.dart";
+
+// Test correct polymorphic inlining of recognized methods like list access.
+
+test(arr) {
+ var r = 0;
+ for (var i = 0; i < 1; ++i) {
+ r += arr[0];
+ }
+ return r;
+}
+
+
+main() {
+ var a = new List<int>(1);
+ a[0] = 0;
+ var b = <int>[0];
+ Expect.equals(0, test(a));
+ Expect.equals(0, test(b));
+ for (var i = 0; i < 20; ++i) test(a);
+ Expect.equals(0, test(a));
+ Expect.equals(0, test(b));
+}
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index bfa469b..52f7602 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -1,3 +1,166 @@
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+lib/_chrome/dart2js/chrome_dart2js: CompileTimeError
+lib/collection/hash_set: CompileTimeError
+lib/collection/linked_hash_set: CompileTimeError
+lib/collection/list: CompileTimeError
+lib/convert/codec: CompileTimeError
+lib/html/dart2js/html_dart2js: CompileTimeError
+lib/html/dartium/html_dartium: CompileTimeError
+lib/html/html_common/lists: Pass, CompileTimeError
+lib/indexed_db/dart2js/indexed_db_dart2js: CompileTimeError
+lib/indexed_db/dartium/indexed_db_dartium: CompileTimeError
+lib/_internal/compiler/samples/compile_loop/compile_loop: CompileTimeError
+lib/_internal/compiler/samples/darttags/darttags: CompileTimeError
+lib/_internal/compiler/samples/jsonify/jsonify: CompileTimeError
+lib/_internal/compiler/samples/leap/leap: CompileTimeError
+lib/_internal/compiler/samples/leap/leap_leg: CompileTimeError
+lib/_internal/compiler/samples/leap/request_cache: CompileTimeError
+lib/_internal/dartdoc/bin/dartdoc: CompileTimeError
+lib/_internal/dartdoc/lib/dartdoc: CompileTimeError
+lib/_internal/dartdoc/lib/src/dartdoc/utils: CompileTimeError
+lib/_internal/dartdoc/lib/src/export_map: CompileTimeError
+lib/_internal/dartdoc/lib/universe_serializer: CompileTimeError
+lib/_internal/pub/bin/pub: CompileTimeError
+lib/_internal/pub/lib/src/barback: CompileTimeError
+lib/_internal/pub/lib/src/barback/dart2js_transformer: CompileTimeError
+lib/_internal/pub/lib/src/barback/dart_forwarding_transformer: CompileTimeError
+lib/_internal/pub/lib/src/barback/load_all_transformers: CompileTimeError
+lib/_internal/pub/lib/src/barback/load_transformers: CompileTimeError
+lib/_internal/pub/lib/src/barback/pub_barback_logger: CompileTimeError
+lib/_internal/pub/lib/src/barback/pub_package_provider: CompileTimeError
+lib/_internal/pub/lib/src/barback/rewrite_import_transformer: CompileTimeError
+lib/_internal/pub/lib/src/barback/server: CompileTimeError
+lib/_internal/pub/lib/src/barback/watch_sources: CompileTimeError
+lib/_internal/pub/lib/src/command: Pass, CompileTimeError # Pass necessary, since CompileTimeError is valid for everything in that directory (not only for src/command.dart)
+lib/_internal/pub/lib/src/command/build: CompileTimeError
+lib/_internal/pub/lib/src/command/lish: CompileTimeError
+lib/_internal/pub/lib/src/command/list_package_dirs: CompileTimeError
+lib/_internal/pub/lib/src/command/uploader: CompileTimeError
+lib/_internal/pub/lib/src/dart: CompileTimeError
+lib/_internal/pub/lib/src/directory_tree: CompileTimeError
+lib/_internal/pub/lib/src/entrypoint: CompileTimeError
+lib/_internal/pub/lib/src/http: CompileTimeError
+lib/_internal/pub/lib/src/io: CompileTimeError
+lib/_internal/pub/lib/src/lock_file: CompileTimeError
+lib/_internal/pub/lib/src/oauth2: CompileTimeError
+lib/_internal/pub/lib/src/package: CompileTimeError
+lib/_internal/pub/lib/src/package_graph: CompileTimeError
+lib/_internal/pub/lib/src/pubspec: CompileTimeError
+lib/_internal/pub/lib/src/safe_http_server: CompileTimeError
+lib/_internal/pub/lib/src/sdk: CompileTimeError
+lib/_internal/pub/lib/src/source: CompileTimeError
+lib/_internal/pub/lib/src/source/git: CompileTimeError
+lib/_internal/pub/lib/src/source/hosted: CompileTimeError
+lib/_internal/pub/lib/src/source/path: CompileTimeError
+lib/_internal/pub/lib/src/system_cache: CompileTimeError
+lib/_internal/pub/lib/src/utils: CompileTimeError
+lib/_internal/pub/lib/src/validator/compiled_dartdoc: CompileTimeError
+lib/_internal/pub/lib/src/validator/directory: CompileTimeError
+lib/_internal/pub/lib/src/validator/lib: CompileTimeError
+lib/_internal/pub/lib/src/validator/license: CompileTimeError
+lib/_internal/pub/lib/src/validator/name: CompileTimeError
+lib/_internal/pub/test/descriptor: CompileTimeError
+lib/_internal/pub/test/descriptor/git: CompileTimeError
+lib/_internal/pub/test/descriptor/tar: CompileTimeError
+lib/_internal/pub/test/lish/utils: CompileTimeError
+lib/_internal/pub/test/oauth2/utils: CompileTimeError
+lib/_internal/pub/test/serve/utils: CompileTimeError
+lib/_internal/pub/test/test_pub: CompileTimeError
+lib/_internal/pub/test/validator/utils: CompileTimeError
+lib/js/dartium/js_dartium: CompileTimeError
+lib/svg/dart2js/svg_dart2js: CompileTimeError
+lib/svg/dartium/svg_dartium: CompileTimeError
+lib/typed_data/dart2js/typed_data_dart2js: CompileTimeError
+lib/web_audio/dartium/web_audio_dartium: CompileTimeError
+lib/web_gl/dart2js/web_gl_dart2js: CompileTimeError
+lib/web_gl/dartium/web_gl_dartium: CompileTimeError
+lib/web_sql/dart2js/web_sql_dart2js: CompileTimeError
+lib/web_sql/dartium/web_sql_dartium: CompileTimeError
+
+
+[ $compiler == dart2analyzer ]
+lib/async/async_error: CompileTimeError
+lib/async/deferred_load: CompileTimeError
+lib/async/future: CompileTimeError
+lib/async/future_impl: CompileTimeError
+lib/async/schedule_microtask: CompileTimeError
+lib/async/stream: CompileTimeError
+lib/async/stream_controller: CompileTimeError
+lib/async/stream_impl: CompileTimeError
+lib/async/timer: CompileTimeError
+lib/async/zone: CompileTimeError
+lib/collection/collections: CompileTimeError
+lib/_collection_dev/iterable: CompileTimeError
+lib/_collection_dev/list: CompileTimeError
+lib/_collection_dev/symbol: CompileTimeError
+lib/collection/hash_map: CompileTimeError
+lib/collection/iterable: CompileTimeError
+lib/collection/linked_hash_map: CompileTimeError
+lib/collection/list: CompileTimeError
+lib/collection/queue: CompileTimeError
+lib/collection/splay_tree: CompileTimeError
+lib/convert/ascii: CompileTimeError
+lib/convert/byte_conversion: CompileTimeError
+lib/convert/converter: CompileTimeError
+lib/convert/encoding: CompileTimeError
+lib/convert/html_escape: CompileTimeError
+lib/convert/json: CompileTimeError
+lib/convert/latin1: CompileTimeError
+lib/convert/line_splitter: CompileTimeError
+lib/convert/string_conversion: CompileTimeError
+lib/convert/utf: CompileTimeError
+lib/core/iterable: CompileTimeError
+lib/core/list: CompileTimeError
+lib/core/map: CompileTimeError
+lib/core/print: CompileTimeError
+lib/core/set: CompileTimeError
+lib/core/string: CompileTimeError
+lib/core/symbol: CompileTimeError
+lib/core/uri: CompileTimeError
+lib/html/html_common/conversions: CompileTimeError
+lib/html/html_common/css_class_set: CompileTimeError
+lib/html/html_common/device: CompileTimeError
+lib/html/html_common/filtered_element_list: CompileTimeError
+lib/html/html_common/lists: CompileTimeError
+lib/io/bytes_builder: CompileTimeError
+lib/io/common: CompileTimeError
+lib/io/crypto: CompileTimeError
+lib/io/data_transformer: CompileTimeError
+lib/io/directory: CompileTimeError
+lib/io/directory_impl: CompileTimeError
+lib/io/eventhandler: CompileTimeError
+lib/io/file: CompileTimeError
+lib/io/file_impl: CompileTimeError
+lib/io/file_system_entity: CompileTimeError
+lib/io/http: CompileTimeError
+lib/io/http_date: CompileTimeError
+lib/io/http_headers: CompileTimeError
+lib/io/http_impl: CompileTimeError
+lib/io/http_parser: CompileTimeError
+lib/io/http_session: CompileTimeError
+lib/io/io_service: CompileTimeError
+lib/io/io_sink: CompileTimeError
+lib/io/link: CompileTimeError
+lib/io/options: CompileTimeError
+lib/io/platform: CompileTimeError
+lib/io/platform_impl: CompileTimeError
+lib/io/process: CompileTimeError
+lib/io/secure_server_socket: CompileTimeError
+lib/io/secure_socket: CompileTimeError
+lib/io/socket: CompileTimeError
+lib/io/stdio: CompileTimeError
+lib/io/string_transformer: CompileTimeError
+lib/io/timer_impl: CompileTimeError
+lib/io/websocket: CompileTimeError
+lib/io/websocket_impl: CompileTimeError
+lib/math/point: CompileTimeError
+lib/math/rectangle: CompileTimeError
+lib/utf/utf16: CompileTimeError
+lib/utf/utf32: CompileTimeError
+lib/utf/utf8: CompileTimeError
+lib/utf/utf_stream: CompileTimeError
+
diff --git a/tests/lib/analyzer/analyze_tests.status b/tests/lib/analyzer/analyze_tests.status
deleted file mode 100644
index 4fe235a..0000000
--- a/tests/lib/analyzer/analyze_tests.status
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# The testing infrastructure is using the dart:io Path and LineTransformer
-# classes.
-standalone/io/skipping_dart2js_compilations_test: Skip # http/dartbug.com/12449
-standalone/io/dependency_graph_test: Skip # http/dartbug.com/12449
-standalone/io/status_file_parser_test: Skip # http/dartbug.com/12449
-
-[ $compiler == dartanalyzer ]
-standalone/javascript_int_overflow_literal_test/01: fail, ok
-
-# https://code.google.com/p/dart/issues/detail?id=11665
-standalone/io/directory_invalid_arguments_test: fail
-standalone/io/file_constructor_test: fail
-standalone/io/http_cookie_date_test: fail
-standalone/io/http_headers_test: fail
-standalone/io/http_parser_test: fail
-standalone/io/process_invalid_arguments_test: fail
-standalone/io/raw_secure_server_socket_argument_test: fail
-standalone/io/secure_socket_argument_test: fail
-standalone/io/stdout_bad_argument_test: fail
-standalone/io/skipping_dart2js_compilations_test: fail
-standalone/io/dependency_graph_test: fail # http/dartbug.com/12449
-standalone/io/web_socket_protocol_processor_test: fail
-standalone/io/test_runner_test: fail
-standalone/package/invalid_uri_test: fail
-standalone/package/package1_test: fail
-standalone/package/package_test: fail
-standalone/typed_data_view_test: fail
-standalone/typed_data_test: fail
-standalone/issue14236_test: Skip # Analyzer can't handle Script snapshots.
-
-
-[ $compiler == dart2analyzer ]
-standalone/javascript_int_overflow_literal_test/01: fail, ok
-
-# https://code.google.com/p/dart/issues/detail?id=11665
-standalone/io/directory_invalid_arguments_test: fail
-standalone/io/file_constructor_test: fail
-standalone/io/http_cookie_date_test: fail
-standalone/io/http_headers_test: fail
-standalone/io/http_parser_test: fail
-standalone/io/process_invalid_arguments_test: fail
-standalone/io/raw_secure_server_socket_argument_test: fail
-standalone/io/secure_socket_argument_test: fail
-standalone/io/stdout_bad_argument_test: fail
-standalone/io/skipping_dart2js_compilations_test: fail
-standalone/io/dependency_graph_test: fail # http/dartbug.com/12449
-standalone/io/web_socket_protocol_processor_test: fail
-standalone/io/test_runner_test: fail
-standalone/package/invalid_uri_test: fail
-standalone/package/package1_test: fail
-standalone/package/package_test: fail
-standalone/typed_data_view_test: fail
-standalone/typed_data_test: fail
-standalone/issue14236_test: Skip # Analyzer can't handle Script snapshots.
diff --git a/tests/lib/analyzer/test_config.dart b/tests/lib/analyzer/test_config.dart
deleted file mode 100644
index d2dcd52..0000000
--- a/tests/lib/analyzer/test_config.dart
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library analyze_library_test_config;
-
-import 'dart:io';
-import '../../../tools/testing/dart/test_suite.dart';
-
-class AnalyzeLibraryTestSuite extends DartcCompilationTestSuite {
- final libraries = [ 'async', 'core', 'crypto', 'io', 'isolate', 'json',
- 'math', 'mirrors', 'typed_data', 'uri',
- 'utf' ];
-
- AnalyzeLibraryTestSuite(Map configuration)
- : super(configuration,
- 'analyze_library',
- 'sdk',
- [ 'lib' ],
- ['tests/lib/analyzer/analyze_library.status'],
- allStaticClean: true);
-
- bool isTestFile(String filename) {
- var sep = Platform.pathSeparator;
- return libraries.any((String lib) {
- return filename.endsWith('lib$sep$lib$sep$lib.dart');
- });
- }
-
- bool get listRecursively => true;
-}
-
-
-class AnalyzeTestsTestSuite extends DartcCompilationTestSuite {
- AnalyzeTestsTestSuite(Map configuration)
- : super(configuration,
- 'analyze_tests',
- 'tests',
- [ 'standalone' ],
- ['tests/lib/analyzer/analyze_tests.status'],
- allStaticClean: true);
-
- bool isTestFile(String filename) {
- return filename.endsWith('_test.dart');
- }
-
- bool get listRecursively => true;
-}
diff --git a/tests/lib/async/stream_controller_async_test.dart b/tests/lib/async/stream_controller_async_test.dart
index d66a6f1..e3c75b7 100644
--- a/tests/lib/async/stream_controller_async_test.dart
+++ b/tests/lib/async/stream_controller_async_test.dart
@@ -675,6 +675,84 @@
}
});
});
+
+ test("$type-controller-addstream-error-stop", () {
+ // Check that addStream defaults to ending after the first error.
+ var done = expectAsync0((){});
+ StreamController c = broadcast
+ ? new StreamController.broadcast(sync: sync)
+ : new StreamController(sync: sync);
+ Stream stream = asBroadcast ? c.stream.asBroadcastStream() : c.stream;
+ var actual = new Events.capture(stream);
+
+ var source = new Events();
+ source..add(1)..add(2)..error("BAD")..add(3)..error("FAIL")..close();
+
+ var expected = new Events()..add(1)..add(2)..error("BAD")..close();
+ StreamController sourceController = new StreamController();
+ c.addStream(sourceController.stream).then((_) {
+ c.close().then((_) {
+ Expect.listEquals(expected.events, actual.events);
+ done();
+ });
+ });
+
+ source.replay(sourceController);
+ });
+
+ test("$type-controller-addstream-error-forward", () {
+ // Check that addStream with cancelOnError:false passes all data and errors
+ // to the controller.
+ var done = expectAsync0((){});
+ StreamController c = broadcast
+ ? new StreamController.broadcast(sync: sync)
+ : new StreamController(sync: sync);
+ Stream stream = asBroadcast ? c.stream.asBroadcastStream() : c.stream;
+ var actual = new Events.capture(stream);
+
+ var source = new Events();
+ source..add(1)..add(2)..addError("BAD")..add(3)..addError("FAIL")..close();
+
+ StreamController sourceController = new StreamController();
+ c.addStream(sourceController.stream, cancelOnError: false).then((_) {
+ c.close().then((_) {
+ Expect.listEquals(source.events, actual.events);
+ done();
+ });
+ });
+
+ source.replay(sourceController);
+ });
+
+ test("$type-controller-addstream-twice", () {
+ // Using addStream twice on the same stream
+ var done = expectAsync0((){});
+ StreamController c = broadcast
+ ? new StreamController.broadcast(sync: sync)
+ : new StreamController(sync: sync);
+ Stream stream = asBroadcast ? c.stream.asBroadcastStream() : c.stream;
+ var actual = new Events.capture(stream);
+
+ // Streams of five events, throws on 3.
+ Stream s1 = new Stream.fromIterable([1,2,3,4,5])
+ .map((x) => (x == 3 ? throw x : x));
+ Stream s2 = new Stream.fromIterable([1,2,3,4,5])
+ .map((x) => (x == 3 ? throw x : x));
+
+ Events expected = new Events();
+ expected..add(1)..add(2)..error(3);
+ expected..add(1)..add(2)..error(3)..add(4)..add(5);
+ expected..close();
+
+ c.addStream(s1).then((_) {
+ c.addStream(s2, cancelOnError: false).then((_) {
+ c.close().then((_) {
+ Expect.listEquals(expected.events, actual.events);
+ done();
+ });
+ });
+ });
+ });
}
main() {
diff --git a/tests/lib/async/stream_from_iterable_test.dart b/tests/lib/async/stream_from_iterable_test.dart
index ab7d543..ad342fe 100644
--- a/tests/lib/async/stream_from_iterable_test.dart
+++ b/tests/lib/async/stream_from_iterable_test.dart
@@ -73,4 +73,79 @@
Expect.listEquals(expected.events, actual.events);
}));
});
+
+ test("iterable-single-subscription", () {
+ Stream stream = new Stream.fromIterable(iter);
+ stream.listen((x){});
+ Expect.throws(() { stream.listen((x){}); },
+ (e) => e is StateError);
+ });
+
+ test("regression-14332", () {
+ // Regression test for http://dartbug.com/14332.
+ // This should succeede.
+ var from = new Stream.fromIterable([1,2,3,4,5]);
+
+ var c = new StreamController();
+ var sink = c.sink;
+
+ var done = expectAsync0((){}, count: 2);
+
+ // if this goes first, test failed (hanged). Swapping addStream and toList
+ // made failure go away.
+ sink.addStream(from).then((_) {
+ c.close();
+ done();
+ });
+
+ c.stream.toList().then((x) {
+ Expect.listEquals([1,2,3,4,5], x);
+ done();
+ });
+ });
+
+ test("regression-14334-a", () {
+ var from = new Stream.fromIterable([1,2,3,4,5]);
+
+ // odd numbers as data events, even numbers as error events
+ from = from.map((x) => x.isOdd ? x : throw x);
+
+ var c = new StreamController();
+ var sink = c.sink;
+
+ var done = expectAsync0((){}, count: 2);
+
+ var data = [], errors = [];
+ c.stream.listen(data.add, onError: errors.add, onDone: () {
+ Expect.listEquals([1], data);
+ Expect.listEquals([2], errors);
+ done();
+ });
+ sink.addStream(from).then((_) {
+ c.close();
+ done();
+ });
+ });
+
+ test("regression-14334-b", () {
+ var from = new Stream.fromIterable([1,2,3,4,5]);
+
+ // odd numbers as data events, even numbers as error events
+ from = from.map((x) => x.isOdd ? x : throw x);
+
+ var c = new StreamController();
+
+ var done = expectAsync0((){}, count: 2);
+
+ var data = [], errors = [];
+ c.stream.listen(data.add, onError: errors.add, onDone: () {
+ Expect.listEquals([1, 3, 5], data);
+ Expect.listEquals([2, 4], errors);
+ done();
+ });
+ c.addStream(from, cancelOnError: false).then((_) {
+ c.close();
+ done();
+ });
+ });
}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index edff803..30c9900 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -19,7 +19,8 @@
mirrors/closure_mirror_find_in_context_test: Fail # Issue 6490
mirrors/constructor_kinds_test: RuntimeError # Issue 13799
mirrors/equality_test/02: RuntimeError # Issue 12333
-mirrors/fake_function_test: RuntimeError # Issue 11612
+mirrors/fake_function_with_call_test: RuntimeError # Issue 11612
+mirrors/fake_function_without_call_test: RuntimeError # Issue 11612
mirrors/find_in_context_fake_function_test: Fail # Issue 6490
mirrors/function_type_mirror_test: RuntimeError # Issue 12166
mirrors/generics_test/01: RuntimeError # Issue 12087
@@ -129,10 +130,6 @@
mirrors/*: Skip # http://dartbug.com/11511
async/schedule_microtask6_test: Fail # Issue 10957 - may be related to issue 10910
async/schedule_microtask3_test: RuntimeError # Issue 13719: Please triage this failure.
-platform/package_root_test: Fail # Issue 14451
-platform/script_test: Fail # Issue 14451
-platform/isolate_test: Fail # Issue 14451
-
[ $compiler == dart2dart && $minified ]
json/json_test: Fail # Issue 10961
@@ -189,7 +186,6 @@
mirrors/library_uri_io_test: Skip # Not intended for drt as it uses dart:io.
mirrors/local_isolate_test: Skip # http://dartbug.com/12188
async/schedule_microtask6_test: Fail # Issue 10910
-platform/isolate_test: Skip # Issue 14444
[ $compiler == none && $runtime == drt && $mode == debug ]
mirrors/hierarchy_invariants_test: Pass, Slow # Issue 14449
@@ -206,32 +202,6 @@
convert/chunked_conversion_utf88_test: Pass, Slow # Issue 12644.
convert/utf85_test: Pass, Slow # Issue 12644.
-[ $compiler == dartanalyzer ]
-mirrors/typedef_test/none: Fail # Issue 13093
-mirrors/generics_test/none: Fail # Issue 13432
-mirrors/generic_bounded_test/none: Fail # Issue 13432
-mirrors/generic_f_bounded_test/none: Fail # Issue 13432
-mirrors/generic_bounded_by_type_parameter_test/none: Fail # Issue 13432
-mirrors/generic_mixin_test/none: Fail # Issue 13432
-mirrors/invoke_named_test/none: Fail # http://dartbug.com/13612
-mirrors/generic_f_bounded_mixin_application_test: Fail # Issue 14116
-mirrors/generic_interface_test/none: Fail # Inexpressible in multitest
-mirrors/typevariable_mirror_metadata_test/none: Fail # Issue 13093
-mirrors/type_variable_owner_test/none: Fail # Issue 14356
-
-[ $compiler == dart2analyzer ]
-mirrors/typedef_test/none: Fail # Issue 13093
-mirrors/generics_test/none: Fail # Issue 13432
-mirrors/generic_bounded_test/none: Fail # Issue 13432
-mirrors/generic_f_bounded_test/none: Fail # Issue 13432
-mirrors/generic_bounded_by_type_parameter_test/none: Fail # Issue 13432
-mirrors/generic_mixin_test/none: Fail # Issue 13432
-mirrors/invoke_named_test/none: Fail # http://dartbug.com/13612
-mirrors/generic_f_bounded_mixin_application_test: Fail # Issue 14116
-mirrors/generic_interface_test/none: Fail # Inexpressible in multitest
-mirrors/typevariable_mirror_metadata_test/none: Fail # Issue 13093
-mirrors/type_variable_owner_test/none: Fail # Issue 14356
-
[ $compiler == none && $runtime == dartium ]
async/schedule_microtask5_test: Pass, Timeout # Issue 13719: Please triage this failure.
async/timer_cancel2_test: Pass, Timeout # Issue 13719: Please triage this failure.
@@ -240,9 +210,46 @@
# Issue 13921: spawnFunction is not allowed on Dartium's DOM thread.
async/timer_isolate_test: Fail
-[ $compiler == none && ($runtime == drt || $runtime == dartium) && $system == windows ]
-platform/uri_test: Fail # Issue 14504
-
[ ($compiler != none && $runtime != none) || ($compiler == none && ($runtime != dartium && $runtime != drt)) ]
async/schedule_microtask_test: Fail # Issue 9001, Issue 9002
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+async/future_test: StaticWarning
+async/future_value_chain4_test: StaticWarning
+async/schedule_microtask3_test: StaticWarning
+async/stream_controller_async_test: StaticWarning
+async/stream_controller_test: StaticWarning
+async/stream_event_transformed_test: StaticWarning
+async/stream_first_where_test: StaticWarning
+async/stream_from_iterable_test: StaticWarning
+async/stream_join_test: StaticWarning
+async/stream_last_where_test: StaticWarning
+async/stream_single_test: StaticWarning
+async/stream_single_to_multi_subscriber_test: StaticWarning
+async/stream_transform_test: StaticWarning
+async/stream_transformer_from_handlers_test: StaticWarning
+async/stream_transformer_test: StaticWarning
+async/zone_debug_test: StaticWarning
+convert/chunked_conversion1_test: StaticWarning
+convert/chunked_conversion_json_decode1_test: StaticWarning
+math/min_max_test: StaticWarning
+mirrors/equality_test/02: StaticWarning # Issue 14524
+mirrors/function_type_mirror_test: StaticWarning # Issue 14524
+mirrors/generic_f_bounded_mixin_application_test: CompileTimeError # Issue 14116
+mirrors/invoke_named_test: StaticWarning # Issue 14522
+mirrors/mirrors_test: StaticWarning # Issue 14524
+mirrors/private_symbol_test: StaticWarning # Issue 14524
+mirrors/reflect_class_test: StaticWarning # Issue 14524
+mirrors/type_variable_owner_test: StaticWarning # Issue 14524
+mirrors/typedef_test: StaticWarning # Issue 14524
+mirrors/typedef_metadata_test: StaticWarning # Issue 14524
+mirrors/typevariable_mirror_metadata_test: StaticWarning # Issue 14524
+
+mirrors/fake_function_without_call_test: StaticWarning, OK # Implements Function without defining call.
+mirrors/find_in_context_fake_function_test: StaticWarning, OK # Implements Function without defining call.
+mirrors/immutable_collections_test: StaticWarning, OK # Expect failure for any type of Iterable.
+mirrors/inference_and_no_such_method_test: StaticWarning, OK # Expect to trigger noSuchMethod.
+mirrors/library_metadata2_test/01: StaticWarning, OK # Compile-time or run-time
+
+mirrors/invoke_test: StaticWarning, OK # API being removed.
+mirrors/invoke_closurization_test: StaticWarning, OK # API being removed.
diff --git a/tests/lib/mirrors/closure_mirror_import1.dart b/tests/lib/mirrors/closure_mirror_import1.dart
index 2788b94..c0e41da 100644
--- a/tests/lib/mirrors/closure_mirror_import1.dart
+++ b/tests/lib/mirrors/closure_mirror_import1.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.
+library closure_mirror_import1;
+
export "closure_mirror_import2.dart" show firstGlobalVariableInImport2;
var globalVariableInImport1 = "globalVariableInImport1";
diff --git a/tests/lib/mirrors/closure_mirror_import2.dart b/tests/lib/mirrors/closure_mirror_import2.dart
index a14b7a9..9d09d36 100644
--- a/tests/lib/mirrors/closure_mirror_import2.dart
+++ b/tests/lib/mirrors/closure_mirror_import2.dart
@@ -2,5 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+library closure_mirror_import2;
+
var firstGlobalVariableInImport2 = "firstGlobalVariableInImport2";
var secondGlobalVariableInImport2 = "secondGlobalVariableInImport2";
diff --git a/tests/lib/mirrors/delegate_test.dart b/tests/lib/mirrors/delegate_test.dart
index 1f7edc6..b7ea729 100644
--- a/tests/lib/mirrors/delegate_test.dart
+++ b/tests/lib/mirrors/delegate_test.dart
@@ -7,7 +7,6 @@
import 'dart:mirrors';
import 'package:expect/expect.dart';
-import 'invoke_test.dart';
class C {
method(a, b, c) => "$a-$b-$c";
diff --git a/tests/lib/mirrors/equality_test.dart b/tests/lib/mirrors/equality_test.dart
index 94c9856..26d1aac 100644
--- a/tests/lib/mirrors/equality_test.dart
+++ b/tests/lib/mirrors/equality_test.dart
@@ -139,9 +139,9 @@
'thisLibrary.variables[#somePredicate].type' /// 02: ok
: thisLibrary.variables[#somePredicate].type}, /// 02: ok
- {'reflectType(Predicate).referent' : reflectType(Predicate).referent, /// 02: ok
+ {'reflectType(Predicate).referent' : (reflectType(Predicate) as TypedefMirror).referent, /// 02: ok
'thisLibrary.variables[#somePredicate].type.referent' /// 02: ok
- : thisLibrary.variables[#somePredicate].type.referent}, /// 02: ok
+ : (thisLibrary.variables[#somePredicate].type as TypedefMirror).referent}, /// 02: ok
{'reflectClass(A).typeVariables.single' /// 02: ok
: reflectClass(A).typeVariables.single, /// 02: ok
diff --git a/tests/lib/mirrors/fake_function_test.dart b/tests/lib/mirrors/fake_function_with_call_test.dart
similarity index 100%
rename from tests/lib/mirrors/fake_function_test.dart
rename to tests/lib/mirrors/fake_function_with_call_test.dart
diff --git a/tests/lib/mirrors/fake_function_without_call_test.dart b/tests/lib/mirrors/fake_function_without_call_test.dart
new file mode 100644
index 0000000..da6bd59
--- /dev/null
+++ b/tests/lib/mirrors/fake_function_without_call_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+class MultiArityFunction implements Function {
+ noSuchMethod(Invocation msg) {
+ if (msg.memberName != #call) return super.noSuchMethod(msg);
+ return msg.positionalArguments.join(",");
+ }
+}
+
+main() {
+ var f = new MultiArityFunction();
+
+ Expect.isTrue(f is Function);
+ Expect.equals('a', f('a'));
+ Expect.equals('a,b', f('a', 'b'));
+ Expect.equals('a,b,c', f('a', 'b', 'c'));
+ Expect.equals('a', Function.apply(f, ['a']));
+ Expect.equals('a,b', Function.apply(f, ['a', 'b']));
+ Expect.equals('a,b,c', Function.apply(f, ['a', 'b', 'c']));
+ Expect.throws(() => f.foo('a', 'b', 'c'),
+ (e) => e is NoSuchMethodError);
+
+ ClosureMirror cm = reflect(f);
+ Expect.isTrue(cm is ClosureMirror);
+ Expect.equals('a', cm.apply(['a']).reflectee);
+ Expect.equals('a,b', cm.apply(['a', 'b']).reflectee);
+ Expect.equals('a,b,c', cm.apply(['a', 'b', 'c']).reflectee);
+
+ MethodMirror mm = cm.function;
+ Expect.isNull(mm);
+
+ ClassMirror km = cm.type;
+ Expect.equals(reflectClass(MultiArityFunction), km);
+}
diff --git a/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart b/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart
index 2391aa5..c6f2b16 100644
--- a/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart
+++ b/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart
@@ -8,61 +8,61 @@
import 'package:expect/expect.dart';
-import 'generics_test.dart';
+import 'generics_helper.dart';
class Super<T, R extends T> {}
class Fixed extends Super<num, int> {}
-class Generic<X, Y> extends Super<X, Y> {}
+class Generic<X, Y> extends Super<X, Y> {} /// 02: static type warning
class Malbounded extends Super<num, String> {} /// 01: static type warning
main() {
ClassMirror superDecl = reflectClass(Super);
ClassMirror superOfNumAndInt = reflectClass(Fixed).superclass;
- ClassMirror genericDecl = reflectClass(Generic);
- ClassMirror superOfXAndY = genericDecl.superclass;
- ClassMirror genericOfNumAndDouble = reflect(new Generic<num, double>()).type;
- ClassMirror superOfNumAndDouble = genericOfNumAndDouble.superclass;
+ ClassMirror genericDecl = reflectClass(Generic); /// 02: continued
+ ClassMirror superOfXAndY = genericDecl.superclass; /// 02: continued
+ ClassMirror genericOfNumAndDouble = reflect(new Generic<num, double>()).type; /// 02: continued
+ ClassMirror superOfNumAndDouble = genericOfNumAndDouble.superclass; /// 02: continued
ClassMirror genericOfNumAndBool = reflect(new Generic<num, bool>()).type; /// 02: static type warning, dynamic type error
ClassMirror superOfNumAndBool = genericOfNumAndBool.superclass; /// 02: continued
ClassMirror superOfNumAndString = reflectClass(Malbounded).superclass; /// 01: continued
Expect.isTrue(superDecl.isOriginalDeclaration);
Expect.isFalse(superOfNumAndInt.isOriginalDeclaration);
- Expect.isTrue(genericDecl.isOriginalDeclaration);
- Expect.isFalse(superOfXAndY.isOriginalDeclaration);
- Expect.isFalse(genericOfNumAndDouble.isOriginalDeclaration);
- Expect.isFalse(superOfNumAndDouble.isOriginalDeclaration);
+ Expect.isTrue(genericDecl.isOriginalDeclaration); /// 02: continued
+ Expect.isFalse(superOfXAndY.isOriginalDeclaration); /// 02: continued
+ Expect.isFalse(genericOfNumAndDouble.isOriginalDeclaration); /// 02: continued
+ Expect.isFalse(superOfNumAndDouble.isOriginalDeclaration); /// 02: continued
Expect.isFalse(genericOfNumAndBool.isOriginalDeclaration); /// 02: continued
Expect.isFalse(superOfNumAndBool.isOriginalDeclaration); /// 02: continued
Expect.isFalse(superOfNumAndString.isOriginalDeclaration); /// 01: continued
TypeVariableMirror tFromSuper = superDecl.typeVariables[0];
TypeVariableMirror rFromSuper = superDecl.typeVariables[1];
- TypeVariableMirror xFromGeneric = genericDecl.typeVariables[0];
- TypeVariableMirror yFromGeneric = genericDecl.typeVariables[1];
+ TypeVariableMirror xFromGeneric = genericDecl.typeVariables[0]; /// 02: continued
+ TypeVariableMirror yFromGeneric = genericDecl.typeVariables[1]; /// 02: continued
Expect.equals(reflectClass(Object), tFromSuper.upperBound);
Expect.equals(tFromSuper, rFromSuper.upperBound);
- Expect.equals(reflectClass(Object), xFromGeneric.upperBound);
- Expect.equals(reflectClass(Object), yFromGeneric.upperBound);
+ Expect.equals(reflectClass(Object), xFromGeneric.upperBound); /// 02: continued
+ Expect.equals(reflectClass(Object), yFromGeneric.upperBound); /// 02: continued
typeParameters(superDecl, [#T, #R]);
typeParameters(superOfNumAndInt, [#T, #R]);
- typeParameters(genericDecl, [#X, #Y]);
- typeParameters(superOfXAndY, [#T, #R]);
- typeParameters(genericOfNumAndDouble, [#X, #Y]);
- typeParameters(superOfNumAndDouble, [#T, #R]);
+ typeParameters(genericDecl, [#X, #Y]); /// 02: continued
+ typeParameters(superOfXAndY, [#T, #R]); /// 02: continued
+ typeParameters(genericOfNumAndDouble, [#X, #Y]); /// 02: continued
+ typeParameters(superOfNumAndDouble, [#T, #R]); /// 02: continued
typeParameters(genericOfNumAndBool, [#X, #Y]); /// 02: continued
typeParameters(superOfNumAndBool, [#T, #R]); /// 02: continued
typeParameters(superOfNumAndString, [#T, #R]); /// 01: continued
typeArguments(superDecl, []);
typeArguments(superOfNumAndInt, [reflectClass(num), reflectClass(int)]);
- typeArguments(genericDecl, []);
- typeArguments(superOfXAndY, [xFromGeneric, yFromGeneric]);
- typeArguments(genericOfNumAndDouble, [reflectClass(num), reflectClass(double)]);
- typeArguments(superOfNumAndDouble, [reflectClass(num), reflectClass(double)]);
+ typeArguments(genericDecl, []); /// 02: continued
+ typeArguments(superOfXAndY, [xFromGeneric, yFromGeneric]); /// 02: continued
+ typeArguments(genericOfNumAndDouble, [reflectClass(num), reflectClass(double)]); /// 02: continued
+ typeArguments(superOfNumAndDouble, [reflectClass(num), reflectClass(double)]); /// 02: continued
typeArguments(genericOfNumAndBool, [reflectClass(num), reflectClass(bool)]); /// 02: continued
typeArguments(superOfNumAndBool, [reflectClass(num), reflectClass(bool)]); /// 02: continued
typeArguments(superOfNumAndString, [reflectClass(num), reflectClass(String)]); /// 01: continued
diff --git a/tests/lib/mirrors/generic_bounded_test.dart b/tests/lib/mirrors/generic_bounded_test.dart
index c59d3af..dec144a 100644
--- a/tests/lib/mirrors/generic_bounded_test.dart
+++ b/tests/lib/mirrors/generic_bounded_test.dart
@@ -8,57 +8,57 @@
import 'package:expect/expect.dart';
-import 'generics_test.dart';
+import 'generics_helper.dart';
class Super<T extends num> {}
class Fixed extends Super<int> {}
-class Generic<R> extends Super<R> {}
+class Generic<R> extends Super<R> {} /// 02: static type warning
class Malbounded extends Super<String> {} /// 01: static type warning
main() {
ClassMirror superDecl = reflectClass(Super);
ClassMirror superOfInt = reflectClass(Fixed).superclass;
- ClassMirror genericDecl = reflectClass(Generic);
- ClassMirror superOfR = genericDecl.superclass;
- ClassMirror genericOfDouble = reflect(new Generic<double>()).type;
- ClassMirror superOfDouble = genericOfDouble.superclass;
+ ClassMirror genericDecl = reflectClass(Generic); /// 02: continued
+ ClassMirror superOfR = genericDecl.superclass; /// 02: continued
+ ClassMirror genericOfDouble = reflect(new Generic<double>()).type; /// 02: continued
+ ClassMirror superOfDouble = genericOfDouble.superclass; /// 02: continued
ClassMirror genericOfBool = reflect(new Generic<bool>()).type; /// 02: static type warning, dynamic type error
ClassMirror superOfBool = genericOfBool.superclass; /// 02: continued
ClassMirror superOfString = reflectClass(Malbounded).superclass; /// 01: continued
Expect.isTrue(superDecl.isOriginalDeclaration);
Expect.isFalse(superOfInt.isOriginalDeclaration);
- Expect.isTrue(genericDecl.isOriginalDeclaration);
- Expect.isFalse(superOfR.isOriginalDeclaration);
- Expect.isFalse(genericOfDouble.isOriginalDeclaration);
- Expect.isFalse(superOfDouble.isOriginalDeclaration);
+ Expect.isTrue(genericDecl.isOriginalDeclaration); /// 02: continued
+ Expect.isFalse(superOfR.isOriginalDeclaration); /// 02: continued
+ Expect.isFalse(genericOfDouble.isOriginalDeclaration); /// 02: continued
+ Expect.isFalse(superOfDouble.isOriginalDeclaration); /// 02: continued
Expect.isFalse(genericOfBool.isOriginalDeclaration); /// 02: continued
Expect.isFalse(superOfBool.isOriginalDeclaration); /// 02: continued
Expect.isFalse(superOfString.isOriginalDeclaration); /// 01: continued
TypeVariableMirror tFromSuper = superDecl.typeVariables.single;
- TypeVariableMirror rFromGeneric = genericDecl.typeVariables.single;
+ TypeVariableMirror rFromGeneric = genericDecl.typeVariables.single; /// 02: continued
Expect.equals(reflectClass(num), tFromSuper.upperBound);
- Expect.equals(reflectClass(Object), rFromGeneric.upperBound);
+ Expect.equals(reflectClass(Object), rFromGeneric.upperBound); /// 02: continued
typeParameters(superDecl, [#T]);
typeParameters(superOfInt, [#T]);
- typeParameters(genericDecl, [#R]);
- typeParameters(superOfR, [#T]);
- typeParameters(genericOfDouble, [#R]);
- typeParameters(superOfDouble, [#T]);
+ typeParameters(genericDecl, [#R]); /// 02: continued
+ typeParameters(superOfR, [#T]); /// 02: continued
+ typeParameters(genericOfDouble, [#R]); /// 02: continued
+ typeParameters(superOfDouble, [#T]); /// 02: continued
typeParameters(genericOfBool, [#R]); /// 02: continued
typeParameters(superOfBool, [#T]); /// 02: continued
typeParameters(superOfString, [#T]); /// 01: continued
typeArguments(superDecl, []);
typeArguments(superOfInt, [reflectClass(int)]);
- typeArguments(genericDecl, []);
- typeArguments(superOfR, [rFromGeneric]);
- typeArguments(genericOfDouble, [reflectClass(double)]);
- typeArguments(superOfDouble, [reflectClass(double)]);
+ typeArguments(genericDecl, []); /// 02: continued
+ typeArguments(superOfR, [rFromGeneric]); /// 02: continued
+ typeArguments(genericOfDouble, [reflectClass(double)]); /// 02: continued
+ typeArguments(superOfDouble, [reflectClass(double)]); /// 02: continued
typeArguments(genericOfBool, [reflectClass(bool)]); /// 02: continued
typeArguments(superOfBool, [reflectClass(bool)]); /// 02: continued
typeArguments(superOfString, [reflectClass(String)]); /// 01: continued
diff --git a/tests/lib/mirrors/generic_f_bounded_mixin_application_test.dart b/tests/lib/mirrors/generic_f_bounded_mixin_application_test.dart
index 5d38af6..334913d 100644
--- a/tests/lib/mirrors/generic_f_bounded_mixin_application_test.dart
+++ b/tests/lib/mirrors/generic_f_bounded_mixin_application_test.dart
@@ -8,7 +8,7 @@
import 'package:expect/expect.dart';
-import 'generics_test.dart';
+import 'generics_helper.dart';
class Collection<C> {}
class Serializable<S> {}
diff --git a/tests/lib/mirrors/generic_f_bounded_test.dart b/tests/lib/mirrors/generic_f_bounded_test.dart
index 96148cc..00e4fbb 100644
--- a/tests/lib/mirrors/generic_f_bounded_test.dart
+++ b/tests/lib/mirrors/generic_f_bounded_test.dart
@@ -8,7 +8,7 @@
import 'package:expect/expect.dart';
-import 'generics_test.dart';
+import 'generics_helper.dart';
class Magnitude<T> {}
class Real extends Magnitude<Real> {}
diff --git a/tests/lib/mirrors/generic_function_typedef_test.dart b/tests/lib/mirrors/generic_function_typedef_test.dart
index e0968f7..3f6853b 100644
--- a/tests/lib/mirrors/generic_function_typedef_test.dart
+++ b/tests/lib/mirrors/generic_function_typedef_test.dart
@@ -8,7 +8,7 @@
import 'package:expect/expect.dart';
-import 'generics_test.dart';
+import 'generics_helper.dart';
typedef bool NonGenericPredicate(num n);
typedef bool GenericPredicate<T>(T t);
diff --git a/tests/lib/mirrors/generic_interface_test.dart b/tests/lib/mirrors/generic_interface_test.dart
index 8a2b9a0..03e3f11 100644
--- a/tests/lib/mirrors/generic_interface_test.dart
+++ b/tests/lib/mirrors/generic_interface_test.dart
@@ -8,7 +8,7 @@
import 'package:expect/expect.dart';
-import 'generics_test.dart';
+import 'generics_helper.dart';
class Interface<T> {}
class Bounded<S extends num> {}
@@ -17,7 +17,7 @@
class Generic<R> implements Interface<R> {}
class Bienbounded implements Bounded<int> {}
-class Malbounded implements Bounded<String> {}
+class Malbounded implements Bounded<String> {} /// 01: static type warning
class FBounded implements Interface<FBounded> {}
class Mixin {}
@@ -37,7 +37,7 @@
ClassMirror interfaceOfBool = reflect(new Generic<bool>()).type.superinterfaces.single;
ClassMirror boundedOfInt = reflectClass(Bienbounded).superinterfaces.single;
- ClassMirror boundedOfString = reflectClass(Malbounded).superinterfaces.single;
+ ClassMirror boundedOfString = reflectClass(Malbounded).superinterfaces.single; /// 01: continued
ClassMirror interfaceOfFBounded = reflectClass(FBounded).superinterfaces.single;
ClassMirror interfaceOfInt2 = reflectClass(FixedMixinApplication).superinterfaces.single;
@@ -55,7 +55,7 @@
Expect.isFalse(interfaceOfR.isOriginalDeclaration);
Expect.isFalse(interfaceOfBool.isOriginalDeclaration);
Expect.isFalse(boundedOfInt.isOriginalDeclaration);
- Expect.isFalse(boundedOfString.isOriginalDeclaration);
+ Expect.isFalse(boundedOfString.isOriginalDeclaration); /// 01: continued
Expect.isFalse(interfaceOfFBounded.isOriginalDeclaration);
Expect.isFalse(interfaceOfInt2.isOriginalDeclaration);
Expect.isFalse(interfaceOfX.isOriginalDeclaration);
@@ -84,7 +84,7 @@
typeParameters(interfaceOfR, [#T]);
typeParameters(interfaceOfBool, [#T]);
typeParameters(boundedOfInt, [#S]);
- typeParameters(boundedOfString, [#S]);
+ typeParameters(boundedOfString, [#S]); /// 01: continued
typeParameters(interfaceOfFBounded, [#T]);
typeParameters(interfaceOfInt2, [#T]);
typeParameters(interfaceOfX, [#T]);
@@ -97,14 +97,14 @@
typeArguments(boundedDecl, []);
typeArguments(interfaceOfInt, [reflectClass(int)]);
typeArguments(interfaceOfR, [rFromGeneric]);
- typeArguments(interfaceOfBool, [reflectClass(bool)]); /// 01: ok
+ typeArguments(interfaceOfBool, [reflectClass(bool)]);
typeArguments(boundedOfInt, [reflectClass(int)]);
- typeArguments(boundedOfString, [reflectClass(String)]);
+ typeArguments(boundedOfString, [reflectClass(String)]); /// 01: continued
typeArguments(interfaceOfFBounded, [reflectClass(FBounded)]);
typeArguments(interfaceOfInt2, [reflectClass(int)]);
typeArguments(interfaceOfX, [xFromGenericMixinApplication]);
- typeArguments(interfaceOfDouble, [reflectClass(double)]); /// 01: ok
+ typeArguments(interfaceOfDouble, [reflectClass(double)]);
typeArguments(interfaceOfInt3, [reflectClass(int)]);
typeArguments(interfaceOfY, [yFromGenericClass]);
- typeArguments(interfaceOfDouble2, [reflectClass(double)]); /// 01: ok
+ typeArguments(interfaceOfDouble2, [reflectClass(double)]);
}
diff --git a/tests/lib/mirrors/generic_mixin_applications_test.dart b/tests/lib/mirrors/generic_mixin_applications_test.dart
index 1cc0acf..aac6e28 100644
--- a/tests/lib/mirrors/generic_mixin_applications_test.dart
+++ b/tests/lib/mirrors/generic_mixin_applications_test.dart
@@ -8,7 +8,7 @@
import 'package:expect/expect.dart';
-import 'generics_test.dart';
+import 'generics_helper.dart';
class Super<S> {}
class Mixin<M> {}
diff --git a/tests/lib/mirrors/generic_mixin_test.dart b/tests/lib/mirrors/generic_mixin_test.dart
index c359d78..22e00ef 100644
--- a/tests/lib/mirrors/generic_mixin_test.dart
+++ b/tests/lib/mirrors/generic_mixin_test.dart
@@ -8,7 +8,7 @@
import 'package:expect/expect.dart';
-import 'generics_test.dart';
+import 'generics_helper.dart';
class Super<S> {}
class Mixin<M> {}
diff --git a/tests/lib/mirrors/generics_helper.dart b/tests/lib/mirrors/generics_helper.dart
new file mode 100644
index 0000000..a8907c4
--- /dev/null
+++ b/tests/lib/mirrors/generics_helper.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library generics_helper;
+
+import 'package:expect/expect.dart';
+
+typeParameters(mirror, parameterNames) {
+ Expect.listEquals(parameterNames,
+ mirror.typeVariables.map((v) => v.simpleName).toList());
+}
+
+typeArguments(mirror, argumentMirrors) {
+ Expect.listEquals(argumentMirrors, mirror.typeArguments);
+}
diff --git a/tests/lib/mirrors/generics_special_types_test.dart b/tests/lib/mirrors/generics_special_types_test.dart
new file mode 100644
index 0000000..49f72ec
--- /dev/null
+++ b/tests/lib/mirrors/generics_special_types_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.generics_special_types;
+
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+main() {
+ TypeMirror dynamicMirror = currentMirrorSystem().dynamicType;
+ Expect.isTrue(dynamicMirror.isOriginalDeclaration);
+ Expect.equals(dynamicMirror, dynamicMirror.originalDeclaration);
+ Expect.listEquals([], dynamicMirror.typeVariables);
+ Expect.listEquals([], dynamicMirror.typeArguments);
+
+ TypeMirror voidMirror = currentMirrorSystem().voidType;
+ Expect.isTrue(voidMirror.isOriginalDeclaration);
+ Expect.equals(voidMirror, voidMirror.originalDeclaration);
+ Expect.listEquals([], voidMirror.typeVariables);
+ Expect.listEquals([], voidMirror.typeArguments);
+
+ TypeMirror dynamicMirror2 = reflectType(dynamic);
+ Expect.equals(dynamicMirror, dynamicMirror2);
+ Expect.isTrue(dynamicMirror2.isOriginalDeclaration);
+ Expect.equals(dynamicMirror2, dynamicMirror2.originalDeclaration);
+ Expect.listEquals([], dynamicMirror2.typeVariables);
+ Expect.listEquals([], dynamicMirror2.typeArguments);
+}
diff --git a/tests/lib/mirrors/generics_test.dart b/tests/lib/mirrors/generics_test.dart
index 8eb63ee..ec2d49a 100644
--- a/tests/lib/mirrors/generics_test.dart
+++ b/tests/lib/mirrors/generics_test.dart
@@ -7,13 +7,14 @@
import 'dart:mirrors';
import 'package:expect/expect.dart';
+import 'generics_helper.dart';
class A<T> {}
class Z<T> {}
-class B extends A {} // Same as class B extends A<dynamic>.
-class C extends A
-<num, int> // TODO(zarah): Should be "01: static warning".
-{} // Same as class C extends A<dynamic>.
+class B extends A {}
+class C
+ extends A<num, int> /// 01: static type warning
+ {}
class D extends A<int> {}
class E<S> extends A<S> {}
class F<R> extends A<int> {}
@@ -21,15 +22,6 @@
class H<A,B,C> {}
class I extends G {}
-typeParameters(mirror, parameterNames) {
- Expect.listEquals(parameterNames,
- mirror.typeVariables.map((v) => v.simpleName).toList());
-}
-
-typeArguments(mirror, argumentMirrors) {
- Expect.listEquals(argumentMirrors, mirror.typeArguments);
-}
-
main() {
// Declarations.
typeParameters(reflectClass(A), [#T]);
@@ -75,7 +67,7 @@
// Instantiations.
typeParameters(reflect(new A<num>()).type, [#T]);
- typeParameters(reflect(new B<num>()).type, []);
+ typeParameters(reflect(new B()).type, []);
typeParameters(reflect(new C()).type, []);
typeParameters(reflect(new D()).type, []);
typeParameters(reflect(new E()).type, [#S]);
diff --git a/tests/lib/mirrors/method_mirror_properties_test.dart b/tests/lib/mirrors/method_mirror_properties_test.dart
index 834871f..950a2a8 100644
--- a/tests/lib/mirrors/method_mirror_properties_test.dart
+++ b/tests/lib/mirrors/method_mirror_properties_test.dart
@@ -12,7 +12,7 @@
int get topGetter => _x;
void set topSetter(x) { _x = x; }
-class AbstractC {
+abstract class AbstractC {
AbstractC();
@@ -21,7 +21,7 @@
set priv(value);
}
-class C extends AbstractC {
+abstract class C extends AbstractC {
static foo() {}
diff --git a/tests/lib/mirrors/method_mirror_returntype_test.dart b/tests/lib/mirrors/method_mirror_returntype_test.dart
index cd525bb..be55156 100644
--- a/tests/lib/mirrors/method_mirror_returntype_test.dart
+++ b/tests/lib/mirrors/method_mirror_returntype_test.dart
@@ -21,20 +21,20 @@
main() {
MethodMirror mm;
- mm = reflect(intFunc).function;
+ mm = (reflect(intFunc) as ClosureMirror).function;
Expect.equals(true, mm.returnType is TypeMirror);
Expect.equals(#int, mm.returnType.simpleName);
Expect.equals(true, mm.returnType.owner is LibraryMirror);
- mm = reflect(dynamicFunc1).function;
+ mm = (reflect(dynamicFunc1) as ClosureMirror).function;
Expect.equals(true, mm.returnType is TypeMirror);
Expect.equals(#dynamic, mm.returnType.simpleName);
- mm = reflect(dynamicFunc2).function;
+ mm = (reflect(dynamicFunc2) as ClosureMirror).function;
Expect.equals(true, mm.returnType is TypeMirror);
Expect.equals(#dynamic, mm.returnType.simpleName);
- mm = reflect(voidFunc).function;
+ mm = (reflect(voidFunc) as ClosureMirror).function;
Expect.equals(true, mm.returnType is TypeMirror);
Expect.equals(const Symbol("void"), mm.returnType.simpleName);
diff --git a/tests/lib/mirrors/method_mirror_source_test.dart b/tests/lib/mirrors/method_mirror_source_test.dart
index 094e36d..2507915 100644
--- a/tests/lib/mirrors/method_mirror_source_test.dart
+++ b/tests/lib/mirrors/method_mirror_source_test.dart
@@ -7,11 +7,14 @@
import "package:expect/expect.dart";
expectSource(Mirror mirror, String source) {
+ MethodMirror methodMirror;
if (mirror is ClosureMirror) {
- mirror = mirror.function;
+ methodMirror = mirror.function;
+ } else {
+ methodMirror = mirror as MethodMirror;
}
- Expect.isTrue(mirror is MethodMirror);
- Expect.equals(mirror.source, source);
+ Expect.isTrue(methodMirror is MethodMirror);
+ Expect.equals(methodMirror.source, source);
}
foo1() {}
diff --git a/tests/lib/mirrors/mixin_members_test.dart b/tests/lib/mirrors/mixin_members_test.dart
index 470f647..12c4192 100644
--- a/tests/lib/mirrors/mixin_members_test.dart
+++ b/tests/lib/mirrors/mixin_members_test.dart
@@ -10,7 +10,7 @@
import 'stringify.dart';
-class Fooer {
+abstract class Fooer {
foo1();
}
diff --git a/tests/lib/mirrors/parameter_metadata_test.dart b/tests/lib/mirrors/parameter_metadata_test.dart
index f27a149..fdb1fc6 100644
--- a/tests/lib/mirrors/parameter_metadata_test.dart
+++ b/tests/lib/mirrors/parameter_metadata_test.dart
@@ -19,15 +19,15 @@
}
class B {
- B.foo(int x);
- factory B.bar(@m3 @m2 int z, x){}
+ B.foo(int x) {}
+ factory B.bar(@m3 @m2 int z, x) {}
- baz(@m1 final int x, @m2 int y, @m3 final int z);
- qux(int x, [@m3 @m2 @m1 int y= 3 + 1]);
- quux(int x, {String str: "foo"});
- corge({@m1 int x: 3 * 17, @m2 String str: "bar"});
+ baz(@m1 final int x, @m2 int y, @m3 final int z) {}
+ qux(int x, [@m3 @m2 @m1 int y= 3 + 1]) {}
+ quux(int x, {String str: "foo"}) {}
+ corge({@m1 int x: 3 * 17, @m2 String str: "bar"}) {}
- set x(@m2 final value);
+ set x(@m2 final value) {}
}
main() {
@@ -38,18 +38,18 @@
checkMetadata(cm.constructors[#B.bar].parameters[0], [m3, m2]);
checkMetadata(cm.constructors[#B.bar].parameters[1], []);
- checkMetadata(cm.members[#baz].parameters[0], [m1]);
- checkMetadata(cm.members[#baz].parameters[1], [m2]);
- checkMetadata(cm.members[#baz].parameters[2], [m3]);
+ checkMetadata(cm.methods[#baz].parameters[0], [m1]);
+ checkMetadata(cm.methods[#baz].parameters[1], [m2]);
+ checkMetadata(cm.methods[#baz].parameters[2], [m3]);
- checkMetadata(cm.members[#qux].parameters[0], []);
- checkMetadata(cm.members[#qux].parameters[1], [m3, m2, m1]);
+ checkMetadata(cm.methods[#qux].parameters[0], []);
+ checkMetadata(cm.methods[#qux].parameters[1], [m3, m2, m1]);
- checkMetadata(cm.members[#quux].parameters[0], []);
- checkMetadata(cm.members[#quux].parameters[1], []);
+ checkMetadata(cm.methods[#quux].parameters[0], []);
+ checkMetadata(cm.methods[#quux].parameters[1], []);
- checkMetadata(cm.members[#corge].parameters[0], [m1]);
- checkMetadata(cm.members[#corge].parameters[1], [m2]);
+ checkMetadata(cm.methods[#corge].parameters[0], [m1]);
+ checkMetadata(cm.methods[#corge].parameters[1], [m2]);
- checkMetadata(cm.members[const Symbol('x=')].parameters[0], [m2]);
+ checkMetadata(cm.setters[const Symbol('x=')].parameters[0], [m2]);
}
diff --git a/tests/lib/mirrors/private_symbol_test.dart b/tests/lib/mirrors/private_symbol_test.dart
index 52eaa09..7624531 100644
--- a/tests/lib/mirrors/private_symbol_test.dart
+++ b/tests/lib/mirrors/private_symbol_test.dart
@@ -109,7 +109,7 @@
Expect.equals(#_F, tdm.simpleName);
Expect.equals('_F', MirrorSystem.getName(tdm.simpleName));
- ParameterMirror pm = cm.members[#m].parameters[0];
+ ParameterMirror pm = (cm.members[#m] as MethodMirror).parameters[0];
Expect.equals(#_p, pm.simpleName);
Expect.equals('_p', MirrorSystem.getName(pm.simpleName));
diff --git a/tests/lib/mirrors/reflect_class_test.dart b/tests/lib/mirrors/reflect_class_test.dart
index c556ba8..f1dff09 100644
--- a/tests/lib/mirrors/reflect_class_test.dart
+++ b/tests/lib/mirrors/reflect_class_test.dart
@@ -14,8 +14,5 @@
Expect.throws(() => reflectClass(dynamic), expectedError);
Expect.throws(() => reflectClass(1), expectedError);
Expect.throws(() => reflectClass("string"), expectedError);
-
- // reflectClass() on a function type should fail once typedefs are represented
- // by TypedefMirrors instead of ClassMirrors.
- // Expect.throws(() => reflectClass(FooFunction), expectedError);
+ Expect.throws(() => reflectClass(FooFunction), expectedError);
}
diff --git a/tests/lib/mirrors/reflected_type_test.dart b/tests/lib/mirrors/reflected_type_test.dart
index df4e578..70ebcf3 100644
--- a/tests/lib/mirrors/reflected_type_test.dart
+++ b/tests/lib/mirrors/reflected_type_test.dart
@@ -9,8 +9,8 @@
import 'package:expect/expect.dart';
class A<T> {}
-class B extends A {} // Same as class B extends A<dynamic>.
-class C extends A<num, int> {} // Same as class C extends A<dynamic>.
+class B extends A {}
+class C extends A<num, int> {} /// 01: static type warning
class D extends A<int> {}
class E<S> extends A<S> {}
class F<R> extends A<int> {}
@@ -33,7 +33,7 @@
// Declarations.
expectReflectedType(reflectClass(A), null);
expectReflectedType(reflectClass(B), B);
- expectReflectedType(reflectClass(C), C);
+ expectReflectedType(reflectClass(C), C); /// 01: continued
expectReflectedType(reflectClass(D), D);
expectReflectedType(reflectClass(E), null);
expectReflectedType(reflectClass(F), null);
@@ -43,7 +43,7 @@
// Instantiations.
expectReflectedType(reflect(new A()).type, new A().runtimeType);
expectReflectedType(reflect(new B()).type, new B().runtimeType);
- expectReflectedType(reflect(new C()).type, new C().runtimeType);
+ expectReflectedType(reflect(new C()).type, new C().runtimeType); /// 01: continued
expectReflectedType(reflect(new D()).type, new D().runtimeType);
expectReflectedType(reflect(new E()).type, new E().runtimeType);
expectReflectedType(reflect(new F()).type, new F().runtimeType);
@@ -51,16 +51,15 @@
expectReflectedType(reflect(new H()).type, new H().runtimeType);
expectReflectedType(reflect(new A<num>()).type, new A<num>().runtimeType);
- expectReflectedType(reflect(new B<num>()).type.superclass,
- new A<dynamic>().runtimeType);
- expectReflectedType(reflect(new C<num>()).type.superclass,
- new A<dynamic>().runtimeType);
- expectReflectedType(reflect(new D<num>()).type.superclass,
- new A<int>().runtimeType);
+ expectReflectedType(reflect(new B<num>()).type.superclass, /// 02: static type warning
+ new A<dynamic>().runtimeType); /// 02: continued
+ expectReflectedType(reflect(new C<num>()).type.superclass, /// 01: continued
+ new A<dynamic>().runtimeType); /// 01: continued
+ expectReflectedType(reflect(new D<num>()).type.superclass, /// 03: static type warning
+ new A<int>().runtimeType); /// 03: continued
expectReflectedType(reflect(new E<num>()).type, new E<num>().runtimeType);
- // TODO(rmacnak): This requires some work to compute.
- // expectReflectedType(reflect(new E<num>()).type.superclass,
- // new A<num>().runtimeType);
+ expectReflectedType(reflect(new E<num>()).type.superclass,
+ new A<num>().runtimeType);
expectReflectedType(reflect(new F<num>()).type.superclass,
new A<int>().runtimeType);
expectReflectedType(reflect(new F<num>()).type, new F<num>().runtimeType);
diff --git a/tests/lib/mirrors/type_argument_is_type_variable_test.dart b/tests/lib/mirrors/type_argument_is_type_variable_test.dart
index d503fed..abada7f 100644
--- a/tests/lib/mirrors/type_argument_is_type_variable_test.dart
+++ b/tests/lib/mirrors/type_argument_is_type_variable_test.dart
@@ -8,7 +8,7 @@
import 'package:expect/expect.dart';
-import 'generics_test.dart';
+import 'generics_helper.dart';
class SuperSuper<SS> {}
class Super<S> extends SuperSuper<S> {}
diff --git a/tests/lib/platform/environment_test.dart b/tests/lib/platform/environment_test.dart
deleted file mode 100644
index 3d2da6a..0000000
--- a/tests/lib/platform/environment_test.dart
+++ /dev/null
@@ -1,16 +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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
- if (platform.operatingSystem != null) {
- expect(platform.environment, new isInstanceOf<Map<String, String>>());
- } else {
- expect(platform.environment, isNull);
- }
-}
-
diff --git a/tests/lib/platform/executable_arguments_test.dart b/tests/lib/platform/executable_arguments_test.dart
deleted file mode 100644
index 8fbf032..0000000
--- a/tests/lib/platform/executable_arguments_test.dart
+++ /dev/null
@@ -1,11 +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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
- expect(platform.executableArguments is List<String>, true);
-}
diff --git a/tests/lib/platform/executable_test.dart b/tests/lib/platform/executable_test.dart
deleted file mode 100644
index fee4539..0000000
--- a/tests/lib/platform/executable_test.dart
+++ /dev/null
@@ -1,16 +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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
- if (platform.operatingSystem != null) {
- expect(platform.executable, contains('dart'));
- } else {
- expect(platform.executable, isNull);
- }
-}
-
diff --git a/tests/lib/platform/import_test.dart b/tests/lib/platform/import_test.dart
deleted file mode 100644
index fcd326f..0000000
--- a/tests/lib/platform/import_test.dart
+++ /dev/null
@@ -1,8 +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.
-
-import "dart:platform";
-
-void main() {
-}
diff --git a/tests/lib/platform/isolate_test.dart b/tests/lib/platform/isolate_test.dart
deleted file mode 100644
index b53f088..0000000
--- a/tests/lib/platform/isolate_test.dart
+++ /dev/null
@@ -1,59 +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.
-
-import "dart:platform" as platform;
-
-import "dart:isolate";
-import "package:unittest/unittest.dart";
-
-sendReceive(SendPort port, msg) {
- var response = new ReceivePort();
- port.send([msg, response.sendPort]);
- return response.first;
-}
-
-main() {
- test("platform in isolate", () {
- var response = new ReceivePort();
- Isolate.spawn(f, response.sendPort);
- response.first.then(expectAsync1((sendPort) {
- expect(sendReceive(sendPort, "platform.executable"),
- completion(platform.executable));
- if (platform.script != null) {
- expect(sendReceive(sendPort, "platform.script").then((s) => s.path),
- completion(endsWith('tests/lib/platform/isolate_test.dart')));
- }
- expect(sendReceive(sendPort, "platform.packageRoot"),
- completion(platform.packageRoot));
- expect(sendReceive(sendPort, "platform.executableArguments"),
- completion(platform.executableArguments));
- }));
- });
-}
-
-void f(initialReplyTo) {
- var port = new ReceivePort();
- initialReplyTo.send(port.sendPort);
- int count = 0;
- port.listen((msg) {
- var data = msg[0];
- var replyTo = msg[1];
- if (data == "platform.executable") {
- replyTo.send(platform.executable);
- }
- if (data == "platform.script") {
- replyTo.send(platform.script);
- }
- if (data == "platform.packageRoot") {
- replyTo.send(platform.packageRoot);
- }
- if (data == "platform.executableArguments") {
- replyTo.send(platform.executableArguments);
- }
- count++;
- if (count == 4) {
- port.close();
- }
- });
-}
diff --git a/tests/lib/platform/local_hostname_test.dart b/tests/lib/platform/local_hostname_test.dart
deleted file mode 100644
index 2095ce0..0000000
--- a/tests/lib/platform/local_hostname_test.dart
+++ /dev/null
@@ -1,16 +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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
- if (platform.operatingSystem != null) {
- expect(platform.localHostname, new isInstanceOf<String>());
- expect(platform.localHostname, isNot(''));
- } else {
- expect(platform.localHostname, isNull);
- }
-}
diff --git a/tests/lib/platform/number_of_processors_test.dart b/tests/lib/platform/number_of_processors_test.dart
deleted file mode 100644
index 043914d..0000000
--- a/tests/lib/platform/number_of_processors_test.dart
+++ /dev/null
@@ -1,15 +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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
- if (platform.operatingSystem != null) {
- expect(platform.numberOfProcessors, isPositive);
- } else {
- expect(platform.numberOfProcessors, isNull);
- }
-}
diff --git a/tests/lib/platform/operating_system_test.dart b/tests/lib/platform/operating_system_test.dart
deleted file mode 100644
index b121833..0000000
--- a/tests/lib/platform/operating_system_test.dart
+++ /dev/null
@@ -1,14 +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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
- if (platform.operatingSystem != null) {
- expect(platform.operatingSystem,
- isIn(['linux', 'macos', 'windows', 'android']));
- }
-}
diff --git a/tests/lib/platform/package_root_test.dart b/tests/lib/platform/package_root_test.dart
deleted file mode 100644
index 7d5de6a..0000000
--- a/tests/lib/platform/package_root_test.dart
+++ /dev/null
@@ -1,16 +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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
- if (platform.operatingSystem != null) {
- expect(platform.packageRoot is String, true);
- expect(platform.packageRoot, isNot(''));
- } else {
- expect(platform.packageRoot, isNull);
- }
-}
diff --git a/tests/lib/platform/path_separator_test.dart b/tests/lib/platform/path_separator_test.dart
deleted file mode 100644
index 2a7a595..0000000
--- a/tests/lib/platform/path_separator_test.dart
+++ /dev/null
@@ -1,15 +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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
- if (platform.operatingSystem == 'windows') {
- expect(platform.pathSeparator, '\\');
- } else {
- expect(platform.pathSeparator, isIn(['/', null]));
- }
-}
diff --git a/tests/lib/platform/script_test.dart b/tests/lib/platform/script_test.dart
deleted file mode 100644
index e7ce111..0000000
--- a/tests/lib/platform/script_test.dart
+++ /dev/null
@@ -1,16 +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.
-
-import "dart:platform" as platform;
-
-import "package:unittest/unittest.dart";
-
-main() {
- if (platform.operatingSystem != null) {
- expect(platform.script.path,
- endsWith('tests/lib/platform/script_test.dart'));
- } else {
- expect(platform.script, isNull);
- }
-}
diff --git a/tests/lib/platform/uri_test.dart b/tests/lib/platform/uri_test.dart
deleted file mode 100644
index bca7b6d..0000000
--- a/tests/lib/platform/uri_test.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart";
-import "dart:platform" as platform;
-
-main() {
- if (platform.operatingSystem == 'windows') {
- Expect.equals("a\\b", Uri.parse("a/b").toFilePath());
- Expect.equals("a\\b\\", Uri.parse("a/b/").toFilePath());
- Expect.equals("a b", Uri.parse("a%20b").toFilePath());
- Expect.equals("\\a b", Uri.parse("file:///a%20b").toFilePath());
- Expect.equals("\\a\\b", Uri.parse("file:///a/b").toFilePath());
- Expect.equals("C:\\", Uri.parse("file:///C:").toFilePath());
- Expect.equals("C:\\", Uri.parse("file:///C:/").toFilePath());
- Expect.equals("\\\\host\\a\\b", Uri.parse("file://host/a/b").toFilePath());
-
- Expect.equals("a\\b", new Uri.file("a/b").toFilePath());
- Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
- Expect.equals("\\a\\b", new Uri.file("/a/b").toFilePath());
- Expect.equals("\\a\\b", new Uri.file("\\a\\b").toFilePath());
- Expect.equals("\\a\\b", new Uri.file("\\a/b").toFilePath());
- Expect.equals("\\a\\b", new Uri.file("/a\\b").toFilePath());
- } else {
- Expect.equals("a/b", Uri.parse("a/b").toFilePath());
- Expect.equals("a/b/", Uri.parse("a/b/").toFilePath());
- Expect.equals("a b", Uri.parse("a%20b").toFilePath());
- Expect.equals("/a b", Uri.parse("file:///a%20b").toFilePath());
- Expect.equals("/a/b", Uri.parse("file:///a/b").toFilePath());
- Expect.equals("/C:", Uri.parse("file:///C:").toFilePath());
- Expect.equals("/C:/", Uri.parse("file:///C:/").toFilePath());
- Expect.throws(() => Uri.parse("file://host/a/b").toFilePath(),
- (e) => e is UnsupportedError);
-
- Expect.equals("a/b", new Uri.file("a/b").toFilePath());
- Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
- }
-}
diff --git a/tests/standalone/io/directory_list_pause_test.dart b/tests/standalone/io/directory_list_pause_test.dart
index 9bb7d47e..c2beb00 100644
--- a/tests/standalone/io/directory_list_pause_test.dart
+++ b/tests/standalone/io/directory_list_pause_test.dart
@@ -43,6 +43,55 @@
});
}
+
+void testPauseResumeCancelList() {
+ asyncStart();
+ // TOTAL should be bigger the our directory listing buffer.
+ const int TOTAL = 128;
+ Directory.systemTemp.createTemp('dart_directory_list_pause').then((d) {
+ for (int i = 0; i < TOTAL; i++) {
+ new Directory("${d.path}/$i").createSync();
+ new File("${d.path}/$i/file").createSync();
+ }
+ var subscription;
+ subscription = d.list(recursive: true).listen((entity) {
+ subscription.pause();
+ subscription.resume();
+ void close() {
+ d.deleteSync(recursive: true);
+ asyncEnd();
+ }
+ var future = subscription.cancel();
+ if (future != null) {
+ future.whenComplete(close);
+ } else {
+ close();
+ }
+ }, onDone: () {
+ Expect.fail('the stream was canceled, onDone should not happend');
+ });
+ });
+}
+
+void testListIsEmpty() {
+ asyncStart();
+ // TOTAL should be bigger the our directory listing buffer.
+ const int TOTAL = 128;
+ Directory.systemTemp.createTemp('dart_directory_list_pause').then((d) {
+ for (int i = 0; i < TOTAL; i++) {
+ new Directory("${d.path}/$i").createSync();
+ new File("${d.path}/$i/file").createSync();
+ }
+ d.list(recursive: true).isEmpty.then((empty) {
+ Expect.isFalse(empty);
+ d.deleteSync(recursive: true);
+ asyncEnd();
+ });
+ });
+}
+
void main() {
testPauseList();
+ testPauseResumeCancelList();
+ testListIsEmpty();
}
diff --git a/tests/standalone/io/file_system_watcher_test.dart b/tests/standalone/io/file_system_watcher_test.dart
index 4540b60..e76f719 100644
--- a/tests/standalone/io/file_system_watcher_test.dart
+++ b/tests/standalone/io/file_system_watcher_test.dart
@@ -7,11 +7,12 @@
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
+import "package:path/path.dart";
void testWatchCreateFile() {
var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
- var file = new File(dir.path + '/file');
+ var file = new File(join(dir.path, 'file'));
var watcher = dir.watch();
@@ -20,6 +21,7 @@
sub = watcher.listen((event) {
if (event is FileSystemCreateEvent &&
event.path.endsWith('file')) {
+ Expect.isFalse(event.isDirectory);
asyncEnd();
sub.cancel();
dir.deleteSync(recursive: true);
@@ -33,9 +35,34 @@
}
+void testWatchCreateDir() {
+ var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+ var subdir = new Directory(join(dir.path, 'dir'));
+
+ var watcher = dir.watch();
+
+ asyncStart();
+ var sub;
+ sub = watcher.listen((event) {
+ if (event is FileSystemCreateEvent &&
+ event.path.endsWith('dir')) {
+ Expect.isTrue(event.isDirectory);
+ asyncEnd();
+ sub.cancel();
+ dir.deleteSync(recursive: true);
+ }
+ }, onError: (e) {
+ dir.deleteSync(recursive: true);
+ throw e;
+ });
+
+ subdir.createSync();
+}
+
+
void testWatchModifyFile() {
var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
- var file = new File(dir.path + '/file');
+ var file = new File(join(dir.path, 'file'));
file.createSync();
var watcher = dir.watch();
@@ -60,7 +87,7 @@
void testWatchMoveFile() {
var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
- var file = new File(dir.path + '/file');
+ var file = new File(join(dir.path, 'file'));
file.createSync();
var watcher = dir.watch();
@@ -82,13 +109,13 @@
throw e;
});
- file.renameSync(dir.path + '/file2');
+ file.renameSync(join(dir.path, 'file2'));
}
void testWatchDeleteFile() {
var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
- var file = new File(dir.path + '/file');
+ var file = new File(join(dir.path, 'file'));
file.createSync();
var watcher = dir.watch();
@@ -112,6 +139,9 @@
void testWatchDeleteDir() {
+ // Windows keeps the directory handle open, even though it's deleted. It'll
+ // be flushed completely, once the watcher is closed as well.
+ if (Platform.isWindows) return;
var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
var watcher = dir.watch(events: 0);
@@ -131,7 +161,7 @@
void testWatchOnlyModifyFile() {
var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
- var file = new File(dir.path + '/file');
+ var file = new File(join(dir.path, 'file'));
var watcher = dir.watch(events: FileSystemEvent.MODIFY);
@@ -155,8 +185,8 @@
void testMultipleEvents() {
var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
- var file = new File(dir.path + '/file');
- var file2 = new File(dir.path + '/file2');
+ var file = new File(join(dir.path, 'file'));
+ var file2 = new File(join(dir.path, 'file2'));
var watcher = dir.watch();
@@ -204,9 +234,9 @@
Expect.throws(() => dir.watch(recursive: true));
return;
}
- var dir2 = new Directory(dir.path + '/dir');
+ var dir2 = new Directory(join(dir.path, 'dir'));
dir2.createSync();
- var file = new File(dir.path + '/dir/file');
+ var file = new File(join(dir.path, 'dir/file'));
var watcher = dir.watch(recursive: true);
@@ -229,9 +259,9 @@
void testWatchNonRecursive() {
var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
- var dir2 = new Directory(dir.path + '/dir');
+ var dir2 = new Directory(join(dir.path, 'dir'));
dir2.createSync();
- var file = new File(dir.path + '/dir/file');
+ var file = new File(join(dir.path, 'dir/file'));
var watcher = dir.watch(recursive: false);
@@ -256,9 +286,24 @@
}
+void testWatchNonExisting() {
+ // MacOS allows listening on non-existing paths.
+ if (Platform.isMacOS) return;
+ asyncStart();
+ new Directory('__some_none_existing_dir__').watch()
+ .listen((_) {
+ Expect.fail('unexpected error');
+ }, onError: (e) {
+ asyncEnd();
+ Expect.isTrue(e is FileSystemException);
+ });
+}
+
+
void main() {
if (!FileSystemEntity.isWatchSupported) return;
testWatchCreateFile();
+ testWatchCreateDir();
testWatchModifyFile();
testWatchMoveFile();
testWatchDeleteFile();
@@ -266,4 +311,5 @@
testWatchOnlyModifyFile();
testMultipleEvents();
testWatchNonRecursive();
+ testWatchNonExisting();
}
diff --git a/tests/standalone/io/http_headers_state_test.dart b/tests/standalone/io/http_headers_state_test.dart
index 42e5384..deeb9cd 100644
--- a/tests/standalone/io/http_headers_state_test.dart
+++ b/tests/standalone/io/http_headers_state_test.dart
@@ -21,13 +21,23 @@
response.headers.add("X-Response-Header", "value");
if (body != null) {
response.write(body);
+ // Cannot change state or reason when data has been sent.
+ Expect.throws(() => response.statusCode = 200,
+ (e) => e is StateError);
+ Expect.throws(() => response.reasonPhrase = "OK",
+ (e) => e is StateError);
// Cannot mutate response headers when data has been sent.
- Expect.throws(() => request.headers.add("X-Request-Header", "value2"),
+ Expect.throws(() => response.headers.add("X-Request-Header", "value2"),
(e) => e is HttpException);
}
response..close();
- // Cannot mutate response headers when data has been sent.
- Expect.throws(() => request.headers.add("X-Request-Header", "value3"),
+ // Cannot change state or reason after connection is closed.
+ Expect.throws(() => response.statusCode = 200,
+ (e) => e is StateError);
+ Expect.throws(() => response.reasonPhrase = "OK",
+ (e) => e is StateError);
+ // Cannot mutate response headers after connection is closed.
+ Expect.throws(() => response.headers.add("X-Request-Header", "value3"),
(e) => e is HttpException);
});
});
diff --git a/tests/standalone/io/uri_platform_test.dart b/tests/standalone/io/uri_platform_test.dart
index 586e7f3..cc67760 100644
--- a/tests/standalone/io/uri_platform_test.dart
+++ b/tests/standalone/io/uri_platform_test.dart
@@ -4,9 +4,39 @@
import "package:expect/expect.dart";
import "dart:io";
-import "dart:platform" as platform;
main() {
+ if (Platform.isWindows) {
+ Expect.equals("a\\b", Uri.parse("a/b").toFilePath());
+ Expect.equals("a\\b\\", Uri.parse("a/b/").toFilePath());
+ Expect.equals("a b", Uri.parse("a%20b").toFilePath());
+ Expect.equals("\\a b", Uri.parse("file:///a%20b").toFilePath());
+ Expect.equals("\\a\\b", Uri.parse("file:///a/b").toFilePath());
+ Expect.equals("C:\\", Uri.parse("file:///C:").toFilePath());
+ Expect.equals("C:\\", Uri.parse("file:///C:/").toFilePath());
+ Expect.equals("\\\\host\\a\\b", Uri.parse("file://host/a/b").toFilePath());
+
+ Expect.equals("a\\b", new Uri.file("a/b").toFilePath());
+ Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
+ Expect.equals("\\a\\b", new Uri.file("/a/b").toFilePath());
+ Expect.equals("\\a\\b", new Uri.file("\\a\\b").toFilePath());
+ Expect.equals("\\a\\b", new Uri.file("\\a/b").toFilePath());
+ Expect.equals("\\a\\b", new Uri.file("/a\\b").toFilePath());
+ } else {
+ Expect.equals("a/b", Uri.parse("a/b").toFilePath());
+ Expect.equals("a/b/", Uri.parse("a/b/").toFilePath());
+ Expect.equals("a b", Uri.parse("a%20b").toFilePath());
+ Expect.equals("/a b", Uri.parse("file:///a%20b").toFilePath());
+ Expect.equals("/a/b", Uri.parse("file:///a/b").toFilePath());
+ Expect.equals("/C:", Uri.parse("file:///C:").toFilePath());
+ Expect.equals("/C:/", Uri.parse("file:///C:/").toFilePath());
+ Expect.throws(() => Uri.parse("file://host/a/b").toFilePath(),
+ (e) => e is UnsupportedError);
+
+ Expect.equals("a/b", new Uri.file("a/b").toFilePath());
+ Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
+ }
+
Expect.equals(Uri.base,
- new Uri.file(Directory.current.path + platform.pathSeparator));
+ new Uri.file(Directory.current.path + Platform.pathSeparator));
}
diff --git a/tests/standalone/issue14236_source.dart b/tests/standalone/issue14236_source.dart
index edb18a8..9b89cef 100644
--- a/tests/standalone/issue14236_source.dart
+++ b/tests/standalone/issue14236_source.dart
@@ -9,9 +9,9 @@
// test.
library test.issue14236;
-import 'dart:isolate';
+import "dart:isolate";
import "package:expect/expect.dart";
-import "package:async_helper/async_helper.dart";
+import "package:async_helper/async_helper.dart";
/*
test(SendPort replyTo) {
diff --git a/tests/standalone/issue14236_test.dart b/tests/standalone/issue14236_test.dart
index 7790795..303eea6 100644
--- a/tests/standalone/issue14236_test.dart
+++ b/tests/standalone/issue14236_test.dart
Binary files differ
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 0b2316a..a293719 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -10,25 +10,10 @@
package/invalid_uri_test: Fail, OK # CompileTimeErrors intentionally
[ $runtime == vm && $system == windows ]
-io/file_system_watcher_test: Pass, Timeout # Issue 13228
io/platform_test: Pass, Fail # Issue 14399
[ $runtime == vm ]
package/package_isolate_test: Fail # Issue 12474
-vmservice/isolate_bad_class_test: Skip # Issue 14448
-vmservice/isolate_bad_object_test: Skip # Issue 14448
-vmservice/isolate_class_field_test: Skip # Issue 14448
-vmservice/isolate_class_test: Skip # Issue 14448
-vmservice/isolate_code_test: Skip # Issue 14448
-vmservice/isolate_echo_test: Skip # Issue 14448
-vmservice/isolate_function_test: Skip # Issue 14448
-vmservice/isolate_library_test: Skip # Issue 14448
-vmservice/isolate_list_test: Skip # Issue 14448
-vmservice/isolate_stacktrace_command_test: Skip # Issue 14448
-vmservice/multiple_isolate_list_test: Skip # Issue 14448
-vmservice/unknown_command_test: Skip # Issue 14448
-vmservice/unknown_isolate_command_test: Skip # Issue 14448
-
[ $runtime == vm && $checked ]
# These tests have type errors on purpose.
@@ -93,7 +78,6 @@
[ $compiler == dart2analyzer ]
javascript_int_overflow_literal_test/01: fail, ok
-package/package_isolate_test: fail # issue 11647
issue14236_test: Skip # Analyzer can't handle Script snapshots.
# test issue https://code.google.com/p/dart/issues/detail?id=11518
@@ -135,6 +119,7 @@
oom_error_stacktrace_test: RuntimeError, OK # (OOM on JS may produce a stacktrace).
vmservice/*: Skip # Do not run standalone vm service tests with dart2js.
issue14236_test: Skip # dart2js does not deal with Script snapshots.
+io/platform_test: Pass, CompileTimeError # Issue 14603
[ $compiler == dart2js && $jscl ]
assert_test: RuntimeError, OK # Assumes unspecified fields on the AssertionError.
@@ -184,3 +169,17 @@
[ $compiler == none && $runtime == dartium ]
javascript_int_overflow_literal_test/01: Fail # Issue 13719: Please triage this failure.
javascript_int_overflow_test: Fail # Issue 13719: Please triage this failure.
+
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
+io/directory_invalid_arguments_test: StaticWarning
+io/process_invalid_arguments_test: StaticWarning
+io/raw_secure_server_socket_argument_test: StaticWarning
+io/secure_socket_argument_test: StaticWarning
+io/skipping_dart2js_compilations_test: CompileTimeError, StaticWarning
+io/stdout_bad_argument_test: StaticWarning
+io/test_runner_test: CompileTimeError, StaticWarning
+package/package1_test: StaticWarning
+package/package_test: StaticWarning
+typed_data_test: StaticWarning
+typed_data_view_test: StaticWarning
+
diff --git a/tests/standalone/vmservice/isolate_class_test.dart b/tests/standalone/vmservice/isolate_class_test.dart
index 9650443..086ae5e 100644
--- a/tests/standalone/vmservice/isolate_class_test.dart
+++ b/tests/standalone/vmservice/isolate_class_test.dart
@@ -28,10 +28,10 @@
onRequestCompleted(Map reply) {
Expect.equals('Library', reply['type']);
Expect.equals('isolate_stacktrace_command_script', reply['name']);
- Expect.equals(1, reply['classes'].length);
- Expect.equals('@Class', reply['classes'][0]['type']);
- Expect.equals('C', reply['classes'][0]['name']);
- _classId = reply['classes'][0]['id'];
+ Expect.equals(2, reply['classes'].length);
+ Expect.equals('@Class', reply['classes'][1]['type']);
+ Expect.equals('C', reply['classes'][1]['name']);
+ _classId = reply['classes'][1]['id'];
}
}
diff --git a/tests/standalone/vmservice/test_helper.dart b/tests/standalone/vmservice/test_helper.dart
index 8157648..8e2b46c 100644
--- a/tests/standalone/vmservice/test_helper.dart
+++ b/tests/standalone/vmservice/test_helper.dart
@@ -18,13 +18,13 @@
client = new HttpClient();
Future makeRequest() {
+ print('** GET: $uri');
return client.getUrl(uri)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
return response
.fold(new BytesBuilder(), (b, d) => b..add(d))
.then((builder) {
- print('** GET: $uri');
return _requestCompleted(builder.takeBytes(), response);
});
}).catchError((error) {
diff --git a/tests/utils/dart2js_test.dart b/tests/utils/dart2js_test.dart
index f7786fb..74d890cd 100644
--- a/tests/utils/dart2js_test.dart
+++ b/tests/utils/dart2js_test.dart
@@ -4,10 +4,6 @@
// Test to ensure that dart2js is free of warnings.
-// Test annotation to let the test framework know that this file
-// should analyze without any warnings.
-// @static-clean
-
import '../../sdk/lib/_internal/compiler/implementation/dart2js.dart'
as dart2js;
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index 95eb2c3..be55dba 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -16,8 +16,3 @@
[ $compiler == none && $runtime == dartium ]
dart2js_test: Skip # Uses dart:io.
-[ $compiler == dartanalyzer ]
-dart2js_test: fail # dart2js issue 13919 - excluded setter for final var
-
-[ $compiler == dart2analyzer ]
-dart2js_test: fail # dart2js issue 13919 - excluded setter for final var
diff --git a/tools/VERSION b/tools/VERSION
index 260a0bd..12474f0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 8
-BUILD 7
+BUILD 8
PATCH 0
diff --git a/tools/bots/bot_utils.py b/tools/bots/bot_utils.py
index 947beed..bee7334 100644
--- a/tools/bots/bot_utils.py
+++ b/tools/bots/bot_utils.py
@@ -99,9 +99,9 @@
return '/'.join([self.editor_directory(revision),
self.editor_zipfilename(system, arch)])
- def editor_installer_zipfilepath(self, revision, system, arch, extension):
+ def editor_installer_filepath(self, revision, system, arch, extension):
return '/'.join([self.editor_directory(revision),
- self.editor_installer_zipfilename(system, arch, extension)])
+ self.editor_installer_filename(system, arch, extension)])
def sdk_zipfilepath(self, revision, system, arch, mode):
return '/'.join([self.sdk_directory(revision),
@@ -148,8 +148,8 @@
return 'darteditor-%s-%s.zip' % (
SYSTEM_RENAMES[system], ARCH_RENAMES[arch])
- def editor_installer_zipfilename(self, system, arch, extension):
- assert extension in ['dmg']
+ def editor_installer_filename(self, system, arch, extension):
+ assert extension in ['dmg', 'msi']
return 'darteditor-installer-%s-%s.%s' % (
SYSTEM_RENAMES[system], ARCH_RENAMES[arch], extension)
diff --git a/tools/copy_dart.py b/tools/copy_dart.py
index 9918e2e..6bd5725 100755
--- a/tools/copy_dart.py
+++ b/tools/copy_dart.py
@@ -106,11 +106,6 @@
or dirname(lib).endswith('dom/src')):
continue
- if lib.endswith('json/json.dart'):
- # TODO(jmesserly): Dartium interprets "json.dart" as "dart_json.dart",
- # so we need that add dart_json.dart here. This is hacky.
- lib = lib.replace('json.dart', 'dart_json.dart')
-
library = parseLibrary(lib)
# Ensure output directory exists
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index c6c83c6..0982ad2 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -203,7 +203,7 @@
join('html', 'dart2js'), join('html', 'dartium'),
join('html', 'html_common'),
join('indexed_db', 'dart2js'), join('indexed_db', 'dartium'),
- 'js', 'math', 'mirrors', 'platform', 'typed_data',
+ 'js', 'math', 'mirrors', 'typed_data',
join('svg', 'dart2js'), join('svg', 'dartium'),
'utf',
join('web_audio', 'dart2js'), join('web_audio', 'dartium'),
diff --git a/tools/create_windows_installer.py b/tools/create_windows_installer.py
new file mode 100644
index 0000000..6566a5b
--- /dev/null
+++ b/tools/create_windows_installer.py
@@ -0,0 +1,387 @@
+#!/usr/bin/env python
+#
+# 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.
+
+# A script to generate a windows installer for the editor bundle.
+# As input the script takes a zip file, a version and the location
+# to store the resulting msi file in.
+#
+# Usage: ./tools/create_windows_installer.py --version <version>
+# --zip_file_location <zip_file> --msi_location <output>
+# [--wix_bin <wix_bin_location>]
+# [--print_wxs]
+#
+# This script assumes that wix is either in path or passed in as --wix_bin.
+# You can get wix from http://wixtoolset.org/.
+
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import utils
+import zipfile
+
+# This should _never_ change, please don't change this value.
+UPGRADE_CODE = '7bacdc33-2e76-4f36-a206-ea58220c0b44'
+
+# The content of the xml
+xml_content = []
+
+# The components we want to add to our feature.
+feature_components = []
+
+# Indentation level, each level is indented 2 spaces
+current_indentation = 0
+
+def GetOptions():
+ options = optparse.OptionParser(usage='usage: %prog [options]')
+ options.add_option("--zip_file_location",
+ help='Where the zip file including the editor is located.')
+ options.add_option("--input_directory",
+ help='Directory where all the files needed is located.')
+ options.add_option("--msi_location",
+ help='Where to store the resulting msi.')
+ options.add_option("--version",
+ help='The version specified as Major.Minor.Build.Patch.')
+ options.add_option("--wix_bin",
+ help='The location of the wix binary files.')
+ options.add_option("--print_wxs", action="store_true", dest="print_wxs",
+ default=False,
+ help="Prints the generated wxs to stdout.")
+ (options, args) = options.parse_args()
+ if len(args) > 0:
+ raise Exception("This script takes no arguments, only options")
+ ValidateOptions(options)
+ return options
+
+def ValidateOptions(options):
+ if not options.version:
+ raise Exception('You must supply a version')
+ if options.zip_file_location and options.input_directory:
+ raise Exception('Please pass either zip_file_location or input_directory')
+ if not options.zip_file_location and not options.input_directory:
+ raise Exception('Please pass either zip_file_location or input_directory')
+ if (options.zip_file_location and
+ not os.path.isfile(options.zip_file_location)):
+ raise Exception('Passed in zip file not found')
+ if (options.input_directory and
+ not os.path.isdir(options.input_directory)):
+ raise Exception('Passed in directory not found')
+
+def GetInputDirectory(options, temp_dir):
+ if options.zip_file_location:
+ ExtractZipFile(options.zip_file_location, temp_dir)
+ return os.path.join(temp_dir, 'dart')
+ return options.input_directory
+
+# We combine the build and patch into a single entry since
+# the windows installer does _not_ consider a change in Patch
+# to require a new install.
+# In addition to that, the limits on the size are:
+# Major: 256
+# Minor: 256
+# Build: 65536
+# To circumvent this we create the version like this:
+# Major.Minor.X
+# where X is Build<<9 + Patch
+# Example version 1.2.4.14 will go to 1.2.2062
+def GetMicrosoftProductVersion(version):
+ version_parts = version.split('.')
+ if len(version_parts) is not 4:
+ raise Exception(
+ "Version string (%s) does not follow specification" % version)
+ (major, minor, build, patch) = map(int, version_parts)
+
+ if build > 127 or patch > 511:
+ raise Exception('Build/Patch can not be above 127/511')
+ if major > 255 or minor > 255:
+ raise Exception('Major/Minor can not be above 256')
+
+ combined = (build << 9) + patch
+ return '%s.%s.%s' % (major, minor, combined)
+
+# Append using the current indentation level
+def Append(data, new_line=True):
+ str = ((' ' * current_indentation) +
+ data +
+ ('\n' if new_line else ''))
+ xml_content.append(str)
+
+# Append without any indentation at the current position
+def AppendRaw(data, new_line=True):
+ xml_content.append(data + ('\n' if new_line else ''))
+
+def AppendComment(comment):
+ Append('<!--%s-->' % comment)
+
+def AppendBlankLine():
+ Append('')
+
+def GetContent():
+ return ''.join(xml_content)
+
+def XmlHeader():
+ Append('<?xml version="1.0" encoding="UTF-8"?>')
+
+def TagIndent(str, indentation_string):
+ return ' ' * len(indentation_string) + str
+
+def IncreaseIndentation():
+ global current_indentation
+ current_indentation += 1
+
+def DecreaseIndentation():
+ global current_indentation
+ current_indentation -= 1
+
+class WixAndProduct(object):
+ def __init__(self, version):
+ self.version = version
+ self.product_name = 'Dart Editor'
+ self.manufacturer = 'Google Inc.'
+ self.upgrade_code = UPGRADE_CODE
+
+ def __enter__(self):
+ self.start_wix()
+ self.start_product()
+
+ def __exit__(self, *_):
+ self.close_product()
+ self.close_wix()
+
+ def get_product_id(self):
+ # This needs to change on every install to guarantee that
+ # we get a full uninstall + reinstall
+ # We let wix choose. If we need to do patch releases later on
+ # we need to retain the value over several installs.
+ return '*'
+
+ def start_product(self):
+ product = '<Product '
+ Append(product, new_line=False)
+ AppendRaw('Id="%s"' % self.get_product_id())
+ Append(TagIndent('Version="%s"' % self.version, product))
+ Append(TagIndent('Name="%s"' % self.product_name, product))
+ Append(TagIndent('UpgradeCode="%s"' % self.upgrade_code,
+ product))
+ Append(TagIndent('Language="1033"', product))
+ Append(TagIndent('Manufacturer="%s"' % self.manufacturer,
+ product),
+ new_line=False)
+ AppendRaw('>')
+ IncreaseIndentation()
+
+ def close_product(self):
+ DecreaseIndentation()
+ Append('</Product>')
+
+ def start_wix(self):
+ Append('<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">')
+ IncreaseIndentation()
+
+ def close_wix(self):
+ DecreaseIndentation()
+ Append('</Wix>')
+
+class Directory(object):
+ def __init__(self, id, name=None):
+ self.id = id
+ self.name = name
+
+ def __enter__(self):
+ directory = '<Directory '
+ Append(directory, new_line=False)
+ AppendRaw('Id="%s"' % self.id, new_line=self.name is not None)
+ if self.name:
+ Append(TagIndent('Name="%s"' % self.name, directory), new_line=False)
+ AppendRaw('>')
+ IncreaseIndentation()
+
+ def __exit__(self, *_):
+ DecreaseIndentation()
+ Append('</Directory>')
+
+class Component(object):
+ def __init__(self, id):
+ self.id = 'CMP_%s' % id
+
+ def __enter__(self):
+ component = '<Component '
+ Append(component, new_line=False)
+ AppendRaw('Id="%s"' % self.id)
+ Append(TagIndent('Guid="*">', component))
+ IncreaseIndentation()
+
+ def __exit__(self, *_):
+ DecreaseIndentation()
+ Append('</Component>')
+ feature_components.append(self.id)
+
+class Feature(object):
+ def __enter__(self):
+ feature = '<Feature '
+ Append(feature, new_line=False)
+ AppendRaw('Id="MainFeature"')
+ Append(TagIndent('Title="Dart Editor"', feature))
+ # Install by default
+ Append(TagIndent('Level="1">', feature))
+ IncreaseIndentation()
+
+ def __exit__(self, *_):
+ DecreaseIndentation()
+ Append('</Feature>')
+
+def Package():
+ package = '<Package '
+ Append(package, new_line=False)
+ AppendRaw('InstallerVersion="301"')
+ Append(TagIndent('Compressed="yes" />', package))
+
+def MediaTemplate():
+ Append('<MediaTemplate EmbedCab="yes" />')
+
+def File(name, id):
+ file = '<File '
+ Append(file, new_line=False)
+ AppendRaw('Id="FILE_%s"' % id)
+ Append(TagIndent('Source="%s"' % name, file))
+ Append(TagIndent('KeyPath="yes" />', file))
+
+def Shortcut(id, name, ref):
+ shortcut = '<Shortcut '
+ Append(shortcut, new_line=False)
+ AppendRaw('Id="%s"' % id)
+ Append(TagIndent('Name="%s"' % name, shortcut))
+ Append(TagIndent('Target="%s" />' % ref, shortcut))
+
+def RemoveFolder(id):
+ remove = '<RemoveFolder '
+ Append(remove, new_line=False)
+ AppendRaw('Id="%s"' % id)
+ Append(TagIndent('On="uninstall" />', remove))
+
+def RegistryEntry(location):
+ registry = '<RegistryValue '
+ Append(registry, new_line=False)
+ AppendRaw('Root="HKCU"')
+ Append(TagIndent('Key="Software\\Microsoft\\%s"' % location, registry))
+ Append(TagIndent('Name="installed"', registry))
+ Append(TagIndent('Type="integer"', registry))
+ Append(TagIndent('Value="1"', registry))
+ Append(TagIndent('KeyPath="yes" />', registry))
+
+
+def MajorUpgrade():
+ upgrade = '<MajorUpgrade '
+ Append(upgrade, new_line=False)
+ down_message = 'You already have a never version installed.'
+ AppendRaw('DowngradeErrorMessage="%s" />' % down_message)
+
+
+# This is a very simplistic id generation.
+# Unfortunately there is no easy way to generate good names,
+# since there is a 72 character limit, and we have way longer
+# paths. We don't really have an issue with files and ids across
+# releases since we do full installs.
+counter = 0
+def FileToId(name):
+ global counter
+ counter += 1
+ return '%s' % counter
+
+def ListFiles(path):
+ for entry in os.listdir(path):
+ full_path = os.path.join(path, entry)
+ id = FileToId(full_path)
+ if os.path.isdir(full_path):
+ with Directory('DIR_%s' % id, entry):
+ ListFiles(full_path)
+ elif os.path.isfile(full_path):
+ # We assume 1 file per component, a File is always a KeyPath.
+ # A KeyPath on a file makes sure that we can always repair and
+ # remove that file in a consistent manner. A component
+ # can only have one child with a KeyPath.
+ with Component(id):
+ File(full_path, id)
+
+def ComponentRefs():
+ for component in feature_components:
+ Append('<ComponentRef Id="%s" />' % component)
+
+def ExtractZipFile(zip, temp_dir):
+ print 'Extracting files'
+ f = zipfile.ZipFile(zip)
+ f.extractall(temp_dir)
+ f.close()
+
+def GenerateInstaller(wxs_content, options, temp_dir):
+ wxs_file = os.path.join(temp_dir, 'installer.wxs')
+ wixobj_file = os.path.join(temp_dir, 'installer.wixobj')
+ print 'Saving wxs output to: %s' % wxs_file
+ with open(wxs_file, 'w') as f:
+ f.write(wxs_content)
+
+ candle_bin = 'candle.exe'
+ light_bin = 'light.exe'
+ if options.wix_bin:
+ candle_bin = os.path.join(options.wix_bin, 'candle.exe')
+ light_bin = os.path.join(options.wix_bin, 'light.exe')
+ print 'Calling candle on %s' % wxs_file
+ subprocess.check_call('%s %s -o %s' % (candle_bin, wxs_file,
+ wixobj_file))
+ print 'Calling light on %s' % wixobj_file
+ subprocess.check_call('%s %s -o %s' % (light_bin, wixobj_file,
+ options.msi_location))
+ print 'Created msi file to %s' % options.msi_location
+
+
+def Main(argv):
+ if sys.platform != 'win32':
+ raise Exception("This script can only be run on windows")
+ options = GetOptions()
+ version = GetMicrosoftProductVersion(options.version)
+ with utils.TempDir('installer') as temp_dir:
+ input_location = GetInputDirectory(options, temp_dir)
+ print "Generating wix XML"
+ XmlHeader()
+ with WixAndProduct(version):
+ AppendBlankLine()
+ Package()
+ MediaTemplate()
+ AppendComment('We always do a major upgrade, at least for now')
+ MajorUpgrade()
+
+ AppendComment('Directory structure')
+ with Directory('TARGETDIR', 'SourceDir'):
+ with Directory('ProgramFilesFolder'):
+ with Directory('RootInstallDir', 'Dart Editor'):
+ AppendComment("Add all files and directories")
+ print 'Installing files and directories in xml'
+ ListFiles(input_location)
+ AppendBlankLine()
+ AppendComment("Create shortcuts")
+ with Directory('ProgramMenuFolder'):
+ with Directory('ShortcutFolder', 'Dart Editor'):
+ with Component('shortcut'):
+ # When generating a shortcut we need an entry with
+ # a KeyPath (RegistryEntry) below - to be able to remove
+ # the shortcut again. The RemoveFolder tag is needed
+ # to clean up everything
+ Shortcut('editor_shortcut', 'Dart Editor',
+ '[RootInstallDir]DartEditor.exe')
+ RemoveFolder('RemoveShortcuts')
+ RegistryEntry('DartEditor')
+ with Feature():
+ # We have only one feature and that consist of all the
+ # files=components we have listed above"
+ ComponentRefs()
+ xml = GetContent()
+ if options.print_wxs:
+ print xml
+ GenerateInstaller(xml, options, temp_dir)
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index a787d3c..82c6737 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -310,6 +310,37 @@
]
}
},
+ "Window": {
+ "comment": [
+ "/**",
+ " * Top-level container for the current browser tab or window.",
+ " *",
+ " * In a web browser, each window has a [Window] object, but within the context",
+ " * of a script, a [Window] object represents only the current window. In",
+ " * addition to the open window, each window, tab, and iframe has its own",
+ " * [Window] object. A [Window] contains a [Document] object, which contains this",
+ " * web page's content.",
+ " *",
+ " * Use `window` to access properties of the current window. For example:",
+ " *",
+ " * // Draw a scene when the window repaints.",
+ " * drawScene(num delta) {...}",
+ " * window.animationFrame.then(drawScene);.",
+ " *",
+ " * // Write to the console.",
+ " * window.console.log('Jinkies!');",
+ " * window.console.error('Jeepers!');",
+ " *",
+ " * **Note:** This class represents the current window, whereas [WindowBase] is",
+ " * a representation of any window, including other tabs, windows, and frames.",
+ " *",
+ " * ## Other resources",
+ " *",
+ " * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.",
+ " * * [Window](http://www.w3.org/TR/Window/) from the W3C.",
+ " */"
+ ]
+ },
"XMLHttpRequest": {
"members": {
"abort": [
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index 8205dad..d549d98 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -445,9 +445,9 @@
# TODO: Include all implemented interfaces, including other Lists.
implements = []
if self._interface_type_info.list_item_type():
- item_type_info = self._type_registry.TypeInfo(
- self._interface_type_info.list_item_type())
- implements.append('List')
+ item_type = self._type_registry.TypeInfo(
+ self._interface_type_info.list_item_type()).dart_type()
+ implements.append('List<%s>' % item_type)
return implements
def Mixins(self):
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index a862cb4..0db0fee 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -62,6 +62,7 @@
'WindowTimers': '_WindowTimers',
'XMLHttpRequest': 'HttpRequest',
'XMLHttpRequestUpload': 'HttpRequestUpload',
+ 'XMLHttpRequestEventTarget': 'HttpRequestEventTarget',
}, **typed_array_renames))
# Interfaces that are suppressed, but need to still exist for Dartium and to
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index 1684988..651900a 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -1208,6 +1208,7 @@
e.Emit(' _DateTimeClassId,\n');
e.Emit(' _JsObjectClassId,\n');
e.Emit(' _JsFunctionClassId,\n');
+ e.Emit(' _JsArrayClassId,\n');
e.Emit(' // New types that are not auto-generated should be added here.\n');
e.Emit('\n');
for interface in database.GetInterfaces():
@@ -1254,6 +1255,7 @@
e.Emit(' { "DateTime", DartCoreLibraryId, -1, false, false, false },\n');
e.Emit(' { "JsObject", DartJsLibraryId, -1, false, false, false },\n');
e.Emit(' { "JsFunction", DartJsLibraryId, _JsObjectClassId, false, false, false },\n');
+ e.Emit(' { "JsArray", DartJsLibraryId, _JsObjectClassId, false, false, false },\n');
e.Emit(' // New types that are not auto-generated should be added here.\n');
e.Emit('\n');
is_node_test = lambda interface: interface.id == 'Node'
diff --git a/tools/dom/src/CrossFrameTypes.dart b/tools/dom/src/CrossFrameTypes.dart
index 9353839..f8ed874 100644
--- a/tools/dom/src/CrossFrameTypes.dart
+++ b/tools/dom/src/CrossFrameTypes.dart
@@ -5,17 +5,16 @@
part of html;
/**
- * An object representing the top-level context object for web scripting.
+ * Top-level container for a browser tab or window.
*
- * In a web browser, a [Window] object represents the actual browser window.
- * In a multi-tabbed browser, each tab has its own [Window] object. A [Window]
- * is the container that displays a [Document]'s content. All web scripting
- * happens within the context of a [Window] object.
+ * In a web browser, a [WindowBase] object represents any browser window. This
+ * abstract class contains the state of the window and its relation to other
+ * windows, such as which window opened it.
*
* **Note:** This class represents any window, whereas [Window] is
- * used to access the properties and content of the current window.
+ * used to access the properties and content of the current window or tab.
*
- * See also:
+ * ## Other resources
*
* * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
* * [Window](http://www.w3.org/TR/Window/) from the W3C.
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index 7f0b364..2e787bd 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -5,6 +5,121 @@
part of html;
/**
+ * A factory to expose DOM events as Streams.
+ */
+class EventStreamProvider<T extends Event> {
+ final String _eventType;
+
+ const EventStreamProvider(this._eventType);
+
+ /**
+ * Gets a [Stream] for this event type, on the specified target.
+ *
+ * This will always return a broadcast stream so multiple listeners can be
+ * used simultaneously.
+ *
+ * This may be used to capture DOM events:
+ *
+ * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
+ *
+ * // Alternate method:
+ * Element.keyDownEvent.forTarget(element).capture(...);
+ *
+ * Or for listening to an event which will bubble through the DOM tree:
+ *
+ * MediaElement.pauseEvent.forTarget(document.body).listen(...);
+ *
+ * See also:
+ *
+ * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+ */
+ Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
+ new _EventStream(e, _eventType, useCapture);
+
+ /**
+ * Gets an [ElementEventStream] for this event type, on the specified element.
+ *
+ * This will always return a broadcast stream so multiple listeners can be
+ * used simultaneously.
+ *
+ * This may be used to capture DOM events:
+ *
+ * Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
+ *
+ * // Alternate method:
+ * Element.keyDownEvent.forElement(element).capture(...);
+ *
+ * Or for listening to an event which will bubble through the DOM tree:
+ *
+ * MediaElement.pauseEvent.forElement(document.body).listen(...);
+ *
+ * See also:
+ *
+ * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+ */
+ ElementStream<T> forElement(Element e, {bool useCapture: false}) {
+ return new _ElementEventStreamImpl(e, _eventType, useCapture);
+ }
+
+ /**
+ * Gets an [ElementEventStream] for this event type, on the list of elements.
+ *
+ * This will always return a broadcast stream so multiple listeners can be
+ * used simultaneously.
+ *
+ * This may be used to capture DOM events:
+ *
+ * Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
+ *
+ * See also:
+ *
+ * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
+ */
+ ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
+ return new _ElementListEventStreamImpl(e, _eventType, useCapture);
+ }
+
+ /**
+ * Gets the type of the event which this would listen for on the specified
+ * event target.
+ *
+ * The target is necessary because some browsers may use different event names
+ * for the same purpose and the target allows differentiating browser support.
+ */
+ String getEventType(EventTarget target) {
+ return _eventType;
+ }
+}
+
+/** A specialized Stream available to [Element]s to enable event delegation. */
+abstract class ElementStream<T extends Event> implements Stream<T> {
+ /**
+ * Return a stream that only fires when the particular event fires for
+ * elements matching the specified CSS selector.
+ *
+ * This is the Dart equivalent to jQuery's
+ * [delegate](http://api.jquery.com/delegate/).
+ */
+ Stream<T> matches(String selector);
+
+ /**
+ * Adds a capturing subscription to this stream.
+ *
+ * If the target of the event is a descendant of the element from which this
+ * stream derives then [onData] is called before the event propagates down to
+ * the target. This is the opposite of bubbling behavior, where the event
+ * is first processed for the event target and then bubbles upward.
+ *
+ * ## Other resources
+ *
+ * * [Event Capture]
+ * (http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture)
+ * from the W3C DOM Events specification.
+ */
+ StreamSubscription<T> capture(void onData(T event));
+}
+
+/**
* Adapter for exposing DOM events as Dart streams.
*/
class _EventStream<T extends Event> extends Stream<T> {
@@ -30,20 +145,6 @@
}
}
-/** A specialized Stream available to [Element]s to enable event delegation. */
-abstract class ElementStream<T extends Event> implements Stream<T> {
- /**
- * Return a stream that only fires when the particular event fires for
- * elements matching the specified CSS selector.
- *
- * This is the Dart equivalent to jQuery's
- * [delegate](http://api.jquery.com/delegate/).
- */
- Stream<T> matches(String selector);
-
- StreamSubscription<T> capture(void onData(T event));
-}
-
/**
* Adapter for exposing DOM Element events as streams, while also allowing
* event delegation.
@@ -110,6 +211,83 @@
bool get isBroadcast => true;
}
+class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
+ int _pauseCount = 0;
+ EventTarget _target;
+ final String _eventType;
+ var _onData;
+ final bool _useCapture;
+
+ _EventStreamSubscription(this._target, this._eventType, onData,
+ this._useCapture) : _onData = _wrapZone(onData) {
+ _tryResume();
+ }
+
+ void cancel() {
+ if (_canceled) return;
+
+ _unlisten();
+ // Clear out the target to indicate this is complete.
+ _target = null;
+ _onData = null;
+ }
+
+ bool get _canceled => _target == null;
+
+ void onData(void handleData(T event)) {
+ if (_canceled) {
+ throw new StateError("Subscription has been canceled.");
+ }
+ // Remove current event listener.
+ _unlisten();
+
+ _onData = _wrapZone(handleData);
+ _tryResume();
+ }
+
+ /// Has no effect.
+ void onError(Function handleError) {}
+
+ /// Has no effect.
+ void onDone(void handleDone()) {}
+
+ void pause([Future resumeSignal]) {
+ if (_canceled) return;
+ ++_pauseCount;
+ _unlisten();
+
+ if (resumeSignal != null) {
+ resumeSignal.whenComplete(resume);
+ }
+ }
+
+ bool get isPaused => _pauseCount > 0;
+
+ void resume() {
+ if (_canceled || !isPaused) return;
+ --_pauseCount;
+ _tryResume();
+ }
+
+ void _tryResume() {
+ if (_onData != null && !isPaused) {
+ _target.addEventListener(_eventType, _onData, _useCapture);
+ }
+ }
+
+ void _unlisten() {
+ if (_onData != null) {
+ _target.removeEventListener(_eventType, _onData, _useCapture);
+ }
+ }
+
+ Future asFuture([var futureValue]) {
+ // We just need a future that will never succeed or fail.
+ Completer completer = new Completer();
+ return completer.future;
+ }
+}
+
/**
* A stream of custom events, which enables the user to "fire" (add) their own
* custom events to a stream.
@@ -223,160 +401,6 @@
}
}
-class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
- int _pauseCount = 0;
- EventTarget _target;
- final String _eventType;
- var _onData;
- final bool _useCapture;
-
- _EventStreamSubscription(this._target, this._eventType, onData,
- this._useCapture) : _onData = _wrapZone(onData) {
- _tryResume();
- }
-
- void cancel() {
- if (_canceled) return;
-
- _unlisten();
- // Clear out the target to indicate this is complete.
- _target = null;
- _onData = null;
- }
-
- bool get _canceled => _target == null;
-
- void onData(void handleData(T event)) {
- if (_canceled) {
- throw new StateError("Subscription has been canceled.");
- }
- // Remove current event listener.
- _unlisten();
-
- _onData = _wrapZone(handleData);
- _tryResume();
- }
-
- /// Has no effect.
- void onError(Function handleError) {}
-
- /// Has no effect.
- void onDone(void handleDone()) {}
-
- void pause([Future resumeSignal]) {
- if (_canceled) return;
- ++_pauseCount;
- _unlisten();
-
- if (resumeSignal != null) {
- resumeSignal.whenComplete(resume);
- }
- }
-
- bool get isPaused => _pauseCount > 0;
-
- void resume() {
- if (_canceled || !isPaused) return;
- --_pauseCount;
- _tryResume();
- }
-
- void _tryResume() {
- if (_onData != null && !isPaused) {
- _target.addEventListener(_eventType, _onData, _useCapture);
- }
- }
-
- void _unlisten() {
- if (_onData != null) {
- _target.removeEventListener(_eventType, _onData, _useCapture);
- }
- }
-
- Future asFuture([var futureValue]) {
- // We just need a future that will never succeed or fail.
- Completer completer = new Completer();
- return completer.future;
- }
-}
-
-/**
- * A factory to expose DOM events as Streams.
- */
-class EventStreamProvider<T extends Event> {
- final String _eventType;
-
- const EventStreamProvider(this._eventType);
-
- /**
- * Gets a [Stream] for this event type, on the specified target.
- *
- * This will always return a broadcast stream so multiple listeners can be
- * used simultaneously.
- *
- * This may be used to capture DOM events:
- *
- * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
- *
- * Or for listening to an event which will bubble through the DOM tree:
- *
- * MediaElement.pauseEvent.forTarget(document.body).listen(...);
- *
- * See also:
- *
- * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
- */
- Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
- new _EventStream(e, _eventType, useCapture);
-
- /**
- * Gets an [ElementEventStream] for this event type, on the specified element.
- *
- * This will always return a broadcast stream so multiple listeners can be
- * used simultaneously.
- *
- * This may be used to capture DOM events:
- *
- * Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
- *
- * See also:
- *
- * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
- */
- ElementStream<T> forElement(Element e, {bool useCapture: false}) {
- return new _ElementEventStreamImpl(e, _eventType, useCapture);
- }
-
- /**
- * Gets an [ElementEventStream] for this event type, on the list of elements.
- *
- * This will always return a broadcast stream so multiple listeners can be
- * used simultaneously.
- *
- * This may be used to capture DOM events:
- *
- * Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
- *
- * See also:
- *
- * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
- */
- ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
- return new _ElementListEventStreamImpl(e, _eventType, useCapture);
- }
-
- /**
- * Gets the type of the event which this would listen for on the specified
- * event target.
- *
- * The target is necessary because some browsers may use different event names
- * for the same purpose and the target allows differentiating browser support.
- */
- String getEventType(EventTarget target) {
- return _eventType;
- }
-}
-
/**
* A factory to expose DOM events as streams, where the DOM event name has to
* be determined on the fly (for example, mouse wheel events).
diff --git a/tools/dom/src/dart2js_KeyEvent.dart b/tools/dom/src/dart2js_KeyEvent.dart
index b8fcfa6..8c7b5fd 100644
--- a/tools/dom/src/dart2js_KeyEvent.dart
+++ b/tools/dom/src/dart2js_KeyEvent.dart
@@ -56,7 +56,7 @@
/** Helper to statically create the dispatch record. */
static _makeRecord() {
- var interceptor = findInterceptorForType(KeyboardEvent);
+ var interceptor = JS_INTERCEPTOR_CONSTANT(KeyboardEvent);
return makeLeafDispatchRecord(interceptor);
}
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index 51e9ced..46b4e71 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -535,6 +535,13 @@
final _forwardingPrintClosure = _Utils.forwardingPrint;
+final _uriBaseClosure = () => Uri.parse(window.location.href);
+
+final _pureIsolateUriBaseClosure = () {
+ throw new UnimplementedError("Uri.base on a background isolate "
+ "is not supported in the browser");
+};
+
class _Timer implements Timer {
var _canceler;
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 394f526..146645c 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -54,9 +54,9 @@
import 'dart:_interceptors' show
Interceptor, JSExtendableArray, findInterceptorConstructorForType,
findConstructorForNativeSubclassType, getNativeInterceptor,
- setDispatchProperty, findInterceptorForType;
+ setDispatchProperty;
import 'dart:_isolate_helper' show IsolateNatives;
-import 'dart:_foreign_helper' show JS;
+import 'dart:_foreign_helper' show JS, JS_INTERCEPTOR_CONSTANT;
export 'dart:math' show Rectangle, Point;
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 3bc56ef..e04ec31 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -259,7 +259,7 @@
// ElementList as there are valid cases where a NodeList JavaScript object
// contains Node objects that are not Elements.
class _FrozenElementList<T extends Element> extends ListBase<T>
- implements ElementList, NodeListWrapper {
+ implements ElementList<T>, NodeListWrapper {
final List<Node> _nodeList;
// The subset of _nodeList that are Elements.
List<Element> _elementList;
diff --git a/tools/test.dart b/tools/test.dart
index d319bdae..0556662 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -29,7 +29,6 @@
import "dart:math" as math;
import "testing/dart/browser_controller.dart";
import "testing/dart/http_server.dart";
-import "testing/dart/record_and_replay.dart";
import "testing/dart/test_options.dart";
import "testing/dart/test_progress.dart";
import "testing/dart/test_runner.dart";
@@ -38,7 +37,6 @@
import "../runtime/tests/vm/test_config.dart";
import "../tests/co19/test_config.dart";
-import "../tests/lib/analyzer/test_config.dart";
/**
* The directories that contain test suites which follow the conventions
@@ -172,6 +170,11 @@
// Safari does not allow us to run from a fresh profile, so we can only
// use one browser.
maxBrowserProcesses = 1;
+ } else if (conf['runtime'] == 'chrome' &&
+ conf['use_browser_controller'] &&
+ Platform.operatingSystem == 'macos') {
+ // Chrome on mac results in random timeouts.
+ maxBrowserProcesses = math.max(1, maxBrowserProcesses ~/ 2);
}
for (String key in selectors.keys) {
@@ -185,9 +188,6 @@
if (key == 'analyze_library') {
testSuites.add(new AnalyzeLibraryTestSuite(conf));
}
- if (key == 'analyze_tests') {
- testSuites.add(new AnalyzeTestsTestSuite(conf));
- }
}
}
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index f45263d..d661e84 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -75,8 +75,7 @@
static const List<String> SUPPORTED_BROWSERS =
const ['safari', 'ff', 'firefox', 'chrome', 'ie9', 'ie10', 'dartium'];
- static const List<String> BROWSERS_WITH_WINDOW_SUPPORT =
- const ['safari', 'ff', 'firefox', 'chrome'];
+ static const List<String> BROWSERS_WITH_WINDOW_SUPPORT = const [];
// TODO(kustermann): add standard support for chrome on android
static bool supportedBrowser(String name) {
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index b942437..197e850 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -229,7 +229,7 @@
openedFile.writeStringSync(tests[key]);
openedFile.closeSync();
Set<String> outcome = outcomes[key];
- bool enableFatalTypeErrors = outcome.contains('static type warning');
+ bool hasStaticWarning = outcome.contains('static type warning');
bool hasRuntimeErrors = outcome.contains('runtime error');
bool hasCompileError = outcome.contains('compile-time error');
bool isNegativeIfChecked = outcome.contains('dynamic type error');
@@ -237,7 +237,7 @@
hasCompileError,
hasRuntimeErrors,
isNegativeIfChecked: isNegativeIfChecked,
- hasFatalTypeErrors: enableFatalTypeErrors,
+ hasStaticWarning: hasStaticWarning,
multitestOutcome: outcome,
multitestKey: key,
originTestPath: filePath);
diff --git a/tools/testing/dart/status_file_parser.dart b/tools/testing/dart/status_file_parser.dart
index b69e6ac..6922687 100644
--- a/tools/testing/dart/status_file_parser.dart
+++ b/tools/testing/dart/status_file_parser.dart
@@ -22,6 +22,9 @@
static Expectation MISSING_RUNTIME_ERROR = byName('MissingRuntimeError');
static Expectation MISSING_COMPILETIME_ERROR =
byName('MissingCompileTimeError');
+ static Expectation STATIC_WARNING = byName('StaticWarning');
+ static Expectation MISSING_STATIC_WARNING =
+ byName('MissingStaticWarning');
// "meta expectations"
static Expectation OK = byName('Ok');
@@ -61,6 +64,9 @@
build("CompileTimeError", group: fail);
build("RuntimeError", group: fail);
+ build("MissingStaticWarning", group: fail);
+ build("StaticWarning", group: fail);
+
build("Skip", isMetaExpectation: true);
build("SkipByDesign", isMetaExpectation: true);
build("Ok", isMetaExpectation: true);
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index ff016e6..b1528ec 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -12,7 +12,7 @@
List<String> defaultTestSelectors =
const ['samples', 'standalone', 'corelib', 'co19', 'language',
'isolate', 'vm', 'html', 'json', 'benchmark_smoke',
- 'utils', 'lib', 'pkg', 'analyze_library', 'analyze_tests'];
+ 'utils', 'lib', 'pkg', 'analyze_library'];
/**
* Specification of a single test option.
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 5527d03..9f62c9c 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -339,23 +339,30 @@
class AnalysisCommand extends Command {
final String flavor;
+ // If [fileFilter] is given, only errors/warnings reported by the analyzer
+ // for which [fileFilter] returns [:true:] are considered.
+ final Function fileFilter;
+
AnalysisCommand._(this.flavor,
String displayName,
String executable,
List<String> arguments,
- String configurationDir)
+ String configurationDir,
+ this.fileFilter)
: super._(displayName, executable, arguments, configurationDir);
void _buildHashCode(HashCodeBuilder builder) {
super._buildHashCode(builder);
builder.add(flavor);
+ builder.add(fileFilter);
}
bool _equal(Command other) {
return
other is AnalysisCommand &&
super._equal(other) &&
- flavor == other.flavor;
+ flavor == other.flavor &&
+ fileFilter == other.fileFilter;
}
}
@@ -434,9 +441,10 @@
AnalysisCommand getAnalysisCommand(
String displayName, executable, arguments, String configurationDir,
- {String flavor: 'dartanalyzer'}) {
+ {String flavor: 'dartanalyzer', Function fileFilter: null}) {
var command = new AnalysisCommand._(
- flavor, displayName, executable, arguments, configurationDir);
+ flavor, displayName, executable, arguments, configurationDir,
+ fileFilter);
return _getUniqueCommand(command);
}
@@ -912,20 +920,14 @@
}
-// The static analyzer does not actually execute code, so
-// the criteria for success now depend on the text sent
-// to stderr.
class AnalysisCommandOutputImpl extends CommandOutputImpl {
// An error line has 8 fields that look like:
// ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source.
final int ERROR_LEVEL = 0;
final int ERROR_TYPE = 1;
+ final int FILENAME = 3;
final int FORMATTED_ERROR = 7;
- bool alreadyComputed = false;
- bool failResult;
-
- // TODO(kustermann): Remove testCase from this class
AnalysisCommandOutputImpl(command,
exitCode,
timedOut,
@@ -941,153 +943,95 @@
time,
compilationSkipped);
- bool didFail(TestCase testCase) {
- if (!alreadyComputed) {
- failResult = _didFail(testCase);
- alreadyComputed = true;
+ Expectation result(TestCase testCase) {
+ // TODO(kustermann): If we run the analyzer not in batch mode, make sure
+ // that command.exitCodes matches 2 (errors), 1 (warnings), 0 (no warnings,
+ // no errors)
+
+ // Handle crashes and timeouts first
+ if (hasCrashed) return Expectation.CRASH;
+ if (hasTimedOut) return Expectation.TIMEOUT;
+
+ // Get the errors/warnings from the analyzer
+ List<String> errors = [];
+ List<String> warnings = [];
+ parseAnalyzerOutput(errors, warnings);
+
+ // Handle errors / missing errors
+ if (testCase.info.hasCompileError) {
+ if (errors.length > 0) {
+ return Expectation.PASS;
+ }
+ return Expectation.MISSING_COMPILETIME_ERROR;
}
- return failResult;
+ if (errors.length > 0) {
+ return Expectation.COMPILETIME_ERROR;
+ }
+
+ // Handle static warnings / missing static warnings
+ if (testCase.info.hasStaticWarning) {
+ if (warnings.length > 0) {
+ return Expectation.PASS;
+ }
+ return Expectation.MISSING_STATIC_WARNING;
+ }
+ if (warnings.length > 0) {
+ return Expectation.STATIC_WARNING;
+ }
+
+ assert (errors.length == 0 && warnings.length == 0);
+ assert (!testCase.info.hasCompileError &&
+ !testCase.info.hasStaticWarning);
+ return Expectation.PASS;
}
- bool _didFail(TestCase testCase) {
- if (hasCrashed) return false;
+ void parseAnalyzerOutput(List<String> outErrors, List<String> outWarnings) {
+ AnalysisCommand analysisCommand = command;
+ Function fileFilter = analysisCommand.fileFilter;
+ if (fileFilter == null) {
+ // If no filter function was given, we don't filter the output at all.
+ fileFilter = (arg) => true;
+ }
- List<String> errors = [];
- List<String> staticWarnings = [];
+ // Parse a line delimited by the | character using \ as an escape charager
+ // like: FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ
+ List<String> splitMachineError(String line) {
+ StringBuffer field = new StringBuffer();
+ List<String> result = [];
+ bool escaped = false;
+ for (var i = 0 ; i < line.length; i++) {
+ var c = line[i];
+ if (!escaped && c == '\\') {
+ escaped = true;
+ continue;
+ }
+ escaped = false;
+ if (c == '|') {
+ result.add(field.toString());
+ field = new StringBuffer();
+ continue;
+ }
+ field.write(c);
+ }
+ result.add(field.toString());
+ return result;
+ }
- // Read the returned list of errors and stuff them away.
- var stderrLines = decodeUtf8(super.stderr).split("\n");
- for (String line in stderrLines) {
+ for (String line in decodeUtf8(super.stderr).split("\n")) {
if (line.length == 0) continue;
List<String> fields = splitMachineError(line);
- if (fields[ERROR_LEVEL] == 'ERROR') {
- errors.add(fields[FORMATTED_ERROR]);
- } else if (fields[ERROR_LEVEL] == 'WARNING') {
- staticWarnings.add(fields[FORMATTED_ERROR]);
- }
- // OK to Skip error output that doesn't match the machine format
- }
- // FIXME(kustermann): This is wrong, we should give the expectations
- // to Command
- if (testCase.info != null
- && testCase.info.optionsFromFile['isMultitest']) {
- return _didMultitestFail(testCase, errors, staticWarnings);
- }
- return _didStandardTestFail(testCase, errors, staticWarnings);
- }
-
- bool _didMultitestFail(TestCase testCase, List errors, List staticWarnings) {
- Set<String> outcome = testCase.info.multitestOutcome;
- if (outcome == null) throw "outcome must not be null";
- if (outcome.contains('compile-time error') && errors.length > 0) {
- return true;
- } else if (outcome.contains('static type warning')
- && staticWarnings.length > 0) {
- return true;
- } else if (outcome.isEmpty
- && (errors.length > 0 || staticWarnings.length > 0)) {
- return true;
- }
- return false;
- }
-
- bool _didStandardTestFail(TestCase testCase, List errors, List staticWarnings) {
- bool hasFatalTypeErrors = false;
- int numStaticTypeAnnotations = 0;
- int numCompileTimeAnnotations = 0;
- var isStaticClean = false;
- if (testCase.info != null) {
- var optionsFromFile = testCase.info.optionsFromFile;
- hasFatalTypeErrors = testCase.info.hasFatalTypeErrors;
- for (Command c in testCase.commands) {
- for (String arg in c.arguments) {
- if (arg == '--fatal-type-errors') {
- hasFatalTypeErrors = true;
- break;
+ // We only consider errors/warnings for files of interest.
+ if (fields.length > FILENAME) {
+ if (fileFilter(fields[FILENAME])) {
+ if (fields[ERROR_LEVEL] == 'ERROR') {
+ outErrors.add(fields[FORMATTED_ERROR]);
+ } else if (fields[ERROR_LEVEL] == 'WARNING') {
+ outWarnings.add(fields[FORMATTED_ERROR]);
}
}
+ // OK to Skip error output that doesn't match the machine format
}
- numStaticTypeAnnotations = optionsFromFile['numStaticTypeAnnotations'];
- numCompileTimeAnnotations = optionsFromFile['numCompileTimeAnnotations'];
- isStaticClean = optionsFromFile['isStaticClean'];
}
-
- if (errors.length == 0) {
- // If the analyzer has warnings it will exit 1.
- // We should reconsider how we do this once we have landed a dart
- // only version of the analyzer for stable use (as in not run in batch
- // mode).
- if (!hasFatalTypeErrors && exitCode != 0 && staticWarnings.length == 0) {
- diagnostics.add("EXIT CODE MISMATCH: Expected error message:");
- diagnostics.add(" command[0]:${testCase.commands[0]}");
- diagnostics.add(" exitCode:${exitCode}");
- return true;
- }
- } else if (exitCode == 0) {
- diagnostics.add("EXIT CODE MISMATCH: Unexpected error message:");
- diagnostics.add(" errors[0]:${errors[0]}");
- diagnostics.add(" command[0]:${testCase.commands[0]}");
- diagnostics.add(" exitCode:${exitCode}");
- return true;
- }
- if (numStaticTypeAnnotations > 0 && isStaticClean) {
- diagnostics.add("Cannot have both @static-clean and /// static "
- "type warning annotations.");
- return true;
- }
-
- if (isStaticClean && (errors.isNotEmpty || staticWarnings.isNotEmpty)) {
- diagnostics.add(
- "@static-clean annotation found but analyzer returned problems.");
- return true;
- }
-
- if (numCompileTimeAnnotations > 0
- && numCompileTimeAnnotations < errors.length) {
- // Expected compile-time errors were not returned.
- // The test did not 'fail' in the way intended so don't return failed.
- diagnostics.add("Fewer compile time errors than annotated: "
- "$numCompileTimeAnnotations");
- return false;
- }
-
- if (numStaticTypeAnnotations > 0 || hasFatalTypeErrors) {
- // TODO(zundel): match up the annotation line numbers
- // with the reported error line numbers
- if (staticWarnings.length < numStaticTypeAnnotations) {
- diagnostics.add("Fewer static type warnings than annotated: "
- "$numStaticTypeAnnotations");
- return true;
- }
- return false;
- } else if (errors.length != 0) {
- return true;
- }
- return false;
- }
-
- // Parse a line delimited by the | character using \ as an escape charager
- // like: FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ
- List<String> splitMachineError(String line) {
- StringBuffer field = new StringBuffer();
- List<String> result = [];
- bool escaped = false;
- for (var i = 0 ; i < line.length; i++) {
- var c = line[i];
- if (!escaped && c == '\\') {
- escaped = true;
- continue;
- }
- escaped = false;
- if (c == '|') {
- result.add(field.toString());
- field = new StringBuffer();
- continue;
- }
- field.write(c);
- }
- result.add(field.toString());
- return result;
}
}
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index caa2c6e..298317b 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -37,7 +37,7 @@
bool hasCompileError,
bool hasRuntimeError,
{bool isNegativeIfChecked,
- bool hasFatalTypeErrors,
+ bool hasStaticWarning,
Set<String> multitestOutcome,
String multitestKey,
Path originTestPath});
@@ -468,13 +468,13 @@
bool hasCompileError;
bool hasRuntimeError;
bool isNegativeIfChecked;
- bool hasFatalTypeErrors;
+ bool hasStaticWarning;
Set<String> multitestOutcome;
String multitestKey;
TestInformation(this.filePath, this.optionsFromFile,
this.hasCompileError, this.hasRuntimeError,
- this.isNegativeIfChecked, this.hasFatalTypeErrors,
+ this.isNegativeIfChecked, this.hasStaticWarning,
this.multitestOutcome,
{this.multitestKey, this.originTestPath}) {
assert(filePath.isAbsolute);
@@ -693,7 +693,8 @@
} else {
createTestCase(filePath,
optionsFromFile['hasCompileError'],
- optionsFromFile['hasRuntimeError']);
+ optionsFromFile['hasRuntimeError'],
+ hasStaticWarning: optionsFromFile['hasStaticWarning']);
}
}
@@ -761,13 +762,6 @@
if (info.hasRuntimeError && hasRuntime) {
negative = true;
}
- if (configuration['analyzer']) {
- // An analyzer can detect static type warnings by the
- // format of the error line
- if (info.hasFatalTypeErrors) {
- negative = true;
- }
- }
return negative;
}
@@ -829,21 +823,26 @@
case 'dartanalyzer':
case 'dart2analyzer':
- return <Command>[CommandBuilder.instance.getAnalysisCommand(
- compiler, dartShellFileName, args, configurationDir,
- flavor: compiler)];
+ return <Command>[makeAnalysisCommand(info, args)];
default:
throw 'Unknown compiler ${configuration["compiler"]}';
}
}
+ AnalysisCommand makeAnalysisCommand(TestInformation info,
+ List<String> arguments) {
+ return CommandBuilder.instance.getAnalysisCommand(
+ configuration['compiler'], dartShellFileName, arguments,
+ configurationDir, flavor: configuration['compiler']);
+ }
+
CreateTest makeTestCaseCreator(Map optionsFromFile) {
return (Path filePath,
bool hasCompileError,
bool hasRuntimeError,
{bool isNegativeIfChecked: false,
- bool hasFatalTypeErrors: false,
+ bool hasStaticWarning: false,
Set<String> multitestOutcome: null,
String multitestKey,
Path originTestPath}) {
@@ -853,7 +852,7 @@
hasCompileError,
hasRuntimeError,
isNegativeIfChecked,
- hasFatalTypeErrors,
+ hasStaticWarning,
multitestOutcome,
multitestKey: multitestKey,
originTestPath: originTestPath);
@@ -1412,11 +1411,6 @@
RegExp packageRootRegExp = new RegExp(r"// PackageRoot=(.*)");
RegExp multiHtmlTestRegExp =
new RegExp(r"useHtmlIndividualConfiguration()");
- RegExp staticTypeRegExp =
- new RegExp(r"/// ([0-9][0-9]:){0,1}\s*static type warning");
- RegExp compileTimeRegExp =
- new RegExp(r"/// ([0-9][0-9]:){0,1}\s*compile-time error");
- RegExp staticCleanRegExp = new RegExp(r"// @static-clean");
RegExp isolateStubsRegExp = new RegExp(r"// IsolateStubs=(.*)");
// TODO(gram) Clean these up once the old directives are not supported.
RegExp domImportRegExp =
@@ -1431,7 +1425,6 @@
List<List> result = new List<List>();
List<String> dartOptions;
String packageRoot;
- bool isStaticClean = false;
Iterable<Match> matches = testOptionsRegExp.allMatches(contents);
for (var match in matches) {
@@ -1461,15 +1454,6 @@
}
}
- matches = staticCleanRegExp.allMatches(contents);
- for (var match in matches) {
- if (isStaticClean) {
- throw new Exception(
- 'More than one "// @static-clean=" line in test $filePath');
- }
- isStaticClean = true;
- }
-
List<String> otherScripts = new List<String>();
matches = otherScriptsRegExp.allMatches(contents);
for (var match in matches) {
@@ -1481,14 +1465,6 @@
Match isolateMatch = isolateStubsRegExp.firstMatch(contents);
String isolateStubs = isolateMatch != null ? isolateMatch[1] : '';
bool containsDomImport = domImportRegExp.hasMatch(contents);
- int numStaticTypeAnnotations = 0;
- for (var i in staticTypeRegExp.allMatches(contents)) {
- numStaticTypeAnnotations++;
- }
- int numCompileTimeAnnotations = 0;
- for (var i in compileTimeRegExp.allMatches(contents)) {
- numCompileTimeAnnotations++;
- }
// Note: This is brittle. It's the age-old problem of having a context free
// language but the means to easily identify the construct is a regular
@@ -1509,15 +1485,13 @@
"packageRoot": packageRoot,
"hasCompileError": false,
"hasRuntimeError": false,
- "isStaticClean" : isStaticClean,
+ "hasStaticWarning" : false,
"otherScripts": otherScripts,
"isMultitest": isMultitest,
"isMultiHtmlTest": isMultiHtmlTest,
"subtestNames": subtestNames,
"isolateStubs": isolateStubs,
- "containsDomImport": containsDomImport,
- "numStaticTypeAnnotations": numStaticTypeAnnotations,
- "numCompileTimeAnnotations": numCompileTimeAnnotations };
+ "containsDomImport": containsDomImport };
}
List<List<String>> getVmOptions(Map optionsFromFile) {
@@ -1579,15 +1553,13 @@
"packageRoot": null,
"hasCompileError": hasCompileError,
"hasRuntimeError": hasRuntimeError,
- "isStaticClean" : !hasCompileError && !hasStaticWarning,
+ "hasStaticWarning" : hasStaticWarning,
"otherScripts": <String>[],
"isMultitest": isMultitest,
"isMultiHtmlTest": false,
"subtestNames": <String>[],
"isolateStubs": '',
"containsDomImport": false,
- "numStaticTypeAnnotations": 0,
- "numCompileTimeAnnotations": 0,
};
}
}
@@ -1597,20 +1569,14 @@
///
/// Usually, the result of a dartc run is determined by the output of
/// dartc in connection with annotations in the test file.
-///
-/// If you want each file that you are running as a test to have no
-/// static warnings or errors you can create a DartcCompilationTestSuite
-/// with the optional allStaticClean constructor parameter set to true.
class DartcCompilationTestSuite extends StandardTestSuite {
List<String> _testDirs;
- bool allStaticClean;
DartcCompilationTestSuite(Map configuration,
String suiteName,
String directoryPath,
List<String> this._testDirs,
- List<String> expectations,
- {bool this.allStaticClean: false})
+ List<String> expectations)
: super(configuration,
suiteName,
new Path(directoryPath),
@@ -1632,16 +1598,45 @@
return group.future;
}
-
- Map readOptionsFromFile(Path p) {
- Map options = super.readOptionsFromFile(p);
- if (allStaticClean) {
- options['isStaticClean'] = true;
- }
- return options;
- }
}
+class AnalyzeLibraryTestSuite extends DartcCompilationTestSuite {
+ AnalyzeLibraryTestSuite(Map configuration)
+ : super(configuration,
+ 'analyze_library',
+ 'sdk',
+ ['lib'],
+ ['tests/lib/analyzer/analyze_library.status']);
+
+ List<String> additionalOptions(Path filePath, {bool showSdkWarnings}) {
+ var options = super.additionalOptions(filePath);
+ // NOTE: This flag has been deprecated.
+ options.add('--show-sdk-warnings');
+ return options;
+ }
+
+ bool isTestFile(String filename) {
+ var sep = Platform.pathSeparator;
+ // NOTE: We exclude tests and patch files for now.
+ return filename.endsWith(".dart") &&
+ !filename.endsWith("_test.dart") &&
+ !filename.contains("_internal/lib");
+ }
+
+ AnalysisCommand makeAnalysisCommand(TestInformation info,
+ List<String> arguments) {
+ bool fileFilter(String filepath) {
+ return filepath == "${info.originTestPath}";
+ }
+
+ return CommandBuilder.instance.getAnalysisCommand(
+ configuration['compiler'], dartShellFileName, arguments,
+ configurationDir, flavor: configuration['compiler'],
+ fileFilter: fileFilter);
+ }
+
+ bool get listRecursively => true;
+}
class JUnitTestSuite extends TestSuite {
String directoryPath;
diff --git a/tools/utils.py b/tools/utils.py
index 8833930..26d78ca 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -231,6 +231,13 @@
def GetBaseDir():
return BASE_DIR
+# Return the base part of the version, Major.Minor.Build.Patch,
+# without the _revision addition
+def GetShortVersion():
+ (major, minor, build, patch) = ReadVersionFile()
+ return '%s.%s.%s.%s' % (major, minor, build, patch)
+
+
def GetVersion():
version_tuple = ReadVersionFile()
if not version_tuple:
diff --git a/utils/compiler/create_snapshot.dart b/utils/compiler/create_snapshot.dart
index 37920a3..3b6cbfd 100644
--- a/utils/compiler/create_snapshot.dart
+++ b/utils/compiler/create_snapshot.dart
@@ -4,7 +4,7 @@
import 'dart:io';
-Future<String> getVersion(var options, var rootPath) {
+Future<String> getVersion(var rootPath) {
var suffix = Platform.operatingSystem == 'windows' ? '.exe' : '';
var printVersionScript = rootPath.resolve("tools/print_version.py");
return Process.run("python$suffix",
@@ -16,25 +16,24 @@
});
}
-Future<String> getSnapshotGenerationFile(var options, var args, var rootPath) {
+Future<String> getSnapshotGenerationFile(var args, var rootPath) {
var dart2js = rootPath.resolve(args["dart2js_main"]);
var dartdoc = rootPath.resolve(args["dartdoc_main"]);
- return getVersion(options, rootPath).then((version) {
+ return getVersion(rootPath).then((version) {
var snapshotGenerationText =
"""
import '${dart2js.toFilePath(windows: false)}' as dart2jsMain;
import '${dartdoc.toFilePath(windows: false)}' as dartdocMain;
import 'dart:io';
-void main() {
- Options options = new Options();
- if (options.arguments.length < 1) throw "No tool given as argument";
- String tool = options.arguments.removeAt(0);
+void main(List<String> arguments) {
+ if (arguments.length < 1) throw "No tool given as argument";
+ String tool = arguments[0];
if (tool == "dart2js") {
dart2jsMain.BUILD_ID = "$version";
- dart2jsMain.mainWithErrorHandler(options);
+ dart2jsMain.main(arguments.skip(1).toList());
} else if (tool == "dartdoc") {
- dartdocMain.mainWithOptions(options);
+ dartdocMain.main(arguments.skip(1).toList());
}
}
@@ -50,8 +49,8 @@
writer.close();
}
-Future createSnapshot(var options, var dart_file, var packageRoot) {
- return Process.run(options.executable,
+Future createSnapshot(var dart_file, var packageRoot) {
+ return Process.run(Platform.executable,
["--package-root=$packageRoot",
"--snapshot=$dart_file.snapshot",
dart_file])
@@ -67,12 +66,11 @@
* --output_dir=val The full path to the output_dir.
* --dart2js_main=val The path to the dart2js main script releative to root.
*/
-void main() {
- Options options = new Options();
+void main(List<String> arguments) {
var validArguments = ["--output_dir", "--dart2js_main", "--dartdoc_main",
"--package_root"];
var args = {};
- for (var argument in options.arguments) {
+ for (var argument in arguments) {
var argumentSplit = argument.split("=");
if (argumentSplit.length != 2) throw "Invalid argument $argument, no =";
if (!validArguments.contains(argumentSplit[0])) {
@@ -85,12 +83,12 @@
if (!args.containsKey("output_dir")) throw "Please specify output_dir";
if (!args.containsKey("package_root")) throw "Please specify package_root";
- var scriptFile = new Uri.file(new File(options.script).fullPathSync());
+ var scriptFile = new Uri.file(new File(Platform.script).fullPathSync());
var path = scriptFile.resolve(".");
var rootPath = path.resolve("../..");
- getSnapshotGenerationFile(options, args, rootPath).then((result) {
+ getSnapshotGenerationFile(args, rootPath).then((result) {
var wrapper = "${args['output_dir']}/utils_wrapper.dart";
writeSnapshotFile(wrapper, result);
- createSnapshot(options, wrapper, args["package_root"]);
+ createSnapshot(wrapper, args["package_root"]);
});
}