Version 0.4.1.0 .
svn merge -r 18904:19417 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 19424 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@19425 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/compiler/build.xml b/compiler/build.xml
index 6db056d..99e2bb6 100644
--- a/compiler/build.xml
+++ b/compiler/build.xml
@@ -43,7 +43,7 @@
-->
<path id="classpath.compile">
<pathelement location="${third_party.dir}/args4j/2.0.12/args4j-2.0.12.jar"/>
- <pathelement location="${third_party.dir}/guava/r09/guava-r09.jar"/>
+ <pathelement location="${third_party.dir}/guava/r13/guava-13.0.1.jar"/>
<pathelement location="${third_party.dir}/json/r2_20080312/json.jar"/>
</path>
diff --git a/compiler/dart-compiler.gyp b/compiler/dart-compiler.gyp
index 2dd44c0..7e589e9 100644
--- a/compiler/dart-compiler.gyp
+++ b/compiler/dart-compiler.gyp
@@ -38,7 +38,7 @@
'scripts/dart_analyzer.bat',
'scripts/analyzer_metrics.sh',
'../third_party/args4j/2.0.12/args4j-2.0.12.jar',
- '../third_party/guava/r09/guava-r09.jar',
+ '../third_party/guava/r13/guava-13.0.1.jar',
'../third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar',
'../third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar',
'../third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar',
@@ -50,7 +50,7 @@
'<(PRODUCT_DIR)/analyzer/bin/dart_analyzer.bat',
'<(PRODUCT_DIR)/analyzer/util/analyzer/dart_analyzer.jar',
'<(PRODUCT_DIR)/analyzer/util/analyzer/args4j/2.0.12/args4j-2.0.12.jar',
- '<(PRODUCT_DIR)/analyzer/util/analyzer/guava/r09/guava-r09.jar',
+ '<(PRODUCT_DIR)/analyzer/util/analyzer/guava/r13/guava-13.0.1.jar',
],
'action' : [
'../third_party/apache_ant/1.8.4/bin/ant<(script_suffix)',
diff --git a/compiler/dart_analyzer.xml b/compiler/dart_analyzer.xml
index 01a5adc..ff63f2f 100644
--- a/compiler/dart_analyzer.xml
+++ b/compiler/dart_analyzer.xml
@@ -36,7 +36,7 @@
-->
<path id="classpath.compile">
<pathelement location="${third_party.dir}/args4j/2.0.12/args4j-2.0.12.jar"/>
- <pathelement location="${third_party.dir}/guava/r09/guava-r09.jar"/>
+ <pathelement location="${third_party.dir}/guava/r13/guava-13.0.1.jar"/>
<pathelement location="${third_party.dir}/json/r2_20080312/json.jar"/>
</path>
diff --git a/compiler/eclipse.workspace/dartc/.classpath b/compiler/eclipse.workspace/dartc/.classpath
index 30fd5cf..12f7079 100644
--- a/compiler/eclipse.workspace/dartc/.classpath
+++ b/compiler/eclipse.workspace/dartc/.classpath
@@ -3,7 +3,7 @@
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="var" path="DART_TRUNK/third_party/args4j/2.0.12/args4j-2.0.12.jar" sourcepath="/DART_TRUNK/third_party/args4j/2.0.12/args4j-2.0.12-src.jar"/>
- <classpathentry kind="var" path="DART_TRUNK/third_party/guava/r09/guava-r09.jar" sourcepath="/DART_TRUNK/third_party/guava/r09/guava-src-r09.zip"/>
+ <classpathentry kind="var" path="DART_TRUNK/third_party/guava/r13/guava-13.0.1.jar" sourcepath="/DART_TRUNK/third_party/guava/r13/guava-13.0.1-sources.zip"/>
<classpathentry kind="var" path="DART_TRUNK/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar"/>
<classpathentry kind="var" path="DART_TRUNK/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar"/>
<classpathentry kind="var" path="DART_TRUNK/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar"/>
diff --git a/compiler/eclipse.workspace/tests/.classpath b/compiler/eclipse.workspace/tests/.classpath
index b16c307..704cbcd 100644
--- a/compiler/eclipse.workspace/tests/.classpath
+++ b/compiler/eclipse.workspace/tests/.classpath
@@ -7,6 +7,6 @@
<classpathentry combineaccessrules="false" kind="src" path="/dartc"/>
<classpathentry kind="var" path="DART_TRUNK/third_party/args4j/2.0.12/args4j-2.0.12.jar" sourcepath="/DART_TRUNK/third_party/args4j/2.0.12/args4j-2.0.12-src.jar"/>
<classpathentry kind="var" path="DART_TRUNK/third_party/junit/v4_8_2/junit.jar"/>
- <classpathentry kind="var" path="DART_TRUNK/third_party/guava/r09/guava-r09.jar"/>
+ <classpathentry kind="var" path="DART_TRUNK/third_party/guava/r13/guava-13.0.1.jar"/>
<classpathentry kind="output" path="output"/>
</classpath>
diff --git a/compiler/java/com/google/dart/compiler/SystemLibrariesReader.java b/compiler/java/com/google/dart/compiler/SystemLibrariesReader.java
index 10b66c1..56d3bbf 100644
--- a/compiler/java/com/google/dart/compiler/SystemLibrariesReader.java
+++ b/compiler/java/com/google/dart/compiler/SystemLibrariesReader.java
@@ -13,6 +13,7 @@
*/
package com.google.dart.compiler;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.CharStreams;
import com.google.common.io.Closeables;
import com.google.dart.compiler.CompilerConfiguration.ErrorFormat;
@@ -53,7 +54,8 @@
*/
public class SystemLibrariesReader {
- class DartLibrary {
+ @VisibleForTesting
+ public class DartLibrary {
private String shortName = null;
private String path = null;
diff --git a/compiler/java/com/google/dart/compiler/resolver/ClassScope.java b/compiler/java/com/google/dart/compiler/resolver/ClassScope.java
index f5625c6..e5c393f 100644
--- a/compiler/java/com/google/dart/compiler/resolver/ClassScope.java
+++ b/compiler/java/com/google/dart/compiler/resolver/ClassScope.java
@@ -76,7 +76,7 @@
InterfaceType mixin = mixins.get(i);
ClassElement mixinElement = mixin.getElement();
if (!examinedTypes.contains(mixinElement)) {
- MixinScope scope = new MixinScope(mixinElement, null);
+ MixinScope scope = new MixinScope(mixinElement);
element = scope.findElement(inLibrary, name);
if (element != null) {
return element;
diff --git a/compiler/java/com/google/dart/compiler/resolver/ElementMap.java b/compiler/java/com/google/dart/compiler/resolver/ElementMap.java
index 1c3b39f..5a186a6 100644
--- a/compiler/java/com/google/dart/compiler/resolver/ElementMap.java
+++ b/compiler/java/com/google/dart/compiler/resolver/ElementMap.java
@@ -4,8 +4,9 @@
package com.google.dart.compiler.resolver;
-import com.google.dart.compiler.ast.DartObsoleteMetadata;
+import com.google.common.annotations.VisibleForTesting;
import com.google.dart.compiler.ast.DartNode;
+import com.google.dart.compiler.ast.DartObsoleteMetadata;
import com.google.dart.compiler.ast.Modifiers;
import com.google.dart.compiler.common.SourceInfo;
import com.google.dart.compiler.type.Type;
@@ -17,7 +18,8 @@
* A more efficient version of {@link com.google.common.collect.Multimap} specifically for
* {@link NodeElement}
*/
-class ElementMap {
+@VisibleForTesting
+public class ElementMap {
/**
* A synthetic place holder for an element where the name given to the element map does not match
@@ -98,7 +100,8 @@
private NodeElement[] elements;
private List<NodeElement> ordered = new ArrayList<NodeElement>();
- ElementMap() {
+ @VisibleForTesting
+ public ElementMap() {
clear();
}
@@ -106,7 +109,8 @@
* Associate the specified element with the specified name. If the element is already associated
* with that name, do not associate it again.
*/
- void add(String name, NodeElement element) {
+ @VisibleForTesting
+ public void add(String name, NodeElement element) {
// Most of the time name equals getName() thus holder == element
NodeElement newHolder;
@@ -161,7 +165,8 @@
*
* @return the element or <code>null</code> if none
*/
- NodeElement get(String name) {
+ @VisibleForTesting
+ public NodeElement get(String name) {
NodeElement element = internalGet(name);
if (element instanceof ElementHolder) {
return ((ElementHolder) element).element;
@@ -175,7 +180,8 @@
*
* @return the element of that kind or <code>null</code> if none
*/
- NodeElement get(String name, ElementKind kind) {
+ @VisibleForTesting
+ public NodeElement get(String name, ElementKind kind) {
NodeElement element = internalGet(name);
if (element instanceof ElementHolder) {
ElementHolder holder = (ElementHolder) element;
@@ -197,15 +203,18 @@
return null;
}
- boolean isEmpty() {
+ @VisibleForTesting
+ public boolean isEmpty() {
return ordered.isEmpty();
}
- int size() {
+ @VisibleForTesting
+ public int size() {
return ordered.size();
}
- List<NodeElement> values() {
+ @VisibleForTesting
+ public List<NodeElement> values() {
return ordered;
}
diff --git a/compiler/java/com/google/dart/compiler/resolver/MixinScope.java b/compiler/java/com/google/dart/compiler/resolver/MixinScope.java
index aafa480..e40ff71 100644
--- a/compiler/java/com/google/dart/compiler/resolver/MixinScope.java
+++ b/compiler/java/com/google/dart/compiler/resolver/MixinScope.java
@@ -8,11 +8,11 @@
* Lexical scope corresponding to a mixin.
*/
class MixinScope extends Scope {
- private final ClassElement classElement;
+ private final ClassElement mixinElement;
- MixinScope(ClassElement classElement, Scope parent) {
- super(classElement.getName(), parent.getLibrary(), parent);
- this.classElement = classElement;
+ MixinScope(ClassElement mixinElement) {
+ super(mixinElement.getName(), mixinElement.getLibrary(), null);
+ this.mixinElement = mixinElement;
}
@Override
@@ -22,6 +22,6 @@
@Override
public Element findLocalElement(String name) {
- return Elements.findElement(classElement, name);
+ return Elements.findElement(mixinElement, name);
}
}
diff --git a/compiler/java/com/google/dart/compiler/resolver/TopLevelElementBuilder.java b/compiler/java/com/google/dart/compiler/resolver/TopLevelElementBuilder.java
index e97667b..891afb1 100644
--- a/compiler/java/com/google/dart/compiler/resolver/TopLevelElementBuilder.java
+++ b/compiler/java/com/google/dart/compiler/resolver/TopLevelElementBuilder.java
@@ -195,7 +195,7 @@
}
@VisibleForTesting
- void fillInUnitScope(DartUnit unit, DartCompilerListener listener, Scope scope,
+ public void fillInUnitScope(DartUnit unit, DartCompilerListener listener, Scope scope,
List<Element> exportedElements) {
for (DartNode node : unit.getTopLevelNodes()) {
if (node instanceof DartFieldDefinition) {
diff --git a/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java b/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java
index d1dad43..c9f05fd 100644
--- a/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java
+++ b/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java
@@ -4,6 +4,7 @@
package com.google.dart.compiler.type;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.google.dart.compiler.resolver.ClassElement;
@@ -22,7 +23,8 @@
/**
* An interface type.
*/
-class InterfaceTypeImplementation extends AbstractType implements InterfaceType {
+@VisibleForTesting
+public class InterfaceTypeImplementation extends AbstractType implements InterfaceType {
private final ClassElement element;
private final List<Type> arguments;
private final Map<ClassElement, Object> subClasses = new MapMaker().weakKeys().makeMap();
diff --git a/compiler/javatests/com/google/dart/compiler/TestAll.java b/compiler/javatests/com/google/dart/compiler/TestAll.java
new file mode 100644
index 0000000..249e544
--- /dev/null
+++ b/compiler/javatests/com/google/dart/compiler/TestAll.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, the Dart project authors.
+ *
+ * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.dart.compiler;
+
+import com.google.dart.compiler.ast.AstTests;
+import com.google.dart.compiler.common.CommonTests;
+import com.google.dart.compiler.end2end.End2EndTests;
+import com.google.dart.compiler.parser.ParserTests;
+import com.google.dart.compiler.resolver.ResolverTests;
+import com.google.dart.compiler.util.UtilTests;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class TestAll {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Tests in " + TestAll.class.getPackage().getName());
+
+ suite.addTest(CompilerTests.suite());
+ suite.addTest(AstTests.suite());
+ suite.addTest(CommonTests.suite());
+ suite.addTest(End2EndTests.suite());
+ suite.addTest(ParserTests.suite());
+ suite.addTest(ResolverTests.suite());
+ //suite.addTest(TypeTests.suite());
+ suite.addTest(UtilTests.suite());
+
+ return suite;
+ }
+
+}
diff --git a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
index ebf9907..d84e226 100644
--- a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
+++ b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
@@ -255,7 +255,7 @@
errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 10, 1, 27),
errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 11, 1, 17));
}
-
+
/**
* Type parameters should not conflict with formal parameters.
* <p>
@@ -433,7 +433,7 @@
libraryResult.getErrors(),
errEx(ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION, 6, 10, 8));
}
-
+
/**
* It is a compile-time error if the class C implements the operator ==.
* <p>
@@ -477,7 +477,7 @@
libraryResult.getErrors(),
errEx(TypeErrorCode.CASE_EXPRESSIONS_SHOULD_BE_SAME_TYPE, 5, 10, 3));
}
-
+
public void test_switchExpression_case_constLocalVariable() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -490,7 +490,7 @@
"");
assertErrors(libraryResult.getErrors());
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=2862
@@ -634,7 +634,7 @@
assertTrue(message.contains("void foo()"));
}
}
-
+
/**
* In contrast, if A is intended to be concrete, the checker should warn about all unimplemented
* methods, but allow clients to instantiate it freely.
@@ -791,7 +791,7 @@
libraryResult.getErrors(),
errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 5, 7, 1));
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=5327
@@ -998,7 +998,7 @@
errEx(TypeErrorCode.NO_SUCH_NAMED_PARAMETER, 15, 18, 4),
errEx(ResolverErrorCode.DUPLICATE_NAMED_ARGUMENT, 16, 25, 5));
}
-
+
/**
* Test that optional positional and named parameters are handled separately.
*/
@@ -1364,7 +1364,7 @@
libraryResult.getErrors(),
errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL, 4, 3, 1));
}
-
+
public void test_assignFinal_topLevelVariable() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -1377,7 +1377,7 @@
libraryResult.getErrors(),
errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL, 4, 3, 1));
}
-
+
public void test_assignFinal_instanceVariable_inConstructor() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -1407,7 +1407,7 @@
"");
assertErrors(libraryResult.getErrors());
}
-
+
public void test_constantEvaluationException_divZero() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -1473,7 +1473,7 @@
libraryResult.getErrors(),
errEx(ResolverErrorCode.NO_SUCH_TYPE_CONST, 3, 9, 10));
}
-
+
public void test_constInstanceCreation_noSuchConstructor() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -1486,7 +1486,7 @@
libraryResult.getErrors(),
errEx(ResolverErrorCode.NEW_EXPRESSION_NOT_CONST_CONSTRUCTOR, 4, 11, 10));
}
-
+
public void test_constInstanceCreation_notType() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -1669,7 +1669,7 @@
result.getErrors(),
errEx(ResolverErrorCode.CANNOT_OVERRIDE_METHOD_OPTIONAL_PARAMS, 5, 3, 3));
}
-
+
public void test_implementsAndOverrides_moreOptionalPositionalParameter() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"abstract class A {",
@@ -1725,7 +1725,7 @@
errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 11, 7, 5),
errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 12, 7, 7));
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=3183
@@ -1879,7 +1879,7 @@
"}");
assertErrors(result.getErrors());
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=7597
@@ -2067,7 +2067,7 @@
"");
assertErrors(result.getErrors());
}
-
+
public void test_inferredTypes_noMemberWarnings() throws Exception {
// disabled by default
{
@@ -2214,7 +2214,7 @@
assertInferredElementTypeString(testUnit, "v6", "Map<String, int>", INFERRED);
assertInferredElementTypeString(testUnit, "v7", "int", INFERRED);
}
-
+
public void test_typesPropagation_arrayAccess() throws Exception {
analyzeLibrary(
"class A {}",
@@ -2365,7 +2365,7 @@
assertInferredElementTypeString(testUnit, "v3", "int", INFERRED_EXACT);
assertInferredElementTypeString(testUnit, "v4", "Object", INFERRED);
}
-
+
public void test_typesPropagation_multiAssign_DoWhile() throws Exception {
analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -2449,7 +2449,7 @@
assertInferredElementTypeString(testUnit, "a1", "List<Object>", INFERRED);
assertInferredElementTypeString(testUnit, "b1", "List<Object>", INFERRED);
}
-
+
/**
* Prefer specific type, not "dynamic" type argument.
* <p>
@@ -2472,7 +2472,7 @@
assertInferredElementTypeString(testUnit, "a1", "List<String>", INFERRED);
assertInferredElementTypeString(testUnit, "b1", "List<String>", INFERRED);
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=4791
@@ -2943,7 +2943,7 @@
// we exited "if" Block, so "assert" may be was not executed, so we don't know type
assertInferredElementTypeString(testUnit, "v5", "dynamic", EXACT);
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=4410
@@ -3029,7 +3029,7 @@
assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT);
assertInferredElementTypeString(testUnit, "v2", "double", INFERRED_EXACT);
}
-
+
/**
* If field is not final, we don't know if is will be assigned somewhere else, may be even not in
* there same unit, so we cannot be sure about its type.
@@ -3063,7 +3063,7 @@
assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT);
assertInferredElementTypeString(testUnit, "v2", "double", INFERRED_EXACT);
}
-
+
/**
* If field is not final, we don't know if is will be assigned somewhere else, may be even not in
* there same unit, so we cannot be sure about its type.
@@ -3980,7 +3980,7 @@
errEx(TypeErrorCode.DEPRECATED_ELEMENT, 11, 7, 1),
errEx(TypeErrorCode.DEPRECATED_ELEMENT, 11, 9, 7));
}
-
+
public void test_metadata_resolving() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -4260,7 +4260,7 @@
assertHasFieldElement(binary.getArg1(), "A", "b");
}
}
-
+
/**
* Test for resolving variants of top-level property access and unary/binary expressions.
* <p>
@@ -4330,7 +4330,7 @@
FieldElement fieldElement = (FieldElement) element;
assertHasFieldElement(fieldElement, className, fieldName);
}
-
+
private static void assertHasFieldElement(FieldElement element, String className, String fieldName) {
EnclosingElement enclosingElement = element.getEnclosingElement();
String enclosingName;
@@ -4344,14 +4344,14 @@
String elementName = element.getName();
assertEquals(fieldName, elementName);
}
-
+
private static void assertHasMethodElement(DartNode node, String className, String methodName) {
Element element = node.getElement();
assertTrue("" + node + " " + element, element instanceof MethodElement);
MethodElement methodElement = (MethodElement) element;
assertMethodElement(methodElement, className, methodName);
}
-
+
private static void assertMethodElement(MethodElement element, String className, String methodName) {
EnclosingElement enclosingElement = element.getEnclosingElement();
String enclosingName;
@@ -4406,7 +4406,7 @@
errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 10, 3, 3),
errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 11, 3, 9));
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=3223
@@ -4420,7 +4420,7 @@
"}");
assertErrors(libraryResult.getErrors());
}
-
+
public void test_invokeNonFunction_getter() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -4632,7 +4632,7 @@
"");
assertErrors(result.getErrors());
}
-
+
/**
* There should be no problem reported, because assignment of "a" cascade to "b" with type "B"
* implicitly set type of "a" to "B".
@@ -4674,7 +4674,7 @@
"");
assertErrors(result.getErrors());
}
-
+
/**
* We assign "a" to field "Holder.b" of type "B", so implicitly set type of "a" to "B".
* <p>
@@ -4814,7 +4814,7 @@
errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 11, 3, 7),
errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 12, 11, 7));
}
-
+
/**
* If "unknown" is separate identifier, it is handled as "this.unknown", but "this" is not
* accessible in static context.
@@ -4854,7 +4854,7 @@
errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 4, 3, 7),
errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 5, 11, 7));
}
-
+
/**
* Unresolved constructor is warning.
* <p>
@@ -4877,7 +4877,7 @@
errEx(TypeErrorCode.NO_SUCH_TYPE, 7, 7, 1),
errEx(TypeErrorCode.NEW_EXPRESSION_NOT_CONSTRUCTOR, 7, 9, 17));
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=4383
@@ -4893,7 +4893,7 @@
libraryResult.getErrors(),
errEx(ResolverErrorCode.USE_ASSIGNMENT_ON_SETTER, 4, 3, 12));
}
-
+
/**
* Every {@link DartExpression} should have {@link Type} set. Just to don't guess this type at
* many other points in the Editor.
@@ -4908,6 +4908,7 @@
" process(aaa);",
"}");
testUnit.accept(new ASTVisitor<Void>() {
+ @Override
public Void visitIdentifier(DartIdentifier node) {
// ignore declaration
if (node.getParent() instanceof DartDeclaration) {
@@ -4923,7 +4924,7 @@
}
});
}
-
+
/**
* Every {@link DartExpression} should have {@link Type} set. Just to don't guess this type at
* many other points in the Editor.
@@ -4938,6 +4939,7 @@
" AAA.foo();",
"}");
testUnit.accept(new ASTVisitor<Void>() {
+ @Override
public Void visitIdentifier(DartIdentifier node) {
// ignore declaration
if (node.getParent() instanceof DartDeclaration) {
@@ -4976,7 +4978,7 @@
errEx(TypeErrorCode.USE_ASSIGNMENT_ON_SETTER, 5, 5, 12),
errEx(TypeErrorCode.USE_ASSIGNMENT_ON_SETTER, 10, 5, 12));
}
-
+
private abstract static class ArgumentsBindingTester {
static List<DartExpression> arguments;
void doTest(DartUnit unit) {
@@ -5034,7 +5036,7 @@
}
}.doTest(testUnit);
}
-
+
public void test_formalParameters_positional_named() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5097,7 +5099,7 @@
libraryResult.getErrors(),
errEx(ResolverErrorCode.CONSTRUCTOR_WITH_NAME_OF_MEMBER, 3, 3, 5));
}
-
+
/**
* It is a compile-time error if M is not the name of the immediately enclosing class.
* It is a static warning if M.id is not a constructor name.
@@ -5173,7 +5175,7 @@
assertSame(elementA.lookupConstructor("named"), nameElement);
}
}
-
+
public void test_redirectingFactoryConstructor_cycle() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5245,7 +5247,7 @@
"");
assertErrors(libraryResult.getErrors());
}
-
+
public void test_redirectingFactoryConstructor_shouldBeSubType3() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5259,7 +5261,7 @@
"");
assertErrors(libraryResult.getErrors());
}
-
+
public void test_redirectingFactoryConstructor_notSubType_typeParameterBounds() throws Exception {
AnalyzeLibraryResult libraryResult = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5463,7 +5465,7 @@
"");
assertErrors(result.getErrors(), errEx(ResolverErrorCode.DUPLICATE_IMPLEMENTS_TYPE, 3, 23, 1));
}
-
+
/**
* It is a compile-time error if the superclass of a class C appears in the implements clause of C.
* <p>
@@ -5477,7 +5479,7 @@
"");
assertErrors(result.getErrors(), errEx(ResolverErrorCode.SUPER_CLASS_IN_IMPLEMENTS, 3, 30, 1));
}
-
+
/**
* We should report only "no such type", but not duplicate.
* <p>
@@ -5562,7 +5564,7 @@
result.getErrors(),
errEx(ResolverErrorCode.DUPLICATE_INITIALIZATION, 4, 9, 5));
}
-
+
public void test_getOverridden_method() throws Exception {
analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5614,7 +5616,7 @@
assertClassMembers(superElements, "field A.foo");
}
}
-
+
public void test_getOverridden_field_withGetter() throws Exception {
analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5667,7 +5669,7 @@
Set<Element> superElements = node.getElement().getOverridden();
assertClassMembers(superElements, "field A.foo");
}
-
+
public void test_getOverridden_getter_withField() throws Exception {
analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5682,7 +5684,7 @@
Set<Element> superElements = node.getElement().getOverridden();
assertClassMembers(superElements, "field A.foo");
}
-
+
public void test_getOverridden_setter_withField() throws Exception {
analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5697,7 +5699,7 @@
Set<Element> superElements = node.getElement().getOverridden();
assertClassMembers(superElements, "field A.setter foo");
}
-
+
public void test_getOverridden_setter_withSetter() throws Exception {
analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5742,7 +5744,7 @@
"");
assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER, 6, 11, 1));
}
-
+
public void test_fieldAccess_notDeclared() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5754,7 +5756,7 @@
"");
assertErrors(result.getErrors(), errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 5, 11, 1));
}
-
+
public void test_fieldAssign_declared_noSetter() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5767,7 +5769,7 @@
"");
assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER, 6, 5, 1));
}
-
+
public void test_fieldAssign_notDeclared() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5792,7 +5794,7 @@
"");
assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER, 5, 13, 1));
}
-
+
public void test_field_unqualifiedAccess_write() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -5855,7 +5857,7 @@
result.getErrors(),
errEx(ResolverErrorCode.CANNOT_RESOLVE_METHOD, 4, 5, 3));
}
-
+
/**
* Developers unfamiliar with Dart frequently write (x/y).toInt() instead of x ~/ y. The editor
* should recognize that pattern.
@@ -5873,7 +5875,7 @@
"");
assertErrors(result.getErrors(), errEx(TypeErrorCode.USE_INTEGER_DIVISION, 5, 10, 15));
}
-
+
/**
* We need to report warning only when arguments are integers.
* <p>
@@ -5923,7 +5925,7 @@
"");
assertErrors(result.getErrors());
}
-
+
/**
* We should resolve sub-type member only if there is only sub-type with such member.
* <p>
@@ -5959,7 +5961,7 @@
// don't report error, because there IS member, we just don't know which one
assertErrors(result.getErrors());
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=6491
@@ -6027,7 +6029,7 @@
assertEquals("bbb", element.getName());
}
}
-
+
public void test_resolveRefInComment_ofMethod() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -6052,7 +6054,7 @@
assertEquals("bar", element.getName());
}
}
-
+
public void test_resolveNewInComment() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -6100,7 +6102,7 @@
errEx(ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, 11, 3, 1),
errEx(ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, 13, 7, 1));
}
-
+
public void test_notGenerativeConstructor_explicitNamed() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -6132,7 +6134,7 @@
assertErrors(result.getErrors(),
errEx(ResolverErrorCode.INITIALIZER_ONLY_IN_GENERATIVE_CONSTRUCTOR, 4, 9, 5));
}
-
+
public void test_variableReferencesItselfInInitializer() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -6287,7 +6289,7 @@
assertNotNull(expectedElement);
assertSame(nameInInvocation.getElement(), expectedElement);
}
-
+
public void test_mixin_1() throws Exception {
AnalyzeLibraryResult result = analyzeLibrary(
"// filler filler filler filler filler filler filler filler filler filler",
@@ -6303,7 +6305,7 @@
"");
assertErrors(result.getErrors());
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=8022
@@ -6321,7 +6323,7 @@
errEx(ResolverErrorCode.ONLY_OBJECT_MIXIN_SUPERCLASS, 4, 25, 1),
errEx(ResolverErrorCode.ONLY_OBJECT_MIXIN_SUPERCLASS, 5, 29, 1));
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=8025
@@ -6338,7 +6340,7 @@
errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_CONSTRUCTOR, 3, 25, 1),
errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_CONSTRUCTOR, 4, 29, 1));
}
-
+
/**
* <p>
* http://code.google.com/p/dart/issues/detail?id=8059
@@ -6355,7 +6357,24 @@
errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_SUPER, 3, 25, 1),
errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_SUPER, 4, 29, 1));
}
-
+
+ /**
+ * <p>
+ * http://code.google.com/p/dart/issues/detail?id=8705
+ */
+ public void test_mixin_useInScope() throws Exception {
+ AnalyzeLibraryResult result = analyzeLibrary(
+ "// filler filler filler filler filler filler filler filler filler filler",
+ "class M { foo() {} }",
+ "class A extends Object with M {",
+ " bar() {",
+ " foo();",
+ " }",
+ "}",
+ "");
+ assertErrors(result.getErrors());
+ }
+
/**
* 20130122. Currently it is not allowed to have mixin with superclass other than Object.
*/
@@ -6408,7 +6427,7 @@
errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 12, 9, 1),
errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 15, 5, 7));
}
-
+
/**
* 20130122. Currently it is not allowed to have mixin with superclass other than Object.
*/
@@ -6455,7 +6474,7 @@
result.getErrors(),
errEx(TypeErrorCode.NOT_A_MEMBER_OF, 13, 11, 2));
}
-
+
/**
* 20130122. Currently it is not allowed to have mixin with superclass other than Object.
*/
@@ -6490,5 +6509,5 @@
result.getErrors(),
errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_MIXINS, 2, 25, 1));
}
-
+
}
diff --git a/pkg/analyzer-experimental/lib/src/generated/ast.dart b/pkg/analyzer-experimental/lib/src/generated/ast.dart
index c7e03c7..3c842d7 100644
--- a/pkg/analyzer-experimental/lib/src/generated/ast.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/ast.dart
@@ -2408,7 +2408,7 @@
} else if (parserErrors.length == 0) {
return resolverErrors;
} else {
- List<AnalysisError> allErrors = new List<AnalysisError>.fixedLength(parserErrors.length + resolverErrors.length);
+ List<AnalysisError> allErrors = new List<AnalysisError>(parserErrors.length + resolverErrors.length);
System.arraycopy(parserErrors, 0, allErrors, 0, parserErrors.length);
System.arraycopy(resolverErrors, 0, allErrors, parserErrors.length, resolverErrors.length);
return allErrors;
@@ -4791,7 +4791,7 @@
*/
List<ParameterElement> get elements {
int count = _parameters.length;
- List<ParameterElement> types = new List<ParameterElement>.fixedLength(count);
+ List<ParameterElement> types = new List<ParameterElement>(count);
for (int i = 0; i < count; i++) {
types[i] = _parameters[i].element;
}
diff --git a/pkg/analyzer-experimental/lib/src/generated/element.dart b/pkg/analyzer-experimental/lib/src/generated/element.dart
index 407dd69..9be35da 100644
--- a/pkg/analyzer-experimental/lib/src/generated/element.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/element.dart
@@ -399,7 +399,7 @@
/**
* An empty array of export elements.
*/
- static List<ExportElement> EMPTY_ARRAY = new List<ExportElement>.fixedLength(0);
+ static List<ExportElement> EMPTY_ARRAY = new List<ExportElement>(0);
/**
* Return an array containing the combinators that were specified as part of the export directive
* in the order in which they were specified.
@@ -498,7 +498,7 @@
/**
* An empty array of import elements.
*/
- static List<ImportElement> EMPTY_ARRAY = new List<ImportElement>.fixedLength(0);
+ static List<ImportElement> EMPTY_ARRAY = new List<ImportElement>(0);
/**
* Return an array containing the combinators that were specified as part of the import directive
* in the order in which they were specified.
@@ -629,7 +629,7 @@
/**
* An empty array of namespace combinators.
*/
- static List<NamespaceCombinator> EMPTY_ARRAY = new List<NamespaceCombinator>.fixedLength(0);
+ static List<NamespaceCombinator> EMPTY_ARRAY = new List<NamespaceCombinator>(0);
}
/**
* The interface {@code ParameterElement} defines the behavior of elements representing a parameter
@@ -815,7 +815,7 @@
/**
* An empty array of annotations.
*/
- static List<AnnotationImpl> EMPTY_ARRAY = new List<AnnotationImpl>.fixedLength(0);
+ static List<AnnotationImpl> EMPTY_ARRAY = new List<AnnotationImpl>(0);
/**
* Initialize a newly created annotation.
* @param element the element representing the field, variable, or constructor being used as an
@@ -871,7 +871,7 @@
/**
* An empty array of type elements.
*/
- static List<ClassElement> EMPTY_ARRAY = new List<ClassElement>.fixedLength(0);
+ static List<ClassElement> EMPTY_ARRAY = new List<ClassElement>(0);
/**
* Initialize a newly created class element to have the given name.
* @param name the name of this element
@@ -1213,7 +1213,7 @@
/**
* An empty array of compilation unit elements.
*/
- static List<CompilationUnitElement> EMPTY_ARRAY = new List<CompilationUnitElement>.fixedLength(0);
+ static List<CompilationUnitElement> EMPTY_ARRAY = new List<CompilationUnitElement>(0);
/**
* Initialize a newly created compilation unit element to have the given name.
* @param name the name of this element
@@ -1332,7 +1332,7 @@
/**
* An empty array of constructor elements.
*/
- static List<ConstructorElement> EMPTY_ARRAY = new List<ConstructorElement>.fixedLength(0);
+ static List<ConstructorElement> EMPTY_ARRAY = new List<ConstructorElement>(0);
/**
* Initialize a newly created constructor element to have the given name.
* @param name the name of this element
@@ -1689,7 +1689,7 @@
/**
* An empty array of executable elements.
*/
- static List<ExecutableElement> EMPTY_ARRAY = new List<ExecutableElement>.fixedLength(0);
+ static List<ExecutableElement> EMPTY_ARRAY = new List<ExecutableElement>(0);
/**
* Initialize a newly created executable element to have the given name.
* @param name the name of this element
@@ -1858,7 +1858,7 @@
/**
* An empty array of field elements.
*/
- static List<FieldElement> EMPTY_ARRAY = new List<FieldElement>.fixedLength(0);
+ static List<FieldElement> EMPTY_ARRAY = new List<FieldElement>(0);
/**
* Initialize a newly created field element to have the given name.
* @param name the name of this element
@@ -1920,7 +1920,7 @@
/**
* An empty array of function elements.
*/
- static List<FunctionElement> EMPTY_ARRAY = new List<FunctionElement>.fixedLength(0);
+ static List<FunctionElement> EMPTY_ARRAY = new List<FunctionElement>(0);
/**
* Initialize a newly created synthetic function element.
*/
@@ -2009,7 +2009,7 @@
/**
* An empty array of HTML file elements.
*/
- static List<HtmlElement> EMPTY_ARRAY = new List<HtmlElement>.fixedLength(0);
+ static List<HtmlElement> EMPTY_ARRAY = new List<HtmlElement>(0);
/**
* The analysis context in which this library is defined.
*/
@@ -2129,7 +2129,7 @@
/**
* An empty array of label elements.
*/
- static List<LabelElement> EMPTY_ARRAY = new List<LabelElement>.fixedLength(0);
+ static List<LabelElement> EMPTY_ARRAY = new List<LabelElement>(0);
/**
* Initialize a newly created label element to have the given name.
* @param name the name of this element
@@ -2160,7 +2160,7 @@
/**
* An empty array of library elements.
*/
- static List<LibraryElement> EMPTY_ARRAY = new List<LibraryElement>.fixedLength(0);
+ static List<LibraryElement> EMPTY_ARRAY = new List<LibraryElement>(0);
/**
* The analysis context in which this library is defined.
*/
@@ -2316,7 +2316,7 @@
/**
* An empty array of method elements.
*/
- static List<MethodElement> EMPTY_ARRAY = new List<MethodElement>.fixedLength(0);
+ static List<MethodElement> EMPTY_ARRAY = new List<MethodElement>(0);
/**
* Initialize a newly created method element to have the given name.
* @param name the name of this element
@@ -2484,7 +2484,7 @@
/**
* An empty array of field elements.
*/
- static List<ParameterElement> EMPTY_ARRAY = new List<ParameterElement>.fixedLength(0);
+ static List<ParameterElement> EMPTY_ARRAY = new List<ParameterElement>(0);
/**
* Initialize a newly created parameter element to have the given name.
* @param name the name of this element
@@ -2528,7 +2528,7 @@
/**
* An empty array of prefix elements.
*/
- static List<PrefixElement> EMPTY_ARRAY = new List<PrefixElement>.fixedLength(0);
+ static List<PrefixElement> EMPTY_ARRAY = new List<PrefixElement>(0);
/**
* Initialize a newly created prefix element to have the given name.
* @param name the name of this element
@@ -2564,7 +2564,7 @@
/**
* An empty array of property accessor elements.
*/
- static List<PropertyAccessorElement> EMPTY_ARRAY = new List<PropertyAccessorElement>.fixedLength(0);
+ static List<PropertyAccessorElement> EMPTY_ARRAY = new List<PropertyAccessorElement>(0);
/**
* Initialize a newly created synthetic property accessor element to be associated with the given
* field.
@@ -2677,7 +2677,7 @@
/**
* An empty array of type alias elements.
*/
- static List<TypeAliasElement> EMPTY_ARRAY = new List<TypeAliasElement>.fixedLength(0);
+ static List<TypeAliasElement> EMPTY_ARRAY = new List<TypeAliasElement>(0);
/**
* Initialize a newly created type alias element to have the given name.
* @param name the name of this element
@@ -2776,7 +2776,7 @@
/**
* An empty array of type variable elements.
*/
- static List<TypeVariableElement> EMPTY_ARRAY = new List<TypeVariableElement>.fixedLength(0);
+ static List<TypeVariableElement> EMPTY_ARRAY = new List<TypeVariableElement>(0);
/**
* Initialize a newly created type variable element to have the given name.
* @param name the name of this element
@@ -2833,7 +2833,7 @@
/**
* An empty array of variable elements.
*/
- static List<VariableElement> EMPTY_ARRAY = new List<VariableElement>.fixedLength(0);
+ static List<VariableElement> EMPTY_ARRAY = new List<VariableElement>(0);
/**
* Initialize a newly created variable element to have the given name.
* @param name the name of this element
@@ -3244,7 +3244,7 @@
/**
* An empty array of types.
*/
- static List<InterfaceType> EMPTY_ARRAY = new List<InterfaceType>.fixedLength(0);
+ static List<InterfaceType> EMPTY_ARRAY = new List<InterfaceType>(0);
/**
* This method computes the longest inheritance path from some passed {@link Type} to Object.
* @param type the {@link Type} to compute the longest inheritance path of from the passed{@link Type} to Object
@@ -3367,7 +3367,7 @@
si.retainAll(sj);
Set<InterfaceType> s = si;
List<InterfaceType> sn = new List.from(s);
- List<int> depths = new List<int>.fixedLength(sn.length);
+ List<int> depths = new List<int>(sn.length);
int maxDepth = 0;
for (int n = 0; n < sn.length; n++) {
depths[n] = computeLongestInheritancePathToObject(sn[n]);
@@ -3557,7 +3557,7 @@
*/
static List<Type2> substitute(List<Type2> types, List<Type2> argumentTypes, List<Type2> parameterTypes) {
int length6 = types.length;
- List<Type2> newTypes = new List<Type2>.fixedLength(length6);
+ List<Type2> newTypes = new List<Type2>(length6);
for (int i = 0; i < length6; i++) {
newTypes[i] = types[i].substitute2(argumentTypes, parameterTypes);
}
@@ -3575,7 +3575,7 @@
/**
* An empty array of types.
*/
- static List<Type2> EMPTY_ARRAY = new List<Type2>.fixedLength(0);
+ static List<Type2> EMPTY_ARRAY = new List<Type2>(0);
/**
* Initialize a newly created type to be declared by the given element and to have the given name.
* @param element the element representing the declaration of the type
@@ -3621,7 +3621,7 @@
*/
static List<TypeVariableType> getTypes(List<TypeVariableElement> typeVariables) {
int count = typeVariables.length;
- List<TypeVariableType> types = new List<TypeVariableType>.fixedLength(count);
+ List<TypeVariableType> types = new List<TypeVariableType>(count);
for (int i = 0; i < count; i++) {
types[i] = typeVariables[i].type;
}
@@ -3967,4 +3967,4 @@
*/
abstract class VoidType implements Type2 {
VoidType substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes);
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/lib/src/generated/engine.dart b/pkg/analyzer-experimental/lib/src/generated/engine.dart
index 20ab924..b1f1265 100644
--- a/pkg/analyzer-experimental/lib/src/generated/engine.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/engine.dart
@@ -513,7 +513,7 @@
}
CompilationUnit resolve(Source source, LibraryElement library) => parse(source);
Token scan(Source source, AnalysisErrorListener errorListener) {
- List<Token> tokens = new List<Token>.fixedLength(1);
+ List<Token> tokens = new List<Token>(1);
Source_ContentReceiver receiver = new Source_ContentReceiver_1(source, errorListener, tokens);
try {
source.getContents(receiver);
@@ -657,4 +657,4 @@
}
void logInformation2(String message, Exception exception) {
}
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/lib/src/generated/error.dart b/pkg/analyzer-experimental/lib/src/generated/error.dart
index 17a0466..d107954 100644
--- a/pkg/analyzer-experimental/lib/src/generated/error.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/error.dart
@@ -120,7 +120,7 @@
/**
* An empty array of errors used when no errors are expected.
*/
- static List<AnalysisError> NO_ERRORS = new List<AnalysisError>.fixedLength(0);
+ static List<AnalysisError> NO_ERRORS = new List<AnalysisError>(0);
/**
* The error code associated with the error.
*/
@@ -226,4 +226,4 @@
builder.add(_message);
return builder.toString();
}
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/lib/src/generated/java_engine.dart b/pkg/analyzer-experimental/lib/src/generated/java_engine.dart
index 9254fdc..b1c131a4 100644
--- a/pkg/analyzer-experimental/lib/src/generated/java_engine.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/java_engine.dart
@@ -45,7 +45,7 @@
//}
class StringUtilities {
- static List<String> EMPTY_ARRAY = new List.fixedLength(0);
+ static List<String> EMPTY_ARRAY = new List(0);
}
File createFile(String path) => new File(path);
@@ -53,4 +53,4 @@
class OSUtilities {
static bool isWindows() => Platform.operatingSystem == 'windows';
static bool isMac() => Platform.operatingSystem == 'macos';
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/lib/src/generated/resolver.dart b/pkg/analyzer-experimental/lib/src/generated/resolver.dart
index ed1a436..2e576fc 100644
--- a/pkg/analyzer-experimental/lib/src/generated/resolver.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/resolver.dart
@@ -125,7 +125,7 @@
element.typeVariables = typeVariables4;
InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
int typeVariableCount = typeVariables4.length;
- List<Type2> typeArguments = new List<Type2>.fixedLength(typeVariableCount);
+ List<Type2> typeArguments = new List<Type2>(typeVariableCount);
for (int i = 0; i < typeVariableCount; i++) {
TypeVariableElementImpl typeVariable = (typeVariables4[i] as TypeVariableElementImpl);
TypeVariableTypeImpl typeArgument = new TypeVariableTypeImpl(typeVariable);
@@ -148,7 +148,7 @@
element.typeVariables = typeVariables5;
InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
int typeVariableCount = typeVariables5.length;
- List<Type2> typeArguments = new List<Type2>.fixedLength(typeVariableCount);
+ List<Type2> typeArguments = new List<Type2>(typeVariableCount);
for (int i = 0; i < typeVariableCount; i++) {
TypeVariableElementImpl typeVariable = (typeVariables5[i] as TypeVariableElementImpl);
TypeVariableTypeImpl typeArgument = new TypeVariableTypeImpl(typeVariable);
@@ -1996,7 +1996,7 @@
*/
List<String> getIdentifiers(NodeList<SimpleIdentifier> names) {
int count = names.length;
- List<String> identifiers = new List<String>.fixedLength(count);
+ List<String> identifiers = new List<String>(count);
for (int i = 0; i < count; i++) {
identifiers[i] = names[i].name;
}
@@ -3536,7 +3536,7 @@
int parameterCount = parameters.length;
if (parameterCount > 0) {
DynamicTypeImpl dynamicType = DynamicTypeImpl.instance;
- List<Type2> arguments = new List<Type2>.fixedLength(parameterCount);
+ List<Type2> arguments = new List<Type2>(parameterCount);
for (int i = 0; i < parameterCount; i++) {
arguments[i] = dynamicType;
}
diff --git a/pkg/analyzer-experimental/lib/src/generated/scanner.dart b/pkg/analyzer-experimental/lib/src/generated/scanner.dart
index 5251003..f2bd02d 100644
--- a/pkg/analyzer-experimental/lib/src/generated/scanner.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/scanner.dart
@@ -1771,7 +1771,7 @@
/**
* An empty transition table used by leaf states.
*/
- static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>.fixedLength(26);
+ static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
/**
* The initial state in the state machine.
*/
@@ -1789,7 +1789,7 @@
* @return the state that was created
*/
static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length12) {
- List<KeywordState> result = new List<KeywordState>.fixedLength(26);
+ List<KeywordState> result = new List<KeywordState>(26);
assert(length12 != 0);
int chunk = 0x0;
int chunkStart = -1;
@@ -1828,7 +1828,7 @@
*/
static KeywordState createKeywordStateTable() {
List<Keyword> values2 = Keyword.values;
- List<String> strings = new List<String>.fixedLength(values2.length);
+ List<String> strings = new List<String>(values2.length);
for (int i = 0; i < values2.length; i++) {
strings[i] = values2[i].syntax;
}
@@ -1867,4 +1867,4 @@
* @return the state that follows this state on a transition of the given character
*/
KeywordState next(int c) => _table[c - 0x61];
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/test/generated/element_test.dart b/pkg/analyzer-experimental/test/generated/element_test.dart
index 384d332..0610a55 100644
--- a/pkg/analyzer-experimental/test/generated/element_test.dart
+++ b/pkg/analyzer-experimental/test/generated/element_test.dart
@@ -613,8 +613,8 @@
element.type = type;
int count = parameterNames.length;
if (count > 0) {
- List<TypeVariableElementImpl> typeVariables = new List<TypeVariableElementImpl>.fixedLength(count);
- List<TypeVariableTypeImpl> typeArguments = new List<TypeVariableTypeImpl>.fixedLength(count);
+ List<TypeVariableElementImpl> typeVariables = new List<TypeVariableElementImpl>(count);
+ List<TypeVariableTypeImpl> typeArguments = new List<TypeVariableTypeImpl>(count);
for (int i = 0; i < count; i++) {
TypeVariableElementImpl variable = new TypeVariableElementImpl(ASTFactory.identifier2(parameterNames[i]));
typeVariables[i] = variable;
@@ -664,7 +664,7 @@
}
int count = normalParameters == null ? 0 : normalParameters.length;
if (count > 0) {
- List<InterfaceType> normalParameterTypes = new List<InterfaceType>.fixedLength(count);
+ List<InterfaceType> normalParameterTypes = new List<InterfaceType>(count);
for (int i = 0; i < count; i++) {
normalParameterTypes[i] = normalParameters[i].type;
}
@@ -672,7 +672,7 @@
}
count = optionalParameters == null ? 0 : optionalParameters.length;
if (count > 0) {
- List<InterfaceType> optionalParameterTypes = new List<InterfaceType>.fixedLength(count);
+ List<InterfaceType> optionalParameterTypes = new List<InterfaceType>(count);
for (int i = 0; i < count; i++) {
optionalParameterTypes[i] = optionalParameters[i].type;
}
@@ -689,7 +689,7 @@
}
int count = normalParameters == null ? 0 : normalParameters.length;
if (count > 0) {
- List<InterfaceType> normalParameterTypes = new List<InterfaceType>.fixedLength(count);
+ List<InterfaceType> normalParameterTypes = new List<InterfaceType>(count);
for (int i = 0; i < count; i++) {
normalParameterTypes[i] = normalParameters[i].type;
}
@@ -747,7 +747,7 @@
static MethodElement methodElement(String methodName, Type2 returnType9, List<Type2> argumentTypes) {
MethodElementImpl method = new MethodElementImpl.con1(ASTFactory.identifier2(methodName));
int count = argumentTypes.length;
- List<ParameterElement> parameters = new List<ParameterElement>.fixedLength(count);
+ List<ParameterElement> parameters = new List<ParameterElement>(count);
for (int i = 0; i < count; i++) {
ParameterElementImpl parameter = new ParameterElementImpl(ASTFactory.identifier2("a${i}"));
parameter.type = argumentTypes[i];
diff --git a/pkg/analyzer-experimental/test/generated/parser_test.dart b/pkg/analyzer-experimental/test/generated/parser_test.dart
index b8ba2d3..421feee 100644
--- a/pkg/analyzer-experimental/test/generated/parser_test.dart
+++ b/pkg/analyzer-experimental/test/generated/parser_test.dart
@@ -21,7 +21,7 @@
/**
* An empty array of objects used as arguments to zero-argument methods.
*/
- static List<Object> _EMPTY_ARGUMENTS = new List<Object>.fixedLength(0);
+ static List<Object> _EMPTY_ARGUMENTS = new List<Object>(0);
/**
* Invoke a parse method in {@link Parser}. The method is assumed to have the given number and
* type of parameters and will be invoked with the given arguments.
@@ -35,7 +35,7 @@
* @throws Exception if the method could not be invoked or throws an exception
* @throws AssertionFailedError if the result is {@code null} or if any errors are produced
*/
- static Object parse(String methodName, List<Object> objects, String source) => parse3(methodName, objects, source, new List<AnalysisError>.fixedLength(0));
+ static Object parse(String methodName, List<Object> objects, String source) => parse3(methodName, objects, source, new List<AnalysisError>(0));
/**
* Invoke a parse method in {@link Parser}. The method is assumed to have the given number and
* type of parameters and will be invoked with the given arguments.
@@ -2888,7 +2888,7 @@
JUnitTestCase.assertNotNull(functionBody.semicolon);
}
void test_parseFunctionDeclaration_function() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
FunctionDeclaration declaration = ParserTestCase.parse("parseFunctionDeclaration", <Object> [commentAndMetadata(comment, []), null, returnType, false], "f() {}");
JUnitTestCase.assertEquals(comment, declaration.documentationComment);
@@ -2901,7 +2901,7 @@
JUnitTestCase.assertNull(declaration.propertyKeyword);
}
void test_parseFunctionDeclaration_function_inStatement() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
FunctionDeclaration declaration = ParserTestCase.parse("parseFunctionDeclaration", <Object> [commentAndMetadata(comment, []), null, returnType, true], "f() {};");
JUnitTestCase.assertEquals(comment, declaration.documentationComment);
@@ -2914,7 +2914,7 @@
JUnitTestCase.assertNull(declaration.propertyKeyword);
}
void test_parseFunctionDeclaration_getter() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
FunctionDeclaration declaration = ParserTestCase.parse("parseFunctionDeclaration", <Object> [commentAndMetadata(comment, []), null, returnType, false], "get p => 0;");
JUnitTestCase.assertEquals(comment, declaration.documentationComment);
@@ -2927,7 +2927,7 @@
JUnitTestCase.assertNotNull(declaration.propertyKeyword);
}
void test_parseFunctionDeclaration_setter() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
FunctionDeclaration declaration = ParserTestCase.parse("parseFunctionDeclaration", <Object> [commentAndMetadata(comment, []), null, returnType, false], "set p(v) {}");
JUnitTestCase.assertEquals(comment, declaration.documentationComment);
@@ -2955,7 +2955,7 @@
JUnitTestCase.assertNotNull(expression.parameters);
}
void test_parseGetter_nonStatic() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
MethodDeclaration method = ParserTestCase.parse("parseGetter", <Object> [commentAndMetadata(comment, []), null, null, returnType], "get a;");
JUnitTestCase.assertNotNull(method.body);
@@ -2969,7 +2969,7 @@
JUnitTestCase.assertEquals(returnType, method.returnType);
}
void test_parseGetter_static() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
Token staticKeyword = TokenFactory.token(Keyword.STATIC);
TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
MethodDeclaration method = ParserTestCase.parse("parseGetter", <Object> [commentAndMetadata(comment, []), null, staticKeyword, returnType], "get a;");
@@ -3096,7 +3096,7 @@
JUnitTestCase.assertNotNull(directive.semicolon);
}
void test_parseInitializedIdentifierList_type() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
Token staticKeyword = TokenFactory.token(Keyword.STATIC);
TypeName type = new TypeName.full(new SimpleIdentifier.full(null), null);
FieldDeclaration declaration = ParserTestCase.parse("parseInitializedIdentifierList", <Object> [commentAndMetadata(comment, []), staticKeyword, null, type], "a = 1, b, c = 3;");
@@ -3110,7 +3110,7 @@
JUnitTestCase.assertNotNull(declaration.semicolon);
}
void test_parseInitializedIdentifierList_var() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
Token staticKeyword = TokenFactory.token(Keyword.STATIC);
Token varKeyword = TokenFactory.token(Keyword.VAR);
FieldDeclaration declaration = ParserTestCase.parse("parseInitializedIdentifierList", <Object> [commentAndMetadata(comment, []), staticKeyword, varKeyword, null], "a = 1, b, c = 3;");
@@ -3515,7 +3515,7 @@
JUnitTestCase.assertNotNull(parameter.identifier);
}
void test_parseOperator() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
MethodDeclaration method = ParserTestCase.parse("parseOperator", <Object> [commentAndMetadata(comment, []), null, returnType], "operator +(A a);");
JUnitTestCase.assertNotNull(method.body);
@@ -3759,7 +3759,7 @@
JUnitTestCase.assertNull(typeName.typeArguments);
}
void test_parseSetter_nonStatic() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
MethodDeclaration method = ParserTestCase.parse("parseSetter", <Object> [commentAndMetadata(comment, []), null, null, returnType], "set a(var x);");
JUnitTestCase.assertNotNull(method.body);
@@ -3773,7 +3773,7 @@
JUnitTestCase.assertEquals(returnType, method.returnType);
}
void test_parseSetter_static() {
- Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+ Comment comment = Comment.createDocumentationComment(new List<Token>(0));
Token staticKeyword = TokenFactory.token(Keyword.STATIC);
TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
MethodDeclaration method = ParserTestCase.parse("parseSetter", <Object> [commentAndMetadata(comment, []), null, staticKeyword, returnType], "set a(var x) {}");
diff --git a/pkg/analyzer-experimental/test/generated/scanner_test.dart b/pkg/analyzer-experimental/test/generated/scanner_test.dart
index 21ce0e8..8506de2 100644
--- a/pkg/analyzer-experimental/test/generated/scanner_test.dart
+++ b/pkg/analyzer-experimental/test/generated/scanner_test.dart
@@ -797,7 +797,7 @@
void test_KeywordState() {
List<Keyword> keywords = Keyword.values;
int keywordCount = keywords.length;
- List<String> textToTest = new List<String>.fixedLength(keywordCount * 3);
+ List<String> textToTest = new List<String>(keywordCount * 3);
for (int i = 0; i < keywordCount; i++) {
String syntax3 = keywords[i].syntax;
textToTest[i] = syntax3;
diff --git a/pkg/analyzer-experimental/test/generated/test_support.dart b/pkg/analyzer-experimental/test/generated/test_support.dart
index a559098..987ff38 100644
--- a/pkg/analyzer-experimental/test/generated/test_support.dart
+++ b/pkg/analyzer-experimental/test/generated/test_support.dart
@@ -37,7 +37,7 @@
/**
* An empty array of errors used when no errors are expected.
*/
- static List<AnalysisError> _NO_ERRORS = new List<AnalysisError>.fixedLength(0);
+ static List<AnalysisError> _NO_ERRORS = new List<AnalysisError>(0);
/**
* Initialize a newly created error listener to collect errors.
*/
@@ -351,7 +351,7 @@
JUnitTestCase.assertNotNull(actualValues);
int expectedLength = expectedValues.length;
JUnitTestCase.assertEquals(expectedLength, actualValues.length);
- List<bool> found = new List<bool>.fixedLength(expectedLength);
+ List<bool> found = new List<bool>(expectedLength);
for (int i = 0; i < expectedLength; i++) {
found[i] = false;
}
diff --git a/pkg/args/lib/args.dart b/pkg/args/lib/args.dart
index 29da1e2..6bdcb7e 100644
--- a/pkg/args/lib/args.dart
+++ b/pkg/args/lib/args.dart
@@ -397,6 +397,6 @@
}
/** Get the names of the options as a [Collection]. */
- Collection<String> get options => _options.keys.toList();
+ Collection<String> get options => _options.keys.toList(growable: false);
}
diff --git a/pkg/args/lib/src/usage.dart b/pkg/args/lib/src/usage.dart
index b83a2d5..45893a5 100644
--- a/pkg/args/lib/src/usage.dart
+++ b/pkg/args/lib/src/usage.dart
@@ -73,7 +73,7 @@
if (option.help != null) write(2, option.help);
if (option.allowedHelp != null) {
- var allowedNames = option.allowedHelp.keys.toList();
+ var allowedNames = option.allowedHelp.keys.toList(growable: false);
allowedNames.sort();
newline();
for (var name in allowedNames) {
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
index 2aad272..02eb213 100644
--- a/pkg/fixnum/lib/src/int32.dart
+++ b/pkg/fixnum/lib/src/int32.dart
@@ -38,12 +38,12 @@
static int32 TWO = const int32._internal(2);
// Hex digit char codes
- static const int _CC_0 = 48; // '0'.charCodeAt(0)
- static const int _CC_9 = 57; // '9'.charCodeAt(0)
- static const int _CC_a = 97; // 'a'.charCodeAt(0)
- static const int _CC_z = 122; // 'z'.charCodeAt(0)
- static const int _CC_A = 65; // 'A'.charCodeAt(0)
- static const int _CC_Z = 90; // 'Z'.charCodeAt(0)
+ static const int _CC_0 = 48; // '0'.codeUnitAt(0)
+ static const int _CC_9 = 57; // '9'.codeUnitAt(0)
+ static const int _CC_a = 97; // 'a'.codeUnitAt(0)
+ static const int _CC_z = 122; // 'z'.codeUnitAt(0)
+ static const int _CC_A = 65; // 'A'.codeUnitAt(0)
+ static const int _CC_Z = 90; // 'Z'.codeUnitAt(0)
static int _decodeHex(int c) {
if (c >= _CC_0 && c <= _CC_9) {
@@ -68,10 +68,10 @@
}
int32 x = ZERO;
for (int i = 0; i < s.length; i++) {
- int c = s.charCodeAt(i);
+ int c = s.codeUnitAt(i);
int digit = _decodeHex(c);
if (digit < 0 || digit >= radix) {
- throw new Exception("Non-radix char code: $c");
+ throw new Exception("Non-radix code unit: $c");
}
x = (x * radix) + digit;
}
@@ -288,7 +288,7 @@
return _i == _convert(other);
}
- int compareTo(other) {
+ int compareTo(Comparable other) {
if (other is int64) {
return this.toInt64().compareTo(other);
}
@@ -338,7 +338,7 @@
int numberOfTrailingZeros() => _numberOfTrailingZeros(_i);
List<int> toBytes() {
- List<int> result = new List<int>.fixedLength(4);
+ List<int> result = new List<int>(4);
result[0] = _i & 0xff;
result[1] = (_i >> 8) & 0xff;
result[2] = (_i >> 16) & 0xff;
diff --git a/pkg/fixnum/lib/src/int64.dart b/pkg/fixnum/lib/src/int64.dart
index b2a263f..81607de 100644
--- a/pkg/fixnum/lib/src/int64.dart
+++ b/pkg/fixnum/lib/src/int64.dart
@@ -130,7 +130,7 @@
i++;
}
for (; i < s.length; i++) {
- int c = s.charCodeAt(i);
+ int c = s.codeUnitAt(i);
int digit = int32._decodeHex(c);
if (digit < 0 || digit >= radix) {
throw new Exception("Non-radix char code: $c");
@@ -625,7 +625,7 @@
}
List<int> toBytes() {
- List<int> result = new List<int>.fixedLength(8);
+ List<int> result = new List<int>(8);
result[0] = _l & 0xff;
result[1] = (_l >> 8) & 0xff;
result[2] = ((_m << 6) & 0xfc) | ((_l >> 16) & 0x3f);
diff --git a/pkg/fixnum/test/int_64_vm_test.dart b/pkg/fixnum/test/int_64_vm_test.dart
index 03ce112..ee1fd74 100644
--- a/pkg/fixnum/test/int_64_vm_test.dart
+++ b/pkg/fixnum/test/int_64_vm_test.dart
@@ -174,7 +174,7 @@
testSet.add(new int64.fromInt(pow));
}
- TEST_VALUES = new List<int64>.fixedLength(testSet.length);
+ TEST_VALUES = new List<int64>(testSet.length);
int index = 0;
for (int64 val in testSet) {
TEST_VALUES[index++] = val;
diff --git a/pkg/http/lib/src/byte_stream.dart b/pkg/http/lib/src/byte_stream.dart
index f6d87ff..96af221 100644
--- a/pkg/http/lib/src/byte_stream.dart
+++ b/pkg/http/lib/src/byte_stream.dart
@@ -35,5 +35,5 @@
toBytes().then((bytes) => decodeString(bytes, encoding));
Stream<String> toStringStream([Encoding encoding=Encoding.UTF_8]) =>
- wrapStream(map((bytes) => decodeString(bytes, encoding)));
+ map((bytes) => decodeString(bytes, encoding));
}
diff --git a/pkg/http/lib/src/multipart_file.dart b/pkg/http/lib/src/multipart_file.dart
index 50f4704..aa30fc3 100644
--- a/pkg/http/lib/src/multipart_file.dart
+++ b/pkg/http/lib/src/multipart_file.dart
@@ -7,6 +7,8 @@
import 'dart:async';
import 'dart:io';
+import '../../../../pkg/pathos/lib/path.dart' as path;
+
import 'byte_stream.dart';
import 'utils.dart';
@@ -78,14 +80,15 @@
}
// TODO(nweiz): Infer the content-type from the filename.
- /// Creates a new [MultipartFile] from a [File].
+ /// Creates a new [MultipartFile] from a path to a file on disk.
///
- /// [filename] defaults to the name of the file on disk. [contentType]
- /// currently defaults to `application/octet-stream`, but in the future may be
- /// inferred from [filename].
- static Future<MultipartFile> fromFile(String field, File file,
+ /// [filename] defaults to the basename of [filePath]. [contentType] currently
+ /// defaults to `application/octet-stream`, but in the future may be inferred
+ /// from [filename].
+ static Future<MultipartFile> fromPath(String field, String filePath,
{String filename, ContentType contentType}) {
- if (filename == null) filename = new Path(file.name).filename;
+ if (filename == null) filename = path.basename(filePath);
+ var file = new File(filePath);
return file.length().then((length) {
var stream = new ByteStream(file.openRead());
return new MultipartFile(field, stream, length,
diff --git a/pkg/http/lib/src/multipart_request.dart b/pkg/http/lib/src/multipart_request.dart
index b89c839..0855063 100644
--- a/pkg/http/lib/src/multipart_request.dart
+++ b/pkg/http/lib/src/multipart_request.dart
@@ -98,7 +98,7 @@
void writeAscii(String string) {
assert(isPlainAscii(string));
- controller.add(string.charCodes);
+ controller.add(string.codeUnits);
}
writeUtf8(String string) => controller.add(encodeUtf8(string));
@@ -165,7 +165,7 @@
/// [length].
String _boundaryString(int length) {
var prefix = "dart-http-boundary-";
- var list = new List<int>.fixedLength(length - prefix.length);
+ var list = new List<int>(length - prefix.length);
for (var i = 0; i < list.length; i++) {
list[i] = _BOUNDARY_CHARACTERS[
_random.nextInt(_BOUNDARY_CHARACTERS.length)];
diff --git a/pkg/http/lib/src/utils.dart b/pkg/http/lib/src/utils.dart
index 739a567..65c4799 100644
--- a/pkg/http/lib/src/utils.dart
+++ b/pkg/http/lib/src/utils.dart
@@ -111,7 +111,7 @@
/// Converts [string] into a byte array according to [encoding].
List<int> encodeString(String string, Encoding encoding) {
// TODO(nweiz): implement this once issue 6284 is fixed.
- return string.charCodes;
+ return string.codeUnits;
}
/// A regular expression that matches strings that are composed entirely of
@@ -149,65 +149,6 @@
return pair.last;
}
-// TODO(nweiz): remove this once issue 7785 is fixed.
-/// Wraps [stream] in a single-subscription [ByteStream] that emits the same
-/// data.
-ByteStream wrapInputStream(InputStream stream) {
- if (stream.closed) return emptyStream;
-
- var controller = new StreamController();
- stream.onClosed = controller.close;
- stream.onData = () => controller.add(stream.read());
- stream.onError = (e) => controller.signalError(new AsyncError(e));
- return new ByteStream(controller.stream);
-}
-
-// TODO(nweiz): remove this once issue 7785 is fixed.
-/// Wraps [stream] in a [StreamConsumer] so that [Stream]s can by piped into it
-/// using [Stream.pipe].
-StreamConsumer<List<int>, dynamic> wrapOutputStream(OutputStream stream) =>
- new _OutputStreamConsumer(stream);
-
-/// A [StreamConsumer] that pipes data into an [OutputStream].
-class _OutputStreamConsumer implements StreamConsumer<List<int>, dynamic> {
- final OutputStream _outputStream;
-
- _OutputStreamConsumer(this._outputStream);
-
- Future consume(Stream<List<int>> stream) {
- // TODO(nweiz): we have to manually keep track of whether or not the
- // completer has completed since the output stream could signal an error
- // after close() has been called but before it has shut down internally. See
- // the following TODO.
- var completed = false;
- var completer = new Completer();
- stream.listen((data) {
- // Writing empty data to a closed stream can cause errors.
- if (data.isEmpty) return;
-
- // TODO(nweiz): remove this try/catch when issue 7836 is fixed.
- try {
- _outputStream.write(data);
- } catch (e, stack) {
- if (!completed) completer.completeError(e, stack);
- completed = true;
- }
- }, onDone: () => _outputStream.close());
-
- _outputStream.onError = (e) {
- if (!completed) completer.completeError(e);
- completed = true;
- };
-
- _outputStream.onClosed = () {
- if (!completed) completer.complete();
- completed = true;
- };
-
- return completer.future;
- }
-}
-
// TODO(nweiz): remove this when issue 7786 is fixed.
/// Pipes all data and errors from [stream] into [sink]. When [stream] is done,
/// [sink] is closed and the returned [Future] is completed.
@@ -309,16 +250,3 @@
}
return nextElement(null);
}
-
-// TODO(nweiz): remove this when issue 8310 is fixed.
-/// Returns a [Stream] identical to [stream], but piped through a new
-/// [StreamController]. This exists to work around issue 8310.
-Stream wrapStream(Stream stream) {
- var controller = stream.isBroadcast
- ? new StreamController.broadcast()
- : new StreamController();
- stream.listen(controller.add,
- onError: (e) => controller.signalError(e),
- onDone: controller.close);
- return controller.stream;
-}
diff --git a/pkg/http/test/client_test.dart b/pkg/http/test/client_test.dart
index e101f28..27cd0b9 100644
--- a/pkg/http/test/client_test.dart
+++ b/pkg/http/test/client_test.dart
@@ -8,8 +8,8 @@
import 'dart:uri';
import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/src/utils.dart';
+import '../lib/src/utils.dart';
+import '../lib/http.dart' as http;
import 'utils.dart';
void main() {
@@ -41,7 +41,7 @@
'body': '{"hello": "world"}'
}))));
- request.sink.add('{"hello": "world"}'.charCodes);
+ request.sink.add('{"hello": "world"}'.codeUnits);
request.sink.close();
}), completes);
});
@@ -56,7 +56,7 @@
expect(client.send(request), throwsSocketIOException);
- request.sink.add('{"hello": "world"}'.charCodes);
+ request.sink.add('{"hello": "world"}'.codeUnits);
request.sink.close();
}), completes);
});
diff --git a/pkg/http/test/http_test.dart b/pkg/http/test/http_test.dart
index 9c567cf..1fc7f57 100644
--- a/pkg/http/test/http_test.dart
+++ b/pkg/http/test/http_test.dart
@@ -7,7 +7,7 @@
import 'dart:io';
import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
+import '../lib/http.dart' as http;
import 'utils.dart';
main() {
diff --git a/pkg/http/test/mock_client_test.dart b/pkg/http/test/mock_client_test.dart
index 59be93f..0c3c578 100644
--- a/pkg/http/test/mock_client_test.dart
+++ b/pkg/http/test/mock_client_test.dart
@@ -10,9 +10,9 @@
import 'dart:uri';
import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/testing.dart';
-import 'package:http/src/utils.dart';
+import '../lib/http.dart' as http;
+import '../lib/testing.dart';
+import '../lib/src/utils.dart';
import 'utils.dart';
void main() {
@@ -37,7 +37,7 @@
return bodyStream.bytesToString().then((bodyString) {
var controller = new StreamController<List<int>>();
async.then((_) {
- controller.add('Request body was "$bodyString"'.charCodes);
+ controller.add('Request body was "$bodyString"'.codeUnits);
controller.close();
});
diff --git a/pkg/http/test/multipart_test.dart b/pkg/http/test/multipart_test.dart
index 64fd330..c3c3dd9 100644
--- a/pkg/http/test/multipart_test.dart
+++ b/pkg/http/test/multipart_test.dart
@@ -8,11 +8,10 @@
import 'dart:io';
import 'dart:utf';
-// TODO(nweiz): get rid of this import before packaging this
-import '../../../tests/utils/test_utils.dart';
import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/src/utils.dart';
+import '../../pathos/lib/path.dart' as path;
+import '../lib/http.dart' as http;
+import '../lib/src/utils.dart';
import 'utils.dart';
@@ -204,4 +203,33 @@
--{{boundary}}--
'''));
});
+
+ group('in a temp directory', () {
+ var tempDir;
+ setUp(() {
+ tempDir = new Directory('').createTempSync();
+ });
+
+ tearDown(() => tempDir.deleteSync(recursive: true));
+
+ test('with a file from disk', () {
+ expect(new Future.of(() {
+ var filePath = path.join(tempDir.path, 'test-file');
+ new File(filePath).writeAsStringSync('hello');
+ return http.MultipartFile.fromPath('file', filePath);
+ }).then((file) {
+ var request = new http.MultipartRequest('POST', dummyUrl);
+ request.files.add(file);
+
+ expect(request, bodyMatches('''
+ --{{boundary}}
+ content-type: application/octet-stream
+ content-disposition: form-data; name="file"; filename="test-file"
+
+ hello
+ --{{boundary}}--
+ '''));
+ }), completes);
+ });
+ });
}
diff --git a/pkg/http/test/request_test.dart b/pkg/http/test/request_test.dart
index 1f009b9..551f694 100644
--- a/pkg/http/test/request_test.dart
+++ b/pkg/http/test/request_test.dart
@@ -7,8 +7,8 @@
import 'dart:io';
import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/src/utils.dart';
+import '../lib/http.dart' as http;
+import '../lib/src/utils.dart';
import 'utils.dart';
void main() {
diff --git a/pkg/http/test/response_test.dart b/pkg/http/test/response_test.dart
index 252df4a..097e0f8 100644
--- a/pkg/http/test/response_test.dart
+++ b/pkg/http/test/response_test.dart
@@ -8,7 +8,7 @@
import 'dart:io';
import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
+import '../lib/http.dart' as http;
void main() {
group('()', () {
diff --git a/pkg/http/test/streamed_request_test.dart b/pkg/http/test/streamed_request_test.dart
index 4ded631..6a62bdc 100644
--- a/pkg/http/test/streamed_request_test.dart
+++ b/pkg/http/test/streamed_request_test.dart
@@ -7,7 +7,7 @@
import 'dart:io';
import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
+import '../lib/http.dart' as http;
import 'utils.dart';
void main() {
diff --git a/pkg/http/test/utils.dart b/pkg/http/test/utils.dart
index 606bb77..8b404a5 100644
--- a/pkg/http/test/utils.dart
+++ b/pkg/http/test/utils.dart
@@ -10,9 +10,9 @@
import 'dart:uri';
import 'package:unittest/unittest.dart';
-import 'package:http/src/byte_stream.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/src/utils.dart';
+import '../lib/src/byte_stream.dart';
+import '../lib/http.dart' as http;
+import '../lib/src/utils.dart';
/// The current server instance.
HttpServer _server;
@@ -109,6 +109,33 @@
_server = null;
}
+/// Removes eight spaces of leading indentation from a multiline string.
+///
+/// Note that this is very sensitive to how the literals are styled. They should
+/// be:
+/// '''
+/// Text starts on own line. Lines up with subsequent lines.
+/// Lines are indented exactly 8 characters from the left margin.
+/// Close is on the same line.'''
+///
+/// This does nothing if text is only a single line.
+// TODO(nweiz): Make this auto-detect the indentation level from the first
+// non-whitespace line.
+String cleanUpLiteral(String text) {
+ var lines = text.split('\n');
+ if (lines.length <= 1) return text;
+
+ for (var j = 0; j < lines.length; j++) {
+ if (lines[j].length > 8) {
+ lines[j] = lines[j].substring(8, lines[j].length);
+ } else {
+ lines[j] = '';
+ }
+ }
+
+ return lines.join('\n');
+}
+
/// A matcher that matches JSON that parses to a value that matches the inner
/// matcher.
Matcher parse(matcher) => new _Parse(matcher);
diff --git a/pkg/intl/lib/bidi_utils.dart b/pkg/intl/lib/bidi_utils.dart
index 35d62b7..e4599da 100644
--- a/pkg/intl/lib/bidi_utils.dart
+++ b/pkg/intl/lib/bidi_utils.dart
@@ -244,11 +244,11 @@
var startIndex = 0;
Match match = new RegExp('<\\w+').firstMatch(html);
if (match != null) {
- buffer..add(html.substring(startIndex, match.end))
- ..add(' dir=$direction');
+ buffer..write(html.substring(startIndex, match.end))
+ ..write(' dir=$direction');
startIndex = match.end;
}
- return (buffer..add(html.substring(startIndex))).toString();
+ return (buffer..write(html.substring(startIndex))).toString();
}
// '\n' is important for FF so that it won't incorrectly merge span groups.
return '\n<span dir=$direction>$html</span>';
@@ -298,13 +298,13 @@
var startIndex = 0;
Iterable matches = regexp.allMatches(str);
for (Match match in matches) {
- buffer..add(str.substring(startIndex, match.start))
- ..add(before)
- ..add(str.substring(match.start, match.end))
- ..add(after);
+ buffer..write(str.substring(startIndex, match.start))
+ ..write(before)
+ ..write(str.substring(match.start, match.end))
+ ..write(after);
startIndex = match.end;
}
- return (buffer..add(str.substring(startIndex))).toString();
+ return (buffer..write(str.substring(startIndex))).toString();
}
/**
@@ -359,19 +359,19 @@
static String normalizeHebrewQuote(String str) {
StringBuffer buf = new StringBuffer();
if (str.length > 0) {
- buf.add(str.substring(0, 1));
+ buf.write(str.substring(0, 1));
}
// Start at 1 because we're looking for the patterns [\u0591-\u05f2])" or
// [\u0591-\u05f2]'.
for (int i = 1; i < str.length; i++) {
if (str.substring(i, i+1) == '"'
&& new RegExp('[\u0591-\u05f2]').hasMatch(str.substring(i-1, i))) {
- buf.add('\u05f4');
+ buf.write('\u05f4');
} else if (str.substring(i, i+1) == "'"
&& new RegExp('[\u0591-\u05f2]').hasMatch(str.substring(i-1, i))) {
- buf.add('\u05f3');
+ buf.write('\u05f3');
} else {
- buf.add(str.substring(i, i+1));
+ buf.write(str.substring(i, i+1));
}
}
return buf.toString();
diff --git a/pkg/intl/lib/date_format.dart b/pkg/intl/lib/date_format.dart
index 4c9ee28..a0d964f 100644
--- a/pkg/intl/lib/date_format.dart
+++ b/pkg/intl/lib/date_format.dart
@@ -225,7 +225,7 @@
String format(DateTime date) {
// TODO(efortuna): read optional TimeZone argument (or similar)?
var result = new StringBuffer();
- _formatFields.forEach((field) => result.add(field.format(date)));
+ _formatFields.forEach((field) => result.write(field.format(date)));
return result.toString();
}
diff --git a/pkg/intl/lib/number_format.dart b/pkg/intl/lib/number_format.dart
index 76f8afa..567fb99 100644
--- a/pkg/intl/lib/number_format.dart
+++ b/pkg/intl/lib/number_format.dart
@@ -166,10 +166,10 @@
// to be printed as an integer and pad the remainder with zeros.
var paddingDigits = new StringBuffer();
while ((intValue & 0x7fffffff) != intValue) {
- paddingDigits.add(symbols.ZERO_DIGIT);
+ paddingDigits.write(symbols.ZERO_DIGIT);
intValue = intValue ~/ 10;
}
- var integerDigits = "${intValue}${paddingDigits}".charCodes;
+ var integerDigits = "${intValue}${paddingDigits}".codeUnits;
var digitLength = integerDigits.length;
if (_hasPrintableIntegerPart(intValue)) {
@@ -191,7 +191,7 @@
* Format the part after the decimal place in a fixed point number.
*/
void _formatFractionPart(String fractionPart) {
- var fractionCodes = fractionPart.charCodes;
+ var fractionCodes = fractionPart.codeUnits;
var fractionLength = fractionPart.length;
while (fractionPart[fractionLength - 1] == '0' &&
fractionLength > _minimumFractionDigits + 1) {
@@ -227,17 +227,17 @@
/** A group of methods that provide support for writing digits and other
* required characters into [_buffer] easily.
*/
- void _add(String x) { _buffer.add(x);}
- void _addCharCode(int x) { _buffer.addCharCode(x); }
- void _addZero() { _buffer.add(symbols.ZERO_DIGIT); }
- void _addDigit(int x) { _buffer.addCharCode(_localeZero + x - _zero); }
+ void _add(String x) { _buffer.write(x);}
+ void _addCharCode(int x) { _buffer.writeCharCode(x); }
+ void _addZero() { _buffer.write(symbols.ZERO_DIGIT); }
+ void _addDigit(int x) { _buffer.writeCharCode(_localeZero + x - _zero); }
/** Print padding up to [numberOfDigits] above what's included in [basic]. */
void _pad(int numberOfDigits, [String basic = '']) {
for (var i = 0; i < numberOfDigits - basic.length; i++) {
_add(symbols.ZERO_DIGIT);
}
- for (var x in basic.charCodes) {
+ for (var x in basic.codeUnits) {
_addDigit(x);
}
}
diff --git a/pkg/intl/lib/src/date_format_field.dart b/pkg/intl/lib/src/date_format_field.dart
index 1d37490..843b6dc 100644
--- a/pkg/intl/lib/src/date_format_field.dart
+++ b/pkg/intl/lib/src/date_format_field.dart
@@ -398,9 +398,9 @@
if (basicString.length >= width) return basicString;
var buffer = new StringBuffer();
for (var i = 0; i < width - basicString.length; i++) {
- buffer.add('0');
+ buffer.write('0');
}
- buffer.add(basicString);
+ buffer.write(basicString);
return buffer.toString();
}
}
diff --git a/pkg/logging/lib/logging.dart b/pkg/logging/lib/logging.dart
index 935b3ae..1bf617c 100644
--- a/pkg/logging/lib/logging.dart
+++ b/pkg/logging/lib/logging.dart
@@ -9,6 +9,10 @@
*/
library logging;
+import 'dart:async';
+
+import '../../meta/lib/meta.dart';
+
/**
* Whether to allow fine-grain logging and configuration of loggers in a
* hierarchy. When false, all logging is merged in the root logger.
@@ -43,8 +47,11 @@
/** Children in the hierarchy of loggers, indexed by their simple names. */
Map<String, Logger> children;
- /** Handlers used to process log entries in this logger. */
- List<LoggerHandler> _handlers;
+ /** Controller used to notify when log entries are added to this logger. */
+ StreamController<LogRecord> _controller;
+
+ // TODO(sigmund): remove together with the deprecated [on] API.
+ Map<LoggerHandler, StreamSubscription> _deprecatedSubscriptions;
/**
* Singleton constructor. Calling `new Logger(name)` will return the same
@@ -91,7 +98,7 @@
}
/** Override the level for this particular [Logger] and its children. */
- set level(value) {
+ set level(Level value) {
if (hierarchicalLoggingEnabled && parent != null) {
_level = value;
} else {
@@ -109,38 +116,27 @@
* by adding a [LoggerHandler] to an event from the event manager, for
* instance:
* logger.on.record.add((record) { ... });
+ *
+ * This API is Deprecated. Use [onRecord] instead.
*/
+ @deprecated
LoggerEvents get on => new LoggerEvents(this);
- /** Adds a handler to listen whenever a log record is added to this logger. */
- void _addHandler(LoggerHandler handler) {
+ /**
+ * Returns an stream of messages added to this [Logger]. You can listen for
+ * messages using the standard stream APIs, for instance:
+ * logger.onRecord.listen((record) { ... });
+ */
+ Stream<LogRecord> get onRecord => _getStream();
+
+ void clearListeners() {
if (hierarchicalLoggingEnabled || parent == null) {
- if (_handlers == null) {
- _handlers = new List<LoggerHandler>();
+ if (_controller != null) {
+ _controller.close();
+ _controller = null;
}
- _handlers.add(handler);
} else {
- root._addHandler(handler);
- }
- }
-
- /** Remove a previously added handler. */
- void _removeHandler(LoggerHandler handler) {
- if (hierarchicalLoggingEnabled || parent == null) {
- if (_handlers == null) return;
- int index = _handlers.indexOf(handler);
- if (index != -1) _handlers.removeRange(index, 1);
- } else {
- root._removeHandler(handler);
- }
- }
-
- /** Removes all handlers previously added to this logger. */
- void _clearHandlers() {
- if (hierarchicalLoggingEnabled || parent == null) {
- _handlers = null;
- } else {
- root._clearHandlers();
+ root.clearListeners();
}
}
@@ -194,14 +190,46 @@
/** Log message at level [Level.SHOUT]. */
void shout(String message) => log(Level.SHOUT, message);
+ Stream<LogRecord> _getStream() {
+ if (hierarchicalLoggingEnabled || parent == null) {
+ if (_controller == null) {
+ _controller = new StreamController<LogRecord>.broadcast();
+ }
+ return _controller.stream;
+ } else {
+ return root._getStream();
+ }
+ }
+
+ /** Adds a handler to listen whenever a log record is added to this logger. */
+ void _addHandler(LoggerHandler handler) {
+ if (_deprecatedSubscriptions == null) {
+ _deprecatedSubscriptions = new Map<LoggerHandler, StreamSubscription>();
+ }
+
+ _deprecatedSubscriptions[handler] = onRecord.listen(handler);
+ }
+
+ void _removeHandler(LoggerHandler handler) {
+ if (_deprecatedSubscriptions != null) {
+ var sub = _deprecatedSubscriptions.remove(handler);
+ if (sub != null) {
+ sub.cancel();
+ }
+ if (_deprecatedSubscriptions.isEmpty) {
+ _deprecatedSubscriptions = null;
+ }
+ }
+ }
+
void _publish(LogRecord record) {
- if (_handlers != null) {
- _handlers.forEach((h) => h(record));
+ if (_controller != null) {
+ _controller.add(record);
}
}
/** Top-level root [Logger]. */
- static get root => new Logger('');
+ static Logger get root => new Logger('');
/** All [Logger]s in the system. */
static Map<String, Logger> _loggers;
@@ -231,7 +259,7 @@
void add(LoggerHandler handler) => _logger._addHandler(handler);
void remove(LoggerHandler handler) => _logger._removeHandler(handler);
- void clear() => _logger._clearHandlers();
+ void clear() => _logger.clearListeners();
}
diff --git a/pkg/logging/pubspec.yaml b/pkg/logging/pubspec.yaml
index 208667b..6e6a540 100644
--- a/pkg/logging/pubspec.yaml
+++ b/pkg/logging/pubspec.yaml
@@ -8,5 +8,7 @@
Logger and java.util.logging.Logger.
dependencies:
+ meta:
+ sdk: meta
unittest:
sdk: unittest
diff --git a/pkg/logging/test/logging_deprecated_test.dart b/pkg/logging/test/logging_deprecated_test.dart
new file mode 100644
index 0000000..10ab616
--- /dev/null
+++ b/pkg/logging/test/logging_deprecated_test.dart
@@ -0,0 +1,336 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+library logging_test;
+
+import '../../../pkg/logging/lib/logging.dart';
+import 'package:unittest/unittest.dart';
+
+main() {
+ test('level comparison is a valid comparator', () {
+ var level1 = const Level('NOT_REAL1', 253);
+ expect(level1 == level1, isTrue);
+ expect(level1 <= level1, isTrue);
+ expect(level1 >= level1, isTrue);
+ expect(level1 < level1, isFalse);
+ expect(level1 > level1, isFalse);
+
+ var level2 = const Level('NOT_REAL2', 455);
+ expect(level1 <= level2, isTrue);
+ expect(level1 < level2, isTrue);
+ expect(level2 >= level1, isTrue);
+ expect(level2 > level1, isTrue);
+
+ var level3 = const Level('NOT_REAL3', 253);
+ expect(!identical(level1, level3), isTrue); // different instances
+ expect(level1 == level3, isTrue); // same value.
+ });
+
+ test('default levels are in order', () {
+ final levels = const [
+ Level.ALL, Level.FINEST, Level.FINER, Level.FINE, Level.CONFIG,
+ Level.INFO, Level.WARNING, Level.SEVERE, Level.SHOUT, Level.OFF
+ ];
+
+ for (int i = 0; i < levels.length; i++) {
+ for (int j = i + 1; j < levels.length; j++) {
+ expect(levels[i] < levels[j], isTrue);
+ }
+ }
+ });
+
+ test('levels are comparable', () {
+ final unsorted = [
+ Level.INFO, Level.CONFIG, Level.FINE, Level.SHOUT, Level.OFF,
+ Level.FINER, Level.ALL, Level.WARNING, Level.FINEST, Level.SEVERE,
+ ];
+ final sorted = const [
+ Level.ALL, Level.FINEST, Level.FINER, Level.FINE, Level.CONFIG,
+ Level.INFO, Level.WARNING, Level.SEVERE, Level.SHOUT, Level.OFF
+ ];
+ expect(unsorted, isNot(orderedEquals(sorted)));
+
+ unsorted.sort((a, b) => a.compareTo(b));
+ expect(unsorted, orderedEquals(sorted));
+ });
+
+ test('levels are hashable', () {
+ var map = new Map<Level, String>();
+ map[Level.INFO] = 'info';
+ map[Level.SHOUT] = 'shout';
+ expect(map[Level.INFO], equals('info'));
+ expect(map[Level.SHOUT], equals('shout'));
+ });
+
+ test('logger name cannot start with a "." ', () {
+ expect(() => new Logger('.c'), throws);
+ });
+
+ test('logger naming is hierarchical', () {
+ Logger c = new Logger('a.b.c');
+ expect(c.name, equals('c'));
+ expect(c.parent.name, equals('b'));
+ expect(c.parent.parent.name, equals('a'));
+ expect(c.parent.parent.parent.name, equals(''));
+ expect(c.parent.parent.parent.parent, isNull);
+ });
+
+ test('logger full name', () {
+ Logger c = new Logger('a.b.c');
+ expect(c.fullName, equals('a.b.c'));
+ expect(c.parent.fullName, equals('a.b'));
+ expect(c.parent.parent.fullName, equals('a'));
+ expect(c.parent.parent.parent.fullName, equals(''));
+ expect(c.parent.parent.parent.parent, isNull);
+ });
+
+ test('logger parent-child links are correct', () {
+ Logger a = new Logger('a');
+ Logger b = new Logger('a.b');
+ Logger c = new Logger('a.c');
+ expect(a == b.parent, isTrue);
+ expect(a == c.parent, isTrue);
+ expect(a.children['b'] == b, isTrue);
+ expect(a.children['c'] == c, isTrue);
+ });
+
+ test('loggers are singletons', () {
+ Logger a1 = new Logger('a');
+ Logger a2 = new Logger('a');
+ Logger b = new Logger('a.b');
+ Logger root = Logger.root;
+ expect(identical(a1, a2), isTrue);
+ expect(identical(a1, b.parent), isTrue);
+ expect(identical(root, a1.parent), isTrue);
+ expect(identical(root, new Logger('')), isTrue);
+ });
+
+ group('mutating levels', () {
+ Logger root = Logger.root;
+ Logger a = new Logger('a');
+ Logger b = new Logger('a.b');
+ Logger c = new Logger('a.b.c');
+ Logger d = new Logger('a.b.c.d');
+ Logger e = new Logger('a.b.c.d.e');
+
+ setUp(() {
+ hierarchicalLoggingEnabled = true;
+ root.level = Level.INFO;
+ a.level = null;
+ b.level = null;
+ c.level = null;
+ d.level = null;
+ e.level = null;
+ root.on.record.clear();
+ a.on.record.clear();
+ b.on.record.clear();
+ c.on.record.clear();
+ d.on.record.clear();
+ e.on.record.clear();
+ hierarchicalLoggingEnabled = false;
+ root.level = Level.INFO;
+ });
+
+ test('cannot set level if hierarchy is disabled', () {
+ expect(() {a.level = Level.FINE;}, throws);
+ });
+
+ test('loggers effective level - no hierarchy', () {
+ expect(root.level, equals(Level.INFO));
+ expect(a.level, equals(Level.INFO));
+ expect(b.level, equals(Level.INFO));
+
+ root.level = Level.SHOUT;
+
+ expect(root.level, equals(Level.SHOUT));
+ expect(a.level, equals(Level.SHOUT));
+ expect(b.level, equals(Level.SHOUT));
+ });
+
+ test('loggers effective level - with hierarchy', () {
+ hierarchicalLoggingEnabled = true;
+ expect(root.level, equals(Level.INFO));
+ expect(a.level, equals(Level.INFO));
+ expect(b.level, equals(Level.INFO));
+ expect(c.level, equals(Level.INFO));
+
+ root.level = Level.SHOUT;
+ b.level = Level.FINE;
+
+ expect(root.level, equals(Level.SHOUT));
+ expect(a.level, equals(Level.SHOUT));
+ expect(b.level, equals(Level.FINE));
+ expect(c.level, equals(Level.FINE));
+ });
+
+ test('isLoggable is appropriate', () {
+ hierarchicalLoggingEnabled = true;
+ root.level = Level.SEVERE;
+ c.level = Level.ALL;
+ e.level = Level.OFF;
+
+ expect(root.isLoggable(Level.SHOUT), isTrue);
+ expect(root.isLoggable(Level.SEVERE), isTrue);
+ expect(root.isLoggable(Level.WARNING), isFalse);
+ expect(c.isLoggable(Level.FINEST), isTrue);
+ expect(c.isLoggable(Level.FINE), isTrue);
+ expect(!e.isLoggable(Level.SHOUT), isTrue);
+ });
+
+ test('add/remove handlers - no hierarchy', () {
+ int calls = 0;
+ var handler = (_) { calls++; };
+ c.on.record.add(handler);
+ root.info("foo");
+ root.info("foo");
+ expect(calls, equals(2));
+ c.on.record.remove(handler);
+ root.info("foo");
+ expect(calls, equals(2));
+ });
+
+ test('add/remove handlers - with hierarchy', () {
+ hierarchicalLoggingEnabled = true;
+ int calls = 0;
+ var handler = (_) { calls++; };
+ c.on.record.add(handler);
+ root.info("foo");
+ root.info("foo");
+ expect(calls, equals(0));
+ });
+
+ test('logging methods store appropriate level', () {
+ root.level = Level.ALL;
+ var rootMessages = [];
+ root.on.record.add((record) {
+ rootMessages.add('${record.level}: ${record.message}');
+ });
+
+ root.finest('1');
+ root.finer('2');
+ root.fine('3');
+ root.config('4');
+ root.info('5');
+ root.warning('6');
+ root.severe('7');
+ root.shout('8');
+
+ expect(rootMessages, equals([
+ 'FINEST: 1',
+ 'FINER: 2',
+ 'FINE: 3',
+ 'CONFIG: 4',
+ 'INFO: 5',
+ 'WARNING: 6',
+ 'SEVERE: 7',
+ 'SHOUT: 8']));
+ });
+
+ test('message logging - no hierarchy', () {
+ root.level = Level.WARNING;
+ var rootMessages = [];
+ var aMessages = [];
+ var cMessages = [];
+ c.on.record.add((record) {
+ cMessages.add('${record.level}: ${record.message}');
+ });
+ a.on.record.add((record) {
+ aMessages.add('${record.level}: ${record.message}');
+ });
+ root.on.record.add((record) {
+ rootMessages.add('${record.level}: ${record.message}');
+ });
+
+ root.info('1');
+ root.fine('2');
+ root.shout('3');
+
+ b.info('4');
+ b.severe('5');
+ b.warning('6');
+ b.fine('7');
+
+ c.fine('8');
+ c.warning('9');
+ c.shout('10');
+
+ expect(rootMessages, equals([
+ // 'INFO: 1' is not loggable
+ // 'FINE: 2' is not loggable
+ 'SHOUT: 3',
+ // 'INFO: 4' is not loggable
+ 'SEVERE: 5',
+ 'WARNING: 6',
+ // 'FINE: 7' is not loggable
+ // 'FINE: 8' is not loggable
+ 'WARNING: 9',
+ 'SHOUT: 10']));
+
+ // no hierarchy means we all hear the same thing.
+ expect(aMessages, equals(rootMessages));
+ expect(cMessages, equals(rootMessages));
+ });
+
+ test('message logging - with hierarchy', () {
+ hierarchicalLoggingEnabled = true;
+
+ b.level = Level.WARNING;
+
+ var rootMessages = [];
+ var aMessages = [];
+ var cMessages = [];
+ c.on.record.add((record) {
+ cMessages.add('${record.level}: ${record.message}');
+ });
+ a.on.record.add((record) {
+ aMessages.add('${record.level}: ${record.message}');
+ });
+ root.on.record.add((record) {
+ rootMessages.add('${record.level}: ${record.message}');
+ });
+
+ root.info('1');
+ root.fine('2');
+ root.shout('3');
+
+ b.info('4');
+ b.severe('5');
+ b.warning('6');
+ b.fine('7');
+
+ c.fine('8');
+ c.warning('9');
+ c.shout('10');
+
+ expect(rootMessages, equals([
+ 'INFO: 1',
+ // 'FINE: 2' is not loggable
+ 'SHOUT: 3',
+ // 'INFO: 4' is not loggable
+ 'SEVERE: 5',
+ 'WARNING: 6',
+ // 'FINE: 7' is not loggable
+ // 'FINE: 8' is not loggable
+ 'WARNING: 9',
+ 'SHOUT: 10']));
+
+ expect(aMessages, equals([
+ // 1,2 and 3 are lower in the hierarchy
+ // 'INFO: 4' is not loggable
+ 'SEVERE: 5',
+ 'WARNING: 6',
+ // 'FINE: 7' is not loggable
+ // 'FINE: 8' is not loggable
+ 'WARNING: 9',
+ 'SHOUT: 10']));
+
+ expect(cMessages, equals([
+ // 1 - 7 are lower in the hierarchy
+ // 'FINE: 8' is not loggable
+ 'WARNING: 9',
+ 'SHOUT: 10']));
+ });
+ });
+}
diff --git a/pkg/logging/test/logging_test.dart b/pkg/logging/test/logging_test.dart
index 6444e3a..5102c42 100644
--- a/pkg/logging/test/logging_test.dart
+++ b/pkg/logging/test/logging_test.dart
@@ -5,7 +5,7 @@
library logging_test;
-import 'package:logging/logging.dart';
+import '../../../pkg/logging/lib/logging.dart';
import 'package:unittest/unittest.dart';
main() {
@@ -123,12 +123,12 @@
c.level = null;
d.level = null;
e.level = null;
- root.on.record.clear();
- a.on.record.clear();
- b.on.record.clear();
- c.on.record.clear();
- d.on.record.clear();
- e.on.record.clear();
+ root.clearListeners();
+ a.clearListeners();
+ b.clearListeners();
+ c.clearListeners();
+ d.clearListeners();
+ e.clearListeners();
hierarchicalLoggingEnabled = false;
root.level = Level.INFO;
});
@@ -182,11 +182,11 @@
test('add/remove handlers - no hierarchy', () {
int calls = 0;
var handler = (_) { calls++; };
- c.on.record.add(handler);
+ final sub = c.onRecord.listen(handler);
root.info("foo");
root.info("foo");
expect(calls, equals(2));
- c.on.record.remove(handler);
+ sub.cancel();
root.info("foo");
expect(calls, equals(2));
});
@@ -195,7 +195,7 @@
hierarchicalLoggingEnabled = true;
int calls = 0;
var handler = (_) { calls++; };
- c.on.record.add(handler);
+ c.onRecord.listen(handler);
root.info("foo");
root.info("foo");
expect(calls, equals(0));
@@ -204,7 +204,7 @@
test('logging methods store appropriate level', () {
root.level = Level.ALL;
var rootMessages = [];
- root.on.record.add((record) {
+ root.onRecord.listen((record) {
rootMessages.add('${record.level}: ${record.message}');
});
@@ -233,13 +233,13 @@
var rootMessages = [];
var aMessages = [];
var cMessages = [];
- c.on.record.add((record) {
+ c.onRecord.listen((record) {
cMessages.add('${record.level}: ${record.message}');
});
- a.on.record.add((record) {
+ a.onRecord.listen((record) {
aMessages.add('${record.level}: ${record.message}');
});
- root.on.record.add((record) {
+ root.onRecord.listen((record) {
rootMessages.add('${record.level}: ${record.message}');
});
@@ -281,13 +281,13 @@
var rootMessages = [];
var aMessages = [];
var cMessages = [];
- c.on.record.add((record) {
+ c.onRecord.listen((record) {
cMessages.add('${record.level}: ${record.message}');
});
- a.on.record.add((record) {
+ a.onRecord.listen((record) {
aMessages.add('${record.level}: ${record.message}');
});
- root.on.record.add((record) {
+ root.onRecord.listen((record) {
rootMessages.add('${record.level}: ${record.message}');
});
diff --git a/pkg/oauth2/lib/src/credentials.dart b/pkg/oauth2/lib/src/credentials.dart
index 26112c6..acc5690 100644
--- a/pkg/oauth2/lib/src/credentials.dart
+++ b/pkg/oauth2/lib/src/credentials.dart
@@ -50,7 +50,8 @@
/// credentials will expire shortly after this is called. However, since the
/// client's expiration date is kept a few seconds earlier than the server's,
/// there should be enough leeway to rely on this.
- bool get isExpired => expiration != null && new DateTime.now() > expiration;
+ bool get isExpired => expiration != null &&
+ new DateTime.now().isAfter(expiration);
/// Whether it's possible to refresh these credentials.
bool get canRefresh => refreshToken != null && tokenEndpoint != null;
diff --git a/pkg/path/README.md b/pkg/pathos/README.md
similarity index 100%
rename from pkg/path/README.md
rename to pkg/pathos/README.md
diff --git a/pkg/path/lib/path.dart b/pkg/pathos/lib/path.dart
similarity index 97%
rename from pkg/path/lib/path.dart
rename to pkg/pathos/lib/path.dart
index 9e540b2..0fe031d 100644
--- a/pkg/path/lib/path.dart
+++ b/pkg/pathos/lib/path.dart
@@ -194,11 +194,11 @@
// Show the arguments.
var message = new StringBuffer();
- message.add("$method(");
- message.add(args.take(numArgs)
+ message.write("$method(");
+ message.write(args.take(numArgs)
.map((arg) => arg == null ? "null" : '"$arg"')
.join(", "));
- message.add("): part ${i - 1} was null, but part $i was not.");
+ message.write("): part ${i - 1} was null, but part $i was not.");
throw new ArgumentError(message.toString());
}
}
@@ -245,7 +245,7 @@
///
/// Trailing separators are ignored.
///
- /// builder.dirname('path/to/'); // -> 'to'
+ /// builder.basename('path/to/'); // -> 'to'
String basename(String path) => _parse(path).basename;
/// Gets the part of [path] after the last separator on the builder's
@@ -255,7 +255,7 @@
///
/// Trailing separators are ignored.
///
- /// builder.dirname('path/to/foo.dart/'); // -> 'foo'
+ /// builder.basenameWithoutExtension('path/to/foo.dart/'); // -> 'foo'
String basenameWithoutExtension(String path) =>
_parse(path).basenameWithoutExtension;
@@ -364,16 +364,16 @@
for (var part in parts) {
if (this.isAbsolute(part)) {
// An absolute path discards everything before it.
- buffer.clear();
- buffer.add(part);
+ buffer = new StringBuffer();
+ buffer.write(part);
} else {
if (part.length > 0 && part[0].contains(style.separatorPattern)) {
// The part starts with a separator, so we don't need to add one.
} else if (needsSeparator) {
- buffer.add(separator);
+ buffer.write(separator);
}
- buffer.add(part);
+ buffer.write(part);
}
// Unless this part ends with a separator, we'll need to add one before
@@ -406,7 +406,8 @@
List<String> split(String path) {
var parsed = _parse(path);
// Filter out empty parts that exist due to multiple separators in a row.
- parsed.parts = parsed.parts.where((part) => !part.isEmpty).toList();
+ parsed.parts = parsed.parts.where((part) => !part.isEmpty)
+ .toList();
if (parsed.root != null) parsed.parts.insertRange(0, 1, parsed.root);
return parsed.parts;
}
@@ -701,10 +702,10 @@
String toString() {
var builder = new StringBuffer();
- if (root != null) builder.add(root);
+ if (root != null) builder.write(root);
for (var i = 0; i < parts.length; i++) {
- builder.add(parts[i]);
- builder.add(separators[i]);
+ builder.write(parts[i]);
+ builder.write(separators[i]);
}
return builder.toString();
diff --git a/pkg/path/pubspec.yaml b/pkg/pathos/pubspec.yaml
similarity index 100%
rename from pkg/path/pubspec.yaml
rename to pkg/pathos/pubspec.yaml
diff --git a/pkg/path/test/path_posix_test.dart b/pkg/pathos/test/pathos_posix_test.dart
similarity index 99%
rename from pkg/path/test/path_posix_test.dart
rename to pkg/pathos/test/pathos_posix_test.dart
index 763035f..d6bfb91 100644
--- a/pkg/path/test/path_posix_test.dart
+++ b/pkg/pathos/test/pathos_posix_test.dart
@@ -2,12 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library path_test;
+library pathos_posix_test;
import 'dart:io' as io;
import 'package:unittest/unittest.dart';
-import 'package:path/path.dart' as path;
+import 'package:pathos/path.dart' as path;
main() {
var builder = new path.Builder(style: path.Style.posix, root: '/root/path');
diff --git a/pkg/path/test/path_test.dart b/pkg/pathos/test/pathos_test.dart
similarity index 95%
rename from pkg/path/test/path_test.dart
rename to pkg/pathos/test/pathos_test.dart
index eea906a..c820a47 100644
--- a/pkg/path/test/path_test.dart
+++ b/pkg/pathos/test/pathos_test.dart
@@ -2,12 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library all_test;
+library pathos_test;
import 'dart:io' as io;
import 'package:unittest/unittest.dart';
-import 'package:path/path.dart' as path;
+import 'package:pathos/path.dart' as path;
main() {
group('path.Style', () {
diff --git a/pkg/path/test/path_windows_test.dart b/pkg/pathos/test/pathos_windows_test.dart
similarity index 99%
rename from pkg/path/test/path_windows_test.dart
rename to pkg/pathos/test/pathos_windows_test.dart
index 8164224..8419b53 100644
--- a/pkg/path/test/path_windows_test.dart
+++ b/pkg/pathos/test/pathos_windows_test.dart
@@ -2,12 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library path_test;
+library pathos_windows_test;
import 'dart:io' as io;
import 'package:unittest/unittest.dart';
-import 'package:path/path.dart' as path;
+import 'package:pathos/path.dart' as path;
main() {
var builder = new path.Builder(style: path.Style.windows,
diff --git a/pkg/pkg.status b/pkg/pkg.status
index cdaed72..d139d96 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -19,9 +19,9 @@
[ $compiler == dart2js || $compiler == dart2dart ]
http/test/*: Skip
oauth2/test/*: Skip
-path/test/*: Skip
+pathos/test/*: Skip
-# Issue 8440 forces us to use path in the scheduled_test tests, which would
+# Issue 8440 forces us to use pathos in the scheduled_test tests, which would
# otherwise be dart2js-compatible.
scheduled_test/test/*: Skip
@@ -29,7 +29,7 @@
[ $runtime == opera || $runtime == ff || $runtime == ie9 || $runtime == dartium || $runtime == chrome || $runtime == safari || $runtime == drt || $runtime == jsshell]
http/test/*: Skip
oauth2/test/*: Skip
-path/test/*: Skip
+pathos/test/*: Skip
intl/test/date_time_format_file_even_test: Skip
intl/test/date_time_format_file_odd_test: Skip
intl/test/find_default_locale_standalone_test: Skip
@@ -39,7 +39,7 @@
analyzer-experimental/test/generated/element_test: Skip # Imports dart:io.
analyzer-experimental/test/generated/ast_test: Skip # Imports dart:io.
-# Issue 8440 forces us to use path in the scheduled_test tests, which would
+# Issue 8440 forces us to use pathos in the scheduled_test tests, which would
# otherwise be dart2js-compatible.
scheduled_test/test/*: Skip
@@ -78,9 +78,6 @@
unittest/test/mock_regexp_negative_test: Fail
unittest/test/mock_stepwise_negative_test: Fail
-# pkg/http issue 7458
-http/test/multipart_test: Fail
-
[ $compiler == dart2js ]
unittest/test/instance_test: Skip
diff --git a/pkg/scheduled_test/lib/descriptor.dart b/pkg/scheduled_test/lib/descriptor.dart
new file mode 100644
index 0000000..60210f6
--- /dev/null
+++ b/pkg/scheduled_test/lib/descriptor.dart
@@ -0,0 +1,110 @@
+// 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 library for declaratively describing a filesystem structure, usually for
+/// the purpose of creating or validating it as part of a scheduled test.
+///
+/// You can use [dir] and [file] to define a filesystem structure. Then, you can
+/// call [Entry.create] to schedule a task that will create that structure on
+/// the physical filesystem, or [Entry.validate] to schedule an assertion that
+/// that structure exists. For example:
+///
+/// import 'package:scheduled_test/descriptor.dart' as d;
+/// import 'package:scheduled_test/scheduled_test.dart';
+///
+/// void main() {
+/// test('Directory.rename', () {
+/// d.dir('parent', [
+/// d.file('sibling', 'sibling-contents'),
+/// d.dir('old-name', [
+/// d.file('child', 'child-contents')
+/// ])
+/// ]).create();
+///
+/// schedule(() =>
+/// new Directory('parent/old-name').rename('parent/new-name'));
+///
+/// d.dir('parent', [
+/// d.file('sibling', 'sibling-contents'),
+/// d.dir('new-name', [
+/// d.file('child', 'child-contents')
+/// ])
+/// ]).validate();
+/// })
+/// }
+///
+/// Usually you don't want your tests cluttering up your working directory with
+/// fake filesystem entities. You can set [defaultRoot] to configure where
+/// filesystem descriptors are rooted on the physical filesystem. For example,
+/// to create a temporary directory for each test:
+///
+/// import 'package:scheduled_test/descriptor.dart' as d;
+/// import 'package:scheduled_test/scheduled_test.dart';
+///
+/// void main() {
+/// setUp(() {
+/// var tempDir;
+/// schedule(() {
+/// return new Directory('').createTemp().then((dir) {
+/// tempDir = dir;
+/// d.defaultRoot = tempDir.path;
+/// });
+/// });
+///
+/// currentSchedule.onComplete.schedule(() {
+/// d.defaultRoot = null;
+/// return tempDir.delete(recursive: true);
+/// });
+/// });
+///
+/// // ...
+/// }
+library descriptor;
+
+import 'dart:async';
+
+import 'package:pathos/path.dart' as path;
+
+import 'scheduled_test.dart';
+import 'src/descriptor/async.dart';
+import 'src/descriptor/directory.dart';
+import 'src/descriptor/entry.dart';
+import 'src/descriptor/file.dart';
+import 'src/descriptor/nothing.dart';
+
+export 'src/descriptor/async.dart';
+export 'src/descriptor/directory.dart';
+export 'src/descriptor/entry.dart';
+export 'src/descriptor/file.dart';
+export 'src/descriptor/nothing.dart';
+
+/// The root path for descriptors. Top-level descriptors will be created and
+/// validated at this path. Defaults to the current working directory.
+///
+/// If this is set to `null`, it will reset itself to the current working
+/// directory.
+String get defaultRoot => _defaultRoot == null ? path.current : _defaultRoot;
+set defaultRoot(String value) {
+ _defaultRoot = value;
+}
+String _defaultRoot;
+
+/// Creates a new text [File] descriptor with [name] and [contents].
+File file(Pattern name, [String contents='']) => new File(name, contents);
+
+/// Creates a new binary [File] descriptor with [name] and [contents].
+File binaryFile(Pattern name, List<int> contents) =>
+ new File.binary(name, contents);
+
+/// Creates a new [Directory] descriptor with [name] and [contents].
+Directory dir(Pattern name, [Iterable<Entry> contents]) =>
+ new Directory(name, contents == null ? <Entry>[] : contents);
+
+/// Creates a new descriptor wrapping a [Future]. This descriptor forwards all
+/// asynchronous operations to the result of [future].
+Async async(Future<Entry> future) => new Async(future);
+
+/// Creates a new [Nothing] descriptor that asserts that no entry named [name]
+/// exists.
+Nothing nothing(Pattern name) => new Nothing(name);
diff --git a/pkg/scheduled_test/lib/scheduled_test.dart b/pkg/scheduled_test/lib/scheduled_test.dart
index 456e50b3..587abb7 100644
--- a/pkg/scheduled_test/lib/scheduled_test.dart
+++ b/pkg/scheduled_test/lib/scheduled_test.dart
@@ -183,7 +183,7 @@
export 'package:unittest/matcher.dart';
export 'package:unittest/unittest.dart' show
- config, configure, Configuration, logMessage, expectThrow, fail;
+ config, configure, Configuration, logMessage, expectThrow;
export 'src/schedule.dart';
export 'src/schedule_error.dart';
@@ -316,7 +316,7 @@
/// initialized.
void _ensureInitialized() {
unittest.ensureInitialized();
- unittest.wrapAsync = (f) {
+ unittest.wrapAsync = (f, [id = '']) {
if (currentSchedule == null) {
throw new StateError("Unexpected call to wrapAsync with no current "
"schedule.");
diff --git a/pkg/scheduled_test/lib/src/descriptor/async.dart b/pkg/scheduled_test/lib/src/descriptor/async.dart
new file mode 100644
index 0000000..c33a68c
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/async.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library descriptor.async;
+
+import 'dart:async';
+import 'dart:io' as io;
+
+import '../../descriptor.dart' as descriptor;
+import '../../scheduled_test.dart';
+import '../utils.dart';
+import 'utils.dart';
+
+/// A descriptor that wraps a [Future<Entry>] and forwards all asynchronous
+/// operations to the result of the future. It's designed for use when the
+/// full filesystem description isn't known when initializing the schedule.
+///
+/// Async descriptors don't support [load], since their names aren't
+/// synchronously available.
+class Async extends descriptor.Entry {
+ /// The [Future] that will complete to the [Entry] this descriptor is
+ /// wrapping.
+ final Future<descriptor.Entry> future;
+
+ Async(this.future)
+ : super('<async descriptor>');
+
+ Future create([String parent]) =>
+ schedule(() => future.then((entry) => entry.create(parent)));
+
+ Future validate([String parent]) =>
+ schedule(() => future.then((entry) => entry.validate(parent)));
+
+ Stream<List<int>> load(String path) => errorStream("Async descriptors don't "
+ "support load().");
+
+ Stream<List<int>> read() => errorStream("Async descriptors don't support "
+ "read().");
+
+ String describe() => "async descriptor";
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/directory.dart b/pkg/scheduled_test/lib/src/descriptor/directory.dart
new file mode 100644
index 0000000..978daef
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/directory.dart
@@ -0,0 +1,96 @@
+// 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 descriptor.file;
+
+import 'dart:async';
+import 'dart:io' as io;
+
+import 'package:pathos/path.dart' as path;
+
+import '../../descriptor.dart' as descriptor;
+import '../../scheduled_test.dart';
+import '../utils.dart';
+import 'utils.dart';
+
+/// A path builder to ensure that [load] uses POSIX paths.
+final path.Builder _path = new path.Builder(style: path.Style.posix);
+
+/// A descriptor describing a directory containing multiple files.
+class Directory extends descriptor.Entry {
+ /// The entries contained within this directory.
+ final Iterable<descriptor.Entry> contents;
+
+ Directory(Pattern name, this.contents)
+ : super(name);
+
+ Future create([String parent]) => schedule(() {
+ if (parent == null) parent = descriptor.defaultRoot;
+ var fullPath = path.join(parent, stringName);
+ return new io.Directory(fullPath).create(recursive: true).then((_) {
+ return Future.wait(
+ contents.map((entry) => entry.create(fullPath)).toList());
+ });
+ }, 'creating directory:\n${describe()}');
+
+ Future validate([String parent]) => schedule(() {
+ if (parent == null) parent = descriptor.defaultRoot;
+ var fullPath = entryMatchingPattern('Directory', parent, name);
+ return Future.wait(
+ contents.map((entry) => entry.validate(fullPath)).toList());
+ }, 'validating directory:\n${describe()}');
+
+ Stream<List<int>> load(String pathToLoad) {
+ return futureStream(new Future.immediate(null).then((_) {
+ if (_path.isAbsolute(pathToLoad)) {
+ throw "Can't load absolute path '$pathToLoad'.";
+ }
+
+ var split = _path.split(_path.normalize(pathToLoad));
+ if (split.isEmpty || split.first == '.' || split.first == '..') {
+ throw "Can't load '$pathToLoad' from within $nameDescription.";
+ }
+
+ var matchingEntries = contents.where((entry) =>
+ entry.stringName == split.first).toList();
+
+ if (matchingEntries.length == 0) {
+ throw "Couldn't find an entry named '${split.first}' within "
+ "$nameDescription.";
+ } else if (matchingEntries.length > 1) {
+ throw "Found multiple entries named '${split.first}' within "
+ "$nameDescription.";
+ } else {
+ var remainingPath = split.getRange(1, split.length - 1);
+ if (remainingPath.isEmpty) {
+ return matchingEntries.first.read();
+ } else {
+ return matchingEntries.first.load(_path.joinAll(remainingPath));
+ }
+ }
+ }));
+ }
+
+ Stream<List<int>> read() => errorStream("Can't read the contents of "
+ "$nameDescription: is a directory.");
+
+ String describe() {
+ var description = name;
+ if (name is! String) description = 'directory matching $nameDescription';
+ if (contents.isEmpty) return description;
+
+ var buffer = new StringBuffer();
+ buffer.writeln(description);
+ for (var entry in contents.take(contents.length - 1)) {
+ var entryString = prefixLines(entry.describe(), prefix: '| ')
+ .replaceFirst('| ', '|-- ');
+ buffer.writeln(entryString);
+ }
+
+ var lastEntryString = prefixLines(contents.last.describe(), prefix: ' ')
+ .replaceFirst(' ', "'-- ");
+ buffer.add(lastEntryString);
+ return buffer.toString();
+ }
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/entry.dart b/pkg/scheduled_test/lib/src/descriptor/entry.dart
new file mode 100644
index 0000000..9605a1c
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/entry.dart
@@ -0,0 +1,70 @@
+// 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 descriptor.entry;
+
+import 'dart:async';
+
+import '../utils.dart';
+import 'utils.dart';
+
+/// The base class for various declarative descriptions of filesystem entries.
+/// All asynchronous operations on descriptors are [schedule]d unless otherwise
+/// noted.
+abstract class Entry {
+ /// The name of this entry. For most operations, this must be a [String];
+ /// however, if the entry will only be used for validation, it may be a
+ /// non-[String] [Pattern]. In this case, there must be only one entry
+ /// matching it in the physical filesystem for validation to succeed.
+ final Pattern name;
+
+ Entry(this.name);
+
+ /// Schedules the creation of the described entry within the [parent]
+ /// directory. Returns a [Future] that completes after the creation is done.
+ ///
+ /// [parent] defaults to [defaultRoot].
+ Future create([String parent]);
+
+ /// Schedules the validation of the described entry. This validates that the
+ /// physical file system under [parent] contains an entry that matches the one
+ /// described by [this]. Returns a [Future] that completes to `null` if the
+ /// entry is valid, or throws an error if it failed.
+ ///
+ /// [parent] defaults to [defaultRoot].
+ Future validate([String parent]);
+
+ /// Treats [this] as an in-memory filesystem and returns a stream of the
+ /// contents of the child entry located at [path]. This only works if [this]
+ /// is a directory entry. This operation is not [schedule]d.
+ ///
+ /// This method uses POSIX paths regardless of the underlying operating
+ /// system.
+ ///
+ /// All errors in loading the file will be passed through the returned
+ /// [Stream].
+ Stream<List<int>> load(String pathToLoad) => errorStream("Can't load "
+ "'$pathToLoad' from within $nameDescription: not a directory.");
+
+ /// Returns the contents of [this] as a stream. This only works if [this] is a
+ /// file entry. This operation is not [schedule]d.
+ ///
+ /// All errors in loading the file will be passed through the returned
+ /// [Stream].
+ Stream<List<int>> read();
+
+ /// Asserts that the name of the descriptor is a [String] and returns it.
+ String get stringName {
+ if (name is String) return name;
+ throw 'Pattern $nameDescription must be a string.';
+ }
+
+ /// Returns a human-readable description of [name], for error reporting. For
+ /// string names, this will just be the name in quotes; for regular
+ /// expressions, it will use JavaScript-style `/.../` notation.
+ String get nameDescription => describePattern(name);
+
+ /// Returns a detailed tree-style description of [this].
+ String describe();
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/file.dart b/pkg/scheduled_test/lib/src/descriptor/file.dart
new file mode 100644
index 0000000..2fefb89
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/file.dart
@@ -0,0 +1,107 @@
+// 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 descriptor.file;
+
+import 'dart:async';
+import 'dart:io' as io;
+import 'dart:math' as math;
+import 'dart:utf';
+
+import 'package:pathos/path.dart' as path;
+
+import '../../descriptor.dart' as descriptor;
+import '../../scheduled_test.dart';
+import '../utils.dart';
+import 'utils.dart';
+
+/// A descriptor describing a single file.
+class File extends descriptor.Entry {
+ /// Whether this descriptor describes a binary file. This is only used when
+ /// displaying error messages.
+ final bool isBinary;
+
+ /// The contents of the file, in bytes.
+ final List<int> contents;
+
+ /// The contents of the file as a String. Assumes UTF-8 encoding.
+ String get textContents => new String.fromCharCodes(contents);
+
+ File.binary(Pattern name, List<int> contents)
+ : this._(name, contents, true);
+
+ File(Pattern name, String contents)
+ : this._(name, encodeUtf8(contents), false);
+
+ File._(Pattern name, this.contents, this.isBinary)
+ : super(name);
+
+ Future create([String parent]) => schedule(() {
+ if (parent == null) parent = descriptor.defaultRoot;
+ return new io.File(path.join(parent, stringName)).writeAsBytes(contents);
+ }, 'creating file $nameDescription');
+
+ Future validate([String parent]) => schedule(() {
+ if (parent == null) parent = descriptor.defaultRoot;
+ var fullPath = entryMatchingPattern('File', parent, name);
+ return new io.File(fullPath).readAsBytes()
+ .then((actualContents) {
+ if (orderedIterableEquals(contents, actualContents)) return;
+ if (isBinary) {
+ // TODO(nweiz): show a hex dump here if the data is small enough.
+ throw "File $nameDescription didn't contain the expected binary "
+ "data.";
+ }
+ var description = nameDescription;
+ if (name is! String) {
+ description = "'${path.basename(fullPath)}' (matching $description)";
+ }
+ throw _textMismatchMessage(description, textContents,
+ new String.fromCharCodes(actualContents));;
+ });
+ }, 'validating file $nameDescription');
+
+ Stream<List<int>> read() => new Future.immediate(contents).asStream();
+
+ String describe() {
+ if (name is String) return name;
+ return 'file matching $nameDescription';
+ }
+}
+
+String _textMismatchMessage(String description, String expected,
+ String actual) {
+ final expectedLines = expected.split('\n');
+ final actualLines = actual.split('\n');
+
+ var results = [];
+
+ // Compare them line by line to see which ones match.
+ var length = math.max(expectedLines.length, actualLines.length);
+ for (var i = 0; i < length; i++) {
+ if (i >= actualLines.length) {
+ // Missing output.
+ results.add('? ${expectedLines[i]}');
+ } else if (i >= expectedLines.length) {
+ // Unexpected extra output.
+ results.add('X ${actualLines[i]}');
+ } else {
+ var expectedLine = expectedLines[i];
+ var actualLine = actualLines[i];
+
+ if (expectedLine != actualLine) {
+ // Mismatched lines.
+ results.add('X $actualLine');
+ } else {
+ // Matched lines.
+ results.add('| $actualLine');
+ }
+ }
+ }
+
+ return "File $description should contain:\n"
+ "${prefixLines(expected)}\n"
+ "but actually contained:\n"
+ "${results.join('\n')}";
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/nothing.dart b/pkg/scheduled_test/lib/src/descriptor/nothing.dart
new file mode 100644
index 0000000..048297e
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/nothing.dart
@@ -0,0 +1,60 @@
+// 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 descriptor.async;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:pathos/path.dart' as path;
+
+import '../../descriptor.dart' as descriptor;
+import '../../scheduled_test.dart';
+import '../utils.dart';
+import 'utils.dart';
+
+/// A descriptor that validates that no file exists with the given name.
+/// Creating this descriptor is a no-op and loading from it is invalid.
+class Nothing extends descriptor.Entry {
+ Nothing(Pattern name)
+ : super(name);
+
+ Future create([String parent]) => new Future.immediate(null);
+
+ Future validate([String parent]) => schedule(() {
+ if (parent == null) parent = descriptor.defaultRoot;
+ if (name is String) {
+ var fullPath = path.join(parent, name);
+ if (new File(fullPath).existsSync()) {
+ throw "Expected nothing to exist at '$fullPath', but found a file.";
+ } else if (new Directory(fullPath).existsSync()) {
+ throw "Expected nothing to exist at '$fullPath', but found a "
+ "directory.";
+ } else {
+ return;
+ }
+ }
+
+ return new Directory(parent).list().toList().then((entries) {
+ var matchingEntries = entries
+ .map((entry) => entry is File ? entry.fullPathSync() : entry.path)
+ .where((entry) => path.basename(entry).contains(name))
+ .toList();
+ matchingEntries.sort();
+
+ if (matchingEntries.length == 0) return;
+ throw "Expected nothing to exist in '$parent' matching $nameDescription, "
+ "but found:\n"
+ "${matchingEntries.map((entry) => '* $entry').join('\n')}";
+ });
+ }, "validating $nameDescription doesn't exist");
+
+ Stream<List<int>> load(String pathToLoad) => errorStream("Nothing "
+ "descriptors don't support load().");
+
+ Stream<List<int>> read() => errorStream("Nothing descriptors don't support "
+ "read().");
+
+ String describe() => "nothing at $nameDescription";
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/utils.dart b/pkg/scheduled_test/lib/src/descriptor/utils.dart
new file mode 100644
index 0000000..c649019
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/utils.dart
@@ -0,0 +1,54 @@
+// 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 descriptor.utils;
+
+import 'dart:io';
+
+import 'package:pathos/path.dart' as path;
+
+/// Returns a single filesystem entry within [parent] whose name matches
+/// [pattern]. If [pattern] is a string, looks for an exact match; otherwise,
+/// looks for an entry that contains [pattern].
+///
+/// If there are no entries in [parent] matching [pattern], or more than one,
+/// this will throw an exception.
+///
+/// [type] is used for error reporting. It should be capitalized.
+String entryMatchingPattern(String type, String parent, Pattern pattern) {
+ if (pattern is String) {
+ var fullPath = path.join(parent, pattern);
+ if (new File(fullPath).existsSync() || new Directory(fullPath).existsSync()) {
+ return fullPath;
+ }
+ throw "$type not found: '$fullPath'.";
+ }
+
+ var matchingEntries = new Directory(parent).listSync()
+ .map((entry) => entry is File ? entry.fullPathSync() : entry.path)
+ .where((entry) => path.basename(entry).contains(pattern))
+ .toList();
+ matchingEntries.sort();
+
+ if (matchingEntries.length == 0) {
+ throw "No entry found in '$parent' matching ${describePattern(pattern)}.";
+ } else if (matchingEntries.length > 1) {
+ throw "Multiple entries found in '$parent' matching "
+ "${describePattern(pattern)}:\n"
+ "${matchingEntries.map((entry) => '* $entry').join('\n')}";
+ } else {
+ return matchingEntries.first;
+ }
+}
+
+/// Returns a human-readable description of [pattern].
+String describePattern(Pattern pattern) {
+ if (pattern is String) return "'$pattern'";
+ if (pattern is! RegExp) return '$pattern';
+
+ var flags = new StringBuffer();
+ if (!pattern.isCaseSensitive) flags.add('i');
+ if (pattern.isMultiLine) flags.add('m');
+ return '/${pattern.pattern}/$flags';
+}
diff --git a/pkg/scheduled_test/lib/src/mock_clock.dart b/pkg/scheduled_test/lib/src/mock_clock.dart
index efcc7eb..bda216f 100644
--- a/pkg/scheduled_test/lib/src/mock_clock.dart
+++ b/pkg/scheduled_test/lib/src/mock_clock.dart
@@ -30,7 +30,7 @@
return _clock;
}
-typedef void TimerCallback(Timer timer);
+typedef void TimerCallback();
/// Returns a new (possibly mocked) [Timer]. Works the same as [new Timer].
Timer newTimer(Duration duration, TimerCallback callback) =>
@@ -94,7 +94,7 @@
_subscription = _clock.onTick.listen((time) {
if (_cancelled || time < _time) return;
_subscription.cancel();
- _callback(this);
+ _callback();
});
}
diff --git a/pkg/scheduled_test/lib/src/schedule.dart b/pkg/scheduled_test/lib/src/schedule.dart
index ac601ea..17ab86a 100644
--- a/pkg/scheduled_test/lib/src/schedule.dart
+++ b/pkg/scheduled_test/lib/src/schedule.dart
@@ -292,7 +292,7 @@
/// The callback to run when the timeout timer fires. Notifies the current
/// queue that a timeout has occurred.
- void _signalTimeout(_) {
+ void _signalTimeout() {
// Reset the timer so that we can detect timeouts in the onException and
// onComplete queues.
_timeoutTimer = null;
diff --git a/pkg/scheduled_test/lib/src/utils.dart b/pkg/scheduled_test/lib/src/utils.dart
index b5e086e..b880a2d 100644
--- a/pkg/scheduled_test/lib/src/utils.dart
+++ b/pkg/scheduled_test/lib/src/utils.dart
@@ -20,7 +20,43 @@
/// Returns a [Future] that completes after pumping the event queue [times]
/// times. By default, this should pump the event queue enough times to allow
/// any code to run, as long as it's not waiting on some external event.
-Future pumpEventQueue([int times=200]) {
+Future pumpEventQueue([int times=20]) {
if (times == 0) return new Future.immediate(null);
return new Future.immediate(null).then((_) => pumpEventQueue(times - 1));
}
+
+/// Returns whether [iterable1] has the same elements in the same order as
+/// [iterable2]. The elements are compared using `==`.
+bool orderedIterableEquals(Iterable iterable1, Iterable iterable2) {
+ var iter1 = iterable1.iterator;
+ var iter2 = iterable2.iterator;
+
+ while (true) {
+ var hasNext1 = iter1.moveNext();
+ var hasNext2 = iter2.moveNext();
+ if (hasNext1 != hasNext2) return false;
+ if (!hasNext1) return true;
+ if (iter1.current != iter2.current) return false;
+ }
+}
+
+// TODO(nweiz): remove this when issue 8731 is fixed.
+/// Returns a [Stream] that will immediately emit [error] and then close.
+Stream errorStream(error) => new Future.immediateError(error).asStream();
+
+/// Returns a buffered stream that will emit the same values as the stream
+/// returned by [future] once [future] completes. If [future] completes to an
+/// error, the return value will emit that error and then close.
+Stream futureStream(Future<Stream> future) {
+ var controller = new StreamController();
+ future.then((stream) {
+ stream.listen(
+ controller.add,
+ onError: (error) => controller.signalError(error),
+ onDone: controller.close);
+ }).catchError((e) {
+ controller.signalError(e);
+ controller.close();
+ });
+ return controller.stream;
+}
diff --git a/pkg/scheduled_test/test/descriptor_test.dart b/pkg/scheduled_test/test/descriptor_test.dart
new file mode 100644
index 0000000..1f5b42a
--- /dev/null
+++ b/pkg/scheduled_test/test/descriptor_test.dart
@@ -0,0 +1,1142 @@
+// 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 descriptor_test;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:pathos/path.dart' as path;
+import 'package:scheduled_test/descriptor.dart' as d;
+import 'package:scheduled_test/scheduled_test.dart';
+
+import 'metatest.dart';
+import 'utils.dart';
+
+String sandbox;
+
+void main() {
+ expectTestsPass('file().create() creates a file', () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.file('name.txt', 'contents').create();
+
+ schedule(() {
+ expect(new File(path.join(sandbox, 'name.txt')).readAsString(),
+ completion(equals('contents')));
+ });
+ });
+ });
+
+ expectTestsPass('file().create() overwrites an existing file', () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.file('name.txt', 'contents1').create();
+
+ d.file('name.txt', 'contents2').create();
+
+ schedule(() {
+ expect(new File(path.join(sandbox, 'name.txt')).readAsString(),
+ completion(equals('contents2')));
+ });
+ });
+ });
+
+ expectTestsPass('file().create() with a RegExp name fails', () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.file(new RegExp(r'name\.txt'), 'contents').create();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.map((e) => e.error), equals([
+ r"Pattern /name\.txt/ must be a string."
+ ]), verbose: true);
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass('file().validate() completes successfully if the filesystem '
+ 'matches the descriptor', () {
+ test('test', () {
+ scheduleSandbox();
+
+ schedule(() {
+ return new File(path.join(sandbox, 'name.txt'))
+ .writeAsString('contents');
+ });
+
+ d.file('name.txt', 'contents').validate();
+ });
+ });
+
+ expectTestsPass("file().validate() fails if there's a file with the wrong "
+ "contents", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ schedule(() {
+ return new File(path.join(sandbox, 'name.txt'))
+ .writeAsString('wrongtents');
+ });
+
+ d.file('name.txt', 'contents').validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.map((e) => e.error), equals([
+ "File 'name.txt' should contain:\n"
+ "| contents\n"
+ "but actually contained:\n"
+ "X wrongtents"
+ ]), verbose: true);
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("file().validate() fails if there's no file", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.file('name.txt', 'contents').validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^File not found: '[^']+[\\/]name\.txt'\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass('file().validate() with a RegExp completes successfully if '
+ 'the filesystem matches the descriptor', () {
+ test('test', () {
+ scheduleSandbox();
+
+ schedule(() {
+ return new File(path.join(sandbox, 'name.txt'))
+ .writeAsString('contents');
+ });
+
+ d.file(new RegExp(r'na..\.txt'), 'contents').validate();
+ });
+ });
+
+ expectTestsPass("file().validate() with a RegExp fails if there's a file "
+ "with the wrong contents", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ schedule(() {
+ return new File(path.join(sandbox, 'name.txt'))
+ .writeAsString('some\nwrongtents');
+ });
+
+ d.file(new RegExp(r'na..\.txt'), 'some\ncontents\nand stuff').validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.map((e) => e.error), equals([
+ "File 'name.txt' (matching /na..\\.txt/) should contain:\n"
+ "| some\n"
+ "| contents\n"
+ "| and stuff\n"
+ "but actually contained:\n"
+ "| some\n"
+ "X wrongtents\n"
+ "? and stuff"
+ ]), verbose: true);
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("file().validate() with a RegExp fails if there's no "
+ "file", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.file(new RegExp(r'na..\.txt'), 'contents').validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^No entry found in '[^']+' matching /na\.\.\\\.txt/\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("file().validate() with a RegExp fails if there are multiple "
+ "matching files", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ schedule(() {
+ return Future.wait([
+ new File(path.join(sandbox, 'name.txt')).writeAsString('contents'),
+ new File(path.join(sandbox, 'nape.txt')).writeAsString('contents'),
+ new File(path.join(sandbox, 'nail.txt')).writeAsString('contents')
+ ]);
+ });
+
+ d.file(new RegExp(r'na..\.txt'), 'contents').validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(
+ r"^Multiple entries found in '[^']+' matching /na\.\.\\\.txt/:\n"
+ r"\* .*[\\/]nail\.txt\n"
+ r"\* .*[\\/]name\.txt\n"
+ r"\* .*[\\/]nape\.txt"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("file().read() returns the contents of the file as a stream",
+ () {
+ test('test', () {
+ expect(byteStreamToString(d.file('name.txt', 'contents').read()),
+ completion(equals('contents')));
+ });
+ });
+
+ expectTestsPass("file().load() throws an error", () {
+ test('test', () {
+ expect(d.file('name.txt', 'contents').load('path').toList(),
+ throwsA(equals("Can't load 'path' from within 'name.txt': not a "
+ "directory.")));
+ });
+ });
+
+ expectTestsPass("file().describe() returns the filename", () {
+ test('test', () {
+ expect(d.file('name.txt', 'contents').describe(), equals('name.txt'));
+ });
+ });
+
+ expectTestsPass("file().describe() with a RegExp describes the file", () {
+ test('test', () {
+ expect(d.file(new RegExp(r'na..\.txt'), 'contents').describe(),
+ equals(r'file matching /na..\.txt/'));
+ });
+ });
+
+ expectTestsPass('binaryFile().create() creates a file', () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.binaryFile('name.bin', [1, 2, 3, 4, 5]).create();
+
+ schedule(() {
+ expect(new File(path.join(sandbox, 'name.bin')).readAsBytes(),
+ completion(equals([1, 2, 3, 4, 5])));
+ });
+ });
+ });
+
+ expectTestsPass('binaryFile().validate() completes successfully if the '
+ 'filesystem matches the descriptor', () {
+ test('test', () {
+ scheduleSandbox();
+
+ schedule(() {
+ return new File(path.join(sandbox, 'name.bin'))
+ .writeAsBytes([1, 2, 3, 4, 5]);
+ });
+
+ d.binaryFile('name.bin', [1, 2, 3, 4, 5]).validate();
+ });
+ });
+
+ expectTestsPass("binaryFile().validate() fails if there's a file with the "
+ "wrong contents", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ schedule(() {
+ return new File(path.join(sandbox, 'name.bin'))
+ .writeAsBytes([2, 4, 6, 8, 10]);
+ });
+
+ d.binaryFile('name.bin', [1, 2, 3, 4, 5]).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.map((e) => e.error), equals([
+ "File 'name.bin' didn't contain the expected binary data."
+ ]), verbose: true);
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("directory().create() creates a directory and its contents",
+ () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.dir('dir', [
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2')
+ ]),
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).create();
+
+ schedule(() {
+ expect(new File(path.join(sandbox, 'dir', 'file1.txt')).readAsString(),
+ completion(equals('contents1')));
+ expect(new File(path.join(sandbox, 'dir', 'file2.txt')).readAsString(),
+ completion(equals('contents2')));
+ expect(new File(path.join(sandbox, 'dir', 'subdir', 'subfile1.txt'))
+ .readAsString(),
+ completion(equals('subcontents1')));
+ expect(new File(path.join(sandbox, 'dir', 'subdir', 'subfile2.txt'))
+ .readAsString(),
+ completion(equals('subcontents2')));
+ });
+ });
+ });
+
+ expectTestsPass("directory().create() works if the directory already exists",
+ () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.dir('dir').create();
+ d.dir('dir', [d.file('name.txt', 'contents')]).create();
+
+ schedule(() {
+ expect(new File(path.join(sandbox, 'dir', 'name.txt')).readAsString(),
+ completion(equals('contents')));
+ });
+ });
+ });
+
+ expectTestsPass("directory().create() with a RegExp name fails", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.dir(new RegExp('dir')).create();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.map((e) => e.error), equals([
+ "Pattern /dir/ must be a string."
+ ]), verbose: true);
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("directory().validate() completes successfully if the "
+ "filesystem matches the descriptor", () {
+ test('test', () {
+ scheduleSandbox();
+
+ schedule(() {
+ var dirPath = path.join(sandbox, 'dir');
+ var subdirPath = path.join(dirPath, 'subdir');
+ return new Directory(subdirPath).create(recursive: true).then((_) {
+ return Future.wait([
+ new File(path.join(dirPath, 'file1.txt'))
+ .writeAsString('contents1'),
+ new File(path.join(dirPath, 'file2.txt'))
+ .writeAsString('contents2'),
+ new File(path.join(subdirPath, 'subfile1.txt'))
+ .writeAsString('subcontents1'),
+ new File(path.join(subdirPath, 'subfile2.txt'))
+ .writeAsString('subcontents2')
+ ]);
+ });
+ });
+
+ d.dir('dir', [
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2')
+ ]),
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).validate();
+ });
+ });
+
+ expectTestsPass("directory().validate() fails if a directory isn't found"
+ , () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ schedule(() {
+ var dirPath = path.join(sandbox, 'dir');
+ return new Directory(dirPath).create().then((_) {
+ return Future.wait([
+ new File(path.join(dirPath, 'file1.txt'))
+ .writeAsString('contents1'),
+ new File(path.join(dirPath, 'file2.txt'))
+ .writeAsString('contents2')
+ ]);
+ });
+ });
+
+ d.dir('dir', [
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2')
+ ]),
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^Directory not found: '[^']+[\\/]dir[\\/]subdir'\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("directory().validate() fails if a file isn't found", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ schedule(() {
+ var dirPath = path.join(sandbox, 'dir');
+ var subdirPath = path.join(dirPath, 'subdir');
+ return new Directory(subdirPath).create(recursive: true).then((_) {
+ return Future.wait([
+ new File(path.join(dirPath, 'file1.txt'))
+ .writeAsString('contents1'),
+ new File(path.join(subdirPath, 'subfile1.txt'))
+ .writeAsString('subcontents1'),
+ new File(path.join(subdirPath, 'subfile2.txt'))
+ .writeAsString('subcontents2')
+ ]);
+ });
+ });
+
+ d.dir('dir', [
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2')
+ ]),
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^File not found: '[^']+[\\/]dir[\\/]file2\.txt'\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("directory().validate() fails if a file has the wrong "
+ "contents", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ schedule(() {
+ var dirPath = path.join(sandbox, 'dir');
+ var subdirPath = path.join(dirPath, 'subdir');
+ return new Directory(subdirPath).create(recursive: true).then((_) {
+ return Future.wait([
+ new File(path.join(dirPath, 'file1.txt'))
+ .writeAsString('contents1'),
+ new File(path.join(dirPath, 'file2.txt'))
+ .writeAsString('contents2'),
+ new File(path.join(subdirPath, 'subfile1.txt'))
+ .writeAsString('wrongtents1'),
+ new File(path.join(subdirPath, 'subfile2.txt'))
+ .writeAsString('subcontents2')
+ ]);
+ });
+ });
+
+ d.dir('dir', [
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2')
+ ]),
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.map((e) => e.error), equals([
+ "File 'subfile1.txt' should contain:\n"
+ "| subcontents1\n"
+ "but actually contained:\n"
+ "X wrongtents1"
+ ]));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("directory().validate() with a RegExp completes successfully "
+ "if the filesystem matches the descriptor", () {
+ test('test', () {
+ scheduleSandbox();
+
+ schedule(() {
+ var dirPath = path.join(sandbox, 'dir');
+ var subdirPath = path.join(dirPath, 'subdir');
+ return new Directory(subdirPath).create(recursive: true).then((_) {
+ return Future.wait([
+ new File(path.join(dirPath, 'file1.txt'))
+ .writeAsString('contents1'),
+ new File(path.join(dirPath, 'file2.txt'))
+ .writeAsString('contents2'),
+ new File(path.join(subdirPath, 'subfile1.txt'))
+ .writeAsString('subcontents1'),
+ new File(path.join(subdirPath, 'subfile2.txt'))
+ .writeAsString('subcontents2')
+ ]);
+ });
+ });
+
+ d.dir(new RegExp('d.r'), [
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2')
+ ]),
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).validate();
+ });
+ });
+
+ expectTestsPass("directory().validate() with a RegExp fails if there's a dir "
+ "with the wrong contents", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ schedule(() {
+ var dirPath = path.join(sandbox, 'dir');
+ var subdirPath = path.join(dirPath, 'subdir');
+ return new Directory(subdirPath).create(recursive: true).then((_) {
+ return Future.wait([
+ new File(path.join(dirPath, 'file1.txt'))
+ .writeAsString('contents1'),
+ new File(path.join(subdirPath, 'subfile1.txt'))
+ .writeAsString('subcontents1'),
+ new File(path.join(subdirPath, 'subfile2.txt'))
+ .writeAsString('subcontents2')
+ ]);
+ });
+ });
+
+ d.dir(new RegExp('d.r'), [
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2')
+ ]),
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^File not found: '[^']+[\\/]dir[\\/]file2\.txt'\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("directory().validate() with a RegExp fails if there's no "
+ "dir", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.dir(new RegExp('d.r'), [
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2')
+ ]),
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^No entry found in '[^']+' matching /d\.r/\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("directory().validate() with a RegExp fails if there are "
+ "multiple matching dirs", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ schedule(() {
+ return Future.wait(['dir', 'dar', 'dor'].map((dir) {
+ var dirPath = path.join(sandbox, dir);
+ var subdirPath = path.join(dirPath, 'subdir');
+ return new Directory(subdirPath).create(recursive: true).then((_) {
+ return Future.wait([
+ new File(path.join(dirPath, 'file1.txt'))
+ .writeAsString('contents1'),
+ new File(path.join(dirPath, 'file2.txt'))
+ .writeAsString('contents2'),
+ new File(path.join(subdirPath, 'subfile1.txt'))
+ .writeAsString('subcontents1'),
+ new File(path.join(subdirPath, 'subfile2.txt'))
+ .writeAsString('subcontents2')
+ ]);
+ });
+ }));
+ });
+
+ d.dir(new RegExp('d.r'), [
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2')
+ ]),
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(
+ r"^Multiple entries found in '[^']+' matching /d\.r/:\n"
+ r"\* .*[\\/]dar\n"
+ r"\* .*[\\/]dir\n"
+ r"\* .*[\\/]dor"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("directory().load() loads a file", () {
+ test('test', () {
+ var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
+ expect(byteStreamToString(dir.load('name.txt')),
+ completion(equals('contents')));
+ });
+ });
+
+ expectTestsPass("directory().load() loads a deeply-nested file", () {
+ test('test', () {
+ var dir = d.dir('dir', [
+ d.dir('subdir', [
+ d.file('name.txt', 'subcontents')
+ ]),
+ d.file('name.txt', 'contents')
+ ]);
+
+ expect(byteStreamToString(dir.load('subdir/name.txt')),
+ completion(equals('subcontents')));
+ });
+ });
+
+ expectTestsPass("directory().read() fails", () {
+ test('test', () {
+ var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
+ expect(dir.read().toList(),
+ throwsA(equals("Can't read the contents of 'dir': is a directory.")));
+ });
+ });
+
+ expectTestsPass("directory().load() fails to load a nested directory", () {
+ test('test', () {
+ var dir = d.dir('dir', [
+ d.dir('subdir', [
+ d.file('name.txt', 'subcontents')
+ ]),
+ d.file('name.txt', 'contents')
+ ]);
+
+ expect(dir.load('subdir').toList(),
+ throwsA(equals("Can't read the contents of 'subdir': is a "
+ "directory.")));
+ });
+ });
+
+ expectTestsPass("directory().load() fails to load an absolute path", () {
+ test('test', () {
+ var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
+
+ expect(dir.load('/name.txt').toList(),
+ throwsA(equals("Can't load absolute path '/name.txt'.")));
+ });
+ });
+
+ expectTestsPass("directory().load() fails to load '.', '..', or ''", () {
+ test('test', () {
+ var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
+
+ expect(dir.load('.').toList(),
+ throwsA(equals("Can't load '.' from within 'dir'.")));
+
+ expect(dir.load('..').toList(),
+ throwsA(equals("Can't load '..' from within 'dir'.")));
+
+ expect(dir.load('').toList(),
+ throwsA(equals("Can't load '' from within 'dir'.")));
+ });
+ });
+
+ expectTestsPass("directory().load() fails to load a file with a RegExp name",
+ () {
+ test('test', () {
+ var dir = d.dir('dir', [d.file(new RegExp(r'name\.txt'), 'contents')]);
+
+ expect(dir.load('name.txt').toList(),
+ throwsA(equals(r"Pattern /name\.txt/ must be a string.")));
+ });
+ });
+
+ expectTestsPass("directory().load() fails to load a file that doesn't exist",
+ () {
+ test('test', () {
+ var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
+
+ expect(dir.load('not-name.txt').toList(),
+ throwsA(equals("Couldn't find an entry named 'not-name.txt' within "
+ "'dir'.")));
+ });
+ });
+
+ expectTestsPass("directory().load() fails to load a file that exists "
+ "multiple times", () {
+ test('test', () {
+ var dir = d.dir('dir', [
+ d.file('name.txt', 'contents'),
+ d.file('name.txt', 'contents')
+ ]);
+
+ expect(dir.load('name.txt').toList(),
+ throwsA(equals("Found multiple entries named 'name.txt' within "
+ "'dir'.")));
+ });
+ });
+
+ expectTestsPass("directory().describe() lists the contents of the directory",
+ () {
+ test('test', () {
+ var dir = d.dir('dir', [
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2'),
+ d.file(new RegExp(r're\.txt'), 're-contents')
+ ]);
+
+ expect(dir.describe(), equals(
+ "dir\n"
+ "|-- file1.txt\n"
+ "|-- file2.txt\n"
+ "'-- file matching /re\\.txt/"));
+ });
+ });
+
+ expectTestsPass("directory().describe() lists the contents of nested "
+ "directories", () {
+ test('test', () {
+ var dir = d.dir('dir', [
+ d.file('file1.txt', 'contents1'),
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents1'),
+ d.file('subfile2.txt', 'subcontents2'),
+ d.dir('subsubdir', [
+ d.file('subsubfile.txt', 'subsubcontents')
+ ])
+ ]),
+ d.file('file2.txt', 'contents2')
+ ]);
+
+ expect(dir.describe(), equals(
+ "dir\n"
+ "|-- file1.txt\n"
+ "|-- subdir\n"
+ "| |-- subfile1.txt\n"
+ "| |-- subfile2.txt\n"
+ "| '-- subsubdir\n"
+ "| '-- subsubfile.txt\n"
+ "'-- file2.txt"));
+ });
+ });
+
+ expectTestsPass("directory().describe() with a RegExp describes the "
+ "directory", () {
+ test('test', () {
+ var dir = d.dir(new RegExp(r'd.r'), [
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]);
+
+ expect(dir.describe(), equals(
+ "directory matching /d.r/\n"
+ "|-- file1.txt\n"
+ "'-- file2.txt"));
+ });
+ });
+
+ expectTestsPass("directory().describe() with no contents returns the "
+ "directory name", () {
+ test('test', () {
+ expect(d.dir('dir').describe(), equals('dir'));
+ });
+ });
+
+ expectTestsPass("async().create() forwards to file().create", () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.async(pumpEventQueue().then((_) {
+ return d.file('name.txt', 'contents');
+ })).create();
+
+ d.file('name.txt', 'contents').validate();
+ });
+ });
+
+ expectTestsPass("async().create() forwards to directory().create", () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.async(pumpEventQueue().then((_) {
+ return d.dir('dir', [
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]);
+ })).create();
+
+ d.dir('dir', [
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).validate();
+ });
+ });
+
+ expectTestsPass("async().validate() forwards to file().validate", () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.file('name.txt', 'contents').create();
+
+ d.async(pumpEventQueue().then((_) {
+ return d.file('name.txt', 'contents');
+ })).validate();
+ });
+ });
+
+ expectTestsPass("async().validate() fails if file().validate fails", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.async(pumpEventQueue().then((_) {
+ return d.file('name.txt', 'contents');
+ })).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^File not found: '[^']+[\\/]name\.txt'\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("async().validate() forwards to directory().validate", () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.dir('dir', [
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]).create();
+
+ d.async(pumpEventQueue().then((_) {
+ return d.dir('dir', [
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]);
+ })).validate();
+ });
+ });
+
+ expectTestsPass("async().create() fails if directory().create fails", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.async(pumpEventQueue().then((_) {
+ return d.dir('dir', [
+ d.file('file1.txt', 'contents1'),
+ d.file('file2.txt', 'contents2')
+ ]);
+ })).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^Directory not found: '[^']+[\\/]dir'\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("async().load() fails", () {
+ test('test', () {
+ scheduleSandbox();
+
+ expect(d.async(new Future.immediate(d.file('name.txt')))
+ .load('path').toList(),
+ throwsA(equals("Async descriptors don't support load().")));
+ });
+ });
+
+ expectTestsPass("async().read() fails", () {
+ test('test', () {
+ scheduleSandbox();
+
+ expect(d.async(new Future.immediate(d.file('name.txt'))).read().toList(),
+ throwsA(equals("Async descriptors don't support read().")));
+ });
+ });
+
+ expectTestsPass("nothing().create() does nothing", () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.nothing('foo').create();
+
+ schedule(() {
+ expect(new File(path.join(sandbox, 'foo')).exists(),
+ completion(isFalse));
+ });
+
+ schedule(() {
+ expect(new Directory(path.join(sandbox, 'foo')).exists(),
+ completion(isFalse));
+ });
+ });
+ });
+
+ expectTestsPass("nothing().validate() succeeds if nothing's there", () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.nothing('foo').validate();
+ });
+ });
+
+ expectTestsPass("nothing().validate() with a RegExp succeeds if nothing's "
+ "there", () {
+ test('test', () {
+ scheduleSandbox();
+
+ d.nothing(new RegExp('f.o')).validate();
+ });
+ });
+
+ expectTestsPass("nothing().validate() fails if there's a file", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.file('name.txt', 'contents').create();
+ d.nothing('name.txt').validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^Expected nothing to exist at '[^']+[\\/]name.txt', but "
+ r"found a file\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("nothing().validate() fails if there's a directory", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.dir('dir').create();
+ d.nothing('dir').validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^Expected nothing to exist at '[^']+[\\/]dir', but found a "
+ r"directory\.$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("nothing().validate() with a RegExp fails if there are "
+ "multiple entries", () {
+ var errors;
+ test('test 1', () {
+ scheduleSandbox();
+
+ currentSchedule.onException.schedule(() {
+ errors = currentSchedule.errors;
+ });
+
+ d.dir('foo').create();
+ d.file('faa', 'contents').create();
+ d.file('not-foo', 'contents').create();
+ d.nothing(new RegExp(r'^f..$')).validate();
+ });
+
+ test('test 2', () {
+ expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+ expect(errors.length, equals(1));
+ expect(errors.first.error,
+ matches(r"^Expected nothing to exist in '[^']+' matching "
+ r"/\^f\.\.\$/, but found:\n"
+ r"\* .*[\\/]faa\n"
+ r"\* .*[\\/]foo$"));
+ });
+ }, passing: ['test 2']);
+
+ expectTestsPass("nothing().load() fails", () {
+ test('test', () {
+ scheduleSandbox();
+
+ expect(d.nothing('name.txt').load('path').toList(),
+ throwsA(equals("Nothing descriptors don't support load().")));
+ });
+ });
+
+ expectTestsPass("nothing().read() fails", () {
+ test('test', () {
+ scheduleSandbox();
+
+ expect(d.nothing('name.txt').read().toList(),
+ throwsA(equals("Nothing descriptors don't support read().")));
+ });
+ });
+}
+
+void scheduleSandbox() {
+ schedule(() {
+ return new Directory('').createTemp().then((dir) {
+ sandbox = dir.path;
+ d.defaultRoot = sandbox;
+ });
+ });
+
+ currentSchedule.onComplete.schedule(() {
+ d.defaultRoot = null;
+ if (sandbox == null) return;
+ var oldSandbox = sandbox;
+ sandbox = null;
+ return new Directory(oldSandbox).delete(recursive: true);
+ });
+}
+
+Future<List<int>> byteStreamToList(Stream<List<int>> stream) {
+ return stream.reduce(<int>[], (buffer, chunk) {
+ buffer.addAll(chunk);
+ return buffer;
+ });
+}
+
+Future<String> byteStreamToString(Stream<List<int>> stream) =>
+ byteStreamToList(stream).then((bytes) => new String.fromCharCodes(bytes));
diff --git a/pkg/scheduled_test/test/metatest.dart b/pkg/scheduled_test/test/metatest.dart
index 2a83015..9850fff 100644
--- a/pkg/scheduled_test/test/metatest.dart
+++ b/pkg/scheduled_test/test/metatest.dart
@@ -12,7 +12,7 @@
import 'dart:async';
import 'dart:isolate';
-import '../../../pkg/path/lib/path.dart' as path;
+import 'package:pathos/path.dart' as path;
import 'package:unittest/unittest.dart';
import 'utils.dart';
diff --git a/pkg/scheduled_test/test/scheduled_test_test.dart b/pkg/scheduled_test/test/scheduled_test_test.dart
index f07024d..79d2e37 100644
--- a/pkg/scheduled_test/test/scheduled_test_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test_test.dart
@@ -877,7 +877,7 @@
test('test 2', () {
expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
expect(errors.map((e) => e.error), equals(["The schedule timed out after "
- "0:00:00.001 of inactivity."]));
+ "0:00:00.001000 of inactivity."]));
});
}, passing: ['test 2']);
@@ -898,7 +898,7 @@
test('test 2', () {
expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
expect(errors.map((e) => e.error), equals(["The schedule timed out after "
- "0:00:00.001 of inactivity."]));
+ "0:00:00.001000 of inactivity."]));
});
}, passing: ['test 2']);
@@ -943,7 +943,7 @@
test('test 2', () {
expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
expect(errors.map((e) => e.error), equals([
- "The schedule timed out after 0:00:00.003 of inactivity.",
+ "The schedule timed out after 0:00:00.003000 of inactivity.",
"out-of-band"
]));
});
@@ -998,7 +998,7 @@
expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
expect(errors.map((e) => e.error), equals([
"out-of-band",
- "The schedule timed out after 0:00:00.002 of inactivity."
+ "The schedule timed out after 0:00:00.002000 of inactivity."
]));
});
}, passing: ['test 2']);
diff --git a/pkg/scheduled_test/test/utils.dart b/pkg/scheduled_test/test/utils.dart
index bd87edf..3d59e66 100644
--- a/pkg/scheduled_test/test/utils.dart
+++ b/pkg/scheduled_test/test/utils.dart
@@ -20,19 +20,16 @@
/// Note that timing out will not cancel the asynchronous operation behind
/// [input].
Future timeout(Future input, int milliseconds, onTimeout()) {
- bool completed = false;
var completer = new Completer();
- var timer = new Timer(milliseconds, (_) {
- completed = true;
- chainToCompleter(new Future.immediate(null).then((_) => onTimeout()),
- completer);
+ var timer = new Timer(new Duration(milliseconds: milliseconds), () {
+ chainToCompleter(new Future.of(onTimeout), completer);
});
input.then((value) {
- if (completed) return;
+ if (completer.isCompleted) return;
timer.cancel();
completer.complete(value);
}).catchError((e) {
- if (completed) return;
+ if (completer.isCompleted) return;
timer.cancel();
completer.completeError(e.error, e.stackTrace);
});
@@ -42,7 +39,7 @@
/// Returns a [Future] that will complete in [milliseconds].
Future sleep(int milliseconds) {
var completer = new Completer();
- mock_clock.newTimer(new Duration(milliseconds: milliseconds), (_) {
+ mock_clock.newTimer(new Duration(milliseconds: milliseconds), () {
completer.complete();
});
return completer.future;
diff --git a/pkg/serialization/lib/src/basic_rule.dart b/pkg/serialization/lib/src/basic_rule.dart
index 19a8bca..fe9428f 100644
--- a/pkg/serialization/lib/src/basic_rule.dart
+++ b/pkg/serialization/lib/src/basic_rule.dart
@@ -130,12 +130,19 @@
useMaps = false;
}
- /** Create either a list or a map to hold the object's state, depending
+ /**
+ * Create either a list or a map to hold the object's state, depending
* on the [useMaps] variable. If using a Map, we wrap it in order to keep
* the protocol compatible. See [configureForLists]/[configureForMaps].
+ *
+ * If a list is returned, it is growable.
*/
- createStateHolder() =>
- useMaps ? new _MapWrapper(fields.contents) : new List(fields.length);
+ createStateHolder() {
+ if (useMaps) return new _MapWrapper(fields.contents);
+ List list = [];
+ list.length = fields.length;
+ return list;
+ }
/**
* Wrap the state if it's passed in as a map, and if the keys are references,
diff --git a/pkg/serialization/lib/src/format.dart b/pkg/serialization/lib/src/format.dart
index 68f6094..4e57384 100644
--- a/pkg/serialization/lib/src/format.dart
+++ b/pkg/serialization/lib/src/format.dart
@@ -187,7 +187,7 @@
var rules = reader.selfDescribing ? data[RULES] : null;
var actualData = reader.selfDescribing ? data[DATA] : data;
reader.readRules(rules);
- var ruleData = new List(reader.rules.length).map((x) => []).toList();
+ var ruleData = new List.generate(reader.rules.length, (_) => []);
var top = recursivelyFixUp(actualData, reader, ruleData);
result["data"] = ruleData;
result["roots"] = [top];
@@ -257,7 +257,7 @@
}
result[0] = w.serializedRules();
result[1] = flatData;
- result[2] = new List();
+ result[2] = [];
w._rootReferences().forEach((x) => x.writeToList(result[2]));
return result;
}
diff --git a/pkg/serialization/lib/src/serialization_rule.dart b/pkg/serialization/lib/src/serialization_rule.dart
index 8c58af6..de5113c 100644
--- a/pkg/serialization/lib/src/serialization_rule.dart
+++ b/pkg/serialization/lib/src/serialization_rule.dart
@@ -542,6 +542,8 @@
indexOf(x, [pos = 0]) => _inflated.toList().indexOf(x);
lastIndexOf(x, [pos]) => _inflated.toList().lastIndexOf(x);
+ Map<int, dynamic> asMap() => IterableMixinWorkaround.asMapList(this);
+
// These operations are all invalid
_throw() {
throw new UnsupportedError("Not modifiable");
diff --git a/pkg/serialization/test/polyfill_identity_map_test.dart b/pkg/serialization/test/polyfill_identity_map_test.dart
index 9988dca..bfc8fef 100644
--- a/pkg/serialization/test/polyfill_identity_map_test.dart
+++ b/pkg/serialization/test/polyfill_identity_map_test.dart
@@ -40,9 +40,9 @@
test('uniquing primitives', () {
var map = new IdentityMap();
var one = 'one';
- var two = new String.fromCharCodes(one.charCodes);
+ var two = new String.fromCharCodes(one.codeUnits);
map[one] = 1;
expect(map[two], 1);
expect(map[one], 1);
});
-}
\ No newline at end of file
+}
diff --git a/pkg/serialization/test/serialization_test.dart b/pkg/serialization/test/serialization_test.dart
index 5a9cc49..7b43793 100644
--- a/pkg/serialization/test/serialization_test.dart
+++ b/pkg/serialization/test/serialization_test.dart
@@ -154,7 +154,7 @@
var l = keysAndValues(list);
var s = keysAndValues(set);
- m.forEach((key, value) {expect(key.charCodes[0], value + 96);});
+ m.forEach((key, value) {expect(key.codeUnits[0], value + 96);});
l.forEach((key, value) {expect(key + 1, value);});
var index = 0;
var seen = new Set();
diff --git a/pkg/unittest/lib/compact_vm_config.dart b/pkg/unittest/lib/compact_vm_config.dart
index ede7010..ae8ec97 100644
--- a/pkg/unittest/lib/compact_vm_config.dart
+++ b/pkg/unittest/lib/compact_vm_config.dart
@@ -101,6 +101,9 @@
buffer.write(': ');
buffer.write(color);
+ // Ensure the line fits under MAX_LINE. [buffer] includes the color escape
+ // sequences too. Because these sequences are not visible characters, we
+ // make sure they are not counted towards the limit.
int nonVisible = _nonVisiblePrefix + color.length +
(failed != 0 ? (_RED.length + _NONE.length) : 0);
int len = buffer.length - nonVisible;
diff --git a/pkg/unittest/lib/html_config.dart b/pkg/unittest/lib/html_config.dart
index 9c64b53..2246bf3 100644
--- a/pkg/unittest/lib/html_config.dart
+++ b/pkg/unittest/lib/html_config.dart
@@ -126,8 +126,6 @@
window.postMessage('unittest-suite-wait-for-done', '*');
}
- void onTestResult(TestCase testCase) {}
-
void onSummary(int passed, int failed, int errors, List<TestCase> results,
String uncaughtError) {
_showResultsInPage(passed, failed, errors, results, _isLayoutTest,
diff --git a/pkg/unittest/lib/html_enhanced_config.dart b/pkg/unittest/lib/html_enhanced_config.dart
index 64c7a57..f9b9088 100644
--- a/pkg/unittest/lib/html_enhanced_config.dart
+++ b/pkg/unittest/lib/html_enhanced_config.dart
@@ -82,8 +82,6 @@
_installOnErrorHandler();
}
- void onTestResult(TestCase testCase) {}
-
void onSummary(int passed, int failed, int errors, List<TestCase> results,
String uncaughtError) {
_showInteractiveResultsInPage(passed, failed, errors, results,
diff --git a/pkg/unittest/lib/src/collection_matchers.dart b/pkg/unittest/lib/src/collection_matchers.dart
index 80ac428..30e38f6 100644
--- a/pkg/unittest/lib/src/collection_matchers.dart
+++ b/pkg/unittest/lib/src/collection_matchers.dart
@@ -142,7 +142,7 @@
} else if (expectedLength < actualLength) {
return 'has too many elements (${actualLength} > ${expectedLength})';
}
- List<bool> matched = new List<bool>.fixedLength(actualLength);
+ List<bool> matched = new List<bool>(actualLength);
for (var i = 0; i < actualLength; i++) {
matched[i] = false;
}
diff --git a/pkg/unittest/lib/src/config.dart b/pkg/unittest/lib/src/config.dart
index 2cd2334..29adfc8 100644
--- a/pkg/unittest/lib/src/config.dart
+++ b/pkg/unittest/lib/src/config.dart
@@ -15,19 +15,19 @@
// The VM won't shut down if a receive port is open. Use this to make sure
// we correctly wait for asynchronous tests.
ReceivePort _receivePort;
- TestCase currentTestCase = null;
/**
* Subclasses can override this with something useful for diagnostics.
* Particularly useful in cases where we have parent/child configurations
* such as layout tests.
*/
- get name => 'Configuration';
+ String get name => 'Configuration';
+
/**
* If true, then tests are started automatically (otherwise [runTests]
* must be called explicitly after the tests are set up.
*/
- get autoStart => true;
+ bool get autoStart => true;
/**
* Called as soon as the unittest framework becomes initialized. This is done
@@ -49,15 +49,24 @@
* a test suite.
*/
void onTestStart(TestCase testCase) {
- currentTestCase = testCase;
+ assert(testCase != null);
}
/**
- * Called when each test is completed. Useful to show intermediate progress on
- * a test suite.
+ * Called when each test is first completed. Useful to show intermediate
+ * progress on a test suite.
*/
void onTestResult(TestCase testCase) {
- currentTestCase = null;
+ assert(testCase != null);
+ }
+
+ /**
+ * Called when an already completed test changes state; for example a test
+ * that was marked as passing may later be marked as being in error because
+ * it still had callbacks being invoked.
+ */
+ void onTestResultChanged(TestCase testCase) {
+ assert(testCase != null);
}
/**
@@ -66,12 +75,9 @@
* should instead override logMessage which is passed the test case.
*/
void logMessage(String message) {
- if (currentTestCase == null || _currentTest >= _tests.length ||
- currentTestCase.id != _tests[_currentTest].id) {
- // Before or after tests run, or with a mismatch between what the
- // config and the test harness think is the current test. In this
- // case we pass null for the test case reference and let the config
- // decide what to do with this.
+ if (currentTestCase == null) {
+ // Before or after tests run. In this case we pass null for the test
+ // case reference and let the config decide what to do with this.
logTestCaseMessage(null, message);
} else {
logTestCaseMessage(currentTestCase, message);
@@ -152,24 +158,9 @@
/** Handle errors that happen outside the tests. */
// TODO(vsm): figure out how to expose the stack trace here
// Currently e.message works in dartium, but not in dartc.
- handleExternalError(e, String message) =>
+ void handleExternalError(e, String message) =>
_reportTestError('$message\nCaught $e', '');
- /**
- * Send messages to the test controller code (see 'test_controller.js'). This
- * is only needed to support browser tests with dart2js. Note: we could wrap
- * tests and send the appropriate messages to the controller through the
- * wrapper, but using wrappers has a noticeable overhead in the testing bots,
- * so we use this approach instead.
- *
- * Configurations that will not run in DRT (such as vm_config and
- * compact_vm_config), can safely override this method to avoid printing extra
- * mesages in the console.
- */
- // TODO(sigmund): find a way to unify notifyController and _postMessage
- void notifyController(String message) {
- }
-
_postMessage(String message) {
// In dart2js browser tests, the JavaScript-based test controller
// intercepts calls to print and listens for "secret" messages.
diff --git a/pkg/unittest/lib/src/core_matchers.dart b/pkg/unittest/lib/src/core_matchers.dart
index 44356d2..236da4e 100644
--- a/pkg/unittest/lib/src/core_matchers.dart
+++ b/pkg/unittest/lib/src/core_matchers.dart
@@ -325,8 +325,7 @@
// Queue up an asynchronous expectation that validates when the future
// completes.
item.then((value) {
- done(() => expect(false, isTrue, reason:
- "Expected future to fail, but succeeded with '$value'."));
+ done(() => fail("Expected future to fail, but succeeded with '$value'."));
}, onError: (e) {
done(() {
if (_matcher == null) return;
@@ -483,18 +482,6 @@
bool matches(item, MatchState matchState) => item is ArgumentError;
}
-/** A matcher for IllegalJSRegExpExceptions. */
-const isIllegalJSRegExpException = const _IllegalJSRegExpException();
-
-/** A matcher for functions that throw IllegalJSRegExpException. */
-const Matcher throwsIllegalJSRegExpException =
- const Throws(isIllegalJSRegExpException);
-
-class _IllegalJSRegExpException extends TypeMatcher {
- const _IllegalJSRegExpException() : super("IllegalJSRegExpException");
- bool matches(item, MatchState matchState) => item is IllegalJSRegExpException;
-}
-
/** A matcher for RangeErrors. */
const isRangeError = const _RangeError();
diff --git a/pkg/unittest/lib/src/expect.dart b/pkg/unittest/lib/src/expect.dart
index 5cc56fd..3542f7a 100644
--- a/pkg/unittest/lib/src/expect.dart
+++ b/pkg/unittest/lib/src/expect.dart
@@ -4,6 +4,18 @@
part of matcher;
+/** The objects thrown by the default failure handler. */
+class TestFailure {
+ String _message;
+
+ get message => _message;
+ set message(String value) => _message = value;
+
+ TestFailure(String message) : _message = message;
+
+ String toString() => _message;
+}
+
/**
* Some matchers, like those for Futures and exception testing,
* can fail in asynchronous sections, and throw exceptions.
@@ -13,7 +25,7 @@
* used safely. For example, the unittest library will set this
* to be expectAsync1. By default this is an identity function.
*/
-Function wrapAsync = (f) => f;
+Function wrapAsync = (f, [id]) => f;
/**
* This is the main assertion function. It asserts that [actual]
@@ -24,8 +36,8 @@
* [matcher] can be a value in which case it will be wrapped in an
* [equals] matcher.
*
- * If the assertion fails, then the default behavior is to throw an
- * [ExpectException], but this behavior can be changed by calling
+ * If the assertion fails, then the default behavior is to throw a
+ * [TestFailure], but this behavior can be changed by calling
* [configureExpectFailureHandler] and providing an alternative handler that
* implements the [IFailureHandler] interface. It is also possible to
* pass a [failureHandler] to [expect] as a final parameter for fine-
@@ -56,6 +68,13 @@
}
}
+void fail(String message, {FailureHandler failureHandler}) {
+ if (failureHandler == null) {
+ failureHandler = getOrCreateExpectFailureHandler();
+ }
+ failureHandler.fail(message);
+}
+
/**
* Takes an argument and returns an equivalent matcher.
* If the argument is already a matcher this does nothing,
@@ -75,7 +94,7 @@
// The handler for failed asserts.
FailureHandler _assertFailureHandler = null;
-// The default failure handler that throws ExpectExceptions.
+// The default failure handler that throws [TestFailure]s.
class DefaultFailureHandler implements FailureHandler {
DefaultFailureHandler() {
if (_assertErrorFormatter == null) {
@@ -83,7 +102,7 @@
}
}
void fail(String reason) {
- throw new ExpectException(reason);
+ throw new TestFailure(reason);
}
void failMatch(actual, Matcher matcher, String reason,
MatchState matchState, bool verbose) {
@@ -95,7 +114,7 @@
* Changes or resets to the default the failure handler for expect()
* [handler] is a reference to the new handler; if this is omitted
* or null then the failure handler is reset to the default, which
- * throws [ExpectExceptions] on [expect] assertion failures.
+ * throws [TestFailure]s on [expect] assertion failures.
*/
void configureExpectFailureHandler([FailureHandler handler = null]) {
if (handler == null) {
diff --git a/pkg/unittest/lib/src/future_matchers.dart b/pkg/unittest/lib/src/future_matchers.dart
index 77ba8bf..cfc0518 100644
--- a/pkg/unittest/lib/src/future_matchers.dart
+++ b/pkg/unittest/lib/src/future_matchers.dart
@@ -13,7 +13,7 @@
* To test that a Future completes with an exception, you can use [throws] and
* [throwsA].
*/
-Matcher completes = const _Completes(null);
+Matcher completes = const _Completes(null, '');
/**
* Matches a [Future] that completes succesfully with a value that matches
@@ -23,29 +23,35 @@
*
* To test that a Future completes with an exception, you can use [throws] and
* [throwsA].
+ *
+ * [id] is an optional tag that can be used to identify the completion matcher
+ * in error messages.
*/
-Matcher completion(matcher) => new _Completes(wrapMatcher(matcher));
+Matcher completion(matcher, [String id = '']) =>
+ new _Completes(wrapMatcher(matcher), id);
class _Completes extends BaseMatcher {
final Matcher _matcher;
+ final String _id;
- const _Completes(this._matcher);
+ const _Completes(this._matcher, this._id);
bool matches(item, MatchState matchState) {
if (item is! Future) return false;
- var done = wrapAsync((fn) => fn());
+ var done = wrapAsync((fn) => fn(), _id);
item.then((value) {
done(() { if (_matcher != null) expect(value, _matcher); });
}, onError: (e) {
- var reason = 'Expected future to complete successfully, but it failed '
- 'with ${e.error}';
+ var id = _id == '' ? '' : '${_id} ';
+ var reason = 'Expected future ${id}to complete successfully, '
+ 'but it failed with ${e.error}';
if (e.stackTrace != null) {
var stackTrace = e.stackTrace.toString();
stackTrace = ' ${stackTrace.replaceAll('\n', '\n ')}';
reason = '$reason\nStack trace:\n$stackTrace';
}
- done(() => expect(false, isTrue, reason: reason));
+ done(() => fail(reason));
});
return true;
diff --git a/pkg/unittest/lib/src/interfaces.dart b/pkg/unittest/lib/src/interfaces.dart
index 960cfbf..909c93e 100644
--- a/pkg/unittest/lib/src/interfaces.dart
+++ b/pkg/unittest/lib/src/interfaces.dart
@@ -79,7 +79,7 @@
/**
* Failed matches are reported using a default IFailureHandler.
- * The default implementation simply throws ExpectExceptions;
+ * The default implementation simply throws [TestFailure]s;
* this can be replaced by some other implementation of
* IFailureHandler by calling configureExpectHandler.
*/
diff --git a/pkg/unittest/lib/src/test_case.dart b/pkg/unittest/lib/src/test_case.dart
index 8efa694..da85f80 100644
--- a/pkg/unittest/lib/src/test_case.dart
+++ b/pkg/unittest/lib/src/test_case.dart
@@ -76,9 +76,25 @@
runningTime = null;
}
- void _runTest() {
+ Future _runTest() {
_prepTest();
- test();
+ // Increment/decrement callbackFunctionsOutstanding to prevent
+ // synchronous 'async' callbacks from causing the test to be
+ // marked as complete before the body is completely executed.
+ ++callbackFunctionsOutstanding;
+ var f = test();
+ --callbackFunctionsOutstanding;
+ if (f is Future) {
+ f.then((_) => _finishTest())
+ .catchError((e) => fail("${e.error}"));
+ return f;
+ } else {
+ _finishTest();
+ return null;
+ }
+ }
+
+ void _finishTest() {
if (result == null && callbackFunctionsOutstanding == 0) {
pass();
}
@@ -98,19 +114,21 @@
_doneTeardown = false;
var rtn = _setUp == null ? null : _setUp();
if (rtn is Future) {
- rtn.then(expectAsync1((_) =>_runTest(),
- id: '[Async setUp completion handler]'))
- .catchError((e) {
- _prepTest();
- // Calling error() will result in the tearDown being done.
- // One could debate whether tearDown should be done after
- // a failed setUp. There is no right answer, but doing it
- // seems to be the more conservative approach, because
- // unittest will not stop at a test failure.
- error("$description: Test setup failed: ${e.error}");
- });
+ rtn.then((_) => _runTest())
+ .catchError((e) {
+ _prepTest();
+ // Calling error() will result in the tearDown being done.
+ // One could debate whether tearDown should be done after
+ // a failed setUp. There is no right answer, but doing it
+ // seems to be the more conservative approach, because
+ // unittest will not stop at a test failure.
+ error("$description: Test setup failed: ${e.error}");
+ });
} else {
- _runTest();
+ var f = _runTest();
+ if (f != null) {
+ return f;
+ }
}
if (result == null) { // Not complete.
_testComplete = new Completer();
@@ -126,71 +144,75 @@
}
}
- void _complete() {
+ // Set the results, notify the config, and return true if this
+ // is the first time the result is being set.
+ void _setResult(String testResult, String messageText, String stack) {
+ message = messageText;
+ stackTrace = stack;
+ if (result == null) {
+ result = testResult;
+ _config.onTestResult(this);
+ } else {
+ result = testResult;
+ _config.onTestResultChanged(this);
+ }
+ }
+
+ void _complete(String testResult,
+ [String messageText = '',
+ String stack = '']) {
if (runningTime == null) {
// TODO(gram): currently the duration measurement code is blocked
// by issue 4437. When that is fixed replace the line below with:
// runningTime = new DateTime.now().difference(startTime);
runningTime = new Duration(milliseconds: 0);
}
+ _setResult(testResult, messageText, stack);
if (!_doneTeardown) {
_doneTeardown = true;
if (_tearDown != null) {
var rtn = _tearDown();
if (rtn is Future) {
rtn.then((_) {
- if (result == null) {
- // The test passed. In some cases we will already
- // have set this result (e.g. if the test was async
- // and all callbacks completed). If not, we do it here.
- pass();
- } else {
- // The test has already been marked as pass/fail.
- // Just report the updated result.
- _config.onTestResult(this);
- }
_notifyComplete();
})
.catchError((e) {
// We don't call fail() as that will potentially result in
// spurious messages like 'test failed more than once'.
- result = ERROR;
- message = "$description: Test teardown failed: ${e.error}";
- _config.onTestResult(this);
+ _setResult(ERROR, "$description: Test teardown failed: ${e.error}",
+ e.stackTrace.toString());
_notifyComplete();
});
return;
}
}
}
- _config.onTestResult(this);
_notifyComplete();
}
void pass() {
- result = PASS;
- _complete();
+ _complete(PASS);
}
void fail(String messageText, [String stack = '']) {
if (result != null) {
- if (result == PASS) {
- error('Test failed after initially passing: $messageText', stack);
- } else if (result == FAIL) {
- error('Test failed more than once: $messageText', stack);
- }
+ String newMessage = (result == PASS)
+ ? 'Test failed after initially passing: $messageText'
+ : 'Test failed more than once: $messageText';
+ // TODO(gram): Should we combine the stack with the old one?
+ _complete(ERROR, newMessage, stack);
} else {
- result = FAIL;
- message = messageText;
- stackTrace = stack;
- _complete();
+ _complete(FAIL, messageText, stack);
}
}
void error(String messageText, [String stack = '']) {
- result = ERROR;
- message = messageText;
- stackTrace = stack;
- _complete();
+ _complete(ERROR, messageText, stack);
+ }
+
+ void markCallbackComplete() {
+ if (--callbackFunctionsOutstanding == 0 && !isComplete) {
+ pass();
+ }
}
}
diff --git a/pkg/unittest/lib/unittest.dart b/pkg/unittest/lib/unittest.dart
index de9cc45..1177de5 100644
--- a/pkg/unittest/lib/unittest.dart
+++ b/pkg/unittest/lib/unittest.dart
@@ -113,6 +113,19 @@
* callback should be protected within a call to guardAsync(); this will ensure
* that exceptions are properly handled.
*
+ * A variation on this is expectAsyncUntilX(), which takes a callback as the
+ * first parameter and a predicate function as the second parameter; after each
+ * time * the callback is called, the predicate function will be called; if it
+ * returns false the test will still be considered incomplete.
+ *
+ * Test functions can return [Future]s, which provide another way of doing
+ * asynchronous tests. The test framework will handle exceptions thrown by
+ * the Future, and will advance to the next test when the Future is complete.
+ * It is still important to use expectAsync/guardAsync with any parts of the
+ * test that may be invoked from a top level context (for example, with
+ * Timer.run()], as the Future exception handler may not capture exceptions
+ * in such code.
+ *
* Note: due to some language limitations we have to use different functions
* depending on the number of positional arguments of the callback. In the
* future, we plan to expose a single `expectAsync` function that can be used
@@ -189,7 +202,7 @@
List<TestCase> _tests;
/** Get the list of tests. */
-get testCases => _tests;
+List<TestCase> get testCases => _tests;
/**
* Callback used to run tests. Entrypoints can replace this with their own
@@ -205,6 +218,12 @@
/** Current test being executed. */
int _currentTest = 0;
+TestCase _currentTestCase;
+
+TestCase get currentTestCase =>
+ (_currentTest >= 0 && _currentTest < _tests.length)
+ ? _tests[_currentTest]
+ : null;
/** Whether the framework is in an initialized state. */
bool _initialized = false;
@@ -274,18 +293,27 @@
// TODO(sigmund): remove this class and simply use a closure with named
// arguments (if still applicable).
class _SpreadArgsHelper {
- Function _callback;
- int _expectedCalls;
- int _actualCalls = 0;
- int _testNum;
- TestCase _testCase;
- Function _shouldCallBack;
- Function _isDone;
- String _id;
- static const _sentinel = const _Sentinel();
+ final Function callback;
+ final int minExpectedCalls;
+ final int maxExpectedCalls;
+ final Function isDone;
+ final int testNum;
+ final String id;
+ int actualCalls = 0;
+ TestCase testCase;
+ bool complete;
+ static const sentinel = const _Sentinel();
- _init(Function callback, Function shouldCallBack, Function isDone,
- [expectedCalls = 0]) {
+ _SpreadArgsHelper(Function callback, int minExpected, int maxExpected,
+ Function isDone, String id)
+ : this.callback = callback,
+ minExpectedCalls = minExpected,
+ maxExpectedCalls = (maxExpected == 0 && minExpected > 0)
+ ? minExpected
+ : maxExpected,
+ this.isDone = isDone,
+ testNum = _currentTest,
+ this.id = _makeCallbackId(id, callback) {
ensureInitialized();
if (!(_currentTest >= 0 &&
_currentTest < _tests.length &&
@@ -296,137 +324,121 @@
assert(_currentTest >= 0 &&
_currentTest < _tests.length &&
_tests[_currentTest] != null);
- _callback = callback;
- _shouldCallBack = shouldCallBack;
- _isDone = isDone;
- _expectedCalls = expectedCalls;
- _testNum = _currentTest;
- _testCase = _tests[_currentTest];
- if (expectedCalls > 0) {
- _testCase.callbackFunctionsOutstanding++;
+ testCase = _tests[_currentTest];
+ if (isDone != null || minExpected > 0) {
+ testCase.callbackFunctionsOutstanding++;
+ complete = false;
+ } else {
+ complete = true;
}
- _id = '';
- // If the callback is not an anonymous closure, try to get the
- // name.
- var fname = callback.toString();
- var prefix = "Function '";
- var pos = fname.indexOf(prefix);
- if (pos > 0) {
- pos += prefix.length;
- var epos = fname.indexOf("'", pos);
- if (epos > 0) {
- _id = "${fname.substring(pos, epos)} ";
+ }
+
+ static _makeCallbackId(String id, Function callback) {
+ // Try to create a reasonable id.
+ if (id != null) {
+ return "$id ";
+ } else {
+ // If the callback is not an anonymous closure, try to get the
+ // name.
+ var fname = callback.toString();
+ var prefix = "Function '";
+ var pos = fname.indexOf(prefix);
+ if (pos > 0) {
+ pos += prefix.length;
+ var epos = fname.indexOf("'", pos);
+ if (epos > 0) {
+ return "${fname.substring(pos, epos)} ";
+ }
}
}
+ return '';
}
- _SpreadArgsHelper(callback, shouldCallBack, isDone) {
- _init(callback, shouldCallBack, isDone);
- }
-
- _SpreadArgsHelper.fixedCallCount(callback, expectedCalls, id) {
- _init(callback, _checkCallCount, _allCallsDone, expectedCalls);
- if (id != null) {
- _id = "$id ";
- }
- }
-
- _SpreadArgsHelper.variableCallCount(callback, isDone) {
- _init(callback, _always, isDone, 1);
- }
-
- _SpreadArgsHelper.optionalCalls(callback) {
- _init(callback, _always, () => false, 0);
- }
-
- _after() {
- if (_isDone()) {
- _handleCallbackFunctionComplete(_testNum, _id);
- }
- }
-
- _allCallsDone() => _actualCalls == _expectedCalls;
-
- _always() {
- // Always run except if the test is done.
- if (_testCase.isComplete) {
- _testCase.error(
- 'Callback ${_id}called after already being marked '
- 'as done ($_actualCalls).',
- '');
+ shouldCallBack() {
+ ++actualCalls;
+ if (testCase.isComplete) {
+ // Don't run if the test is done. We don't throw here as this is not
+ // the current test, but we do mark the old test as having an error
+ // if it previously passed.
+ if (testCase.result == PASS) {
+ testCase.error(
+ 'Callback ${id}called ($actualCalls) after test case '
+ '${testCase.description} has already been marked as '
+ '${testCase.result}.', '');
+ }
return false;
- } else {
- return true;
+ } else if (maxExpectedCalls >= 0 && actualCalls > maxExpectedCalls) {
+ throw new TestFailure('Callback ${id}called more times than expected '
+ '($maxExpectedCalls).');
+ }
+ return true;
+ }
+
+ after() {
+ if (!complete) {
+ if (minExpectedCalls > 0 && actualCalls < minExpectedCalls) return;
+ if (isDone != null && !isDone()) return;
+
+ // Mark this callback as complete and remove it from the testcase
+ // oustanding callback count; if that hits zero the testcase is done.
+ complete = true;
+ testCase.markCallbackComplete();
}
}
- invoke([arg0 = _sentinel, arg1 = _sentinel, arg2 = _sentinel,
- arg3 = _sentinel, arg4 = _sentinel]) {
- return guardAsync(() {
- ++_actualCalls;
- if (!_shouldCallBack()) {
+ invoke([arg0 = sentinel, arg1 = sentinel, arg2 = sentinel,
+ arg3 = sentinel, arg4 = sentinel]) {
+ return _guardAsync(() {
+ if (!shouldCallBack()) {
return;
- } else if (arg0 == _sentinel) {
- return _callback();
- } else if (arg1 == _sentinel) {
- return _callback(arg0);
- } else if (arg2 == _sentinel) {
- return _callback(arg0, arg1);
- } else if (arg3 == _sentinel) {
- return _callback(arg0, arg1, arg2);
- } else if (arg4 == _sentinel) {
- return _callback(arg0, arg1, arg2, arg3);
+ } else if (arg0 == sentinel) {
+ return callback();
+ } else if (arg1 == sentinel) {
+ return callback(arg0);
+ } else if (arg2 == sentinel) {
+ return callback(arg0, arg1);
+ } else if (arg3 == sentinel) {
+ return callback(arg0, arg1, arg2);
+ } else if (arg4 == sentinel) {
+ return callback(arg0, arg1, arg2, arg3);
} else {
- _testCase.error(
+ testCase.error(
'unittest lib does not support callbacks with more than'
' 4 arguments.',
'');
}
},
- _after, _testNum);
+ after, testNum);
}
invoke0() {
- return guardAsync(
+ return _guardAsync(
() {
- ++_actualCalls;
- if (_shouldCallBack()) {
- return _callback();
+ if (shouldCallBack()) {
+ return callback();
}
},
- _after, _testNum);
+ after, testNum);
}
invoke1(arg1) {
- return guardAsync(
+ return _guardAsync(
() {
- ++_actualCalls;
- if (_shouldCallBack()) {
- return _callback(arg1);
+ if (shouldCallBack()) {
+ return callback(arg1);
}
},
- _after, _testNum);
+ after, testNum);
}
invoke2(arg1, arg2) {
- return guardAsync(
+ return _guardAsync(
() {
- ++_actualCalls;
- if (_shouldCallBack()) {
- return _callback(arg1, arg2);
+ if (shouldCallBack()) {
+ return callback(arg1, arg2);
}
},
- _after, _testNum);
- }
-
- /** Returns false if we exceded the number of expected calls. */
- bool _checkCallCount() {
- if (_actualCalls > _expectedCalls) {
- _testCase.error('Callback ${_id}called more times than expected '
- '($_actualCalls > $_expectedCalls).', '');
- return false;
- }
- return true;
+ after, testNum);
}
}
@@ -440,9 +452,9 @@
* to provide more descriptive error messages if the callback is called more
* often than expected.
*/
-Function _expectAsync(Function callback, {int count: 1, String id}) {
- return new _SpreadArgsHelper.
- fixedCallCount(callback, count, id).invoke;
+Function _expectAsync(Function callback,
+ {int count: 1, int max: 0, String id}) {
+ return new _SpreadArgsHelper(callback, count, max, null, id).invoke;
}
/**
@@ -453,26 +465,31 @@
* tracked and reported. [callback] should take 0 positional arguments (named
* arguments are not supported). [id] can be used to provide more
* descriptive error messages if the callback is called more often than
- * expected.
+ * expected. [max] can be used to specify an upper bound on the number of
+ * calls; if this is exceeded the test will fail (or be marked as in error if
+ * it was already complete). A value of 0 for [max] (the default) will set
+ * the upper bound to the same value as [count]; i.e. the callback should be
+ * called exactly [count] times. A value of -1 for [max] will mean no upper
+ * bound.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsync0(Function callback, {int count: 1, String id}) {
- return new _SpreadArgsHelper.
- fixedCallCount(callback, count, id).invoke0;
+Function expectAsync0(Function callback,
+ {int count: 1, int max: 0, String id}) {
+ return new _SpreadArgsHelper(callback, count, max, null, id).invoke0;
}
/** Like [expectAsync0] but [callback] should take 1 positional argument. */
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsync1(Function callback, {int count: 1, String id}) {
- return new _SpreadArgsHelper.
- fixedCallCount(callback, count, id).invoke1;
+Function expectAsync1(Function callback,
+ {int count: 1, int max: 0, String id}) {
+ return new _SpreadArgsHelper(callback, count, max, null, id).invoke1;
}
/** Like [expectAsync0] but [callback] should take 2 positional arguments. */
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsync2(Function callback, {int count: 1, String id}) {
- return new _SpreadArgsHelper.
- fixedCallCount(callback, count, id).invoke2;
+Function expectAsync2(Function callback,
+ {int count: 1, int max: 0, String id}) {
+ return new _SpreadArgsHelper(callback, count, max, null, id).invoke2;
}
/**
@@ -481,10 +498,12 @@
* when it returns true will it continue with the following test. Using
* [expectAsyncUntil] will also ensure that errors that occur within
* [callback] are tracked and reported. [callback] should take between 0 and
- * 4 positional arguments (named arguments are not supported).
+ * 4 positional arguments (named arguments are not supported). [id] can be
+ * used to identify the callback in error messages (for example if it is called
+ * after the test case is complete).
*/
-Function _expectAsyncUntil(Function callback, Function isDone) {
- return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke;
+Function _expectAsyncUntil(Function callback, Function isDone, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke;
}
/**
@@ -493,27 +512,29 @@
* when it returns true will it continue with the following test. Using
* [expectAsyncUntil0] will also ensure that errors that occur within
* [callback] are tracked and reported. [callback] should take 0 positional
- * arguments (named arguments are not supported).
+ * arguments (named arguments are not supported). [id] can be used to
+ * identify the callback in error messages (for example if it is called
+ * after the test case is complete).
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil0(Function callback, Function isDone) {
- return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke0;
+Function expectAsyncUntil0(Function callback, Function isDone, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke0;
}
/**
* Like [expectAsyncUntil0] but [callback] should take 1 positional argument.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil1(Function callback, Function isDone) {
- return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke1;
+Function expectAsyncUntil1(Function callback, Function isDone, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke1;
}
/**
* Like [expectAsyncUntil0] but [callback] should take 2 positional arguments.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil2(Function callback, Function isDone) {
- return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2;
+Function expectAsyncUntil2(Function callback, Function isDone, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke2;
}
/**
@@ -522,10 +543,11 @@
* test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
* might optionally be called but may never be called during the test.
* [callback] should take between 0 and 4 positional arguments (named arguments
- * are not supported).
+ * are not supported). [id] can be used to identify the callback in error
+ * messages (for example if it is called after the test case is complete).
*/
-Function _protectAsync(Function callback) {
- return new _SpreadArgsHelper.optionalCalls(callback).invoke;
+Function _protectAsync(Function callback, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke;
}
/**
@@ -534,27 +556,28 @@
* test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
* might optionally be called but may never be called during the test.
* [callback] should take 0 positional arguments (named arguments are not
- * supported).
+ * supported). [id] can be used to identify the callback in error
+ * messages (for example if it is called after the test case is complete).
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function protectAsync0(Function callback) {
- return new _SpreadArgsHelper.optionalCalls(callback).invoke0;
+Function protectAsync0(Function callback, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke0;
}
/**
* Like [protectAsync0] but [callback] should take 1 positional argument.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function protectAsync1(Function callback) {
- return new _SpreadArgsHelper.optionalCalls(callback).invoke1;
+Function protectAsync1(Function callback, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke1;
}
/**
* Like [protectAsync0] but [callback] should take 2 positional arguments.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function protectAsync2(Function callback) {
- return new _SpreadArgsHelper.optionalCalls(callback).invoke2;
+Function protectAsync2(Function callback, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke2;
}
/**
@@ -617,38 +640,6 @@
_testTeardown = teardownTest;
}
-/**
- * Called when one of the callback functions is done with all expected
- * calls.
- */
-void _handleCallbackFunctionComplete(testNum, [id = '']) {
- // TODO (gram): we defer this to give the nextBatch recursive
- // stack a chance to unwind. This is a temporary hack but
- // really a bunch of code here needs to be fixed. We have a
- // single array that is being iterated through by nextBatch(),
- // which is recursively invoked in the case of async tests that
- // run synchronously. Bad things can then happen.
- _defer(() {
- if (_currentTest != testNum) {
- if (_tests[testNum].result == PASS) {
- _tests[testNum].error("${id}Unexpected extra callbacks", '');
- }
- } else if (_currentTest < _tests.length) {
- final testCase = _tests[_currentTest];
- --testCase.callbackFunctionsOutstanding;
- if (testCase.callbackFunctionsOutstanding < 0) {
- // TODO(gram): Check: Can this even happen?
- testCase.error(
- 'More calls to _handleCallbackFunctionComplete() than expected.',
- '');
- } else if (testCase.callbackFunctionsOutstanding == 0 &&
- !testCase.isComplete) {
- testCase.pass();
- }
- }
- });
-}
-
/** Advance to the next test case. */
void _nextTestCase() {
_defer(() {
@@ -658,14 +649,6 @@
}
/**
- * Temporary hack: expose old API.
- * TODO(gram) remove this when WebKit tests are working with new framework
- */
-void callbackDone() {
- _handleCallbackFunctionComplete(_currentTest);
-}
-
-/**
* Utility function that can be used to notify the test framework that an
* error was caught outside of this library.
*/
@@ -678,20 +661,20 @@
}
}
-/** Runs [callback] at the end of the event loop. */
+/**
+ * Runs [callback] at the end of the event loop. Note that we don't wrap
+ * the callback in guardAsync; this is for test framework functions which
+ * should not be throwing unexpected exceptions that end up failing test
+ * cases! Furthermore, we need the final exception to be thrown but not
+ * caught by the test framework if any test cases failed. However, tests
+ * that make use of a similar defer function *should* wrap the callback
+ * (as we do in unitttest_test.dart).
+ */
_defer(void callback()) {
- // Exploit isolate ports as a platform-independent mechanism to queue a
- // message at the end of the event loop.
- // TODO(sigmund): expose this functionality somewhere in our libraries.
- final port = new ReceivePort();
- port.receive((msg, reply) {
- callback();
- port.close();
- });
- port.toSendPort().send(null, null);
+ (new Future.immediate(null)).then((_) => callback());
}
-rerunTests() {
+void rerunTests() {
_uncaughtErrorMessage = null;
_initialized = true; // We don't want to reset the test array.
runTests();
@@ -712,11 +695,11 @@
} else if (testFilter is Function) {
filterFunction = testFilter;
}
- _tests = _tests.where(filterFunction).toList();
+ _tests.retainMatching(filterFunction);
}
/** Runs all queued tests, one at a time. */
-runTests() {
+void runTests() {
_currentTest = 0;
_currentGroup = '';
@@ -733,11 +716,17 @@
}
/**
- * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update
- * the [_currentTest] status accordingly.
+ * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is
+ * passed to the corresponding test.
+ *
+ * The value returned by [tryBody] (if any) is returned by [guardAsync].
*/
-guardAsync(tryBody, [finallyBody, testNum = -1]) {
- if (testNum < 0) testNum = _currentTest;
+guardAsync(Function tryBody) {
+ return _guardAsync(tryBody, null, _currentTest);
+}
+
+_guardAsync(Function tryBody, Function finallyBody, int testNum) {
+ assert(testNum >= 0);
try {
return tryBody();
} catch (e, trace) {
@@ -750,7 +739,7 @@
/**
* Registers that an exception was caught for the current test.
*/
-registerException(e, [trace]) {
+void registerException(e, [trace]) {
_registerException(_currentTest, e, trace);
}
@@ -759,11 +748,11 @@
*/
_registerException(testNum, e, [trace]) {
trace = trace == null ? '' : trace.toString();
+ String message = (e is TestFailure) ? e.message : 'Caught $e';
if (_tests[testNum].result == null) {
- String message = (e is ExpectException) ? e.message : 'Caught $e';
_tests[testNum].fail(message, trace);
} else {
- _tests[testNum].error('Caught $e', trace);
+ _tests[testNum].error(message, trace);
}
}
@@ -779,13 +768,9 @@
break;
}
final testCase = _tests[_currentTest];
- var f = guardAsync(testCase.run, null, _currentTest);
+ var f = _guardAsync(testCase.run, null, _currentTest);
if (f != null) {
- f.then((_){})
- .catchError((e) {
- testCase.error(e.toString(), e.stackTrace);
- })
- .whenComplete(() {
+ f.whenComplete(() {
_nextTestCase(); // Schedule the next test.
});
break;
@@ -819,20 +804,16 @@
return _currentGroup != '' ? '$_currentGroup$groupSep$spec' : spec;
}
-void fail(String message) {
- throw new ExpectException(message);
-}
-
/**
* Lazily initializes the test library if not already initialized.
*/
-ensureInitialized() {
+void ensureInitialized() {
if (_initialized) {
return;
}
_initialized = true;
// Hook our async guard into the matcher library.
- wrapAsync = expectAsync1;
+ wrapAsync = (f, [id]) => expectAsync1(f, id: id);
_tests = <TestCase>[];
_testRunner = _nextBatch;
@@ -882,4 +863,4 @@
void disableTest(int testId) => _setTestEnabledState(testId, false);
/** Signature for a test function. */
-typedef void TestFunction();
+typedef dynamic TestFunction();
diff --git a/pkg/unittest/lib/vm_config.dart b/pkg/unittest/lib/vm_config.dart
index 1aabe06..d75cb2a 100644
--- a/pkg/unittest/lib/vm_config.dart
+++ b/pkg/unittest/lib/vm_config.dart
@@ -21,8 +21,6 @@
exit(1);
}
}
-
- void notifyController(String msg) {}
}
void useVMConfiguration() {
diff --git a/pkg/unittest/test/matchers_test.dart b/pkg/unittest/test/matchers_test.dart
index 71cdb6b..b11f7a6 100644
--- a/pkg/unittest/test/matchers_test.dart
+++ b/pkg/unittest/test/matchers_test.dart
@@ -158,16 +158,6 @@
"ArgumentError.");
});
- test('throwsIllegalJSRegExpException', () {
- shouldPass(() { throw new IllegalJSRegExpException('',''); },
- throwsIllegalJSRegExpException);
- shouldFail(() { throw new Exception(); },
- throwsIllegalJSRegExpException,
- "Expected: throws an exception which matches IllegalJSRegExpException "
- "but: exception <Exception> does not match "
- "IllegalJSRegExpException.");
- });
-
test('throwsRangeError', () {
shouldPass(() { throw new RangeError(0); },
throwsRangeError);
diff --git a/pkg/unittest/test/unittest_test.dart b/pkg/unittest/test/unittest_test.dart
index 0ee50c2..c6ab7a0 100644
--- a/pkg/unittest/test/unittest_test.dart
+++ b/pkg/unittest/test/unittest_test.dart
@@ -20,14 +20,7 @@
var _testconfig; // test configuration to capture onDone
_defer(void fn()) {
- // Exploit isolate ports as a platform-independent mechanism to queue a
- // message at the end of the event loop. Stolen from unittest.dart.
- final port = new ReceivePort();
- port.receive((msg, reply) {
- fn();
- port.close();
- });
- port.toSendPort().send(null, null);
+ return (new Future.immediate(null)).then((_) => guardAsync(fn));
}
String buildStatusString(int passed, int failed, int errors,
@@ -115,9 +108,14 @@
() =>_defer(expectAsync0((){ ++_testconfig.count;})));
} else if (testName == 'excess callback test') {
test(testName, () {
- var _callback = expectAsync0(() => ++_testconfig.count);
- _defer(_callback);
- _defer(_callback);
+ var _callback0 = expectAsync0(() => ++_testconfig.count);
+ var _callback1 = expectAsync0(() => ++_testconfig.count);
+ var _callback2 = expectAsync0(() {
+ _callback1();
+ _callback1();
+ _callback0();
+ });
+ _defer(_callback2);
});
} else if (testName == 'completion test') {
test(testName, () {
@@ -136,15 +134,13 @@
_defer(() => guardAsync(() { throw "error!"; }));
});
} else if (testName == 'late exception test') {
+ var f;
test('testOne', () {
- var f = expectAsync0(() {});
- _defer(protectAsync0(() {
- _defer(protectAsync0(() => expect(false, isTrue)));
- expect(false, isTrue);
- }));
+ f = expectAsync0(() {});
+ _defer(f);
});
test('testTwo', () {
- _defer(expectAsync0(() {}));
+ _defer(expectAsync0(() { f(); }));
});
} else if (testName == 'middle exception test') {
test('testOne', () { expect(true, isTrue); });
@@ -234,6 +230,107 @@
// The next test is just to make sure we make steady progress
// through the tests.
test('post groups', () {});
+ } else if (testName == 'test returning future') {
+ test("successful", () {
+ return _defer(() {
+ expect(true, true);
+ });
+ });
+ // We repeat the fail and error tests, because during development
+ // I had a situation where either worked fine on their own, and
+ // error/fail worked, but fail/error would time out.
+ test("error1", () {
+ var callback = expectAsync0((){});
+ var excesscallback = expectAsync0((){});
+ return _defer(() {
+ excesscallback();
+ excesscallback();
+ excesscallback();
+ callback();
+ });
+ });
+ test("fail1", () {
+ return _defer(() {
+ expect(true, false);
+ });
+ });
+ test("error2", () {
+ var callback = expectAsync0((){});
+ var excesscallback = expectAsync0((){});
+ return _defer(() {
+ excesscallback();
+ excesscallback();
+ callback();
+ });
+ });
+ test("fail2", () {
+ return _defer(() {
+ fail('failure');
+ });
+ });
+ test('foo5', () {
+ });
+ } else if (testName == 'test returning future using Timer') {
+ test("successful", () {
+ return _defer(() {
+ Timer.run(() {
+ guardAsync(() {
+ expect(true, true);
+ });
+ });
+ });
+ });
+ test("fail1", () {
+ var callback = expectAsync0((){});
+ return _defer(() {
+ Timer.run(() {
+ guardAsync(() {
+ expect(true, false);
+ callback();
+ });
+ });
+ });
+ });
+ test('error1', () {
+ var callback = expectAsync0((){});
+ var excesscallback = expectAsync0((){});
+ return _defer(() {
+ Timer.run(() {
+ guardAsync(() {
+ excesscallback();
+ excesscallback();
+ callback();
+ });
+ });
+ });
+ });
+ test("fail2", () {
+ var callback = expectAsync0((){});
+ return _defer(() {
+ Timer.run(() {
+ guardAsync(() {
+ fail('failure');
+ callback();
+ });
+ });
+ });
+ });
+ test('error2', () {
+ var callback = expectAsync0((){});
+ var excesscallback = expectAsync0((){});
+ return _defer(() {
+ Timer.run(() {
+ guardAsync(() {
+ excesscallback();
+ excesscallback();
+ excesscallback();
+ callback();
+ });
+ });
+ });
+ });
+ test('foo6', () {
+ });
}
});
}
@@ -267,7 +364,9 @@
'async exception test',
'late exception test',
'middle exception test',
- 'async setup/teardown test'
+ 'async setup/teardown test',
+ 'test returning future',
+ 'test returning future using Timer'
];
expected = [
@@ -282,13 +381,13 @@
buildStatusString(1, 0, 0, 'a ${tests[6]}', count: 0,
setup: 'setup', teardown: 'teardown'),
buildStatusString(1, 0, 0, tests[7], count: 1),
- buildStatusString(0, 0, 1, tests[8], count: 1,
- message: 'Callback called more times than expected (2 > 1).'),
+ buildStatusString(0, 1, 0, tests[8], count: 1,
+ message: 'Callback called more times than expected (1).'),
buildStatusString(1, 0, 0, tests[9], count: 10),
buildStatusString(0, 1, 0, tests[10], message: 'Caught error!'),
buildStatusString(1, 0, 1, 'testOne',
- message: 'Callback called after already being marked as done '
- '(1).:testTwo:'),
+ message: 'Callback called (2) after test case testOne has already '
+ 'been marked as pass.:testTwo:'),
buildStatusString(2, 1, 0,
'testOne::testTwo:Expected: false but: was <true>.:testThree'),
buildStatusString(2, 0, 3,
@@ -299,7 +398,21 @@
'foo3: Test setup failed: Failed to complete setUp:'
'bad setup/bad teardown foo4:bad setup/bad teardown '
'foo4: Test teardown failed: Failed to complete tearDown:'
- 'post groups')
+ 'post groups'),
+ buildStatusString(2, 4, 0,
+ 'successful::'
+ 'error1:Callback called more times than expected (1).:'
+ 'fail1:Expected: <false> but: was <true>.:'
+ 'error2:Callback called more times than expected (1).:'
+ 'fail2:failure:'
+ 'foo5'),
+ buildStatusString(2, 4, 0,
+ 'successful::'
+ 'fail1:Expected: <false> but: was <true>.:'
+ 'error1:Callback called more times than expected (1).:'
+ 'fail2:failure:'
+ 'error2:Callback called more times than expected (1).:'
+ 'foo6'),
];
actual = [];
diff --git a/pkg/webdriver/lib/src/base64decoder.dart b/pkg/webdriver/lib/src/base64decoder.dart
index 616f2f4..7e9175b 100644
--- a/pkg/webdriver/lib/src/base64decoder.dart
+++ b/pkg/webdriver/lib/src/base64decoder.dart
@@ -11,7 +11,7 @@
class Base64Decoder {
static int getVal(String s, pos) {
- int code = s.charCodeAt(pos);
+ int code = s.codeUnitAt(pos);
if (code >= 65 && code < (65+26)) { // 'A'..'Z'
return code - 65;
} else if (code >= 97 && code < (97+26)) { // 'a'..'z'
diff --git a/pkg/webdriver/lib/webdriver.dart b/pkg/webdriver/lib/webdriver.dart
index ffb0dff..41d0cbc 100644
--- a/pkg/webdriver/lib/webdriver.dart
+++ b/pkg/webdriver/lib/webdriver.dart
@@ -276,15 +276,14 @@
results = sbuf.toString().trim();
// For some reason we get a bunch of NULs on the end
// of the text and the json.parse blows up on these, so
- // strip them. We have to do this the hard way as
- // replaceAll('\0', '') does not work.
+ // strip them.
// These NULs can be seen in the TCP packet, so it is not
// an issue with character encoding; it seems to be a bug
// in WebDriver stack.
for (var i = results.length; --i >= 0;) {
- var code = results.charCodeAt(i);
+ var code = results.codeUnitAt(i);
if (code != 0) {
- results = results.substring(0, i+1);
+ results = results.substring(0, i + 1);
break;
}
}
diff --git a/pkg/yaml/lib/composer.dart b/pkg/yaml/lib/composer.dart
index e9c1879..e22159f 100644
--- a/pkg/yaml/lib/composer.dart
+++ b/pkg/yaml/lib/composer.dart
@@ -120,12 +120,7 @@
match = new RegExp("^0o([0-7]+)\$").firstMatch(content);
if (match != null) {
- // TODO(nweiz): clean this up when Dart can parse an octal string
- var n = 0;
- for (var c in match.group(1).charCodes) {
- n *= 8;
- n += c - 48;
- }
+ int n = int.parse(match.group(1), radix: 8);
return new _ScalarNode(_Tag.yaml("int"), value: n);
}
@@ -153,15 +148,13 @@
match = new RegExp("^([+-]?)\.(inf|Inf|INF)\$").firstMatch(content);
if (match != null) {
- var infinityStr = match.group(1) == "-" ? "-Infinity" : "Infinity";
- return new _ScalarNode(_Tag.yaml("float"),
- value: double.parse(infinityStr));
+ var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY;
+ return new _ScalarNode(_Tag.yaml("float"), value: value);
}
match = new RegExp("^\.(nan|NaN|NAN)\$").firstMatch(content);
if (match != null) {
- return new _ScalarNode(_Tag.yaml("float"),
- value: double.parse("NaN"));
+ return new _ScalarNode(_Tag.yaml("float"), value: double.NAN);
}
return null;
diff --git a/pkg/yaml/lib/model.dart b/pkg/yaml/lib/model.dart
index 9f1474e..5c09aa5 100644
--- a/pkg/yaml/lib/model.dart
+++ b/pkg/yaml/lib/model.dart
@@ -149,7 +149,7 @@
// TODO(nweiz): This could be faster if we used a RegExp to check for
// special characters and short-circuited if they didn't exist.
- var escapedValue = value.charCodes.map((c) {
+ var escapedValue = value.codeUnits.map((c) {
switch (c) {
case _Parser.TAB: return "\\t";
case _Parser.LF: return "\\n";
diff --git a/pkg/yaml/lib/parser.dart b/pkg/yaml/lib/parser.dart
index f2f255e..386bb59 100644
--- a/pkg/yaml/lib/parser.dart
+++ b/pkg/yaml/lib/parser.dart
@@ -172,7 +172,7 @@
/// forward one character. Also updates the current line and column numbers.
int next() {
if (pos == len) return -1;
- var char = s.charCodeAt(pos++);
+ var char = s.codeUnitAt(pos++);
if (isBreak(char)) {
line++;
column = 0;
@@ -193,14 +193,14 @@
return char;
}
- /// Returns the character at the current position, or the character [i]
+ /// Returns the code unit at the current position, or the character [i]
/// characters after the current position.
///
/// Returns -1 if this would return a character after the end or before the
/// beginning of the input string.
int peek([int i = 0]) {
var peekPos = pos + i;
- return (peekPos >= len || peekPos < 0) ? -1 : s.charCodeAt(peekPos);
+ return (peekPos >= len || peekPos < 0) ? -1 : s.codeUnitAt(peekPos);
}
/// The truthiness operator. Returns `false` if [obj] is `null` or `false`,
@@ -304,7 +304,7 @@
///
/// Returns whether or not the string was consumed.
bool rawString(String str) =>
- nAtOnce(str.length, (c, i) => str.charCodeAt(i) == c);
+ nAtOnce(str.length, (c, i) => str.codeUnitAt(i) == c);
/// Consumes and returns a string of characters matching [matcher], or null if
/// there are no such characters.
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 51d6740..8f41e50 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -345,6 +345,9 @@
'sources': [
'main.cc',
'builtin_nolib.cc',
+ 'vmstats.h',
+ 'vmstats_impl.cc',
+ 'vmstats_impl.h',
'<(snapshot_cc_file)',
],
'conditions': [
@@ -384,6 +387,9 @@
'sources': [
'main.cc',
'builtin.cc',
+ 'vmstats.h',
+ 'vmstats_impl.cc',
+ 'vmstats_impl.h',
# Include generated source files.
'<(builtin_cc_file)',
'<(io_cc_file)',
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index 85bb4d7..75b4edf 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -37,7 +37,7 @@
V(File_SetPosition, 2) \
V(File_Truncate, 2) \
V(File_Length, 1) \
- V(File_LengthFromName, 1) \
+ V(File_LengthFromPath, 1) \
V(File_LastModified, 1) \
V(File_Flush, 1) \
V(File_Create, 1) \
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index ea53472..a780780 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -15,7 +15,7 @@
const char* DartUtils::original_working_directory = NULL;
const char* DartUtils::kDartScheme = "dart:";
const char* DartUtils::kDartExtensionScheme = "dart-ext:";
-const char* DartUtils::kASyncLibURL = "dart:async";
+const char* DartUtils::kAsyncLibURL = "dart:async";
const char* DartUtils::kBuiltinLibURL = "dart:builtin";
const char* DartUtils::kCoreLibURL = "dart:core";
const char* DartUtils::kIOLibURL = "dart:io";
@@ -394,7 +394,7 @@
print);
// Setup the 'timer' factory.
- Dart_Handle url = NewString(kASyncLibURL);
+ Dart_Handle url = NewString(kAsyncLibURL);
DART_CHECK_VALID(url);
Dart_Handle async_lib = Dart_LookupLibrary(url);
DART_CHECK_VALID(async_lib);
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 07404e5..7f539de 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -159,7 +159,7 @@
static const char* kDartScheme;
static const char* kDartExtensionScheme;
- static const char* kASyncLibURL;
+ static const char* kAsyncLibURL;
static const char* kBuiltinLibURL;
static const char* kCoreLibURL;
static const char* kIOLibURL;
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index e366fc2..3a2c455 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -180,12 +180,25 @@
Dart_SetReturnValue(args, err);
} else {
if (bytes_read < length) {
- // TODO(ager): cache the 'length' string if this becomes a bottle neck.
- Dart_SetField(external_array,
- DartUtils::NewString("length"),
- Dart_NewInteger(bytes_read));
+ const int kNumArgs = 3;
+ Dart_Handle dart_args[kNumArgs];
+ dart_args[0] = external_array;
+ dart_args[1] = Dart_NewInteger(0);
+ dart_args[2] = Dart_NewInteger(bytes_read);
+ // TODO(sgjesse): Cache the _makeUint8ListView function somewhere.
+ Dart_Handle io_lib =
+ Dart_LookupLibrary(DartUtils::NewString("dart:io"));
+ if (Dart_IsError(io_lib)) Dart_PropagateError(io_lib);
+ Dart_Handle array_view =
+ Dart_Invoke(io_lib,
+ DartUtils::NewString("_makeUint8ListView"),
+ kNumArgs,
+ dart_args);
+ if (Dart_IsError(array_view)) Dart_PropagateError(array_view);
+ Dart_SetReturnValue(args, array_view);
+ } else {
+ Dart_SetReturnValue(args, external_array);
}
- Dart_SetReturnValue(args, external_array);
}
} else {
OSError os_error(-1, "Invalid argument", OSError::kUnknown);
@@ -349,11 +362,11 @@
}
-void FUNCTION_NAME(File_LengthFromName)(Dart_NativeArguments args) {
+void FUNCTION_NAME(File_LengthFromPath)(Dart_NativeArguments args) {
Dart_EnterScope();
- const char* name =
+ const char* path =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
- intptr_t return_value = File::LengthFromName(name);
+ intptr_t return_value = File::LengthFromPath(path);
if (return_value >= 0) {
Dart_SetReturnValue(args, Dart_NewInteger(return_value));
} else {
@@ -689,10 +702,10 @@
}
-static CObject* FileLengthFromNameRequest(const CObjectArray& request) {
+static CObject* FileLengthFromPathRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
- CObjectString filename(request[1]);
- intptr_t return_value = File::LengthFromName(filename.CString());
+ CObjectString filepath(request[1]);
+ intptr_t return_value = File::LengthFromPath(filepath.CString());
if (return_value >= 0) {
return new CObjectIntptr(CObject::NewIntptr(return_value));
} else {
@@ -705,8 +718,8 @@
static CObject* FileLastModifiedRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
- CObjectString filename(request[1]);
- int64_t return_value = File::LastModified(filename.CString());
+ CObjectString filepath(request[1]);
+ int64_t return_value = File::LastModified(filepath.CString());
if (return_value >= 0) {
return new CObjectIntptr(CObject::NewInt64(return_value * kMSPerSecond));
} else {
@@ -933,8 +946,8 @@
case File::kLengthRequest:
response = FileLengthRequest(request);
break;
- case File::kLengthFromNameRequest:
- response = FileLengthFromNameRequest(request);
+ case File::kLengthFromPathRequest:
+ response = FileLengthFromPathRequest(request);
break;
case File::kLastModifiedRequest:
response = FileLastModifiedRequest(request);
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 53a1e44..05be61c 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -56,7 +56,7 @@
kSetPositionRequest = 8,
kTruncateRequest = 9,
kLengthRequest = 10,
- kLengthFromNameRequest = 11,
+ kLengthFromPathRequest = 11,
kLastModifiedRequest = 12,
kFlushRequest = 13,
kReadByteRequest = 14,
@@ -103,25 +103,25 @@
// Returns whether the file has been closed.
bool IsClosed();
- // Open the file with the given name. The file is always opened for
+ // Open the file with the given path. The file is always opened for
// reading. If mode contains kWrite the file is opened for both
// reading and writing. If mode contains kWrite and the file does
// not exist the file is created. The file is truncated to length 0 if
// mode contains kTruncate.
- static File* Open(const char* name, FileOpenMode mode);
+ static File* Open(const char* path, FileOpenMode mode);
// Create a file object for the specified stdio file descriptor
// (stdin, stout or stderr).
static File* OpenStdio(int fd);
- static bool Exists(const char* name);
- static bool Create(const char* name);
- static bool Delete(const char* name);
- static off_t LengthFromName(const char* name);
- static time_t LastModified(const char* name);
- static bool IsAbsolutePath(const char* pathname);
- static char* GetCanonicalPath(const char* name);
- static char* GetContainingDirectory(char* name);
+ static bool Exists(const char* path);
+ static bool Create(const char* path);
+ static bool Delete(const char* path);
+ static off_t LengthFromPath(const char* path);
+ static time_t LastModified(const char* path);
+ static bool IsAbsolutePath(const char* path);
+ static char* GetCanonicalPath(const char* path);
+ static char* GetContainingDirectory(char* path);
static const char* PathSeparator();
static const char* StringEscapedPathSeparator();
static StdioHandleType GetStdioHandleType(int fd);
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index 7ae6415..390ef4d 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -168,7 +168,7 @@
}
-off_t File::LengthFromName(const char* name) {
+off_t File::LengthFromPath(const char* name) {
struct stat st;
if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
return st.st_size;
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 3a73135..459a692 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -168,7 +168,7 @@
}
-off_t File::LengthFromName(const char* name) {
+off_t File::LengthFromPath(const char* name) {
struct stat st;
if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
return st.st_size;
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 14b2fd8..37b5328 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -170,7 +170,7 @@
}
-off_t File::LengthFromName(const char* name) {
+off_t File::LengthFromPath(const char* name) {
struct stat st;
if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
return st.st_size;
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index eb55dae..2355f9d 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -7,15 +7,15 @@
}
patch class _File {
- /* patch */ static _exists(String name) native "File_Exists";
- /* patch */ static _create(String name) native "File_Create";
- /* patch */ static _delete(String name) native "File_Delete";
- /* patch */ static _directory(String name) native "File_Directory";
- /* patch */ static _lengthFromName(String name) native "File_LengthFromName";
- /* patch */ static _lastModified(String name) native "File_LastModified";
- /* patch */ static _open(String name, int mode) native "File_Open";
+ /* patch */ static _exists(String path) native "File_Exists";
+ /* patch */ static _create(String path) native "File_Create";
+ /* patch */ static _delete(String path) native "File_Delete";
+ /* patch */ static _directory(String path) native "File_Directory";
+ /* patch */ static _lengthFromPath(String path) native "File_LengthFromPath";
+ /* patch */ static _lastModified(String path) native "File_LastModified";
+ /* patch */ static _open(String path, int mode) native "File_Open";
/* patch */ static int _openStdio(int fd) native "File_OpenStdio";
- /* patch */ static _fullPath(String name) native "File_FullPath";
+ /* patch */ static _fullPath(String path) native "File_FullPath";
}
patch class _RandomAccessFile {
@@ -34,3 +34,7 @@
/* patch */ static _length(int id) native "File_Length";
/* patch */ static _flush(int id) native "File_Flush";
}
+
+List<int> _makeUint8ListView(List<int> source, int from, int to) {
+ return new Uint8List.view(source.asByteArray(), from, to);
+}
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 2ce097d..e18071a 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -165,7 +165,7 @@
}
-off_t File::LengthFromName(const char* name) {
+off_t File::LengthFromPath(const char* name) {
struct _stat st;
const wchar_t* system_name = StringUtils::Utf8ToWide(name);
int stat_status = _wstat(system_name, &st);
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 6a06bf3..4ccc87a 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -20,6 +20,7 @@
#include "bin/log.h"
#include "bin/platform.h"
#include "bin/process.h"
+#include "bin/vmstats_impl.h"
#include "platform/globals.h"
// snapshot_buffer points to a snapshot if we link in a snapshot otherwise
@@ -47,6 +48,9 @@
static const char* debug_ip = DEFAULT_DEBUG_IP;
static int debug_port = 0;
+// Global state that defines the VmStats web server port and root directory.
+static int vmstats_port = -1;
+static const char* vmstats_root = NULL;
// Value of the --package-root flag.
// (This pointer points into an argv buffer and does not need to be
@@ -164,6 +168,31 @@
}
+static bool ProcessVmStatsOption(const char* port) {
+ ASSERT(port != NULL);
+ if (*port == '\0') {
+ vmstats_port = 0; // Dynamically assigned port number.
+ } else {
+ if ((*port == '=') || (*port == ':')) {
+ vmstats_port = atoi(port + 1);
+ }
+ }
+ if (vmstats_port < 0) {
+ Log::PrintErr("unrecognized --stats option syntax. "
+ "Use --stats[:<port number>]\n");
+ return false;
+ }
+ return true;
+}
+
+
+static bool ProcessVmStatsRootOption(const char* arg) {
+ ASSERT(arg != NULL);
+ vmstats_root = arg;
+ return true;
+}
+
+
static bool ProcessGenScriptSnapshotOption(const char* filename) {
if (filename != NULL && strlen(filename) != 0) {
// Ensure that are already running using a full snapshot.
@@ -207,6 +236,8 @@
{ "--debug", ProcessDebugOption },
{ "--use-script-snapshot=", ProcessUseScriptSnapshotOption },
{ "--generate-script-snapshot=", ProcessGenScriptSnapshotOption },
+ { "--stats-root=", ProcessVmStatsRootOption },
+ { "--stats", ProcessVmStatsOption },
{ NULL, NULL }
};
@@ -489,6 +520,7 @@
return false;
}
Dart_ExitScope();
+ VmStats::AddIsolate(reinterpret_cast<IsolateData*>(data), isolate);
return true;
}
@@ -551,6 +583,14 @@
"--generate-script-snapshot=<file_name>\n"
" loads Dart script and generates a snapshot in the specified file\n"
"\n"
+"--stats[:<port number>]\n"
+" enables VM stats service and listens on specified port for HTTP requests\n"
+" (default port number is dynamically assigned)\n"
+"\n"
+"--stats-root=<path>\n"
+" where to find static files used by the vmstats application\n"
+" (used during vmstats plug-in development)\n"
+"\n"
"The following options are only used for VM development and may\n"
"be changed in any future version:\n");
const char* print_flags = "--print_flags";
@@ -628,6 +668,7 @@
static void ShutdownIsolate(void* callback_data) {
IsolateData* isolate_data = reinterpret_cast<IsolateData*>(callback_data);
+ VmStats::RemoveIsolate(isolate_data);
EventHandler* handler = isolate_data->event_handler;
if (handler != NULL) handler->Shutdown();
delete isolate_data;
@@ -714,6 +755,10 @@
Dart_EnterScope();
+ if (vmstats_port >= 0) {
+ VmStats::Start(vmstats_port, vmstats_root);
+ }
+
if (generate_script_snapshot) {
// First create a snapshot.
Dart_Handle result;
@@ -774,6 +819,9 @@
}
Dart_ExitScope();
+ if (vmstats_port >= 0) {
+ VmStats::Stop();
+ }
// Shutdown the isolate.
Dart_ShutdownIsolate();
// Terminate process exit-code handler.
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 29913b1..4468ec0 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -53,7 +53,7 @@
throw new ArgumentError("Arguments is not a List: $arguments");
}
int len = arguments.length;
- _arguments = new List<String>.fixedLength(len);
+ _arguments = new List<String>(len);
for (int i = 0; i < len; i++) {
var arg = arguments[i];
if (arg is !String) {
@@ -107,14 +107,14 @@
// Replace any number of '\' followed by '"' with
// twice as many '\' followed by '\"'.
- var backslash = '\\'.charCodeAt(0);
+ var backslash = '\\'.codeUnitAt(0);
var sb = new StringBuffer();
var nextPos = 0;
var quotePos = argument.indexOf('"', nextPos);
while (quotePos != -1) {
var numBackslash = 0;
var pos = quotePos - 1;
- while (pos >= 0 && argument.charCodeAt(pos) == backslash) {
+ while (pos >= 0 && argument.codeUnitAt(pos) == backslash) {
numBackslash++;
pos--;
}
@@ -134,7 +134,7 @@
sb = new StringBuffer('"');
sb.add(result);
nextPos = argument.length - 1;
- while (argument.charCodeAt(nextPos) == backslash) {
+ while (argument.codeUnitAt(nextPos) == backslash) {
sb.add('\\');
nextPos--;
}
@@ -156,7 +156,7 @@
var completer = new Completer();
// TODO(ager): Make the actual process starting really async instead of
// simulating it with a timer.
- new Timer(0, (_) {
+ Timer.run(() {
var status = new _ProcessStartStatus();
bool success = _startNative(_path,
_arguments,
@@ -181,7 +181,7 @@
// callback when a process terminates.
int exitDataRead = 0;
final int EXIT_DATA_SIZE = 8;
- List<int> exitDataBuffer = new List<int>.fixedLength(EXIT_DATA_SIZE);
+ List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE);
_exitHandler.listen((data) {
int exitCode(List<int> ints) {
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index 31e55a3..db68c32 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -41,6 +41,8 @@
static int GetType(intptr_t fd);
static intptr_t GetStdioHandle(int num);
static void Close(intptr_t fd);
+ static bool SetNonBlocking(intptr_t fd);
+ static bool SetBlocking(intptr_t fd);
// Perform a IPv4 hostname lookup. Returns the hostname string in
// IPv4 dotted-decimal format.
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 8bd9683..07a7a10 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -34,7 +34,7 @@
}
FDUtils::SetCloseOnExec(fd);
- FDUtils::SetNonBlocking(fd);
+ Socket::SetNonBlocking(fd);
server = gethostbyname(host);
if (server == NULL) {
@@ -218,7 +218,7 @@
return -1;
}
- FDUtils::SetNonBlocking(fd);
+ Socket::SetNonBlocking(fd);
return fd;
}
@@ -247,7 +247,7 @@
socket = kTemporaryFailure;
}
} else {
- FDUtils::SetNonBlocking(socket);
+ Socket::SetNonBlocking(socket);
}
return socket;
}
@@ -264,4 +264,14 @@
}
}
+
+bool Socket::SetNonBlocking(intptr_t fd) {
+ return FDUtils::SetNonBlocking(fd);
+}
+
+
+bool Socket::SetBlocking(intptr_t fd) {
+ return FDUtils::SetBlocking(fd);
+}
+
#endif // defined(TARGET_OS_ANDROID)
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 746adcf..cdaab92 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -36,7 +36,7 @@
}
FDUtils::SetCloseOnExec(fd);
- FDUtils::SetNonBlocking(fd);
+ Socket::SetNonBlocking(fd);
static const size_t kTempBufSize = 1024;
char temp_buf[kTempBufSize];
@@ -230,7 +230,7 @@
return -1;
}
- FDUtils::SetNonBlocking(fd);
+ Socket::SetNonBlocking(fd);
return fd;
}
@@ -259,7 +259,7 @@
socket = kTemporaryFailure;
}
} else {
- FDUtils::SetNonBlocking(socket);
+ Socket::SetNonBlocking(socket);
}
return socket;
}
@@ -276,4 +276,14 @@
}
}
+
+bool Socket::SetNonBlocking(intptr_t fd) {
+ return FDUtils::SetNonBlocking(fd);
+}
+
+
+bool Socket::SetBlocking(intptr_t fd) {
+ return FDUtils::SetBlocking(fd);
+}
+
#endif // defined(TARGET_OS_LINUX)
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 50ad16f..849e1fa 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -36,7 +36,7 @@
}
FDUtils::SetCloseOnExec(fd);
- FDUtils::SetNonBlocking(fd);
+ Socket::SetNonBlocking(fd);
server = gethostbyname(host);
if (server == NULL) {
@@ -226,7 +226,7 @@
return -1;
}
- FDUtils::SetNonBlocking(fd);
+ Socket::SetNonBlocking(fd);
return fd;
}
@@ -245,7 +245,7 @@
socket = kTemporaryFailure;
}
} else {
- FDUtils::SetNonBlocking(socket);
+ Socket::SetNonBlocking(socket);
}
return socket;
}
@@ -262,4 +262,14 @@
}
}
+
+bool Socket::SetNonBlocking(intptr_t fd) {
+ return FDUtils::SetNonBlocking(fd);
+}
+
+
+bool Socket::SetBlocking(intptr_t fd) {
+ return FDUtils::SetBlocking(fd);
+}
+
#endif // defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 15dd4c7..3b9aaae 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -123,17 +123,17 @@
}
_NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET {
- eventHandlers = new List.fixedLength(EVENT_COUNT + 1);
+ eventHandlers = new List(EVENT_COUNT + 1);
_EventHandler._start();
}
_NativeSocket.listen() : typeFlags = TYPE_LISTENING_SOCKET {
- eventHandlers = new List.fixedLength(EVENT_COUNT + 1);
+ eventHandlers = new List(EVENT_COUNT + 1);
_EventHandler._start();
}
_NativeSocket.pipe() : typeFlags = TYPE_PIPE {
- eventHandlers = new List.fixedLength(EVENT_COUNT + 1);
+ eventHandlers = new List(EVENT_COUNT + 1);
_EventHandler._start();
}
@@ -152,6 +152,7 @@
if (len != null && len <= 0) {
throw new ArgumentError("Illegal length $len");
}
+ if (isClosed) return null;
var result = nativeRead(len == null ? -1 : len);
if (result is OSError) {
reportError(result, "Read failed");
@@ -395,7 +396,7 @@
nativeRead(int len) native "Socket_Read";
nativeWrite(List<int> buffer, int offset, int bytes)
native "Socket_WriteList";
- bool nativeCreateConnect(String host, int port) native "Socket_CreateConnect";
+ nativeCreateConnect(String host, int port) native "Socket_CreateConnect";
nativeCreateBindListen(String address, int port, int backlog)
native "ServerSocket_CreateBindListen";
nativeAccept(_NativeSocket socket) native "ServerSocket_Accept";
@@ -658,17 +659,23 @@
_SocketStreamConsumer(this.socket);
Future<Socket> consume(Stream<List<int>> stream) {
- subscription = stream.listen(
- (data) {
- assert(!paused);
- assert(buffer == null);
- buffer = data;
- offset = 0;
- write();
- },
- onDone: () {
- socket._consumerDone();
- });
+ if (socket._raw != null) {
+ subscription = stream.listen(
+ (data) {
+ assert(!paused);
+ assert(buffer == null);
+ buffer = data;
+ offset = 0;
+ write();
+ },
+ onError: (error) {
+ socket._consumerDone(error);
+ },
+ onDone: () {
+ socket._consumerDone();
+ },
+ unsubscribeOnError: true);
+ }
return socket._doneFuture;
}
@@ -697,6 +704,7 @@
}
}
} catch (e) {
+ stop();
socket._consumerDone(e);
}
}
@@ -778,8 +786,8 @@
void destroy() {
// Destroy can always be called to get rid of a socket.
if (_raw == null) return;
- _closeRawSocket();
_consumer.stop();
+ _closeRawSocket();
_controllerClosed = true;
_controller.close();
}
@@ -895,11 +903,11 @@
}
void _consumerDone([error]) {
+ _done(error);
if (_raw != null) {
_raw.shutdown(SocketDirection.SEND);
_disableWriteEvent();
}
- _done(error);
}
}
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index a60f1e4..4fcf156 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -288,4 +288,26 @@
client_socket->Close();
}
+
+static bool SetBlockingHelper(intptr_t fd, bool blocking) {
+ SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
+ u_long iMode = blocking ? 0 : 1;
+ int status = ioctlsocket(handle->socket(), FIONBIO, &iMode);
+ if (status != NO_ERROR) {
+ Log::PrintErr("ioctlsocket FIONBIO failed: %d\n", status);
+ return false;
+ }
+ return true;
+}
+
+
+bool Socket::SetNonBlocking(intptr_t fd) {
+ return SetBlockingHelper(fd, false);
+}
+
+
+bool Socket::SetBlocking(intptr_t fd) {
+ return SetBlockingHelper(fd, true);
+}
+
#endif // defined(TARGET_OS_WINDOWS)
diff --git a/runtime/bin/vmstats.h b/runtime/bin/vmstats.h
new file mode 100644
index 0000000..14716e8
--- /dev/null
+++ b/runtime/bin/vmstats.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef BIN_VMSTATS_H_
+#define BIN_VMSTATS_H_
+
+#include "include/dart_api.h"
+
+/**
+ * A VM status callback. Status plug-ins implement and register this
+ * function using Dart_RegisterStatusPlugin. When Dart_GetVMStatus is
+ * called, each callback is invoked to provide the requested information,
+ * and the first one to do so "wins".
+ *
+ * Note: status requests execute outside of an isolate (which is why
+ * handles aren't used).
+ *
+ * \param request an optional string that defines REST-like parameters
+ * to define what information is requested.
+ *
+ * \return Returns a valid JSON string, allocated from C heap. The caller
+ * is responsible for releasing this string. NULL is returned if the
+ * callback didn't handle that request.
+ */
+typedef char* (*Dart_VmStatusCallback)(const char* request);
+
+
+/**
+ * Register a VM status plug-in. The specified status type must not already
+ * have a registered plug-in.
+ *
+ * \return 0 if the plug-in was registered, or -1 if there is an error.
+ */
+DART_EXPORT int Dart_RegisterVmStatusPlugin(Dart_VmStatusCallback callback);
+
+#endif // BIN_VMSTATS_H_
diff --git a/runtime/bin/vmstats_impl.cc b/runtime/bin/vmstats_impl.cc
new file mode 100644
index 0000000..e7e2812
--- /dev/null
+++ b/runtime/bin/vmstats_impl.cc
@@ -0,0 +1,332 @@
+// 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.
+
+#include "bin/vmstats_impl.h"
+
+#include <sstream>
+
+#include "bin/file.h"
+#include "bin/log.h"
+#include "bin/platform.h"
+#include "bin/socket.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+#include "include/dart_debugger_api.h"
+#include "platform/json.h"
+
+#define BUFSIZE 8192
+#define RETRY_PAUSE 100 // milliseconds
+
+static const char* INDEX_HTML = "index.html";
+static const char* VMSTATS_HTML = "vmstats.html";
+static const char* DEFAULT_HOST = "localhost";
+
+// Global static pointer used to ensure a single instance of the class.
+VmStats* VmStats::instance_ = NULL;
+dart::Monitor* VmStats::instance_monitor_;
+dart::Mutex* VmStatusService::mutex_;
+
+
+void VmStats::Start(int port, const char* root_dir) {
+ if (instance_ != NULL) {
+ FATAL("VmStats already started.");
+ }
+ instance_ = new VmStats();
+ instance_monitor_ = new dart::Monitor();
+ VmStatusService::InitOnce();
+ Socket::Initialize();
+
+ if (root_dir != NULL) {
+ instance_->root_directory_ = root_dir;
+ }
+
+ // TODO(tball): allow host to be specified.
+ char* host = const_cast<char*>(DEFAULT_HOST);
+ OSError* os_error;
+ const char* host_ip = Socket::LookupIPv4Address(host, &os_error);
+ if (host_ip == NULL) {
+ Log::PrintErr("Failed IP lookup of VmStats host %s: %s\n",
+ host, os_error->message());
+ return;
+ }
+
+ const intptr_t BACKLOG = 128; // Default value from HttpServer.dart
+ int64_t address = ServerSocket::CreateBindListen(host_ip, port, BACKLOG);
+ if (address < 0) {
+ Log::PrintErr("Failed binding VmStats socket: %s:%d\n", host, port);
+ return;
+ }
+ instance_->bind_address_ = address;
+ Log::Print("VmStats URL: http://%s:%"Pd"/\n", host, Socket::GetPort(address));
+
+ MonitorLocker ml(instance_monitor_);
+ instance_->running_ = true;
+ int err = dart::Thread::Start(WebServer, address);
+ if (err != 0) {
+ Log::PrintErr("Failed starting VmStats thread: %d\n", err);
+ Shutdown();
+ }
+}
+
+
+void VmStats::Stop() {
+ ASSERT(instance_ != NULL);
+ MonitorLocker ml(instance_monitor_);
+ instance_->running_ = false;
+}
+
+
+void VmStats::Shutdown() {
+ ASSERT(instance_ != NULL);
+ MonitorLocker ml(instance_monitor_);
+ Socket::Close(instance_->bind_address_);
+ delete instance_;
+ instance_ = NULL;
+}
+
+
+void VmStats::AddIsolate(IsolateData* isolate_data,
+ Dart_Isolate isolate) {
+ if (instance_ != NULL) {
+ MonitorLocker ml(instance_monitor_);
+ instance_->isolate_table_[isolate_data] = isolate;
+ }
+}
+
+
+void VmStats::RemoveIsolate(IsolateData* isolate_data) {
+ if (instance_ != NULL) {
+ MonitorLocker ml(instance_monitor_);
+ instance_->isolate_table_.erase(isolate_data);
+ }
+}
+
+
+static const char* ContentType(const char* url) {
+ const char* suffix = strrchr(url, '.');
+ if (suffix != NULL) {
+ if (!strcmp(suffix, ".html")) {
+ return "text/html; charset=UTF-8";
+ }
+ if (!strcmp(suffix, ".dart")) {
+ return "application/dart; charset=UTF-8";
+ }
+ if (!strcmp(suffix, ".js")) {
+ return "application/javascript; charset=UTF-8";
+ }
+ if (!strcmp(suffix, ".css")) {
+ return "text/css; charset=UTF-8";
+ }
+ if (!strcmp(suffix, ".gif")) {
+ return "image/gif";
+ }
+ if (!strcmp(suffix, ".png")) {
+ return "image/png";
+ }
+ if (!strcmp(suffix, ".jpg") || !strcmp(suffix, ".jpeg")) {
+ return "image/jpeg";
+ }
+ }
+ return "text/plain";
+}
+
+
+void VmStats::WebServer(uword bind_address) {
+ while (true) {
+ intptr_t socket = ServerSocket::Accept(bind_address);
+ if (socket == ServerSocket::kTemporaryFailure) {
+ // Not a real failure, woke up but no connection available.
+
+ // Use MonitorLocker.Wait(), since it has finer granularity than sleep().
+ dart::Monitor m;
+ MonitorLocker ml(&m);
+ ml.Wait(RETRY_PAUSE);
+
+ continue;
+ }
+ if (socket < 0) {
+ // Stop() closed the socket.
+ return;
+ }
+ Socket::SetBlocking(socket);
+
+ // TODO(tball): rewrite this to use STL, so as to eliminate the static
+ // buffer and support resource URLs that are longer than BUFSIZE.
+
+ // Read request.
+ char buffer[BUFSIZE + 1];
+ intptr_t len = Socket::Read(socket, buffer, BUFSIZE);
+ if (len <= 0) {
+ // Invalid HTTP request, ignore.
+ continue;
+ }
+ buffer[len] = '\0';
+
+ // Verify it's a GET request.
+ // TODO(tball): support POST requests.
+ if (strncmp("GET ", buffer, 4) != 0 && strncmp("get ", buffer, 4) != 0) {
+ Log::PrintErr("Unsupported HTTP request type");
+ const char* response = "HTTP/1.1 403 Forbidden\n"
+ "Content-Length: 120\n"
+ "Connection: close\n"
+ "Content-Type: text/html\n\n"
+ "<html><head>\n<title>403 Forbidden</title>\n</head>"
+ "<body>\n<h1>Forbidden</h1>\nUnsupported HTTP request type\n</body>"
+ "</html>\n";
+ Socket::Write(socket, response, strlen(response));
+ Socket::Close(socket);
+ continue;
+ }
+
+ // Extract GET URL, and null-terminate URL in case request line has
+ // HTTP version.
+ for (int i = 4; i < len; i++) {
+ if (buffer[i] == ' ') {
+ buffer[i] = '\0';
+ }
+ }
+ char* url = &buffer[4];
+
+ Log::Print("vmstats: %s requested\n", url);
+ char* content = NULL;
+
+ // Check for VmStats-specific URLs.
+ if (strcmp(url, "/isolates") == 0) {
+ content = instance_->IsolatesStatus();
+ } else {
+ // Check plug-ins.
+ content = VmStatusService::GetVmStatus(url);
+ }
+
+ if (content != NULL) {
+ size_t content_len = strlen(content);
+ len = snprintf(buffer, BUFSIZE,
+ "HTTP/1.1 200 OK\nContent-Type: application/json; charset=UTF-8\n"
+ "Content-Length: %"Pu"\n\n",
+ content_len);
+ Socket::Write(socket, buffer, strlen(buffer));
+ Socket::Write(socket, content, content_len);
+ Socket::Write(socket, "\n", 1);
+ Socket::Write(socket, buffer, strlen(buffer));
+ free(content);
+ } else {
+ // No status content with this URL, return file or resource content.
+ std::string path(instance_->root_directory_);
+ path.append(url);
+
+ // Expand directory URLs.
+ if (strcmp(url, "/") == 0) {
+ path.append(VMSTATS_HTML);
+ } else if (url[strlen(url) - 1] == '/') {
+ path.append(INDEX_HTML);
+ }
+
+ bool success = false;
+ if (File::Exists(path.c_str())) {
+ File* f = File::Open(path.c_str(), File::kRead);
+ if (f != NULL) {
+ intptr_t len = f->Length();
+ char* text_buffer = reinterpret_cast<char*>(malloc(len));
+ if (f->ReadFully(text_buffer, len)) {
+ const char* content_type = ContentType(path.c_str());
+ snprintf(buffer, BUFSIZE,
+ "HTTP/1.1 200 OK\nContent-Type: %s\n"
+ "Content-Length: %"Pu"\n\n",
+ content_type, len);
+ Socket::Write(socket, buffer, strlen(buffer));
+ Socket::Write(socket, text_buffer, len);
+ Socket::Write(socket, "\n", 1);
+ success = true;
+ }
+ free(text_buffer);
+ delete f;
+ }
+ } else {
+ // TODO(tball): look up linked in resource.
+ }
+ if (!success) {
+ const char* response = "HTTP/1.1 404 Not Found\n\n";
+ Socket::Write(socket, response, strlen(response));
+ }
+ }
+ Socket::Close(socket);
+ }
+
+ Shutdown();
+}
+
+
+char* VmStats::IsolatesStatus() {
+ std::ostringstream stream;
+ stream << '{' << std::endl;
+ stream << "\"isolates\": [" << std::endl;
+ IsolateTable::iterator itr;
+ bool first = true;
+ for (itr = isolate_table_.begin(); itr != isolate_table_.end(); ++itr) {
+ Dart_Isolate isolate = itr->second;
+ static char request[512];
+ snprintf(request, sizeof(request),
+ "/isolate/0x%"Px,
+ reinterpret_cast<intptr_t>(isolate));
+ char* status = VmStatusService::GetVmStatus(request);
+ if (status != NULL) {
+ stream << status;
+ if (!first) {
+ stream << "," << std::endl;
+ }
+ first = false;
+ }
+ free(status);
+ }
+ stream << std::endl << "]";
+ stream << std::endl << '}' << std::endl;
+ return strdup(stream.str().c_str());
+}
+
+
+// Global static pointer used to ensure a single instance of the class.
+VmStatusService* VmStatusService::instance_ = NULL;
+
+
+void VmStatusService::InitOnce() {
+ ASSERT(VmStatusService::instance_ == NULL);
+ VmStatusService::instance_ = new VmStatusService();
+ VmStatusService::mutex_ = new dart::Mutex();
+
+ // Register built-in status plug-ins. RegisterPlugin is not used because
+ // this isn't called within an isolate, and because parameter checking
+ // isn't necessary.
+ instance_->RegisterPlugin(&Dart_GetVmStatus);
+
+ // TODO(tball): dynamically load any additional plug-ins.
+}
+
+
+int VmStatusService::RegisterPlugin(Dart_VmStatusCallback callback) {
+ MutexLocker ml(mutex_);
+ if (callback == NULL) {
+ return -1;
+ }
+ VmStatusPlugin* plugin = new VmStatusPlugin(callback);
+ VmStatusPlugin* list = instance_->registered_plugin_list_;
+ if (list == NULL) {
+ instance_->registered_plugin_list_ = plugin;
+ } else {
+ list->Append(plugin);
+ }
+ return 0;
+}
+
+
+char* VmStatusService::GetVmStatus(const char* request) {
+ VmStatusPlugin* plugin = instance_->registered_plugin_list_;
+ while (plugin != NULL) {
+ char* result = (plugin->callback())(request);
+ if (result != NULL) {
+ return result;
+ }
+ plugin = plugin->next();
+ }
+ return NULL;
+}
diff --git a/runtime/bin/vmstats_impl.h b/runtime/bin/vmstats_impl.h
new file mode 100644
index 0000000..63749b3
--- /dev/null
+++ b/runtime/bin/vmstats_impl.h
@@ -0,0 +1,99 @@
+// 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.
+
+#ifndef BIN_VMSTATS_IMPL_H_
+#define BIN_VMSTATS_IMPL_H_
+
+#include "bin/vmstats.h"
+
+#include <map>
+#include <sstream>
+#include <string>
+
+#include "bin/isolate_data.h"
+#include "platform/thread.h"
+
+// VmStats is a HTTP singleton service that reports status information
+// of the running VM.
+
+class VmStats {
+ public:
+ static void Start(int port, const char* root_dir);
+ static void Stop();
+
+ // Add and remove functions for the isolate_table, called by main.cc.
+ static void AddIsolate(IsolateData* isolate_data, Dart_Isolate isolate);
+ static void RemoveIsolate(IsolateData* isolate_data);
+
+ private:
+ VmStats() : running_(false), bind_address_(0) {}
+
+ static void WebServer(uword bind_address);
+ static void Shutdown();
+
+ // Status text generators.
+ char* IsolatesStatus();
+
+ typedef std::map<IsolateData*, Dart_Isolate> IsolateTable;
+
+ std::string root_directory_;
+ IsolateTable isolate_table_;
+ bool running_;
+ int64_t bind_address_;
+
+ static VmStats* instance_;
+ static dart::Monitor* instance_monitor_;
+
+ // Disallow copy constructor.
+ DISALLOW_COPY_AND_ASSIGN(VmStats);
+};
+
+
+// Status plug-in and linked-list node.
+class VmStatusPlugin {
+ public:
+ explicit VmStatusPlugin(Dart_VmStatusCallback callback)
+ : callback_(callback), next_(NULL) {}
+
+ void Append(VmStatusPlugin* plugin) {
+ VmStatusPlugin* list = this;
+ while (list->next_ != NULL) {
+ list = list->next_;
+ }
+ list->next_ = plugin;
+ }
+
+ Dart_VmStatusCallback callback() { return callback_; }
+ VmStatusPlugin* next() { return next_; }
+
+ private:
+ Dart_VmStatusCallback callback_;
+ VmStatusPlugin* next_;
+};
+
+
+// Singleton service managing VM status gathering and status plug-in
+// registration.
+class VmStatusService {
+ public:
+ static int RegisterPlugin(Dart_VmStatusCallback callback);
+
+ // Returns VM status for a specified request. The caller is responsible
+ // for releasing the heap memory after use.
+ static char* GetVmStatus(const char* request);
+
+ static void InitOnce();
+
+ private:
+ VmStatusService() : registered_plugin_list_(NULL) {}
+
+ static VmStatusService* instance_;
+ static dart::Mutex* mutex_;
+
+ VmStatusPlugin* registered_plugin_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(VmStatusService);
+};
+
+#endif // BIN_VMSTATS_IMPL_H_
diff --git a/runtime/embedders/openglui/android/android_graphics_handler.cc b/runtime/embedders/openglui/android/android_graphics_handler.cc
index e96febe..f2c0ea2 100644
--- a/runtime/embedders/openglui/android/android_graphics_handler.cc
+++ b/runtime/embedders/openglui/android/android_graphics_handler.cc
@@ -5,8 +5,9 @@
#include "embedders/openglui/android/android_graphics_handler.h"
#include "embedders/openglui/common/log.h"
-AndroidGraphicsHandler::AndroidGraphicsHandler(android_app* application)
- : GraphicsHandler(),
+AndroidGraphicsHandler::AndroidGraphicsHandler(android_app* application,
+ const char* resource_path)
+ : GraphicsHandler(resource_path),
application_(application),
display_(EGL_NO_DISPLAY),
surface_(EGL_NO_SURFACE),
diff --git a/runtime/embedders/openglui/android/android_graphics_handler.h b/runtime/embedders/openglui/android/android_graphics_handler.h
index 6849ac3..c157d95 100644
--- a/runtime/embedders/openglui/android/android_graphics_handler.h
+++ b/runtime/embedders/openglui/android/android_graphics_handler.h
@@ -10,7 +10,8 @@
class AndroidGraphicsHandler : public GraphicsHandler {
public:
- explicit AndroidGraphicsHandler(android_app* application);
+ AndroidGraphicsHandler(android_app* application,
+ const char* resource_path);
int32_t Start();
void Stop();
diff --git a/runtime/embedders/openglui/android/android_sound_handler.cc b/runtime/embedders/openglui/android/android_sound_handler.cc
index 6e97833..8d0b2b7 100644
--- a/runtime/embedders/openglui/android/android_sound_handler.cc
+++ b/runtime/embedders/openglui/android/android_sound_handler.cc
@@ -55,23 +55,48 @@
}
void AndroidSoundHandler::Stop() {
- StopBackground();
- if (output_mix_ != NULL) {
- (*output_mix_)->Destroy(output_mix_);
- output_mix_ = NULL;
- }
- if (engine_ != NULL) {
- (*engine_)->Destroy(engine_);
- engine_ = NULL;
- engine_if_ = NULL;
- }
+ LOGI("Stopping SoundService");
if (sample_player_ != NULL) {
+ LOGI("Destroying sample player");
(*sample_player_)->Destroy(sample_player_);
sample_player_ = NULL;
sample_player_if_ = NULL;
sample_player_queue_ = NULL;
}
samples_.clear();
+ if (output_mix_ != NULL) {
+ LOGI("Destroying output mix");
+ (*output_mix_)->Destroy(output_mix_);
+ output_mix_ = NULL;
+ }
+ if (engine_ != NULL) {
+ LOGI("Destroying engine");
+ (*engine_)->Destroy(engine_);
+ engine_ = NULL;
+ engine_if_ = NULL;
+ }
+}
+
+int32_t AndroidSoundHandler::SetBackgroundPlayerState(int state) {
+ if (background_player_if_ != NULL) {
+ SLuint32 state;
+ (*background_player_)->GetState(background_player_, &state);
+ if (state == SL_OBJECT_STATE_REALIZED) {
+ (*background_player_if_)->SetPlayState(background_player_if_,
+ state);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int32_t AndroidSoundHandler::Pause() {
+ return SetBackgroundPlayerState(SL_PLAYSTATE_PAUSED);
+}
+
+
+int32_t AndroidSoundHandler::Resume() {
+ return SetBackgroundPlayerState(SL_PLAYSTATE_PLAYING);
}
int32_t AndroidSoundHandler::CreateAudioPlayer(SLEngineItf engine_if,
@@ -171,18 +196,11 @@
}
void AndroidSoundHandler::StopBackground() {
- if (background_player_if_ != NULL) {
- SLuint32 state;
- (*background_player_)->GetState(background_player_, &state);
- if (state == SL_OBJECT_STATE_REALIZED) {
- (*background_player_if_)->SetPlayState(background_player_if_,
- SL_PLAYSTATE_PAUSED);
-
- (*background_player_)->Destroy(background_player_);
- background_player_ = NULL;
- background_player_if_ = NULL;
- background_player_seek_if_ = NULL;
- }
+ if (Pause() == 0) {
+ (*background_player_)->Destroy(background_player_);
+ background_player_ = NULL;
+ background_player_if_ = NULL;
+ background_player_seek_if_ = NULL;
}
}
diff --git a/runtime/embedders/openglui/android/android_sound_handler.h b/runtime/embedders/openglui/android/android_sound_handler.h
index 027d644..e699a69 100644
--- a/runtime/embedders/openglui/android/android_sound_handler.h
+++ b/runtime/embedders/openglui/android/android_sound_handler.h
@@ -20,6 +20,8 @@
explicit AndroidSoundHandler(android_app* application);
int32_t Start();
void Stop();
+ int32_t Pause();
+ int32_t Resume();
int32_t PlayBackground(const char* path);
void StopBackground();
@@ -34,6 +36,7 @@
SLObjectItf& player_out,
SLPlayItf& player_if_out);
+ int32_t SetBackgroundPlayerState(int state);
int32_t StartSamplePlayer();
android_app* application_;
diff --git a/runtime/embedders/openglui/android/eventloop.cc b/runtime/embedders/openglui/android/eventloop.cc
index 2d3bf6c..ea536fe 100644
--- a/runtime/embedders/openglui/android/eventloop.cc
+++ b/runtime/embedders/openglui/android/eventloop.cc
@@ -6,9 +6,152 @@
#include "embedders/openglui/common/log.h"
+/*
+ * The Android lifecycle events are:
+ *
+ * OnCreate: In NDK this is the call to android_main
+ *
+ * OnStart: technically, called to initiate the “visible” lifespan of the
+ * app; at any time between OnStart and OnStop, the app may be visible.
+ * We can either be OnResume’d or OnStop’ped from this state. Note that
+ * there is also an event for OnRestart, which is called before OnStart
+ * if the application is transitioning from OnStop to OnStart instead of
+ * being started from scratch.
+ *
+ * OnResume: technically, the start of the “foreground” lifespan of the app,
+ * but this does not mean that the app is fully visible and should be
+ * rendering – more on that later
+ *
+ * OnPause: the app is losing its foregrounded state; this is normally an
+ * indication that something is fully covering the app. On versions of
+ * Android before Honeycomb, once we returned from this callback, we
+ * could be killed at any time with no further app code called. We can
+ * either be OnResume’d or OnStop’ped from this state. OnPause halts the
+ * visible UI thread and so should be handled as quickly as possible.
+ *
+ * OnStop: the end of the current visible lifespan of the app – we may
+ * transition to On(Re)Start to become visible again, or to OnDestroy if
+ * we are shutting down entirely. Once we return from this callback, we
+ * can be killed at any time with no further app code called on any
+ * version of Android.
+ *
+ * OnDestroy: this can only be followed by the application being killed or
+ * restarted with OnCreate.
+ *
+ * The above events occur in fixed orders. The events below can occur at
+ * various times:
+ *
+ * OnGainedFocus: happens between OnResume and OnPause.
+ * OnLostFocus: may occur at arbitrary times, and may in fact not happen
+ * at all if the app is being destroyed. So OnPause and OnGainedFocus/
+ * OnLostFocus must be used together to determine the visible and
+ * interactable state of the app.
+ *
+ * OnCreateWindow: usually happens in the resumed state
+ * OnDestroyWindow: can happen after OnPause or OnDestroy, so apps may
+ * need to handle shutting down EGL before their surfaces are
+ * destroyed.
+ * OnConfigurationChanged: typically means the size has changed
+ *
+ * An application's EGL surface may only exist between the OnCreateWindow
+ * and OnDestroyWindow callbacks.
+ *
+ * An application is "killable" after OnStop or OnDestroy (in earlier
+ * Android versions, after OnPause too). That means any critical state
+ * or resources must be handled by any of these callbacks.
+ *
+ * These callbacks run on the main thread. If they block any event
+ * processing for more than 5 seconds this will result in an ANR
+ * (Application Not Responding message).
+ *
+ * On application launch, this sequence will occur:
+ *
+ * - OnCreate
+ * - OnStart
+ * - OnResume
+ * - OnCreateWindow
+ * - OnConfigurationChanged
+ * - OnGainedFocus
+ *
+ * If the back button is pressed, and the app does not handle it,
+ * Android will pop the app of the UI stack and destroy the application's
+ * activity:
+ *
+ * - OnPause
+ * - OnLostFocus
+ * - OnDestroyWindow
+ * - OnStop
+ * - OnDestroy
+ *
+ * If the home button is pressed, the app is sent down in the UI stack.
+ * The app's Activity still exists but may be killed at any time, and
+ * it loses its rendering surface:
+ *
+ * - OnPause
+ * - OnLostFocus
+ * - OnDestroyWindow
+ * - OnStop
+ *
+ * If the app is then restarted (without having been killed in between):
+ *
+ * - OnRestart
+ * - OnStart
+ * - OnResume
+ * - OnCreateWindow
+ * - OnConfigurationChanged
+ * - OnGainedFocus
+ *
+ * If a status icon pop up is opened, the app is still visible and can render
+ * but is not focused and cannot receive input:
+ *
+ * - OnLostFocus
+ *
+ * When the popup is dismissed, the app regains focus:
+ *
+ * - OnGainedFocus
+ *
+ * When the device is suspended (power button or screen saver), the application
+ * will typically be paused and lose focus:
+ *
+ * - OnPause
+ * - OnLostFocus (sometimes this will only come when the device is resumed
+ * to the lock screen)
+ *
+ * The application should have stopped all rendering and sound and any
+ * non-critical background processing.
+ *
+ * When the device is resumed but not yet unlocked, the app will be resumed:
+ *
+ * - OnResume
+ *
+ * The application should not perform sound or graphics yet. If the lock
+ * screen times out, the app will be paused again. If the screen is
+ * unlocked, the app will regain focus.
+ *
+ * Turning all of this into a general framework, we can use the following:
+ *
+ * 1. In OnCreate/android_main, set up the main classes and possibly
+ * load some lightweight resources.
+ * 2. In OnCreateWindow, create the EGLSurface, bind the context, load
+ * OpenGL resources. No rendering.
+ * 3. When we are between OnResume and OnPause, and between OnCreateWindow
+ * and OnDestroyWindow, and between OnGainedFocus and OnLostFocus,
+ * we can render and process input.
+ * 4. In OnLostFocus, stop sounds from playing, and stop rendering.
+ * 5. In OnPause, stop all rendering
+ * 6. In OnResume, prepare to start rendering again, but don't render.
+ * 7. In OnGainedFocus after OnResume, start rendering and sound again.
+ * 8. In OnStop, free all graphic resources, either through GLES calls
+ * if the EGLContext is still bound, or via eglDestroyContext if the
+ * context has been unbound because the rendering surface was destroyed.
+ * 9. In OnDestroy, release all other resources.
+ */
EventLoop::EventLoop(android_app* application)
: enabled_(false),
quit_(false),
+ isResumed_(false),
+ hasSurface_(false),
+ hasFocus_(false),
application_(application),
lifecycle_handler_(NULL),
input_handler_(NULL) {
@@ -25,97 +168,86 @@
lifecycle_handler_ = lifecycle_handler;
input_handler_ = input_handler;
- LOGI("Starting event loop");
- while (true) {
- // If not enabled, block indefinitely on events. If enabled, block
- // briefly so we can do useful work in onStep. Ultimately this is
- // where we would want to look at elapsed time since the last call
- // to onStep completed and use a delay that gives us ~60fps.
- while ((result = ALooper_pollAll(enabled_ ? (1000/60) : -1,
- NULL,
- &events,
- reinterpret_cast<void**>(&source))) >= 0) {
- if (source != NULL) {
- source->process(application_, source);
+ if (lifecycle_handler_->OnStart() == 0) {
+ LOGI("Starting event loop");
+ while (!quit_) {
+ // If not enabled, block indefinitely on events. If enabled, block
+ // briefly so we can do useful work in onStep. Ultimately this is
+ // where we would want to look at elapsed time since the last call
+ // to onStep completed and use a delay that gives us ~60fps.
+ while ((result = ALooper_pollAll(enabled_ ? (1000/60) : -1, NULL,
+ &events, reinterpret_cast<void**>(&source))) >= 0) {
+ if (source != NULL) {
+ source->process(application_, source);
+ }
+ if (application_->destroyRequested) {
+ return;
+ }
}
- if (application_->destroyRequested) {
- return;
- }
- }
- if (enabled_ && !quit_) {
- LOGI("step");
- if (lifecycle_handler_->OnStep() != 0) {
- quit_ = true;
- ANativeActivity_finish(application_->activity);
+ if (enabled_ && !quit_) {
+ LOGI("step");
+ if (lifecycle_handler_->OnStep() != 0) {
+ quit_ = true;
+ }
}
}
}
-}
-
-// Called when we gain focus.
-void EventLoop::Activate() {
- LOGI("activate");
- if (!enabled_ && application_->window != NULL) {
- quit_ = false;
- enabled_ = true;
- if (lifecycle_handler_->OnActivate() != 0) {
- quit_ = true;
- ANativeActivity_finish(application_->activity);
- }
- }
-}
-
-// Called when we lose focus.
-void EventLoop::Deactivate() {
- LOGI("deactivate");
- if (enabled_) {
- lifecycle_handler_->OnDeactivate();
- enabled_ = false;
- }
+ ANativeActivity_finish(application_->activity);
}
void EventLoop::ProcessActivityEvent(int32_t command) {
switch (command) {
+ case APP_CMD_INIT_WINDOW:
+ if (lifecycle_handler_->Activate() != 0) {
+ quit_ = true;
+ } else {
+ hasSurface_ = true;
+ }
+ break;
case APP_CMD_CONFIG_CHANGED:
lifecycle_handler_->OnConfigurationChanged();
break;
- case APP_CMD_INIT_WINDOW:
- lifecycle_handler_->OnCreateWindow();
- break;
case APP_CMD_DESTROY:
- lifecycle_handler_->OnDestroy();
+ hasFocus_ = false;
+ lifecycle_handler_->FreeAllResources();
break;
case APP_CMD_GAINED_FOCUS:
- Activate();
- lifecycle_handler_->OnGainedFocus();
+ hasFocus_ = true;
+ if (hasSurface_ && isResumed_ && hasFocus_) {
+ enabled_ = (lifecycle_handler_->Resume() == 0);
+ }
break;
case APP_CMD_LOST_FOCUS:
- lifecycle_handler_->OnLostFocus();
- Deactivate();
+ hasFocus_ = false;
+ enabled_ = false;
+ lifecycle_handler_->Pause();
break;
case APP_CMD_LOW_MEMORY:
lifecycle_handler_->OnLowMemory();
break;
case APP_CMD_PAUSE:
- lifecycle_handler_->OnPause();
- Deactivate();
+ isResumed_ = false;
+ enabled_ = false;
+ lifecycle_handler_->Pause();
break;
case APP_CMD_RESUME:
- lifecycle_handler_->OnResume();
+ isResumed_ = true;
break;
case APP_CMD_SAVE_STATE:
lifecycle_handler_->OnSaveState(&application_->savedState,
&application_->savedStateSize);
break;
case APP_CMD_START:
- lifecycle_handler_->OnStart();
break;
case APP_CMD_STOP:
- lifecycle_handler_->OnStop();
+ hasFocus_ = false;
+ lifecycle_handler_->Deactivate();
break;
case APP_CMD_TERM_WINDOW:
- lifecycle_handler_->OnDestroyWindow();
- Deactivate();
+ hasFocus_ = false;
+ hasSurface_ = false;
+ enabled_ = false;
+ lifecycle_handler_->Pause();
break;
default:
break;
diff --git a/runtime/embedders/openglui/android/eventloop.h b/runtime/embedders/openglui/android/eventloop.h
index 23b16db..2c548c8 100644
--- a/runtime/embedders/openglui/android/eventloop.h
+++ b/runtime/embedders/openglui/android/eventloop.h
@@ -17,8 +17,6 @@
InputHandler* input_handler);
protected:
- void Activate();
- void Deactivate();
void ProcessActivityEvent(int32_t command);
int32_t ProcessInputEvent(AInputEvent* event);
bool OnTouchEvent(AInputEvent* event);
@@ -28,8 +26,8 @@
static int32_t InputCallback(android_app* application, AInputEvent* event);
private:
- bool enabled_;
- bool quit_;
+ bool enabled_, quit_;
+ bool isResumed_, hasSurface_, hasFocus_;
android_app* application_;
LifeCycleHandler* lifecycle_handler_;
InputHandler* input_handler_;
diff --git a/runtime/embedders/openglui/android/main.cc b/runtime/embedders/openglui/android/main.cc
index 4cd8790..5569627 100644
--- a/runtime/embedders/openglui/android/main.cc
+++ b/runtime/embedders/openglui/android/main.cc
@@ -12,8 +12,9 @@
void android_main(android_app* application) {
app_dummy(); // Link in native_app_glue.
- AndroidGraphicsHandler graphics_handler(application);
- VMGlue vm_glue(&graphics_handler, "/data/data/com.google.dartndk/app_dart");
+ const char* resource_path = "/data/data/com.google.dartndk/app_dart";
+ AndroidGraphicsHandler graphics_handler(application, resource_path);
+ VMGlue vm_glue(&graphics_handler, resource_path);
AndroidInputHandler input_handler(&vm_glue, &graphics_handler);
AndroidSoundHandler sound_handler(application);
Timer timer;
diff --git a/runtime/embedders/openglui/common/canvas_context.cc b/runtime/embedders/openglui/common/canvas_context.cc
index 3750344..851a30d 100644
--- a/runtime/embedders/openglui/common/canvas_context.cc
+++ b/runtime/embedders/openglui/common/canvas_context.cc
@@ -6,7 +6,7 @@
#include <ctype.h>
#include <string.h>
-
+#include "core/SkStream.h"
#include "embedders/openglui/common/support.h"
// TODO(gram): this should be dynamic.
@@ -15,11 +15,25 @@
CanvasContext* Context2D(int handle) {
if (handle < 0 || handle >= MAX_CONTEXTS) {
+ LOGE("Request for out-of-range handle %d", handle);
return NULL;
}
+ if (contexts[handle] == NULL) {
+ LOGE("Warning: request for context with handle %d returns NULL", handle);
+ }
return contexts[handle];
}
+void FreeContexts() {
+ extern CanvasContext* display_context;
+ for (int i = 0; i < MAX_CONTEXTS; i++) {
+ delete contexts[i];
+ contexts[i] = NULL;
+ }
+ display_context = NULL;
+}
+
+
CanvasContext::CanvasContext(int handle, int16_t widthp, int16_t heightp)
: canvas_(NULL),
width_(widthp),
@@ -33,6 +47,7 @@
}
state_ = new CanvasState(canvas_);
contexts[handle] = this;
+ LOGI("Created context with handle %d", handle);
}
CanvasContext::~CanvasContext() {
@@ -52,18 +67,45 @@
SkDevice* device = otherContext->canvas_->getDevice();
bm = device->accessBitmap(false);
} else {
- // TODO(gram): We need a way to remap URLs to local file names.
- // For now I am just using the characters after the last '/'.
- // Note also that if we want to support URLs and network fetches,
- // then we introduce more complexity; this can't just be an URL.
- int pos = strlen(src_url);
- while (--pos >= 0 && src_url[pos] != '/');
- const char *path = src_url + pos + 1;
- if (!SkImageDecoder::DecodeFile(path, &bm)) {
- LOGI("Image decode of %s failed", path);
- return;
+ const char* filepath;
+ if (strncmp(src_url, "file://", 7) == 0) {
+ filepath = src_url + 7;
} else {
- LOGI("Decode image: width=%d,height=%d", bm.width(), bm.height());
+ // TODO(gram): We need a way to remap URLs to local file names.
+ // For now I am just using the characters after the last '/'.
+ // Note also that if we want to support URLs and network fetches,
+ // then we introduce more complexity; this can't just be an URL.
+ int pos = strlen(src_url);
+ while (--pos >= 0 && src_url[pos] != '/');
+ filepath = src_url + pos + 1;
+ }
+ char* path;
+ if (filepath[0] == '/') {
+ path = const_cast<char*>(filepath);
+ } else {
+ size_t len1 = strlen(graphics->resource_path());
+ size_t len2 = strlen(filepath);
+ path = new char[len1 + 1 + len2 + 1];
+ strncpy(path, graphics->resource_path(), len1+1);
+ strncat(path, "/", 1);
+ strncat(path, filepath, len2);
+ }
+ SkFILEStream stream(path);
+ if (stream.isValid()) {
+ // We could use DecodeFile and pass the path, but by creating the
+ // SkStream here we can produce better error log messages.
+ if (!SkImageDecoder::DecodeStream(&stream, &bm)) {
+ LOGI("Image decode of %s failed", path);
+ return;
+ } else {
+ LOGI("Decode image %s: width=%d,height=%d",
+ path, bm.width(), bm.height());
+ }
+ } else {
+ LOGI("Path %s is invalid", path);
+ }
+ if (path != filepath) {
+ delete[] path;
}
}
if (!has_src_dimensions) {
@@ -75,6 +117,7 @@
dh = bm.height();
}
state_->DrawImage(bm, sx, sy, sw, sh, dx, dy, dw, dh);
+ isDirty_ = true;
}
void CanvasContext::ClearRect(float left, float top,
@@ -83,5 +126,6 @@
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(0xFFFFFFFF);
canvas_->drawRectCoords(left, top, left + width, top + height, paint);
+ isDirty_ = true;
}
diff --git a/runtime/embedders/openglui/common/canvas_context.h b/runtime/embedders/openglui/common/canvas_context.h
index 72b3852..3fc44ef 100644
--- a/runtime/embedders/openglui/common/canvas_context.h
+++ b/runtime/embedders/openglui/common/canvas_context.h
@@ -27,11 +27,9 @@
class CanvasContext {
protected:
SkCanvas* canvas_;
-
int16_t width_, height_;
-
bool imageSmoothingEnabled_;
-
+ bool isDirty_;
CanvasState* state_;
static inline float Radians2Degrees(float angle) {
@@ -46,6 +44,14 @@
CanvasContext(int handle, int16_t width, int16_t height);
virtual ~CanvasContext();
+ inline bool isDirty() {
+ return isDirty_;
+ }
+
+ inline void clearDirty() {
+ isDirty_ = false;
+ }
+
inline void setGlobalAlpha(float alpha) {
state_->setGlobalAlpha(alpha);
}
@@ -165,6 +171,7 @@
inline void Clear() {
canvas_->drawColor(0xFFFFFFFF);
+ isDirty_ = true;
}
void ClearRect(float left, float top, float width, float height);
@@ -172,11 +179,13 @@
inline void FillRect(float left, float top, float width, float height) {
// Does not affect the path.
state_->FillRect(left, top, width, height);
+ isDirty_ = true;
}
inline void StrokeRect(float left, float top, float width, float height) {
// Does not affect the path.
state_->StrokeRect(left, top, width, height);
+ isDirty_ = true;
}
inline void BeginPath() {
@@ -185,10 +194,12 @@
inline void Fill() {
state_->Fill();
+ isDirty_ = true;
}
inline void Stroke() {
state_->Stroke();
+ isDirty_ = true;
}
inline void ClosePath() {
@@ -269,11 +280,13 @@
inline void FillText(const char* text, float x, float y,
float maxWidth = -1) {
state_->FillText(text, x, y, maxWidth);
+ isDirty_ = true;
}
inline void StrokeText(const char* text, float x, float y,
float maxWidth = -1) {
state_->StrokeText(text, x, y, maxWidth);
+ isDirty_ = true;
}
inline float MeasureText(const char *text) {
@@ -296,6 +309,7 @@
};
CanvasContext* Context2D(int handle);
+void FreeContexts();
#endif // EMBEDDERS_OPENGLUI_COMMON_CANVAS_CONTEXT_H_
diff --git a/runtime/embedders/openglui/common/dart_host.cc b/runtime/embedders/openglui/common/dart_host.cc
index 8e8c2a6..af886b0 100644
--- a/runtime/embedders/openglui/common/dart_host.cc
+++ b/runtime/embedders/openglui/common/dart_host.cc
@@ -15,85 +15,90 @@
sound_handler_(context->sound_handler),
timer_(context->timer),
vm_glue_(context->vm_glue),
+ has_context_(false),
+ started_(false),
active_(false) {
- LOGI("Creating DartHost");
}
DartHost::~DartHost() {
- LOGI("Freeing DartHost");
}
-int32_t DartHost::OnActivate() {
- return Activate();
+int32_t DartHost::OnStart() {
+ int result = vm_glue_->StartMainIsolate();
+ if (result != 0) {
+ LOGE("startMainIsolate returned %d", result);
+ return -1;
+ }
+ started_ = true;
+ return 0;
}
int32_t DartHost::Activate() {
- if (!active_) {
- LOGI("Activating DartHost");
+ if (!has_context_) {
if (graphics_handler_->Start() != 0) {
return -1;
}
if (sound_handler_->Start() != 0) {
+ graphics_handler_->Stop();
return -1;
}
if (input_handler_->Start() != 0) {
+ sound_handler_->Stop();
+ graphics_handler_->Stop();
return -1;
}
+ int32_t rtn = vm_glue_->CallSetup(true);
timer_->Reset();
- LOGI("Starting main isolate");
- int result = vm_glue_->StartMainIsolate();
- if (result != 0) {
- LOGE("startMainIsolate returned %d", result);
- return -1;
- }
- active_ = true;
- return vm_glue_->CallSetup();
+ has_context_ = true;
+ return rtn;
}
return 0;
}
-void DartHost::OnDeactivate() {
- Deactivate();
-}
-
void DartHost::Deactivate() {
- if (active_) {
- active_ = false;
- vm_glue_->FinishMainIsolate();
- LOGI("Deactivating DartHost");
+ Pause();
+ if (has_context_) {
+ vm_glue_->CallShutdown();
input_handler_->Stop();
sound_handler_->Stop();
graphics_handler_->Stop();
+ has_context_ = false;
}
}
int32_t DartHost::OnStep() {
- timer_->Update();
- if (vm_glue_->CallUpdate() != 0 ||
- graphics_handler_->Update() != 0) {
- return -1;
+ if (active_) {
+ timer_->Update();
+ if (vm_glue_->CallUpdate() != 0 ||
+ graphics_handler_->Update() != 0) {
+ return -1;
+ }
}
return 0;
}
-void DartHost::OnStart() {
- LOGI("Starting DartHost");
+int32_t DartHost::Resume() {
+ if (!active_) {
+ if (Activate() == 0) {
+ sound_handler_->Resume();
+ active_ = true;
+ }
+ }
+ return 0;
}
-void DartHost::OnResume() {
- LOGI("Resuming DartHost");
+void DartHost::Pause() {
+ if (active_) {
+ active_ = false; // This stops update() calls.
+ sound_handler_->Suspend();
+ }
}
-void DartHost::OnPause() {
- LOGI("Pausing DartHost");
-}
-
-void DartHost::OnStop() {
- LOGI("Stopping DartHost");
-}
-
-void DartHost::OnDestroy() {
- LOGI("Destroying DartHost");
+void DartHost::FreeAllResources() {
+ if (started_) {
+ vm_glue_->FinishMainIsolate();
+ started_ = false;
+ }
}
void DartHost::OnSaveState(void** data, size_t* size) {
@@ -108,19 +113,3 @@
LOGI("DartHost low on memory");
}
-void DartHost::OnCreateWindow() {
- LOGI("DartHost creating window");
-}
-
-void DartHost::OnDestroyWindow() {
- LOGI("DartHost destroying window");
-}
-
-void DartHost::OnGainedFocus() {
- LOGI("DartHost gained focus");
-}
-
-void DartHost::OnLostFocus() {
- LOGI("DartHost lost focus");
-}
-
diff --git a/runtime/embedders/openglui/common/dart_host.h b/runtime/embedders/openglui/common/dart_host.h
index 7c85d15..9233aa2f 100644
--- a/runtime/embedders/openglui/common/dart_host.h
+++ b/runtime/embedders/openglui/common/dart_host.h
@@ -14,43 +14,32 @@
#include "embedders/openglui/common/vm_glue.h"
#include "include/dart_api.h"
-// Currently the life cycle management is very crude. We conservatively
-// shutdown the main isolate when we lose focus and create a new one when
-// we resume. This needs to be improved later when we understand this better,
-// and we need some hooks to tell the Dart script to save/restore state
-// (and an API that will support that).
-
class DartHost : public LifeCycleHandler {
public:
explicit DartHost(Context* context);
virtual ~DartHost();
- void OnStart();
- void OnResume();
- void OnPause();
- void OnStop();
- void OnDestroy();
+ int32_t OnStart();
void OnSaveState(void** data, size_t* size);
void OnConfigurationChanged();
void OnLowMemory();
- void OnCreateWindow();
- void OnDestroyWindow();
- void OnGainedFocus();
- void OnLostFocus();
- int32_t OnActivate();
- void OnDeactivate();
+ int32_t Activate();
+ void Deactivate();
+ void Pause();
+ int32_t Resume();
+ void FreeAllResources();
int32_t OnStep();
private:
void Clear();
- int32_t Activate();
- void Deactivate();
GraphicsHandler* graphics_handler_;
InputHandler* input_handler_;
SoundHandler* sound_handler_;
Timer* timer_;
VMGlue* vm_glue_;
+ bool has_context_;
+ bool started_;
bool active_;
};
diff --git a/runtime/embedders/openglui/common/extension.cc b/runtime/embedders/openglui/common/extension.cc
index d0c24b3..abe627d 100644
--- a/runtime/embedders/openglui/common/extension.cc
+++ b/runtime/embedders/openglui/common/extension.cc
@@ -923,7 +923,7 @@
// 2D Canvas.
-CanvasContext* display_context;
+CanvasContext* display_context = NULL;
void C2DCreateNativeContext(Dart_NativeArguments arguments) {
LOGI("In C2DCreateNativeContext");
@@ -935,6 +935,7 @@
CanvasContext* rtn = new CanvasContext(handle, width, height);
if (display_context == NULL) {
+ LOGI("Created display context");
display_context = rtn;
}
Dart_ExitScope();
diff --git a/runtime/embedders/openglui/common/gl.dart b/runtime/embedders/openglui/common/gl.dart
index 071f128..1cb506d 100644
--- a/runtime/embedders/openglui/common/gl.dart
+++ b/runtime/embedders/openglui/common/gl.dart
@@ -395,11 +395,15 @@
TextMetrics(this.width);
}
+void shutdown() {
+ CanvasRenderingContext2D.next_handle = 0;
+}
+
class CanvasRenderingContext2D extends CanvasRenderingContext {
// TODO(gram): We need to support multiple contexts, for cached content
// prerendered to an offscreen buffer. For this we will use handles, with
// handle 0 being the physical display.
- static int _next_handle = 0;
+ static int next_handle = 0;
int _handle = 0;
get handle => _handle;
@@ -412,7 +416,7 @@
CanvasRenderingContext2D(canvas, width, height) : super(canvas) {
_width = width;
_height = height;
- C2DCreateNativeContext(_handle = _next_handle++, width, height);
+ C2DCreateNativeContext(_handle = next_handle++, width, height);
}
double _alpha = 1.0;
diff --git a/runtime/embedders/openglui/common/graphics_handler.cc b/runtime/embedders/openglui/common/graphics_handler.cc
index c68da4b..98d3461 100644
--- a/runtime/embedders/openglui/common/graphics_handler.cc
+++ b/runtime/embedders/openglui/common/graphics_handler.cc
@@ -9,13 +9,38 @@
extern void CheckGLError(const char *function);
GraphicsHandler* graphics;
+extern CanvasContext* display_context;
-GraphicsHandler::GraphicsHandler()
- : ag(),
+GraphicsHandler::GraphicsHandler(const char* resource_path)
+ : resource_path_(resource_path),
+ ag(),
grcontext(NULL),
width_(0),
height_(0) {
graphics = this;
+ DecoderHack(0, NULL);
+}
+
+void GraphicsHandler::DecoderHack(int x, SkStream* s) {
+ if (x) { // hack to keep the linker from throwing these out
+ extern SkImageDecoder* sk_libpng_dfactory(SkStream* s);
+ sk_libpng_dfactory(s);
+
+ // TODO(gram): For some reason I get linker errors on these, even though
+ // they are defined in libskia_images. Figure out why...
+ /*
+ extern SkImageDecoder* sk_libjpeg_dfactory(SkStream* s);
+ extern SkImageDecoder* sk_libbmp_dfactory(SkStream* s);
+ extern SkImageDecoder* sk_libgif_dfactory(SkStream* s);
+ extern SkImageDecoder* sk_libico_dfactory(SkStream* s);
+ extern SkImageDecoder* sk_libwbmp_dfactory(SkStream* s);
+ sk_libjpeg_dfactory(s);
+ sk_libbmp_dfactory(s);
+ sk_libgif_dfactory(s);
+ sk_libico_dfactory(s);
+ sk_libwbmp_dfactory(s);
+ */
+ }
}
// Kludge to get around an issue with Android emulator, which returns
@@ -31,7 +56,6 @@
}
int32_t GraphicsHandler::Start() {
- SkGraphics::Init();
GrGLInterface* fGL = const_cast<GrGLInterface*>(GrGLCreateNativeInterface());
LOGI("Created native interface %s\n", fGL ? "succeeded" : "failed");
fGL->fGetString = myGLGetString;
@@ -41,7 +65,10 @@
}
void GraphicsHandler::Stop() {
- SkGraphics::Term();
+ LOGI("Releasing display context");
+ FreeContexts();
+ grcontext->unref();
+ grcontext = NULL;
}
SkCanvas* GraphicsHandler::CreateDisplayCanvas() {
@@ -82,15 +109,12 @@
}
int32_t GraphicsHandler::Update() {
- extern CanvasContext* display_context;
- if (display_context != NULL) {
+ if (display_context != NULL && display_context->isDirty()) {
LOGI("Flushing display context\n");
display_context->Flush();
+ SwapBuffers();
+ display_context->clearDirty();
}
- SwapBuffers();
return 0;
}
-
-
-
diff --git a/runtime/embedders/openglui/common/graphics_handler.h b/runtime/embedders/openglui/common/graphics_handler.h
index 25fae53..77f57ec 100644
--- a/runtime/embedders/openglui/common/graphics_handler.h
+++ b/runtime/embedders/openglui/common/graphics_handler.h
@@ -11,8 +11,11 @@
#include "embedders/openglui/common/timer.h"
class GraphicsHandler : public ISized {
+ private:
+ void DecoderHack(int x, SkStream* s);
+
public:
- GraphicsHandler();
+ explicit GraphicsHandler(const char* resource_path);
const int32_t& height() {
return height_;
@@ -39,10 +42,15 @@
SkCanvas* CreateDisplayCanvas();
SkCanvas* CreateBitmapCanvas(int width, int height);
+ inline const char* resource_path() {
+ return resource_path_;
+ }
+
virtual ~GraphicsHandler() {
}
protected:
+ const char* resource_path_;
SkAutoGraphics ag;
GrContext* grcontext;
int32_t width_, height_;
diff --git a/runtime/embedders/openglui/common/lifecycle_handler.h b/runtime/embedders/openglui/common/lifecycle_handler.h
index 801e6d8..cc1a659 100644
--- a/runtime/embedders/openglui/common/lifecycle_handler.h
+++ b/runtime/embedders/openglui/common/lifecycle_handler.h
@@ -7,21 +7,18 @@
class LifeCycleHandler {
public:
- virtual int32_t OnActivate() = 0;
- virtual void OnDeactivate() = 0;
+ virtual int32_t OnStart() = 0;
+ virtual int32_t Activate() = 0;
+ virtual void Deactivate() = 0;
virtual int32_t OnStep() = 0;
- virtual void OnStart() {}
- virtual void OnResume() {}
- virtual void OnPause() {}
- virtual void OnStop() {}
- virtual void OnDestroy() {}
+ virtual void Pause() {}
+ virtual int32_t Resume() {
+ return 0;
+ }
+ virtual void FreeAllResources() {}
virtual void OnSaveState(void** data, size_t* size) {}
virtual void OnConfigurationChanged() {}
virtual void OnLowMemory() {}
- virtual void OnCreateWindow() {}
- virtual void OnDestroyWindow() {}
- virtual void OnGainedFocus() {}
- virtual void OnLostFocus() {}
virtual ~LifeCycleHandler() {}
};
diff --git a/runtime/embedders/openglui/common/log.h b/runtime/embedders/openglui/common/log.h
index 5bfa782..f816792 100644
--- a/runtime/embedders/openglui/common/log.h
+++ b/runtime/embedders/openglui/common/log.h
@@ -7,8 +7,16 @@
#ifndef ANDROID
#include <stdio.h>
-#define LOGI(...) fprintf(stdout, __VA_ARGS__)
-#define LOGE(...) fprintf(stderr, __VA_ARGS__)
+#define LOGI(...) do {\
+ fprintf(stdout, __VA_ARGS__);\
+ fprintf(stdout, "\n");\
+ fflush(stdout);\
+ } while (0)
+#define LOGE(...) do { \
+ fprintf(stderr, __VA_ARGS__);\
+ fprintf(stderr, "\n");\
+ fflush(stderr);\
+ } while (0)
#else
#include "embedders/openglui/android/android_log.h"
#endif
diff --git a/runtime/embedders/openglui/common/sound_handler.h b/runtime/embedders/openglui/common/sound_handler.h
index 100d0a5..0110db9 100644
--- a/runtime/embedders/openglui/common/sound_handler.h
+++ b/runtime/embedders/openglui/common/sound_handler.h
@@ -24,6 +24,14 @@
virtual void Stop() {
}
+ virtual int32_t Suspend() {
+ return 0;
+ }
+
+ virtual int32_t Resume() {
+ return 0;
+ }
+
virtual int32_t PlayBackground(const char* path) {
return 0;
}
diff --git a/runtime/embedders/openglui/common/vm_glue.cc b/runtime/embedders/openglui/common/vm_glue.cc
index b5e33e0..39ee799 100644
--- a/runtime/embedders/openglui/common/vm_glue.cc
+++ b/runtime/embedders/openglui/common/vm_glue.cc
@@ -198,8 +198,10 @@
return 0;
}
-int VMGlue::CallSetup() {
- if (!initialized_script_) {
+int VMGlue::CallSetup(bool force) {
+ // TODO(gram): See if we actually need this flag guard here, or if
+ // we can eliminate it along with the need for the force parameter.
+ if (!initialized_script_ || force) {
initialized_script_ = true;
LOGI("Invoking setup(NULL, %d,%d)", surface_->width(), surface_->height());
Dart_EnterIsolate(isolate_);
@@ -233,13 +235,23 @@
int VMGlue::CallUpdate() {
if (initialized_script_) {
- LOGI("Invoking update");
Dart_EnterIsolate(isolate_);
Dart_EnterScope();
int rtn = Invoke("update", 0, 0);
Dart_ExitScope();
Dart_ExitIsolate();
- LOGI("Done update");
+ return rtn;
+ }
+ return -1;
+}
+
+int VMGlue::CallShutdown() {
+ if (initialized_script_) {
+ Dart_EnterIsolate(isolate_);
+ Dart_EnterScope();
+ int rtn = Invoke("shutdown", 0, 0);
+ Dart_ExitScope();
+ Dart_ExitIsolate();
return rtn;
}
return -1;
@@ -289,10 +301,7 @@
int argc,
Dart_Handle* args,
bool failIfNotDefined) {
- LOGI("in invoke(%s)", function);
-
// Lookup the library of the root script.
- LOGI("looking up the root library");
Dart_Handle library = Dart_RootLibrary();
if (Dart_IsNull(library)) {
LOGE("Unable to find root library\n");
@@ -301,7 +310,6 @@
Dart_Handle nameHandle = Dart_NewStringFromCString(function);
- LOGI("invoking %s", function);
Dart_Handle result = Dart_Invoke(library, nameHandle, argc, args);
if (Dart_IsError(result)) {
@@ -314,14 +322,12 @@
// TODO(vsm): I don't think we need this.
// Keep handling messages until the last active receive port is closed.
- LOGI("Entering Dart message loop");
result = Dart_RunLoop();
if (Dart_IsError(result)) {
LOGE("Dart_RunLoop: %s\n", Dart_GetError(result));
return -1;
}
- LOGI("out invoke");
return 0;
}
diff --git a/runtime/embedders/openglui/common/vm_glue.h b/runtime/embedders/openglui/common/vm_glue.h
index fc353a6..72db660 100644
--- a/runtime/embedders/openglui/common/vm_glue.h
+++ b/runtime/embedders/openglui/common/vm_glue.h
@@ -24,8 +24,9 @@
int InitializeVM();
int StartMainIsolate();
- int CallSetup();
+ int CallSetup(bool force = false);
int CallUpdate();
+ int CallShutdown();
int OnMotionEvent(const char* funtion, int64_t when,
float move_x, float move_y);
int OnKeyEvent(const char* funtion, int64_t when, int32_t flags,
diff --git a/runtime/embedders/openglui/emulator/emulator_embedder.cc b/runtime/embedders/openglui/emulator/emulator_embedder.cc
index 4f53b42..01c5188 100644
--- a/runtime/embedders/openglui/emulator/emulator_embedder.cc
+++ b/runtime/embedders/openglui/emulator/emulator_embedder.cc
@@ -11,6 +11,7 @@
#include "embedders/openglui/common/dart_host.h"
#include "embedders/openglui/common/events.h"
#include "embedders/openglui/common/input_handler.h"
+#include "embedders/openglui/common/log.h"
#include "embedders/openglui/common/sound_handler.h"
#include "embedders/openglui/common/vm_glue.h"
#include "embedders/openglui/emulator/emulator_graphics_handler.h"
@@ -55,7 +56,24 @@
input_handler_ptr->OnKeyEvent(kKeyDown, time(0), 0, key, 0, 0);
input_handler_ptr->OnKeyEvent(kKeyUp, time(0), 0, key, 0, 0);
if (key == 27) {
+ lifecycle_handler_ptr->Pause();
+ lifecycle_handler_ptr->Deactivate();
+ lifecycle_handler_ptr->FreeAllResources();
exit(0);
+ } else if (key == '0') {
+ LOGI("Simulating suspend");
+ lifecycle_handler_ptr->Pause();
+ lifecycle_handler_ptr->Deactivate();
+ } else if (key == '1') {
+ LOGI("Simulating resume");
+ lifecycle_handler_ptr->Activate();
+ lifecycle_handler_ptr->Resume();
+ } else if (key == '+') {
+ LOGI("Simulating focus gain");
+ lifecycle_handler_ptr->Resume();
+ } else if (key == '-') {
+ LOGI("Simulating focus loss");
+ lifecycle_handler_ptr->Pause();
}
}
@@ -84,7 +102,9 @@
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
- lifecycle_handler_ptr->OnActivate();
+ lifecycle_handler_ptr->OnStart();
+ lifecycle_handler_ptr->Activate();
+ lifecycle_handler_ptr->Resume();
gettimeofday(&tvStart, NULL);
glutTimerFunc(1, tick, 0);
glutMainLoop();
diff --git a/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc b/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc
index b552813..451e909 100644
--- a/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc
+++ b/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc
@@ -9,7 +9,7 @@
EmulatorGraphicsHandler::EmulatorGraphicsHandler(int argc,
char** argv)
- : GraphicsHandler() {
+ : GraphicsHandler(".") {
glutInit(&argc, argv);
SetViewport(0, 0, 480, 800);
for (int i = 1; i < argc; i++) {
@@ -33,6 +33,5 @@
void EmulatorGraphicsHandler::Stop() {
GraphicsHandler::Stop();
- exit(0);
}
diff --git a/runtime/embedders/openglui/openglui_embedder.gypi b/runtime/embedders/openglui/openglui_embedder.gypi
index ab66125..a9ca5dd 100644
--- a/runtime/embedders/openglui/openglui_embedder.gypi
+++ b/runtime/embedders/openglui/openglui_embedder.gypi
@@ -26,6 +26,7 @@
'../../../third_party/skia/trunk/include/config',
'../../../third_party/skia/trunk/include/core',
'../../../third_party/skia/trunk/include/gpu',
+ '../../../third_party/skia/trunk/include/lazy',
'../../../third_party/skia/trunk/include/utils',
],
'defines': [
@@ -182,6 +183,7 @@
'../../../third_party/skia/trunk/include/config',
'../../../third_party/skia/trunk/include/core',
'../../../third_party/skia/trunk/include/gpu',
+ '../../../third_party/skia/trunk/include/lazy',
'../../../third_party/skia/trunk/include/utils',
],
'defines': [
diff --git a/runtime/include/dart_debugger_api.h b/runtime/include/dart_debugger_api.h
index 09033c6..5d71e4d 100755
--- a/runtime/include/dart_debugger_api.h
+++ b/runtime/include/dart_debugger_api.h
@@ -578,4 +578,28 @@
*/
DART_EXPORT Dart_Isolate Dart_GetIsolate(Dart_IsolateId isolate_id);
+
+/**
+ * Returns VM status information. VM status is implemented using a
+ * different status plug-in for each type of status; for example, there
+ * might be an "isolate" plug-in that returns information about the
+ * current isolates.
+ *
+ * To get a list of status types, this function is called with a
+ * status_type parameter of "statustypes". This list is useful when
+ * building a status dashboard.
+ *
+ * TODO(tball): we need to figure out which isolate this command needs
+ * to be sent to after parsing the string and then send an OOB message
+ * to that isolate.
+ *
+ * \param request A REST-like string, which uses '/' to separate
+ * parameters. The first parameter is always the status type.
+ *
+ * \return The requested status as a JSON formatted string, with the
+ * contents defined by the status plug-in. The caller is responsible
+ * for freeing this string.
+ */
+DART_EXPORT char* Dart_GetVmStatus(const char* request);
+
#endif // INCLUDE_DART_DEBUGGER_API_H_
diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc
index 6be9093..ac879d3 100644
--- a/runtime/lib/array.cc
+++ b/runtime/lib/array.cc
@@ -14,20 +14,29 @@
DEFINE_NATIVE_ENTRY(ObjectArray_allocate, 2) {
const AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::CheckedHandle(arguments->NativeArgAt(0));
+ AbstractTypeArguments::CheckedHandle(isolate, arguments->NativeArgAt(0));
ASSERT(type_arguments.IsNull() ||
(type_arguments.IsInstantiated() && (type_arguments.Length() == 1)));
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));
- intptr_t len = length.Value();
+ const Instance& length = Instance::CheckedHandle(
+ isolate, arguments->NativeArgAt(1));
+ if (!length.IsSmi()) {
+ const String& error = String::Handle(String::NewFormatted(
+ "Length must be an integer in the range [0..%"Pd"].",
+ Array::kMaxElements));
+ const Array& args = Array::Handle(Array::New(1));
+ args.SetAt(0, error);
+ Exceptions::ThrowByType(Exceptions::kArgument, args);
+ }
+ intptr_t len = Smi::Cast(length).Value();
if (len < 0 || len > Array::kMaxElements) {
const String& error = String::Handle(String::NewFormatted(
- "length (%"Pd") must be in the range [0..%"Pd"]",
+ "Length (%"Pd") must be an integer in the range [0..%"Pd"].",
len, Array::kMaxElements));
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0, error);
Exceptions::ThrowByType(Exceptions::kArgument, args);
}
- const Array& new_array = Array::Handle(Array::New(length.Value()));
+ const Array& new_array = Array::Handle(Array::New(len));
new_array.SetTypeArguments(type_arguments);
return new_array.raw();
}
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart
index 1441dc2..eb7bc70 100644
--- a/runtime/lib/array.dart
+++ b/runtime/lib/array.dart
@@ -6,7 +6,7 @@
// TODO(srdjan): Use shared array implementation.
class _ObjectArray<E> implements List<E> {
- factory _ObjectArray(int length) native "ObjectArray_allocate";
+ factory _ObjectArray(length) native "ObjectArray_allocate";
E operator [](int index) native "ObjectArray_getIndexed";
@@ -228,13 +228,17 @@
E max([int compare(E a, E b)]) => IterableMixinWorkaround.max(this, compare);
- List<E> toList() {
- return new List<E>.from(this);
+ List<E> toList({ bool growable: true}) {
+ return new List<E>.from(this, growable: growable);
}
Set<E> toSet() {
return new Set<E>.from(this);
}
+
+ Map<int, E> asMap() {
+ return IterableMixinWorkaround.asMapList(this);
+ }
}
@@ -467,13 +471,17 @@
E max([int compare(E a, E b)]) => IterableMixinWorkaround.max(this, compare);
- List<E> toList() {
- return new List<E>.from(this);
+ List<E> toList({ bool growable: true }) {
+ return new List<E>.from(this, growable: growable);
}
Set<E> toSet() {
return new Set<E>.from(this);
}
+
+ Map<int, E> asMap() {
+ return IterableMixinWorkaround.asMapList(this);
+ }
}
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart
index da5bf73..386e8ac 100644
--- a/runtime/lib/array_patch.dart
+++ b/runtime/lib/array_patch.dart
@@ -2,23 +2,28 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// Note that the optimizing compiler depends on the algorithm which
-// returns a _GrowableObjectArray if length is null, otherwise returns
-// fixed size array.
+// The _GrowableArrayMarker class is used to signal to the List() factory
+// whether a parameter was passed.
+class _GrowableArrayMarker implements int {
+ const _GrowableArrayMarker();
+}
+
+const _GROWABLE_ARRAY_MARKER = const _GrowableArrayMarker();
+
patch class List<E> {
- /* patch */ factory List([int length = 0]) {
- if ((length is! int) || (length < 0)) {
- _throwArgumentError(length);
+ /* patch */ factory List([int length = _GROWABLE_ARRAY_MARKER]) {
+ if (identical(length, _GROWABLE_ARRAY_MARKER)) {
+ return new _GrowableObjectArray<E>(0);
}
- _GrowableObjectArray<E> result = new _GrowableObjectArray<E>(length);
- return result;
+ // All error handling on the length parameter is done at the implementation
+ // of new _ObjectArray.
+ return new _ObjectArray<E>(length);
}
- /* patch */ factory List.fixedLength(int length, {E fill: null}) {
- if ((length is! int) || (length < 0)) {
- _throwArgumentError(length);
- }
- _ObjectArray<E> result = new _ObjectArray<E>(length);
+ /* patch */ factory List.filled(int length, E fill) {
+ // All error handling on the length parameter is done at the implementation
+ // of new _ObjectArray.
+ var result = new _ObjectArray<E>(length);
if (fill != null) {
for (int i = 0; i < length; i++) {
result[i] = fill;
@@ -37,8 +42,4 @@
result._setLength(elements.length);
return result;
}
-
- static void _throwArgumentError(int length) {
- throw new ArgumentError("Length must be a positive integer: $length.");
- }
}
diff --git a/runtime/lib/byte_array.cc b/runtime/lib/byte_array.cc
index a96d211..08e0bc8 100644
--- a/runtime/lib/byte_array.cc
+++ b/runtime/lib/byte_array.cc
@@ -251,6 +251,16 @@
}
+DEFINE_NATIVE_ENTRY(ByteArray_getFloat32x4, 2) {
+ UNALIGNED_GETTER(ByteArray, Float32x4, simd_value_t);
+}
+
+
+DEFINE_NATIVE_ENTRY(ByteArray_setFloat32x4, 3) {
+ UNALIGNED_SETTER(ByteArray, Float32x4, value, simd_value_t);
+}
+
+
DEFINE_NATIVE_ENTRY(ByteArray_getFloat32, 2) {
UNALIGNED_GETTER(ByteArray, Double, float);
}
@@ -596,6 +606,38 @@
SETTER_UINT64(Uint64Array);
}
+// Float32x4Array
+
+DEFINE_NATIVE_ENTRY(Float32x4Array_new, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+ intptr_t len = length.Value();
+ LengthCheck(len, Float32x4Array::kMaxElements);
+ return Float32x4Array::New(len);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4List_newTransferable, 1) {
+ const int kAlignment = 16;
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+ intptr_t len = length.Value();
+ LengthCheck(len, Float32x4Array::kMaxElements);
+ simd_value_t* bytes = OS::AllocateAlignedArray<simd_value_t>(len, kAlignment);
+ const ExternalFloat32x4Array& obj =
+ ExternalFloat32x4Array::Handle(ExternalFloat32x4Array::New(bytes, len));
+ obj.AddFinalizer(bytes, PeerFinalizer);
+ return obj.raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4Array_getIndexed, 2) {
+ GETTER(Float32x4Array, Float32x4, simd_value_t);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4Array_setIndexed, 3) {
+ SETTER(Float32x4Array, Float32x4, value, simd_value_t);
+}
+
// Float32Array
@@ -771,6 +813,18 @@
}
+// ExternalFloat32x4Array
+
+DEFINE_NATIVE_ENTRY(ExternalFloat32x4Array_getIndexed, 2) {
+ GETTER(ExternalFloat32x4Array, Float32x4, simd_value_t);
+}
+
+
+DEFINE_NATIVE_ENTRY(ExternalFloat32x4Array_setIndexed, 3) {
+ SETTER(ExternalFloat32x4Array, Float32x4, value, simd_value_t);
+}
+
+
// ExternalFloat32Array
DEFINE_NATIVE_ENTRY(ExternalFloat32Array_getIndexed, 2) {
diff --git a/runtime/lib/byte_array.dart b/runtime/lib/byte_array.dart
index 7eb126a..2323fdf 100644
--- a/runtime/lib/byte_array.dart
+++ b/runtime/lib/byte_array.dart
@@ -325,12 +325,11 @@
}
int indexOf(element, [int start = 0]) {
- return Arrays.indexOf(this, element, start, this.length);
+ return IterableMixinWorkaround.indexOfList(this, element, start);
}
int lastIndexOf(element, [int start = null]) {
- if (start == null) start = length - 1;
- return Arrays.lastIndexOf(this, element, start);
+ return IterableMixinWorkaround.lastIndexOfList(this, element, start);
}
void clear() {
@@ -408,8 +407,8 @@
length * this.bytesPerElement());
}
- List<int> toList() {
- return new List<int>.from(this);
+ List<int> toList({ bool growable: true }) {
+ return new List<int>.from(this, growable: growable);
}
Set<int> toSet() {
@@ -446,6 +445,10 @@
int _getUint64(int byteOffset) native "ByteArray_getUint64";
int _setUint64(int byteOffset, int value) native "ByteArray_setUint64";
+ Float32x4 _getFloat32x4(int byteOffset) native "ByteArray_getFloat32x4";
+ int _setFloat32x4(int byteOffset, Float32x4 value)
+ native "ByteArray_setFloat32x4";
+
double _getFloat32(int byteOffset) native "ByteArray_getFloat32";
int _setFloat32(int byteOffset, double value) native "ByteArray_setFloat32";
@@ -567,7 +570,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -631,7 +635,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -696,7 +701,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -759,7 +765,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -822,7 +829,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -885,7 +893,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -949,7 +958,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1012,7 +1022,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1075,7 +1086,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1138,7 +1150,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1201,7 +1214,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1253,7 +1267,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1303,7 +1318,7 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
}
@@ -1355,7 +1370,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1405,7 +1421,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1455,7 +1472,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1507,7 +1525,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1559,7 +1578,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1611,7 +1631,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1663,7 +1684,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1715,7 +1737,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1767,7 +1790,8 @@
from,
startFrom * _BYTES_PER_ELEMENT);
} else {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
}
}
@@ -1894,6 +1918,13 @@
return _array._setUint64(_offset + byteOffset, value);
}
+ Float32x4 getFloat32x4(int byteOffset) {
+ return _array._getFloat32x4(_offset + byteOffset);
+ }
+ int setFloat32x4(int byteOffset, Float32x4 value) {
+ return _array._setFloat32x4(_offset + byteOffset, value);
+ }
+
double getFloat32(int byteOffset) {
return _array._getFloat32(_offset + byteOffset);
}
@@ -1962,12 +1993,11 @@
}
int indexOf(element, [int start = 0]) {
- return Arrays.indexOf(this, element, start, this.length);
+ return IterableMixinWorkaround.indexOfList(this, element, start);
}
int lastIndexOf(element, [int start = null]) {
- if (start == null) start = length - 1;
- return Arrays.lastIndexOf(this, element, start);
+ return IterableMixinWorkaround.lastIndexOfList(this, element, start);
}
void clear() {
@@ -2036,6 +2066,10 @@
"Cannot add to a non-extendable array");
}
+ Map<int, int> asMap() {
+ return IterableMixinWorkaround.asMapList(this);
+ }
+
final ByteArray _array;
final int _offset;
final int length;
@@ -2079,7 +2113,7 @@
}
void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
@@ -2143,7 +2177,7 @@
}
void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
@@ -2207,7 +2241,7 @@
}
void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
@@ -2271,7 +2305,7 @@
}
void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
@@ -2335,7 +2369,7 @@
}
void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
@@ -2399,7 +2433,7 @@
}
void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
@@ -2463,7 +2497,7 @@
}
void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
@@ -2527,7 +2561,7 @@
}
void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
@@ -2591,7 +2625,7 @@
}
void setRange(int start, int length, List<double> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
@@ -2655,7 +2689,7 @@
}
void setRange(int start, int length, List<double> from, [int startFrom = 0]) {
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
String toString() {
diff --git a/tests/language/script_negative_lib.dart b/runtime/lib/core_patch.dart
similarity index 63%
rename from tests/language/script_negative_lib.dart
rename to runtime/lib/core_patch.dart
index 72ea4f9..abaaea2 100644
--- a/tests/language/script_negative_lib.dart
+++ b/runtime/lib/core_patch.dart
@@ -1,7 +1,5 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-class A {
- var a;
-}
+import "dart:math";
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index e133681..3fc2261 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -200,6 +200,36 @@
DEFINE_NATIVE_ENTRY(Double_parse, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
+ if (value.IsOneByteString()) {
+ // Quick conversion for unpadded doubles in strings.
+ const intptr_t len = value.Length();
+ if (len > 0) {
+ const char* cstr = value.ToCString();
+ ASSERT(cstr != NULL);
+ // Dart differences from strtod:
+ // a) '5.' is not a valid double (no digit after period).
+ // b) '+5.0' is not a valid double (leading plus).
+ if (cstr[0] != '+') {
+ bool dot_ok = true;
+ const char* tmp = cstr;
+ while (*tmp != '\0') {
+ const char ch = *tmp++;
+ if (ch == '.') {
+ const char nextCh = *tmp;
+ dot_ok = ('0' <= nextCh) && (nextCh <= '9');
+ break;
+ }
+ }
+ if (dot_ok) {
+ char* p_end = NULL;
+ const double double_value = strtod(cstr, &p_end);
+ if (p_end == (cstr + len)) {
+ return Double::New(double_value);
+ }
+ }
+ }
+ }
+ }
Scanner scanner(value, Symbols::Empty());
const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
String* number_string;
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc
index b821791..6f3fb4a 100644
--- a/runtime/lib/function.cc
+++ b/runtime/lib/function.cc
@@ -16,15 +16,11 @@
DEFINE_NATIVE_ENTRY(Function_apply, 2) {
const Array& fun_arguments = Array::CheckedHandle(arguments->NativeArgAt(0));
const Array& fun_arg_names = Array::CheckedHandle(arguments->NativeArgAt(1));
- Instance& instance = Instance::Handle();
- instance ^= fun_arguments.At(0);
const Array& fun_args_desc =
Array::Handle(ArgumentsDescriptor::New(fun_arguments.Length(),
fun_arg_names));
const Object& result =
- Object::Handle(DartEntry::InvokeClosure(instance,
- fun_arguments,
- fun_args_desc));
+ Object::Handle(DartEntry::InvokeClosure(fun_arguments, fun_args_desc));
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
}
diff --git a/runtime/lib/function_patch.dart b/runtime/lib/function_patch.dart
index cb5a0c27..56b817d 100644
--- a/runtime/lib/function_patch.dart
+++ b/runtime/lib/function_patch.dart
@@ -13,10 +13,10 @@
(positionalArguments != null ? positionalArguments.length : 0);
int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
int numArguments = numPositionalArguments + numNamedArguments;
- List arguments = new List.fixedLength(numArguments);
+ List arguments = new List(numArguments);
arguments[0] = function;
arguments.setRange(1, numPositionalArguments - 1, positionalArguments);
- List names = new List.fixedLength(numNamedArguments);
+ List names = new List(numNamedArguments);
int argumentIndex = numPositionalArguments;
int nameIndex = 0;
if (numNamedArguments > 0) {
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index 27699e2..5759178 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -48,10 +48,7 @@
}
void setRange(int start, int length, List<T> from, [int startFrom = 0]) {
- if (length < 0) {
- throw new ArgumentError("negative length $length");
- }
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
void removeRange(int start, int length) {
@@ -194,12 +191,11 @@
T max([int compare(T a, T b)]) => IterableMixinWorkaround.max(this, compare);
int indexOf(T element, [int start = 0]) {
- return Arrays.indexOf(this, element, start, length);
+ return IterableMixinWorkaround.indexOfList(this, element, start);
}
int lastIndexOf(T element, [int start = null]) {
- if (start == null) start = length - 1;
- return Arrays.lastIndexOf(this, element, start);
+ return IterableMixinWorkaround.lastIndexOfList(this, element, start);
}
void _grow(int new_length) {
@@ -320,11 +316,15 @@
return new ListIterator<T>(this);
}
- List<T> toList() {
- return new List<T>.from(this);
+ List<T> toList({ bool growable: true }) {
+ return new List<T>.from(this, growable: growable);
}
Set<T> toSet() {
return new Set<T>.from(this);
}
+
+ Map<int, T> asMap() {
+ return IterableMixinWorkaround.asMapList(this);
+ }
}
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index c0eb573..f6133dd 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -183,6 +183,26 @@
DEFINE_NATIVE_ENTRY(Integer_parse, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
+ if (value.IsOneByteString()) {
+ // Quick conversion for unpadded integers in strings.
+ const intptr_t len = value.Length();
+ if (len > 0) {
+ const char* cstr = value.ToCString();
+ ASSERT(cstr != NULL);
+ // Dart differences from strtol:
+ // a) '+5' is not a valid integer (leading plus).
+ if (cstr[0] != '+') {
+ char* p_end = NULL;
+ const int64_t int_value = strtol(cstr, &p_end, 10);
+ if (p_end == (cstr + len)) {
+ if ((Smi::kMinValue <= int_value) && (int_value <= Smi::kMaxValue)) {
+ return Smi::New(int_value);
+ }
+ }
+ }
+ }
+ }
+
Scanner scanner(value, Symbols::Empty());
const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
String* int_string;
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index c6485ab..de4abdb 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -15,9 +15,14 @@
/* patch */ static int parse(String source,
{ int radix,
int onError(String str) }) {
+ if ((radix == null) && (onError == null)) return _parse(source);
+ return _slowParse(source, radix, onError);
+ }
+
+ static int _slowParse(String source, int radix, int onError(String str)) {
if (source is! String) throw new ArgumentError(source);
if (radix == null) {
- if (onError == null) return _parse(source);
+ assert(onError != null);
try {
return _parse(source);
} on FormatException {
@@ -50,12 +55,12 @@
];
int i = 0;
- int code = source.charCodeAt(i);
+ int code = source.codeUnitAt(i);
if (code == 0x2d || code == 0x2b) { // Starts with a plus or minus-sign.
negative = (code == 0x2d);
if (source.length == 1) return onError(source);
i = 1;
- code = source.charCodeAt(i);
+ code = source.codeUnitAt(i);
}
do {
if (code < 0x30 || code > 0x7f) return onError(source);
@@ -64,7 +69,7 @@
result = result * radix + digit;
i++;
if (i == source.length) break;
- code = source.charCodeAt(i);
+ code = source.codeUnitAt(i);
} while (true);
return negative ? -result : result;
}
diff --git a/runtime/lib/invocation_mirror.cc b/runtime/lib/invocation_mirror.cc
index 8e0880a..a8c70b3 100644
--- a/runtime/lib/invocation_mirror.cc
+++ b/runtime/lib/invocation_mirror.cc
@@ -44,9 +44,9 @@
invoke_arguments,
fun_args_desc);
} else {
- result = DartEntry::InvokeDynamic(function,
- invoke_arguments,
- fun_args_desc);
+ result = DartEntry::InvokeFunction(function,
+ invoke_arguments,
+ fun_args_desc);
}
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index e7edbe0..ea975ca 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -74,7 +74,7 @@
const Array& args = Array::Handle(isolate, Array::New(kNumArguments));
args.SetAt(0, Integer::Handle(isolate, Integer::New(port_id)));
const Object& result =
- Object::Handle(isolate, DartEntry::InvokeStatic(func, args));
+ Object::Handle(isolate, DartEntry::InvokeFunction(func, args));
if (!result.IsError()) {
PortMap::SetLive(port_id);
}
@@ -374,7 +374,7 @@
ASSERT(result.IsFunction());
Function& func = Function::Handle(isolate);
func ^= result.raw();
- result = DartEntry::InvokeStatic(func, Object::empty_array());
+ result = DartEntry::InvokeFunction(func, Object::empty_array());
if (result.IsError()) {
StoreError(isolate, result);
return false;
diff --git a/runtime/lib/json_patch.dart b/runtime/lib/json_patch.dart
new file mode 100644
index 0000000..0b637a1
--- /dev/null
+++ b/runtime/lib/json_patch.dart
@@ -0,0 +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.
+
+// JSON parsing and serialization.
+
+patch parse(String json, [reviver(var key, var value)]) {
+ return _parse(json, reviver);
+}
diff --git a/runtime/lib/json_sources.gypi b/runtime/lib/json_sources.gypi
new file mode 100644
index 0000000..1622f7b
--- /dev/null
+++ b/runtime/lib/json_sources.gypi
@@ -0,0 +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.
+
+{
+ 'sources': [
+ 'json_patch.dart',
+ ],
+}
diff --git a/runtime/lib/lib_sources.gypi b/runtime/lib/lib_sources.gypi
index f5b6c04..27e36a9 100644
--- a/runtime/lib/lib_sources.gypi
+++ b/runtime/lib/lib_sources.gypi
@@ -6,6 +6,8 @@
{
'sources': [
+ 'core_patch.dart',
+ # The above file needs to be first as it imports required libraries.
'bool_patch.dart',
'date.cc',
'date_patch.dart',
@@ -41,6 +43,8 @@
'regexp_jsc.cc',
'regexp_jsc.h',
'regexp_patch.dart',
+ 'stacktrace.cc',
+ 'stacktrace_patch.dart',
'stopwatch_patch.dart',
'stopwatch.cc',
'string.cc',
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index fa9dc7e..0be4213 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -51,7 +51,7 @@
class _Random implements Random {
// Internal state of the random number generator.
- final _state = new List.fixedLength(2);
+ final _state = new List(2);
static const kSTATE_LO = 0;
static const kSTATE_HI = 1;
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 7ece160..d8c78e1 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -244,7 +244,8 @@
output = r'\v';
break;
default:
- int code = input.charCodeAt(0);
+ // TODO(lrn): Someone decide if this should combine surrogate pairs.
+ int code = input.codeUnitAt(0);
if (isNice(code)) {
output = input;
} else {
diff --git a/runtime/lib/mirrors_patch.dart b/runtime/lib/mirrors_patch.dart
index 9b61edb..78bbbd6 100644
--- a/runtime/lib/mirrors_patch.dart
+++ b/runtime/lib/mirrors_patch.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import "dart:nativewrappers";
+
/**
* Returns a [MirrorSystem] for the current isolate.
*/
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 674ab64..3416698 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -54,12 +54,12 @@
return regexp.num_bracket_expressions();
}
const String& pattern = String::Handle(regexp.pattern());
- const String& errmsg =
- String::Handle(String::New("Regular expression is not initialized yet"));
- const Array& args = Array::Handle(Array::New(2));
- args.SetAt(0, pattern);
- args.SetAt(1, errmsg);
- Exceptions::ThrowByType(Exceptions::kIllegalJSRegExp, args);
+ const String& errmsg = String::Handle(
+ String::New("Regular expression is not initialized yet. "));
+ const String& message = String::Handle(String::Concat(errmsg, pattern));
+ const Array& args = Array::Handle(Array::New(1));
+ args.SetAt(0, message);
+ Exceptions::ThrowByType(Exceptions::kFormat, args);
return Object::null();
}
diff --git a/runtime/lib/regexp_jsc.cc b/runtime/lib/regexp_jsc.cc
index cb3ec68..158579f 100644
--- a/runtime/lib/regexp_jsc.cc
+++ b/runtime/lib/regexp_jsc.cc
@@ -41,13 +41,13 @@
static void ThrowExceptionOnError(const String& pattern,
const char* error_msg) {
if (error_msg == NULL) {
- error_msg = "Unknown regexp compile error";
+ error_msg = "Unknown regexp compile error. ";
}
const String& errmsg = String::Handle(String::New(error_msg));
- const Array& args = Array::Handle(Array::New(2));
- args.SetAt(0, pattern);
- args.SetAt(1, errmsg);
- Exceptions::ThrowByType(Exceptions::kIllegalJSRegExp, args);
+ const String& message = String::Handle(String::Concat(errmsg, pattern));
+ const Array& args = Array::Handle(Array::New(1));
+ args.SetAt(0, message);
+ Exceptions::ThrowByType(Exceptions::kFormat, args);
}
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index 2eab296..e365f30 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -44,7 +44,7 @@
}
List<String> groups(List<int> groupsSpec) {
- var groupsList = new List<String>.fixedLength(groupsSpec.length);
+ var groupsList = new List<String>(groupsSpec.length);
for (int i = 0; i < groupsSpec.length; i++) {
groupsList[i] = group(groupsSpec[i]);
}
diff --git a/runtime/lib/scalarlist_sources.gypi b/runtime/lib/scalarlist_sources.gypi
index cb7c3dd..678ceb6 100644
--- a/runtime/lib/scalarlist_sources.gypi
+++ b/runtime/lib/scalarlist_sources.gypi
@@ -8,6 +8,8 @@
'sources': [
'byte_array.cc',
'byte_array.dart',
+ 'simd128.cc',
+ 'simd128.dart',
],
}
diff --git a/runtime/lib/simd128.cc b/runtime/lib/simd128.cc
new file mode 100644
index 0000000..25e8db7
--- /dev/null
+++ b/runtime/lib/simd128.cc
@@ -0,0 +1,612 @@
+// 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.
+
+#include "vm/bootstrap_natives.h"
+
+#include "vm/exceptions.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+#include "vm/symbols.h"
+
+namespace dart {
+
+DEFINE_NATIVE_ENTRY(Float32x4_fromDoubles, 5) {
+ ASSERT(AbstractTypeArguments::CheckedHandle(
+ arguments->NativeArgAt(0)).IsNull());
+ GET_NON_NULL_NATIVE_ARGUMENT(Double, x, arguments->NativeArgAt(1));
+ GET_NON_NULL_NATIVE_ARGUMENT(Double, y, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(Double, z, arguments->NativeArgAt(3));
+ GET_NON_NULL_NATIVE_ARGUMENT(Double, w, arguments->NativeArgAt(4));
+ float _x = x.value();
+ float _y = y.value();
+ float _z = z.value();
+ float _w = w.value();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_zero, 1) {
+ ASSERT(AbstractTypeArguments::CheckedHandle(
+ arguments->NativeArgAt(0)).IsNull());
+ return Float32x4::New(0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_add, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
+ float _x = self.x() + other.x();
+ float _y = self.y() + other.y();
+ float _z = self.z() + other.z();
+ float _w = self.w() + other.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_negate, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ float _x = -self.x();
+ float _y = -self.y();
+ float _z = -self.z();
+ float _w = -self.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_sub, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
+ float _x = self.x() - other.x();
+ float _y = self.y() - other.y();
+ float _z = self.z() - other.z();
+ float _w = self.w() - other.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_mul, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other,
+ arguments->NativeArgAt(1));
+ float _x = self.x() * other.x();
+ float _y = self.y() * other.y();
+ float _z = self.z() * other.z();
+ float _w = self.w() * other.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_div, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
+ float _x = self.x() / other.x();
+ float _y = self.y() / other.y();
+ float _z = self.z() / other.z();
+ float _w = self.w() / other.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmplt, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+ uint32_t _x = a.x() < b.x() ? 0xFFFFFFFF : 0x0;
+ uint32_t _y = a.y() < b.y() ? 0xFFFFFFFF : 0x0;
+ uint32_t _z = a.z() < b.z() ? 0xFFFFFFFF : 0x0;
+ uint32_t _w = a.w() < b.w() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmplte, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+ uint32_t _x = a.x() <= b.x() ? 0xFFFFFFFF : 0x0;
+ uint32_t _y = a.y() <= b.y() ? 0xFFFFFFFF : 0x0;
+ uint32_t _z = a.z() <= b.z() ? 0xFFFFFFFF : 0x0;
+ uint32_t _w = a.w() <= b.w() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmpgt, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+ uint32_t _x = a.x() > b.x() ? 0xFFFFFFFF : 0x0;
+ uint32_t _y = a.y() > b.y() ? 0xFFFFFFFF : 0x0;
+ uint32_t _z = a.z() > b.z() ? 0xFFFFFFFF : 0x0;
+ uint32_t _w = a.w() > b.w() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmpgte, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+ uint32_t _x = a.x() >= b.x() ? 0xFFFFFFFF : 0x0;
+ uint32_t _y = a.y() >= b.y() ? 0xFFFFFFFF : 0x0;
+ uint32_t _z = a.z() >= b.z() ? 0xFFFFFFFF : 0x0;
+ uint32_t _w = a.w() >= b.w() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmpequal, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+ uint32_t _x = a.x() == b.x() ? 0xFFFFFFFF : 0x0;
+ uint32_t _y = a.y() == b.y() ? 0xFFFFFFFF : 0x0;
+ uint32_t _z = a.z() == b.z() ? 0xFFFFFFFF : 0x0;
+ uint32_t _w = a.w() == b.w() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmpnequal, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+ uint32_t _x = a.x() != b.x() ? 0xFFFFFFFF : 0x0;
+ uint32_t _y = a.y() != b.y() ? 0xFFFFFFFF : 0x0;
+ uint32_t _z = a.z() != b.z() ? 0xFFFFFFFF : 0x0;
+ uint32_t _w = a.w() != b.w() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_scale, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Double, scale, arguments->NativeArgAt(1));
+ float _s = static_cast<float>(scale.value());
+ float _x = self.x() * _s;
+ float _y = self.y() * _s;
+ float _z = self.z() * _s;
+ float _w = self.w() * _s;
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_abs, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ float _x = fabsf(self.x());
+ float _y = fabsf(self.y());
+ float _z = fabsf(self.z());
+ float _w = fabsf(self.w());
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_clamp, 3) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, lo, arguments->NativeArgAt(1));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, hi, arguments->NativeArgAt(2));
+ float _x = self.x() > lo.x() ? self.x() : lo.x();
+ float _y = self.y() > lo.y() ? self.y() : lo.y();
+ float _z = self.z() > lo.z() ? self.z() : lo.z();
+ float _w = self.w() > lo.w() ? self.w() : lo.w();
+ _x = _x > hi.x() ? hi.x() : _x;
+ _y = _y > hi.y() ? hi.y() : _y;
+ _z = _z > hi.z() ? hi.z() : _z;
+ _w = _w > hi.w() ? hi.w() : _w;
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getX, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ double value = static_cast<double>(self.x());
+ return Double::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getY, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ double value = static_cast<double>(self.y());
+ return Double::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getZ, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ double value = static_cast<double>(self.z());
+ return Double::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getW, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ double value = static_cast<double>(self.w());
+ return Double::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getXXXX, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ float value = self.x();
+ return Float32x4::New(value, value, value, value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getYYYY, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ float value = self.y();
+ return Float32x4::New(value, value, value, value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getZZZZ, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ float value = self.z();
+ return Float32x4::New(value, value, value, value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getWWWW, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ float value = self.w();
+ return Float32x4::New(value, value, value, value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_setX, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Double, x, arguments->NativeArgAt(1));
+ float _x = static_cast<float>(x.value());
+ float _y = self.y();
+ float _z = self.z();
+ float _w = self.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_setY, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Double, y, arguments->NativeArgAt(1));
+ float _x = self.x();
+ float _y = static_cast<float>(y.value());
+ float _z = self.z();
+ float _w = self.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_setZ, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Double, z, arguments->NativeArgAt(1));
+ float _x = self.x();
+ float _y = self.y();
+ float _z = static_cast<float>(z.value());
+ float _w = self.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_setW, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Double, w, arguments->NativeArgAt(1));
+ float _x = self.x();
+ float _y = self.y();
+ float _z = self.z();
+ float _w = static_cast<float>(w.value());
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_min, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other,
+ arguments->NativeArgAt(1));
+ float _x = self.x() < other.x() ? self.x() : other.x();
+ float _y = self.y() < other.y() ? self.y() : other.y();
+ float _z = self.z() < other.z() ? self.z() : other.z();
+ float _w = self.w() < other.w() ? self.w() : other.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_max, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other,
+ arguments->NativeArgAt(1));
+ float _x = self.x() > other.x() ? self.x() : other.x();
+ float _y = self.y() > other.y() ? self.y() : other.y();
+ float _z = self.z() > other.z() ? self.z() : other.z();
+ float _w = self.w() > other.w() ? self.w() : other.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_sqrt, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ float _x = sqrtf(self.x());
+ float _y = sqrtf(self.y());
+ float _z = sqrtf(self.z());
+ float _w = sqrtf(self.w());
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_reciprocal, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ float _x = 1.0f / self.x();
+ float _y = 1.0f / self.y();
+ float _z = 1.0f / self.z();
+ float _w = 1.0f / self.w();
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_reciprocalSqrt, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+ float _x = sqrtf(1.0f / self.x());
+ float _y = sqrtf(1.0f / self.y());
+ float _z = sqrtf(1.0f / self.z());
+ float _w = sqrtf(1.0f / self.w());
+ return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_toUint32x4, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(0));
+ return Uint32x4::New(v.value());
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_fromInts, 5) {
+ ASSERT(AbstractTypeArguments::CheckedHandle(
+ arguments->NativeArgAt(0)).IsNull());
+ GET_NON_NULL_NATIVE_ARGUMENT(Integer, x, arguments->NativeArgAt(1));
+ GET_NON_NULL_NATIVE_ARGUMENT(Integer, y, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(Integer, z, arguments->NativeArgAt(3));
+ GET_NON_NULL_NATIVE_ARGUMENT(Integer, w, arguments->NativeArgAt(4));
+ uint32_t _x = static_cast<uint32_t>(x.AsInt64Value() & 0xFFFFFFFF);
+ uint32_t _y = static_cast<uint32_t>(y.AsInt64Value() & 0xFFFFFFFF);
+ uint32_t _z = static_cast<uint32_t>(z.AsInt64Value() & 0xFFFFFFFF);
+ uint32_t _w = static_cast<uint32_t>(w.AsInt64Value() & 0xFFFFFFFF);
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_fromBools, 5) {
+ ASSERT(AbstractTypeArguments::CheckedHandle(
+ arguments->NativeArgAt(0)).IsNull());
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, x, arguments->NativeArgAt(1));
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, y, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, z, arguments->NativeArgAt(3));
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, w, arguments->NativeArgAt(4));
+ uint32_t _x = x.value() ? 0xFFFFFFFF : 0x0;
+ uint32_t _y = y.value() ? 0xFFFFFFFF : 0x0;
+ uint32_t _z = z.value() ? 0xFFFFFFFF : 0x0;
+ uint32_t _w = w.value() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_or, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, other, arguments->NativeArgAt(1));
+ uint32_t _x = self.x() | other.x();
+ uint32_t _y = self.y() | other.y();
+ uint32_t _z = self.z() | other.z();
+ uint32_t _w = self.w() | other.w();
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_and, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, other, arguments->NativeArgAt(1));
+ uint32_t _x = self.x() & other.x();
+ uint32_t _y = self.y() & other.y();
+ uint32_t _z = self.z() & other.z();
+ uint32_t _w = self.w() & other.w();
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_xor, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, other, arguments->NativeArgAt(1));
+ uint32_t _x = self.x() ^ other.x();
+ uint32_t _y = self.y() ^ other.y();
+ uint32_t _z = self.z() ^ other.z();
+ uint32_t _w = self.w() ^ other.w();
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getX, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ uint32_t value = self.x();
+ return Integer::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getY, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ uint32_t value = self.y();
+ return Integer::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getZ, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ uint32_t value = self.z();
+ return Integer::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getW, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ uint32_t value = self.w();
+ return Integer::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setX, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Integer, x, arguments->NativeArgAt(1));
+ uint32_t _x = static_cast<uint32_t>(x.AsInt64Value() & 0xFFFFFFFF);
+ uint32_t _y = self.y();
+ uint32_t _z = self.z();
+ uint32_t _w = self.w();
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setY, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Integer, y, arguments->NativeArgAt(1));
+ uint32_t _x = self.x();
+ uint32_t _y = static_cast<uint32_t>(y.AsInt64Value() & 0xFFFFFFFF);
+ uint32_t _z = self.z();
+ uint32_t _w = self.w();
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setZ, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Integer, z, arguments->NativeArgAt(1));
+ uint32_t _x = self.x();
+ uint32_t _y = self.y();
+ uint32_t _z = static_cast<uint32_t>(z.AsInt64Value() & 0xFFFFFFFF);
+ uint32_t _w = self.w();
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setW, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Integer, w, arguments->NativeArgAt(1));
+ uint32_t _x = self.x();
+ uint32_t _y = self.y();
+ uint32_t _z = self.z();
+ uint32_t _w = static_cast<uint32_t>(w.AsInt64Value() & 0xFFFFFFFF);
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getFlagX, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ uint32_t value = self.x();
+ return value != 0 ? Bool::True().raw() : Bool::False().raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getFlagY, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ uint32_t value = self.y();
+ return value != 0 ? Bool::True().raw() : Bool::False().raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getFlagZ, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ uint32_t value = self.z();
+ return value != 0 ? Bool::True().raw() : Bool::False().raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getFlagW, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ uint32_t value = self.w();
+ return value != 0 ? Bool::True().raw() : Bool::False().raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setFlagX, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, flagX, arguments->NativeArgAt(1));
+ uint32_t _x = self.x();
+ uint32_t _y = self.y();
+ uint32_t _z = self.z();
+ uint32_t _w = self.w();
+ _x = flagX.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setFlagY, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, flagY, arguments->NativeArgAt(1));
+ uint32_t _x = self.x();
+ uint32_t _y = self.y();
+ uint32_t _z = self.z();
+ uint32_t _w = self.w();
+ _y = flagY.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setFlagZ, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, flagZ, arguments->NativeArgAt(1));
+ uint32_t _x = self.x();
+ uint32_t _y = self.y();
+ uint32_t _z = self.z();
+ uint32_t _w = self.w();
+ _z = flagZ.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setFlagW, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, flagW, arguments->NativeArgAt(1));
+ uint32_t _x = self.x();
+ uint32_t _y = self.y();
+ uint32_t _z = self.z();
+ uint32_t _w = self.w();
+ _w = flagW.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+ return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+// Used to convert between uint32_t and float32 without breaking strict
+// aliasing rules.
+union float32_uint32 {
+ float f;
+ uint32_t u;
+ float32_uint32(float v) {
+ f = v;
+ }
+ float32_uint32(uint32_t v) {
+ u = v;
+ }
+};
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_select, 3) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, tv, arguments->NativeArgAt(1));
+ GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, fv, arguments->NativeArgAt(2));
+ uint32_t _maskX = self.x();
+ uint32_t _maskY = self.y();
+ uint32_t _maskZ = self.z();
+ uint32_t _maskW = self.w();
+ // Extract floats and interpret them as masks.
+ float32_uint32 tvx(tv.x());
+ float32_uint32 tvy(tv.y());
+ float32_uint32 tvz(tv.z());
+ float32_uint32 tvw(tv.w());
+ float32_uint32 fvx(fv.x());
+ float32_uint32 fvy(fv.y());
+ float32_uint32 fvz(fv.z());
+ float32_uint32 fvw(fv.w());
+ // Perform select.
+ float32_uint32 tempX((_maskX & tvx.u) | (~_maskX & fvx.u));
+ float32_uint32 tempY((_maskY & tvy.u) | (~_maskY & fvy.u));
+ float32_uint32 tempZ((_maskZ & tvz.u) | (~_maskZ & fvz.u));
+ float32_uint32 tempW((_maskW & tvw.u) | (~_maskW & fvw.u));
+ return Float32x4::New(tempX.f, tempY.f, tempZ.f, tempW.f);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_toFloat32x4, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, v, arguments->NativeArgAt(0));
+ return Float32x4::New(v.value());
+}
+
+
+} // namespace dart
diff --git a/runtime/lib/simd128.dart b/runtime/lib/simd128.dart
new file mode 100644
index 0000000..5052773
--- /dev/null
+++ b/runtime/lib/simd128.dart
@@ -0,0 +1,758 @@
+// 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 class Float32x4 {
+ /* patch */ factory Float32x4(double x, double y, double z, double w) {
+ return new _Float32x4(x, y, z, w);
+ }
+ /* patch */ factory Float32x4.zero() {
+ return new _Float32x4.zero();
+ }
+}
+
+patch class Uint32x4 {
+ /* patch */ factory Uint32x4(int x, int y, int z, int w) {
+ return new _Uint32x4(x, y, z, w);
+ }
+ /* patch */ factory Uint32x4.bool(bool x, bool y, bool z, bool w) {
+ return new _Uint32x4.bool(x, y, z, w);
+ }
+}
+
+
+patch class Float32x4List {
+ /* patch */ factory Float32x4List(int length) {
+ return new _Float32x4Array(length);
+ }
+
+ /* patch */ factory Float32x4List.transferable(int length) {
+ return _newTransferable(length);
+ }
+
+ /* patch */ factory Float32x4List.view(ByteArray array,
+ [int start = 0, int length]) {
+ return new _Float32x4ArrayView(array, start, length);
+ }
+
+ static _ExternalFloat32x4Array _newTransferable(int length)
+ native "Float32x4List_newTransferable";
+}
+
+
+// Expose native square root.
+double _sqrt(double x) native "Math_sqrt";
+class _Float32x4Dart implements Float32x4 {
+ final Float32List _storage = new Float32List(4);
+ _Float32x4Dart.empty() {
+ }
+ _Float32x4Dart.copy(Float32List other) {
+ _storage[0] = other._storage[0];
+ _storage[1] = other._storage[1];
+ _storage[2] = other._storage[2];
+ _storage[3] = other._storage[3];
+ }
+ factory _Float32x4Dart(double x, double y, double z, double w) {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = x;
+ instance._storage[1] = y;
+ instance._storage[2] = z;
+ instance._storage[3] = w;
+ return instance;
+ }
+ factory _Float32x4Dart.zero() {
+ var instance = new _Float32x4Dart.empty();
+ return instance;
+ }
+ Float32x4 operator +(Float32x4 other) {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _storage[0] + other._storage[0];
+ instance._storage[1] = _storage[1] + other._storage[1];
+ instance._storage[2] = _storage[2] + other._storage[2];
+ instance._storage[3] = _storage[3] + other._storage[3];
+ return instance;
+ }
+ Float32x4 operator -() {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = -_storage[0];
+ instance._storage[1] = -_storage[1];
+ instance._storage[2] = -_storage[2];
+ instance._storage[3] = -_storage[3];
+ return instance;
+ }
+ Float32x4 operator -(Float32x4 other) {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _storage[0] - other._storage[0];
+ instance._storage[1] = _storage[1] - other._storage[1];
+ instance._storage[2] = _storage[2] - other._storage[2];
+ instance._storage[3] = _storage[3] - other._storage[3];
+ return instance;
+ }
+ Float32x4 operator *(Float32x4 other) {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _storage[0] * other._storage[0];
+ instance._storage[1] = _storage[1] * other._storage[1];
+ instance._storage[2] = _storage[2] * other._storage[2];
+ instance._storage[3] = _storage[3] * other._storage[3];
+ return instance;
+ }
+ Float32x4 operator /(Float32x4 other) {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _storage[0] / other._storage[0];
+ instance._storage[1] = _storage[1] / other._storage[1];
+ instance._storage[2] = _storage[2] / other._storage[2];
+ instance._storage[3] = _storage[3] / other._storage[3];
+ return instance;
+ }
+ Uint32x4 lessThan(Float32x4 other) {
+ bool _x = _storage[0] < other._storage[0];
+ bool _y = _storage[1] < other._storage[1];
+ bool _z = _storage[2] < other._storage[2];
+ bool _w = _storage[3] < other._storage[3];
+ return new Uint32x4.bool(_x, _y, _z, _w);
+ }
+ Uint32x4 lessThanOrEqual(Float32x4 other) {
+ bool _x = _storage[0] <= other._storage[0];
+ bool _y = _storage[1] <= other._storage[1];
+ bool _z = _storage[2] <= other._storage[2];
+ bool _w = _storage[3] <= other._storage[3];
+ return new Uint32x4.bool(_x, _y, _z, _w);
+ }
+ Uint32x4 greaterThan(Float32x4 other) {
+ bool _x = _storage[0] > other._storage[0];
+ bool _y = _storage[1] > other._storage[1];
+ bool _z = _storage[2] > other._storage[2];
+ bool _w = _storage[3] > other._storage[3];
+ return new Uint32x4.bool(_x, _y, _z, _w);
+ }
+ Uint32x4 greaterThanOrEqual(Float32x4 other) {
+ bool _x = _storage[0] >= other._storage[0];
+ bool _y = _storage[1] >= other._storage[1];
+ bool _z = _storage[2] >= other._storage[2];
+ bool _w = _storage[3] >= other._storage[3];
+ return new Uint32x4.bool(_x, _y, _z, _w);
+ }
+ Uint32x4 equal(Float32x4 other) {
+ bool _x = _storage[0] == other._storage[0];
+ bool _y = _storage[1] == other._storage[1];
+ bool _z = _storage[2] == other._storage[2];
+ bool _w = _storage[3] == other._storage[3];
+ return new Uint32x4.bool(_x, _y, _z, _w);
+ }
+ Uint32x4 notEqual(Float32x4 other) {
+ bool _x = _storage[0] != other._storage[0];
+ bool _y = _storage[1] != other._storage[1];
+ bool _z = _storage[2] != other._storage[2];
+ bool _w = _storage[3] != other._storage[3];
+ return new Uint32x4.bool(_x, _y, _z, _w);
+ }
+ Float32x4 scale(double s) {
+ var instance = new _Float32x4Dart.copy(this);
+ instance._storage[0] *= s;
+ instance._storage[1] *= s;
+ instance._storage[2] *= s;
+ instance._storage[3] *= s;
+ return instance;
+ }
+ Float32x4 abs() {
+ var instance = new _Float32x4Dart.copy(this);
+ instance._storage[0] = instance._storage[0].abs();
+ instance._storage[1] = instance._storage[1].abs();
+ instance._storage[2] = instance._storage[2].abs();
+ instance._storage[3] = instance._storage[3].abs();
+ return instance;
+ }
+ Float32x4 clamp(Float32x4 lowerLimit,
+ Float32x4 upperLimit) {
+ var instance = new _Float32x4Dart.copy(this);
+ if (instance._storage[0] > upperLimit._storage[0]) {
+ instance._storage[0] = upperLimit._storage[0];
+ }
+ if (instance._storage[1] > upperLimit._storage[1]) {
+ instance._storage[1] = upperLimit._storage[1];
+ }
+ if (instance._storage[2] > upperLimit._storage[2]) {
+ instance._storage[2] = upperLimit._storage[2];
+ }
+ if (instance._storage[3] > upperLimit._storage[3]) {
+ instance._storage[3] = upperLimit._storage[3];
+ }
+ if (instance._storage[0] < lowerLimit._storage[0]) {
+ instance._storage[0] = lowerLimit._storage[0];
+ }
+ if (instance._storage[1] < lowerLimit._storage[1]) {
+ instance._storage[1] = lowerLimit._storage[1];
+ }
+ if (instance._storage[2] < lowerLimit._storage[2]) {
+ instance._storage[2] = lowerLimit._storage[2];
+ }
+ if (instance._storage[3] < lowerLimit._storage[3]) {
+ instance._storage[3] = lowerLimit._storage[3];
+ }
+ return instance;
+ }
+ double get x => _storage[0];
+ double get y => _storage[1];
+ double get z => _storage[2];
+ double get w => _storage[3];
+ Float32x4 get xxxx {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _storage[0];
+ instance._storage[1] = _storage[0];
+ instance._storage[2] = _storage[0];
+ instance._storage[3] = _storage[0];
+ return instance;
+ }
+ Float32x4 get yyyy {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _storage[1];
+ instance._storage[1] = _storage[1];
+ instance._storage[2] = _storage[1];
+ instance._storage[3] = _storage[1];
+ return instance;
+ }
+ Float32x4 get zzzz {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _storage[2];
+ instance._storage[1] = _storage[2];
+ instance._storage[2] = _storage[2];
+ instance._storage[3] = _storage[2];
+ return instance;
+ }
+ Float32x4 get wwww {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _storage[3];
+ instance._storage[1] = _storage[3];
+ instance._storage[2] = _storage[3];
+ instance._storage[3] = _storage[3];
+ return instance;
+ }
+ Float32x4 withX(double x) {
+ var instance = new _Float32x4Dart.copy(this);
+ instance._storage[0] = x;
+ return instance;
+ }
+ Float32x4 withY(double y) {
+ var instance = new _Float32x4Dart.copy(this);
+ instance._storage[1] = y;
+ return instance;
+ }
+ Float32x4 withZ(double z) {
+ var instance = new _Float32x4Dart.copy(this);
+ instance._storage[2] = z;
+ return instance;
+ }
+ Float32x4 withW(double w) {
+ var instance = new _Float32x4Dart.copy(this);
+ instance._storage[3] = w;
+ return instance;
+ }
+ Float32x4 min(Float32x4 other) {
+ var instance = new _Float32x4Dart.copy(this);
+ if (instance._storage[0] > other._storage[0]) {
+ instance._storage[0] = other._storage[0];
+ }
+ if (instance._storage[1] > other._storage[1]) {
+ instance._storage[1] = other._storage[1];
+ }
+ if (instance._storage[2] > other._storage[2]) {
+ instance._storage[2] = other._storage[2];
+ }
+ if (instance._storage[3] > other._storage[3]) {
+ instance._storage[3] = other._storage[3];
+ }
+ return instance;
+ }
+ Float32x4 max(Float32x4 other) {
+ var instance = new _Float32x4Dart.copy(this);
+ if (instance._storage[0] < other._storage[0]) {
+ instance._storage[0] = other._storage[0];
+ }
+ if (instance._storage[1] < other._storage[1]) {
+ instance._storage[1] = other._storage[1];
+ }
+ if (instance._storage[2] < other._storage[2]) {
+ instance._storage[2] = other._storage[2];
+ }
+ if (instance._storage[3] < other._storage[3]) {
+ instance._storage[3] = other._storage[3];
+ }
+ return instance;
+ }
+ Float32x4 sqrt() {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _sqrt(_storage[0]);
+ instance._storage[1] = _sqrt(_storage[1]);
+ instance._storage[2] = _sqrt(_storage[2]);
+ instance._storage[3] = _sqrt(_storage[3]);
+ return instance;
+ }
+ Float32x4 reciprocal() {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = (1.0 / _storage[0]);
+ instance._storage[1] = (1.0 / _storage[1]);
+ instance._storage[2] = (1.0 / _storage[2]);
+ instance._storage[3] = (1.0 / _storage[3]);
+ return instance;
+ }
+ Float32x4 reciprocalSqrt() {
+ var instance = new _Float32x4Dart.empty();
+ instance._storage[0] = _sqrt(1.0 / _storage[0]);
+ instance._storage[1] = _sqrt(1.0 / _storage[1]);
+ instance._storage[2] = _sqrt(1.0 / _storage[2]);
+ instance._storage[3] = _sqrt(1.0 / _storage[3]);
+ return instance;
+ }
+ Uint32x4 toUint32x4() {
+ Uint32List view = new Uint32List.view(_storage.asByteArray());
+ return new Uint32x4(view[0], view[1], view[2], view[3]);
+ }
+}
+
+class _Uint32x4Dart implements Uint32x4 {
+ final Uint32List _storage = new Uint32List(4);
+ _Uint32x4Dart.empty() {
+ }
+ _Uint32x4Dart.copy(_Uint32x4Dart other) {
+ _storage[0] = other._storage[0];
+ _storage[1] = other._storage[1];
+ _storage[2] = other._storage[2];
+ _storage[3] = other._storage[3];
+ }
+ factory _Uint32x4Dart(int x, int y, int z, int w) {
+ var instance = new _Uint32x4Dart.empty();
+ instance._storage[0] = x;
+ instance._storage[1] = y;
+ instance._storage[2] = z;
+ instance._storage[3] = w;
+ return instance;
+ }
+ factory _Uint32x4Dart.bool(bool x, bool y, bool z, bool w) {
+ var instance = new _Uint32x4Dart.empty();
+ instance._storage[0] = x ? 0xFFFFFFFF : 0x0;
+ instance._storage[1] = y ? 0xFFFFFFFF : 0x0;
+ instance._storage[2] = z ? 0xFFFFFFFF : 0x0;
+ instance._storage[3] = w ? 0xFFFFFFFF : 0x0;
+ return instance;
+ }
+ Uint32x4 operator |(Uint32x4 other) {
+ var instance = new _Uint32x4Dart.empty();
+ instance._storage[0] = _storage[0] | other._storage[0];
+ instance._storage[1] = _storage[1] | other._storage[1];
+ instance._storage[2] = _storage[2] | other._storage[2];
+ instance._storage[3] = _storage[3] | other._storage[3];
+ return instance;
+ }
+ Uint32x4 operator &(Uint32x4 other) {
+ var instance = new _Uint32x4Dart.empty();
+ instance._storage[0] = _storage[0] & other._storage[0];
+ instance._storage[1] = _storage[1] & other._storage[1];
+ instance._storage[2] = _storage[2] & other._storage[2];
+ instance._storage[3] = _storage[3] & other._storage[3];
+ return instance;
+ }
+ Uint32x4 operator ^(Uint32x4 other) {
+ var instance = new _Uint32x4Dart.empty();
+ instance._storage[0] = _storage[0] ^ other._storage[0];
+ instance._storage[1] = _storage[1] ^ other._storage[1];
+ instance._storage[2] = _storage[2] ^ other._storage[2];
+ instance._storage[3] = _storage[3] ^ other._storage[3];
+ return instance;
+ }
+ int get x => _storage[0];
+ int get y => _storage[1];
+ int get z => _storage[2];
+ int get w => _storage[3];
+ Uint32x4 withX(int x) {
+ var instance = new _Uint32x4Dart.copy(this);
+ instance._storage[0] = x & 0xFFFFFFFF;
+ return instance;
+ }
+ Uint32x4 withY(int y) {
+ var instance = new _Uint32x4Dart.copy(this);
+ instance._storage[1] = y & 0xFFFFFFFF;
+ return instance;
+ }
+ Uint32x4 withZ(int z) {
+ var instance = new _Uint32x4Dart.copy(this);
+ instance._storage[2] = z & 0xFFFFFFFF;
+ return instance;
+ }
+ Uint32x4 withW(int w) {
+ var instance = new _Uint32x4Dart.copy(this);
+ instance._storage[3] = w & 0xFFFFFFFF;
+ return instance;
+ }
+ bool get flagX => _storage[0] != 0x0;
+ bool get flagY => _storage[1] != 0x0;
+ bool get flagZ => _storage[2] != 0x0;
+ bool get flagW => _storage[3] != 0x0;
+ Uint32x4 withFlagX(bool x) {
+ var instance = new _Uint32x4Dart.copy(this);
+ instance._storage[0] = x ? 0xFFFFFFFF : 0x0;
+ return instance;
+ }
+ Uint32x4 withFlagY(bool y) {
+ var instance = new _Uint32x4Dart.copy(this);
+ instance._storage[1] = y ? 0xFFFFFFFF : 0x0;
+ return instance;
+ }
+ Uint32x4 withFlagZ(bool z) {
+ var instance = new _Uint32x4Dart.copy(this);
+ instance._storage[2] = z ? 0xFFFFFFFF : 0x0;
+ return instance;
+ }
+ Uint32x4 withFlagW(bool w) {
+ var instance = new _Uint32x4Dart.copy(this);
+ instance._storage[3] = w ? 0xFFFFFFFF : 0x0;
+ return instance;
+ }
+ Float32x4 select(Float32x4 trueValue,
+ Float32x4 falseValue) {
+ Uint32x4 trueMask = trueValue.toUint32x4();
+ Uint32x4 falseMask = falseValue.toUint32x4();
+ var instance = new _Uint32x4Dart.empty();
+ instance._storage[0] = (_storage[0] & trueMask._storage[0]);
+ instance._storage[1] = (_storage[1] & trueMask._storage[1]);
+ instance._storage[2] = (_storage[2] & trueMask._storage[2]);
+ instance._storage[3] = (_storage[3] & trueMask._storage[3]);
+ instance._storage[0] |= (~_storage[0] & falseMask._storage[0]);
+ instance._storage[1] |= (~_storage[1] & falseMask._storage[1]);
+ instance._storage[2] |= (~_storage[2] & falseMask._storage[2]);
+ instance._storage[3] |= (~_storage[3] & falseMask._storage[3]);
+ return instance.toFloat32x4();
+ }
+ Float32x4 toFloat32x4() {
+ Float32List view = new Float32List.view(_storage.asByteArray());
+ return new Float32x4(view[0], view[1], view[2], view[3]);
+ }
+}
+
+class _Float32x4 implements Float32x4 {
+ factory _Float32x4(double x, double y, double z, double w)
+ native "Float32x4_fromDoubles";
+ factory _Float32x4.zero() native "Float32x4_zero";
+ Float32x4 operator +(Float32x4 other) {
+ return _add(other);
+ }
+ Float32x4 _add(Float32x4 other) native "Float32x4_add";
+ Float32x4 operator -() {
+ return _negate();
+ }
+ Float32x4 _negate() native "Float32x4_negate";
+ Float32x4 operator -(Float32x4 other) {
+ return _sub(other);
+ }
+ Float32x4 _sub(Float32x4 other) native "Float32x4_sub";
+ Float32x4 operator *(Float32x4 other) {
+ return _mul(other);
+ }
+ Float32x4 _mul(Float32x4 other) native "Float32x4_mul";
+ Float32x4 operator /(Float32x4 other) {
+ return _div(other);
+ }
+ Float32x4 _div(Float32x4 other) native "Float32x4_div";
+ Uint32x4 lessThan(Float32x4 other) {
+ return _cmplt(other);
+ }
+ Uint32x4 _cmplt(Float32x4 other) native "Float32x4_cmplt";
+ Uint32x4 lessThanOrEqual(Float32x4 other) {
+ return _cmplte(other);
+ }
+ Uint32x4 _cmplte(Float32x4 other) native "Float32x4_cmplte";
+ Uint32x4 greaterThan(Float32x4 other) {
+ return _cmpgt(other);
+ }
+ Uint32x4 _cmpgt(Float32x4 other) native "Float32x4_cmpgt";
+ Uint32x4 greaterThanOrEqual(Float32x4 other) {
+ return _cmpgte(other);
+ }
+ Uint32x4 _cmpgte(Float32x4 other) native "Float32x4_cmpgte";
+ Uint32x4 equal(Float32x4 other) {
+ return _cmpequal(other);
+ }
+ Uint32x4 _cmpequal(Float32x4 other)
+ native "Float32x4_cmpequal";
+ Uint32x4 notEqual(Float32x4 other) {
+ return _cmpnequal(other);
+ }
+ Uint32x4 _cmpnequal(Float32x4 other)
+ native "Float32x4_cmpnequal";
+ Float32x4 scale(double s) {
+ return _scale(s);
+ }
+ Float32x4 _scale(double s) native "Float32x4_scale";
+ Float32x4 abs() {
+ return _abs();
+ }
+ Float32x4 _abs() native "Float32x4_abs";
+ Float32x4 clamp(Float32x4 lowerLimit,
+ Float32x4 upperLimit) {
+ return _clamp(lowerLimit, upperLimit);
+ }
+ Float32x4 _clamp(Float32x4 lowerLimit,
+ Float32x4 upperLimit)
+ native "Float32x4_clamp";
+ double get x native "Float32x4_getX";
+ double get y native "Float32x4_getY";
+ double get z native "Float32x4_getZ";
+ double get w native "Float32x4_getW";
+ Float32x4 get xxxx native "Float32x4_getXXXX";
+ Float32x4 get yyyy native "Float32x4_getYYYY";
+ Float32x4 get zzzz native "Float32x4_getZZZZ";
+ Float32x4 get wwww native "Float32x4_getWWWW";
+ Float32x4 withX(double x) native "Float32x4_setX";
+ Float32x4 withY(double y) native "Float32x4_setY";
+ Float32x4 withZ(double z) native "Float32x4_setZ";
+ Float32x4 withW(double w) native "Float32x4_setW";
+ Float32x4 min(Float32x4 other) {
+ return _min(other);
+ }
+ Float32x4 _min(Float32x4 other) native "Float32x4_min";
+ Float32x4 max(Float32x4 other) {
+ return _max(other);
+ }
+ Float32x4 _max(Float32x4 other) native "Float32x4_max";
+ Float32x4 sqrt() {
+ return _sqrt();
+ }
+ Float32x4 _sqrt() native "Float32x4_sqrt";
+ Float32x4 reciprocal() {
+ return _reciprocal();
+ }
+ Float32x4 _reciprocal() native "Float32x4_reciprocal";
+ Float32x4 reciprocalSqrt() {
+ return _reciprocalSqrt();
+ }
+ Float32x4 _reciprocalSqrt() native "Float32x4_reciprocalSqrt";
+ Uint32x4 toUint32x4() {
+ return _toUint32x4();
+ }
+ Uint32x4 _toUint32x4() native "Float32x4_toUint32x4";
+}
+
+class _Uint32x4 implements Uint32x4 {
+ factory _Uint32x4(int x, int y, int z, int w)
+ native "Uint32x4_fromInts";
+ factory _Uint32x4.bool(bool x, bool y, bool z, bool w)
+ native "Uint32x4_fromBools";
+ Uint32x4 operator |(Uint32x4 other) {
+ return _or(other);
+ }
+ Uint32x4 _or(Uint32x4 other) native "Uint32x4_or";
+ Uint32x4 operator &(Uint32x4 other) {
+ return _and(other);
+ }
+ Uint32x4 _and(Uint32x4 other) native "Uint32x4_and";
+ Uint32x4 operator ^(Uint32x4 other) {
+ return _xor(other);
+ }
+ Uint32x4 _xor(Uint32x4 other) native "Uint32x4_xor";
+ int get x native "Uint32x4_getX";
+ int get y native "Uint32x4_getY";
+ int get z native "Uint32x4_getZ";
+ int get w native "Uint32x4_getW";
+ Uint32x4 withX(int x) native "Uint32x4_setX";
+ Uint32x4 withY(int y) native "Uint32x4_setY";
+ Uint32x4 withZ(int z) native "Uint32x4_setZ";
+ Uint32x4 withW(int w) native "Uint32x4_setW";
+ bool get flagX native "Uint32x4_getFlagX";
+ bool get flagY native "Uint32x4_getFlagY";
+ bool get flagZ native "Uint32x4_getFlagZ";
+ bool get flagW native "Uint32x4_getFlagW";
+ Uint32x4 withFlagX(bool x) native "Uint32x4_setFlagX";
+ Uint32x4 withFlagY(bool y) native "Uint32x4_setFlagY";
+ Uint32x4 withFlagZ(bool z) native "Uint32x4_setFlagZ";
+ Uint32x4 withFlagW(bool w) native "Uint32x4_setFlagW";
+ Float32x4 select(Float32x4 trueValue,
+ Float32x4 falseValue) {
+ return _select(trueValue, falseValue);
+ }
+ Float32x4 _select(Float32x4 trueValue,
+ Float32x4 falseValue)
+ native "Uint32x4_select";
+ Float32x4 toFloat32x4() {
+ return _toFloat32x4();
+ }
+ Float32x4 _toFloat32x4() native "Uint32x4_toFloat32x4";
+}
+
+
+class _Float32x4Array extends _ByteArrayBase
+ implements Float32x4List {
+ factory _Float32x4Array(int length) {
+ return _new(length);
+ }
+ factory _Float32x4Array.view(ByteArray array,
+ [int start = 0, int length]) {
+ if (length == null) {
+ length = (array.lengthInBytes() - start) ~/ _BYTES_PER_ELEMENT;
+ }
+ return new _Float32x4ArrayView(array, start, length);
+ }
+ Float32x4 operator [](int index) {
+ return _getIndexed(index);
+ }
+ int operator []=(int index, Float32x4 value) {
+ _setIndexed(index, value);
+ }
+ Iterator<Float32x4> get iterator {
+ return new _ByteArrayIterator<Float32x4>(this);
+ }
+ List<Float32x4> getRange(int start, int length) {
+ _rangeCheck(this.length, start, length);
+ List<Float32x4> result = _new(length);
+ result.setRange(0, length, this, start);
+ return result;
+ }
+ void setRange(int start, int length, List<Float32x4> from,
+ [int startFrom = 0]) {
+ if (from is _Float32x4Array) {
+ _setRange(start * _BYTES_PER_ELEMENT,
+ length * _BYTES_PER_ELEMENT,
+ from,
+ startFrom * _BYTES_PER_ELEMENT);
+ } else {
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
+ }
+ }
+ String toString() {
+ return Collections.collectionToString(this);
+ }
+ int bytesPerElement() {
+ return _BYTES_PER_ELEMENT;
+ }
+ int lengthInBytes() {
+ return _length() * _BYTES_PER_ELEMENT;
+ }
+ static const int _BYTES_PER_ELEMENT = 16;
+ static _Float32x4Array _new(int length)
+ native "Float32x4Array_new";
+ Float32x4 _getIndexed(int index)
+ native "Float32x4Array_getIndexed";
+ int _setIndexed(int index, Float32x4 value)
+ native "Float32x4Array_setIndexed";
+}
+
+
+class _Float32x4ArrayView extends _ByteArrayViewBase
+ implements Float32x4List {
+ _Float32x4ArrayView(ByteArray array,
+ [int offsetInBytes = 0, int _length])
+ : super(array, _requireInteger(offsetInBytes),
+ _requireIntegerOrNull(
+ _length,
+ ((array.lengthInBytes() - offsetInBytes) ~/ _BYTES_PER_ELEMENT))) {
+ _rangeCheck(array.lengthInBytes(), _offset, length * _BYTES_PER_ELEMENT);
+ }
+
+ Float32x4 operator [](int index) {
+ if (index < 0 || index >= length) {
+ String message = "$index must be in the range [0..$length)";
+ throw new RangeError(message);
+ }
+ return _array.getFloat32x4(_offset + (index * _BYTES_PER_ELEMENT));
+ }
+
+ void operator []=(int index, Float32x4 value) {
+ if (index < 0 || index >= length) {
+ String message = "$index must be in the range [0..$length)";
+ throw new RangeError(message);
+ }
+ _array.setFloat32x4(_offset + (index * _BYTES_PER_ELEMENT), value);
+ }
+
+ Iterator<Float32x4> get iterator {
+ return new _ByteArrayIterator<Float32x4>(this);
+ }
+
+ List<Float32x4> getRange(int start, int length) {
+ _rangeCheck(this.length, start, length);
+ List<Float32x4> result = new Float32List(length);
+ result.setRange(0, length, this, start);
+ return result;
+ }
+
+ void setRange(int start, int length, List<Float32x4> from,
+ [int startFrom = 0]) {
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
+ }
+
+ String toString() {
+ return Collections.collectionToString(this);
+ }
+
+ int bytesPerElement() {
+ return _BYTES_PER_ELEMENT;
+ }
+
+ int lengthInBytes() {
+ return length * _BYTES_PER_ELEMENT;
+ }
+
+ ByteArray asByteArray([int start = 0, int length]) {
+ if (length == null) {
+ length = this.lengthInBytes();
+ }
+ _rangeCheck(this.length, start, length);
+ return _array.subByteArray(_offset + start, length);
+ }
+
+ static const int _BYTES_PER_ELEMENT = 16;
+}
+
+
+class _ExternalFloat32x4Array extends _ByteArrayBase
+ implements Float32x4List {
+ Float32x4 operator [](int index) {
+ return _getIndexed(index);
+ }
+
+ int operator []=(int index, Float32x4 value) {
+ _setIndexed(index, value);
+ }
+
+ Iterator<Float32x4> get iterator {
+ return new _ByteArrayIterator<Float32x4>(this);
+ }
+
+ List<Float32x4> getRange(int start, int length) {
+ _rangeCheck(this.length, start, length);
+ List<Float32x4> result = new Float32x4List(length);
+ result.setRange(0, length, this, start);
+ return result;
+ }
+
+ void setRange(int start, int length, List<Float32x4> from,
+ [int startFrom = 0]) {
+ if (from is _ExternalFloat32x4Array) {
+ _setRange(start * _BYTES_PER_ELEMENT,
+ length * _BYTES_PER_ELEMENT,
+ from,
+ startFrom * _BYTES_PER_ELEMENT);
+ } else {
+ IterableMixinWorkaround.setRangeList(
+ this, start, length, from, startFrom);
+ }
+ }
+
+ String toString() {
+ return Collections.collectionToString(this);
+ }
+
+ int bytesPerElement() {
+ return _BYTES_PER_ELEMENT;
+ }
+
+ int lengthInBytes() {
+ return _length() * _BYTES_PER_ELEMENT;
+ }
+
+ static const int _BYTES_PER_ELEMENT = 16;
+
+ Float32x4 _getIndexed(int index)
+ native "ExternalFloat32x4Array_getIndexed";
+ int _setIndexed(int index, Float32x4 value)
+ native "ExternalFloat32x4Array_setIndexed";
+}
diff --git a/runtime/lib/stacktrace.cc b/runtime/lib/stacktrace.cc
new file mode 100644
index 0000000..085d9dc
--- /dev/null
+++ b/runtime/lib/stacktrace.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "lib/error.h"
+
+#include "vm/bootstrap_natives.h"
+#include "vm/exceptions.h"
+#include "vm/object_store.h"
+#include "vm/runtime_entry.h"
+#include "vm/stack_frame.h"
+
+namespace dart {
+
+// Get a full stack trace.
+// Arg0: stack trace object.
+// Return value: String that represents the full stack trace.
+DEFINE_NATIVE_ENTRY(Stacktrace_getFullStacktrace, 1) {
+ const Stacktrace& trace =
+ Stacktrace::CheckedHandle(arguments->NativeArgAt(0));
+ return trace.FullStacktrace();
+}
+
+
+// Get a concise and pertinent stack trace.
+// Arg0: stack trace object.
+// Return value: String that represents the concise and pertinent stack trace.
+DEFINE_NATIVE_ENTRY(Stacktrace_getStacktrace, 1) {
+ const Stacktrace& trace =
+ Stacktrace::CheckedHandle(arguments->NativeArgAt(0));
+ return String::New(trace.ToCStringInternal(0));
+}
+
+
+// Setup a full stack trace.
+// Arg0: stack trace object.
+// Return value: None.
+DEFINE_NATIVE_ENTRY(Stacktrace_setupFullStacktrace, 1) {
+ const Stacktrace& trace =
+ Stacktrace::CheckedHandle(arguments->NativeArgAt(0));
+ const GrowableObjectArray& func_list =
+ GrowableObjectArray::Handle(GrowableObjectArray::New());
+ const GrowableObjectArray& code_list =
+ GrowableObjectArray::Handle(GrowableObjectArray::New());
+ const GrowableObjectArray& pc_offset_list =
+ GrowableObjectArray::Handle(GrowableObjectArray::New());
+ StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
+ StackFrame* frame = frames.NextFrame();
+ ASSERT(frame != NULL); // We expect to find a dart invocation frame.
+ Function& func = Function::Handle();
+ Code& code = Code::Handle();
+ Smi& offset = Smi::Handle();
+ bool catch_frame_skipped = false; // Tracks if catch frame has been skipped.
+ while (!frame->IsEntryFrame()) {
+ if (frame->IsDartFrame()) {
+ code = frame->LookupDartCode();
+ if (code.is_optimized()) {
+ // For optimized frames, extract all the inlined functions if any
+ // into the stack trace.
+ for (InlinedFunctionsIterator it(frame); !it.Done(); it.Advance()) {
+ func = it.function();
+ code = it.code();
+ uword pc = it.pc();
+ ASSERT(pc != 0);
+ ASSERT(code.EntryPoint() <= pc);
+ ASSERT(pc < (code.EntryPoint() + code.Size()));
+ if (func.is_visible()) {
+ if (!catch_frame_skipped) {
+ catch_frame_skipped = true;
+ } else {
+ offset = Smi::New(pc - code.EntryPoint());
+ func_list.Add(func);
+ code_list.Add(code);
+ pc_offset_list.Add(offset);
+ }
+ }
+ }
+ } else {
+ offset = Smi::New(frame->pc() - code.EntryPoint());
+ func = code.function();
+ if (func.is_visible()) {
+ if (!catch_frame_skipped) {
+ catch_frame_skipped = true;
+ } else {
+ func_list.Add(func);
+ code_list.Add(code);
+ pc_offset_list.Add(offset);
+ }
+ }
+ }
+ }
+ frame = frames.NextFrame();
+ ASSERT(frame != NULL);
+ }
+ const Array& func_array = Array::Handle(Array::MakeArray(func_list));
+ const Array& code_array = Array::Handle(Array::MakeArray(code_list));
+ const Array& pc_offset_array =
+ Array::Handle(Array::MakeArray(pc_offset_list));
+ trace.SetCatchStacktrace(func_array, code_array, pc_offset_array);
+ return Object::null();
+}
+
+} // namespace dart
diff --git a/runtime/lib/stacktrace_patch.dart b/runtime/lib/stacktrace_patch.dart
new file mode 100644
index 0000000..2d5fdc5
--- /dev/null
+++ b/runtime/lib/stacktrace_patch.dart
@@ -0,0 +1,13 @@
+// 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 class StackTrace {
+ /* patch */ String get fullStackTrace native "Stacktrace_getFullStacktrace";
+
+ /* patch */ String get stackTrace native "Stacktrace_getStacktrace";
+
+ /* patch */ void _setupFullStackTrace()
+ native "Stacktrace_setupFullStacktrace";
+}
+
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index d17b9134..3b5b633 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -149,13 +149,13 @@
return Symbols::FromCharCode(value);
}
-DEFINE_NATIVE_ENTRY(String_charCodeAt, 2) {
+DEFINE_NATIVE_ENTRY(String_codeUnitAt, 2) {
const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
int32_t value = StringValueAt(receiver, index);
ASSERT(value >= 0);
- ASSERT(value <= 0x10FFFF);
+ ASSERT(value <= 0xFFFF);
return Smi::New(value);
}
diff --git a/runtime/lib/string_base.dart b/runtime/lib/string_base.dart
index 8b28aae..8ed74b6 100644
--- a/runtime/lib/string_base.dart
+++ b/runtime/lib/string_base.dart
@@ -38,11 +38,7 @@
String operator [](int index) native "String_charAt";
- int charCodeAt(int index) native "String_charCodeAt";
-
- int codeUnitAt(int index) {
- return charCodeAt(index);
- }
+ int codeUnitAt(int index) native "String_codeUnitAt";
int get length native "String_getLength";
@@ -73,8 +69,8 @@
int otherLength = other.length;
int len = (thisLength < otherLength) ? thisLength : otherLength;
for (int i = 0; i < len; i++) {
- int thisCodePoint = this.charCodeAt(i);
- int otherCodePoint = other.charCodeAt(i);
+ int thisCodePoint = this.codeUnitAt(i);
+ int otherCodePoint = other.codeUnitAt(i);
if (thisCodePoint < otherCodePoint) {
return -1;
}
@@ -97,7 +93,7 @@
return false;
}
for (int i = 0; i < len; i++) {
- if (this.charCodeAt(i + start) != other.charCodeAt(i)) {
+ if (this.codeUnitAt(i + start) != other.codeUnitAt(i)) {
return false;
}
}
@@ -216,7 +212,7 @@
final int len = this.length;
int first = 0;
for (; first < len; first++) {
- if (!_isWhitespace(this.charCodeAt(first))) {
+ if (!_isWhitespace(this.codeUnitAt(first))) {
break;
}
}
@@ -226,7 +222,7 @@
}
int last = len - 1;
for (; last >= first; last--) {
- if (!_isWhitespace(this.charCodeAt(last))) {
+ if (!_isWhitespace(this.codeUnitAt(last))) {
break;
}
}
@@ -300,10 +296,10 @@
while (i < length) {
buffer.add(onMatch(new _StringMatch(i, this, "")));
// Special case to avoid splitting a surrogate pair.
- int code = this.charCodeAt(i);
+ int code = this.codeUnitAt(i);
if ((code & ~0x3FF) == 0xD800 && length > i + 1) {
// Leading surrogate;
- code = this.charCodeAt(i + 1);
+ code = this.codeUnitAt(i + 1);
if ((code & ~0x3FF) == 0xDC00) {
// Matching trailing surrogate.
buffer.add(onNonMatch(this.substring(i, i + 2)));
@@ -351,7 +347,7 @@
*/
static String _interpolate(List values) {
int numValues = values.length;
- var stringList = new List.fixedLength(numValues);
+ var stringList = new List(numValues);
for (int i = 0; i < numValues; i++) {
stringList[i] = values[i].toString();
}
@@ -383,7 +379,11 @@
List<String> split(Pattern pattern) {
if ((pattern is String) && pattern.isEmpty) {
- return splitChars();
+ List<String> result = new List<String>(length);
+ for (int i = 0; i < length; i++) {
+ result[i] = this[i];
+ }
+ return result;
}
int length = this.length;
Iterator iterator = pattern.allMatches(this).iterator;
@@ -415,25 +415,7 @@
return result;
}
- List<String> splitChars() {
- int len = this.length;
- final result = new List<String>.fixedLength(len);
- for (int i = 0; i < len; i++) {
- result[i] = this[i];
- }
- return result;
- }
-
- List<int> get charCodes {
- int len = this.length;
- final result = new List<int>.fixedLength(len);
- for (int i = 0; i < len; i++) {
- result[i] = this.charCodeAt(i);
- }
- return result;
- }
-
- Iterable<int> get codeUnits => new CodeUnits(this);
+ List<int> get codeUnits => new CodeUnits(this);
Runes get runes => new Runes(this);
@@ -490,6 +472,8 @@
"_OneByteString can only be allocated by the VM");
}
+ int get hashCode native "String_getHashCode";
+
// Checks for one-byte whitespaces only.
// TODO(srdjan): Investigate if 0x85 (NEL) and 0xA0 (NBSP) are valid
// whitespaces for one byte strings.
@@ -507,7 +491,7 @@
List<String> split(Pattern pattern) {
if ((pattern is _OneByteString) && (pattern.length == 1)) {
- return _splitWithCharCode(pattern.charCodeAt(0));
+ return _splitWithCharCode(pattern.codeUnitAt(0));
}
return super.split(pattern);
}
diff --git a/runtime/lib/timer_patch.dart b/runtime/lib/timer_patch.dart
index 1024915..fd3efbd 100644
--- a/runtime/lib/timer_patch.dart
+++ b/runtime/lib/timer_patch.dart
@@ -2,39 +2,22 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-typedef void _TimerCallback0();
-typedef void _TimerCallback1(Timer timer);
-
patch class Timer {
- /* patch */ factory Timer(var duration, Function callback) {
- // TODO(floitsch): remove these checks when we remove the deprecated
- // millisecond argument and the 1-argument callback. Also remove
- // the int-test below.
- if (callback is! _TimerCallback0 && callback is! _TimerCallback1) {
- throw new ArgumentError(callback);
- }
- int milliseconds = duration is int ? duration : duration.inMilliseconds;
- if (milliseconds < 0) milliseconds = 0;
- _TimerCallback1 oneArgumentCallback =
- callback is _TimerCallback1 ? callback : (_) { callback(); };
+ /* patch */ factory Timer(Duration duration, void callback()) {
if (_TimerFactory._factory == null) {
throw new UnsupportedError("Timer interface not supported.");
}
- return _TimerFactory._factory(milliseconds, oneArgumentCallback, false);
+ int milliseconds = duration.inMilliseconds;
+ if (milliseconds < 0) milliseconds = 0;
+ return _TimerFactory._factory(milliseconds, (_) { callback(); }, false);
}
- /**
- * Creates a new repeating timer. The [callback] is invoked every
- * [milliseconds] millisecond until cancelled.
- */
- /* patch */ factory Timer.repeating(var duration,
+ /* patch */ factory Timer.repeating(Duration duration,
void callback(Timer timer)) {
if (_TimerFactory._factory == null) {
throw new UnsupportedError("Timer interface not supported.");
}
- // TODO(floitsch): remove this check when we remove the deprecated
- // millisecond argument.
- int milliseconds = duration is int ? duration : duration.inMilliseconds;
+ int milliseconds = duration.inMilliseconds;
if (milliseconds < 0) milliseconds = 0;
return _TimerFactory._factory(milliseconds, callback, true);
}
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 4c5d053..f06f04c 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -124,6 +124,19 @@
#error Architecture was not detected as supported by Dart.
#endif
+// DART_FORCE_INLINE strongly hints to the compiler that a function should
+// be inlined. Your function is not guaranteed to be inlined but this is
+// stronger than just using "inline".
+// See: http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx for an
+// explanation of some the cases when a function can never be inlined.
+#ifdef _MSC_VER
+#define DART_FORCE_INLINE __forceinline
+#elif __GNUC__
+#define DART_FORCE_INLINE inline __attribute__((always_inline))
+#else
+#error Automatic compiler detection failed.
+#endif
+
#if !defined(TARGET_ARCH_MIPS)
#if !defined(TARGET_ARCH_ARM)
#if !defined(TARGET_ARCH_X64)
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index 26bc3dd..94eaa3f 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -286,26 +286,26 @@
// Test function type mirrors.
var func_cls_mirror = typedef_mirror.referent;
Expect.isTrue(func_cls_mirror is FunctionTypeMirror);
- Expect.equals('void (dart:core.String)', func_cls_mirror.simpleName);
+ Expect.equals('void (dart.core.String)', func_cls_mirror.simpleName);
Expect.equals('void', func_cls_mirror.returnType.simpleName);
}
void testLibrariesMap(Map libraries) {
// Just look for a couple of well-known libs.
- LibraryMirror core_lib = libraries['dart:core'];
+ LibraryMirror core_lib = libraries['dart.core'];
Expect.isTrue(core_lib is LibraryMirror);
- LibraryMirror mirror_lib = libraries['dart:mirrors'];
+ LibraryMirror mirror_lib = libraries['dart.mirrors'];
Expect.isTrue(mirror_lib is LibraryMirror);
// Lookup an interface from a library and make sure it is sane.
ClassMirror list_intf = core_lib.members['List'];
Expect.isTrue(list_intf is ClassMirror);
Expect.equals('List', list_intf.simpleName);
- Expect.equals('dart:core.List', list_intf.qualifiedName);
+ Expect.equals('dart.core.List', list_intf.qualifiedName);
Expect.isFalse(list_intf.isPrivate);
Expect.equals('Object', list_intf.superclass.simpleName);
- Expect.equals('dart:core', list_intf.owner.simpleName);
+ Expect.equals('dart.core', list_intf.owner.simpleName);
Expect.isTrue(list_intf.isClass);
Expect.equals('Collection', list_intf.superinterfaces[0].simpleName);
Expect.equals("ClassMirror on 'List'", list_intf.toString());
@@ -314,11 +314,11 @@
ClassMirror oom_cls = core_lib.members['OutOfMemoryError'];
Expect.isTrue(oom_cls is ClassMirror);
Expect.equals('OutOfMemoryError', oom_cls.simpleName);
- Expect.equals('dart:core.OutOfMemoryError', oom_cls.qualifiedName);
+ Expect.equals('dart.core.OutOfMemoryError', oom_cls.qualifiedName);
Expect.isFalse(oom_cls.isPrivate);
Expect.equals('Object', oom_cls.superclass.simpleName);
Expect.isTrue(oom_cls.defaultFactory == null);
- Expect.equals('dart:core', oom_cls.owner.simpleName);
+ Expect.equals('dart.core', oom_cls.owner.simpleName);
Expect.isTrue(oom_cls.isClass);
Expect.equals('Error', oom_cls.superinterfaces[0].simpleName);
Expect.equals("ClassMirror on 'OutOfMemoryError'",
diff --git a/runtime/tests/vm/dart/simd128float32_array_test.dart b/runtime/tests/vm/dart/simd128float32_array_test.dart
new file mode 100644
index 0000000..44f4591
--- /dev/null
+++ b/runtime/tests/vm/dart/simd128float32_array_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Library tag to be able to run in html test framework.
+library simd128float32_array_test;
+
+import 'dart:scalarlist';
+
+testLoadStore(array) {
+ Expect.equals(8, array.length);
+ Expect.isTrue(array is List<Float32x4>);
+ array[0] = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ Expect.equals(1.0, array[0].x);
+ Expect.equals(2.0, array[0].y);
+ Expect.equals(3.0, array[0].z);
+ Expect.equals(4.0, array[0].w);
+ array[1] = array[0];
+ array[0] = array[0].withX(9.0);
+ Expect.equals(9.0, array[0].x);
+ Expect.equals(2.0, array[0].y);
+ Expect.equals(3.0, array[0].z);
+ Expect.equals(4.0, array[0].w);
+ Expect.equals(1.0, array[1].x);
+ Expect.equals(2.0, array[1].y);
+ Expect.equals(3.0, array[1].z);
+ Expect.equals(4.0, array[1].w);
+}
+
+testView(array) {
+ Expect.equals(8, array.length);
+ Expect.isTrue(array is List<Float32x4>);
+ Expect.equals(0.0, array[0].x);
+ Expect.equals(1.0, array[0].y);
+ Expect.equals(2.0, array[0].z);
+ Expect.equals(3.0, array[0].w);
+ Expect.equals(4.0, array[1].x);
+ Expect.equals(5.0, array[1].y);
+ Expect.equals(6.0, array[1].z);
+ Expect.equals(7.0, array[1].w);
+}
+
+main() {
+ var list;
+
+ list = new Float32x4List(8);
+ for (int i = 0; i < 3000; i++) {
+ testLoadStore(list);
+ }
+
+ list = new Float32x4List.transferable(8);
+ for (int i = 0; i < 3000; i++) {
+ testLoadStore(list);
+ }
+ Float32List floatList = new Float32List(32);
+ for (int i = 0; i < floatList.length; i++) {
+ floatList[i] = i.toDouble();
+ }
+ list = new Float32x4List.view(floatList.asByteArray());
+ for (int i = 0; i < 3000; i++) {
+ testView(list);
+ }
+ for (int i = 0; i < 3000; i++) {
+ testLoadStore(list);
+ }
+}
diff --git a/runtime/tests/vm/dart/simd128float32_test.dart b/runtime/tests/vm/dart/simd128float32_test.dart
new file mode 100644
index 0000000..cac2b63
--- /dev/null
+++ b/runtime/tests/vm/dart/simd128float32_test.dart
@@ -0,0 +1,375 @@
+// 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 tag to be able to run in html test framework.
+library simd128_float32_test;
+
+import 'dart:scalarlist';
+
+testAdd() {
+ var m = new Float32x4(-1.0, -2.0, -3.0, -4.0);
+ var n = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ var o = m + n;
+ Expect.equals(0.0, o.x);
+ Expect.equals(0.0, o.y);
+ Expect.equals(0.0, o.z);
+ Expect.equals(0.0, o.w);
+}
+
+testNegate() {
+ var m = new Float32x4(1.0, 2.0, -3.0, -4.0);
+ m = -m;
+ Expect.equals(-1.0, m.x);
+ Expect.equals(-2.0, m.y);
+ Expect.equals(3.0, m.z);
+ Expect.equals(4.0, m.w);
+}
+
+testSub() {
+ var m = new Float32x4(-1.0, -2.0, -3.0, -4.0);
+ var n = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ var o = m - n;
+ Expect.equals(-2.0, o.x);
+ Expect.equals(-4.0, o.y);
+ Expect.equals(-6.0, o.z);
+ Expect.equals(-8.0, o.w);
+}
+
+testMul() {
+ var m = new Float32x4(-1.0, -2.0, -3.0, -4.0);
+ var n = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ var o = m * n;
+ Expect.equals(-1.0, o.x);
+ Expect.equals(-4.0, o.y);
+ Expect.equals(-9.0, o.z);
+ Expect.equals(-16.0, o.w);
+}
+
+testDiv() {
+ var m = new Float32x4(-1.0, -2.0, -3.0, -4.0);
+ var n = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ var o = m / n;
+ Expect.equals(-1.0, o.x);
+ Expect.equals(-1.0, o.y);
+ Expect.equals(-1.0, o.z);
+ Expect.equals(-1.0, o.w);
+}
+
+testComparison() {
+ var m = new Float32x4(1.0, 2.0, 0.1, 0.001);
+ var n = new Float32x4(2.0, 2.0, 0.001, 0.1);
+ var cmp;
+ cmp = m.lessThan(n);
+ Expect.equals(0xFFFFFFFF, cmp.x);
+ Expect.equals(0x0, cmp.y);
+ Expect.equals(0x0, cmp.z);
+ Expect.equals(0xFFFFFFFF, cmp.w);
+
+ cmp = m.lessThanOrEqual(n);
+ Expect.equals(0xFFFFFFFF, cmp.x);
+ Expect.equals(0xFFFFFFFF, cmp.y);
+ Expect.equals(0x0, cmp.z);
+ Expect.equals(0xFFFFFFFF, cmp.w);
+
+ cmp = m.equal(n);
+ Expect.equals(0x0, cmp.x);
+ Expect.equals(0xFFFFFFFF, cmp.y);
+ Expect.equals(0x0, cmp.z);
+ Expect.equals(0x0, cmp.w);
+
+ cmp = m.notEqual(n);
+ Expect.equals(0xFFFFFFFF, cmp.x);
+ Expect.equals(0x0, cmp.y);
+ Expect.equals(0xFFFFFFFF, cmp.z);
+ Expect.equals(0xFFFFFFFF, cmp.w);
+
+ cmp = m.greaterThanOrEqual(n);
+ Expect.equals(0x0, cmp.x);
+ Expect.equals(0xFFFFFFFF, cmp.y);
+ Expect.equals(0xFFFFFFFF, cmp.z);
+ Expect.equals(0x0, cmp.w);
+
+ cmp = m.greaterThan(n);
+ Expect.equals(0x0, cmp.x);
+ Expect.equals(0x0, cmp.y);
+ Expect.equals(0xFFFFFFFF, cmp.z);
+ Expect.equals(0x0, cmp.w);
+}
+
+testAbs() {
+ var m = new Float32x4(1.0, -2.0, 3.0, -4.0);
+ m = m.abs();
+ Expect.equals(1.0, m.x);
+ Expect.equals(2.0, m.y);
+ Expect.equals(3.0, m.z);
+ Expect.equals(4.0, m.w);
+}
+
+testScale() {
+ var m = new Float32x4(1.0, -2.0, 3.0, -4.0);
+ m = m.scale(20.0);
+ Expect.equals(20.0, m.x);
+ Expect.equals(-40.0, m.y);
+ Expect.equals(60.0, m.z);
+ Expect.equals(-80.0, m.w);
+}
+
+testClamp() {
+ var m = new Float32x4(1.0, -2.0, 3.0, -4.0);
+ var lo = new Float32x4(0.0, 0.0, 0.0, 0.0);
+ var hi = new Float32x4(2.0, 2.0, 2.0, 2.0);
+ m = m.clamp(lo, hi);
+ Expect.equals(1.0, m.x);
+ Expect.equals(0.0, m.y);
+ Expect.equals(2.0, m.z);
+ Expect.equals(0.0, m.w);
+}
+
+testShuffle() {
+ var m = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ var xxxx = m.xxxx;
+ Expect.equals(1.0, xxxx.x);
+ Expect.equals(1.0, xxxx.y);
+ Expect.equals(1.0, xxxx.z);
+ Expect.equals(1.0, xxxx.w);
+ var yyyy = m.yyyy;
+ Expect.equals(2.0, yyyy.x);
+ Expect.equals(2.0, yyyy.y);
+ Expect.equals(2.0, yyyy.z);
+ Expect.equals(2.0, yyyy.w);
+ var zzzz = m.zzzz;
+ Expect.equals(3.0, zzzz.x);
+ Expect.equals(3.0, zzzz.y);
+ Expect.equals(3.0, zzzz.z);
+ Expect.equals(3.0, zzzz.w);
+ var wwww = m.wwww;
+ Expect.equals(4.0, wwww.x);
+ Expect.equals(4.0, wwww.y);
+ Expect.equals(4.0, wwww.z);
+ Expect.equals(4.0, wwww.w);
+}
+
+testMin() {
+ var m = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ var n = new Float32x4(1.0, 0.0, 2.5, 5.0);
+ m = m.min(n);
+ Expect.equals(1.0, m.x);
+ Expect.equals(0.0, m.y);
+ Expect.equals(2.5, m.z);
+ Expect.equals(4.0, m.w);
+}
+
+testMax() {
+ var m = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ var n = new Float32x4(1.0, 0.0, 2.5, 5.0);
+ m = m.max(n);
+ Expect.equals(1.0, m.x);
+ Expect.equals(2.0, m.y);
+ Expect.equals(3.0, m.z);
+ Expect.equals(5.0, m.w);
+}
+
+testSqrt() {
+ var m = new Float32x4(1.0, 4.0, 9.0, 16.0);
+ m = m.sqrt();
+ Expect.equals(1.0, m.x);
+ Expect.equals(2.0, m.y);
+ Expect.equals(3.0, m.z);
+ Expect.equals(4.0, m.w);
+}
+
+testReciprocal() {
+ var m = new Float32x4(1.0, 4.0, 9.0, 16.0);
+ m = m.reciprocal();
+ Expect.approxEquals(1.0, m.x);
+ Expect.approxEquals(0.25, m.y);
+ Expect.approxEquals(0.1111111, m.z);
+ Expect.approxEquals(0.0625, m.w);
+}
+
+testReciprocalSqrt() {
+ var m = new Float32x4(1.0, 0.25, 0.111111, 0.0625);
+ m = m.reciprocalSqrt();
+ Expect.approxEquals(1.0, m.x);
+ Expect.approxEquals(2.0, m.y);
+ Expect.approxEquals(3.0, m.z);
+ Expect.approxEquals(4.0, m.w);
+}
+
+testSelect() {
+ var m = new Uint32x4.bool(true, true, false, false);
+ var t = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ var f = new Float32x4(5.0, 6.0, 7.0, 8.0);
+ var s = m.select(t, f);
+ Expect.equals(1.0, s.x);
+ Expect.equals(2.0, s.y);
+ Expect.equals(7.0, s.z);
+ Expect.equals(8.0, s.w);
+}
+
+testConversions() {
+ var m = new Uint32x4(0x3F800000, 0x40000000, 0x40400000, 0x40800000);
+ var n = m.toFloat32x4();
+ Expect.equals(1.0, n.x);
+ Expect.equals(2.0, n.y);
+ Expect.equals(3.0, n.z);
+ Expect.equals(4.0, n.w);
+ n = new Float32x4(5.0, 6.0, 7.0, 8.0);
+ m = n.toUint32x4();
+ Expect.equals(0x40A00000, m.x);
+ Expect.equals(0x40C00000, m.y);
+ Expect.equals(0x40E00000, m.z);
+ Expect.equals(0x41000000, m.w);
+ // Flip sign using bit-wise operators.
+ n = new Float32x4(9.0, 10.0, 11.0, 12.0);
+ m = new Uint32x4(0x80000000, 0x80000000, 0x80000000, 0x80000000);
+ var nMask = n.toUint32x4();
+ nMask = nMask ^ m; // flip sign.
+ n = nMask.toFloat32x4();
+ Expect.equals(-9.0, n.x);
+ Expect.equals(-10.0, n.y);
+ Expect.equals(-11.0, n.z);
+ Expect.equals(-12.0, n.w);
+ nMask = n.toUint32x4();
+ nMask = nMask ^ m; // flip sign.
+ n = nMask.toFloat32x4();
+ Expect.equals(9.0, n.x);
+ Expect.equals(10.0, n.y);
+ Expect.equals(11.0, n.z);
+ Expect.equals(12.0, n.w);
+}
+
+
+testBitOperators() {
+ var m = new Uint32x4(0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA);
+ var n = new Uint32x4(0x55555555, 0x55555555, 0x55555555, 0x55555555);
+ Expect.equals(0xAAAAAAAA, m.x);
+ Expect.equals(0xAAAAAAAA, m.y);
+ Expect.equals(0xAAAAAAAA, m.z);
+ Expect.equals(0xAAAAAAAA, m.w);
+ Expect.equals(0x55555555, n.x);
+ Expect.equals(0x55555555, n.y);
+ Expect.equals(0x55555555, n.z);
+ Expect.equals(0x55555555, n.w);
+ Expect.equals(true, n.flagX);
+ Expect.equals(true, n.flagY);
+ Expect.equals(true, n.flagZ);
+ Expect.equals(true, n.flagW);
+ var o = m|n; // or
+ Expect.equals(0xFFFFFFFF, o.x);
+ Expect.equals(0xFFFFFFFF, o.y);
+ Expect.equals(0xFFFFFFFF, o.z);
+ Expect.equals(0xFFFFFFFF, o.w);
+ Expect.equals(true, o.flagX);
+ Expect.equals(true, o.flagY);
+ Expect.equals(true, o.flagZ);
+ Expect.equals(true, o.flagW);
+ o = m&n; // and
+ Expect.equals(0x0, o.x);
+ Expect.equals(0x0, o.y);
+ Expect.equals(0x0, o.z);
+ Expect.equals(0x0, o.w);
+ n = n.withX(0xAAAAAAAA);
+ n = n.withY(0xAAAAAAAA);
+ n = n.withZ(0xAAAAAAAA);
+ n = n.withW(0xAAAAAAAA);
+ Expect.equals(0xAAAAAAAA, n.x);
+ Expect.equals(0xAAAAAAAA, n.y);
+ Expect.equals(0xAAAAAAAA, n.z);
+ Expect.equals(0xAAAAAAAA, n.w);
+ o = m^n; // xor
+ Expect.equals(0x0, o.x);
+ Expect.equals(0x0, o.y);
+ Expect.equals(0x0, o.z);
+ Expect.equals(0x0, o.w);
+ Expect.equals(false, o.flagX);
+ Expect.equals(false, o.flagY);
+ Expect.equals(false, o.flagZ);
+ Expect.equals(false, o.flagW);
+}
+
+testSetters() {
+ var f = new Float32x4.zero();
+ Expect.equals(0.0, f.x);
+ Expect.equals(0.0, f.y);
+ Expect.equals(0.0, f.z);
+ Expect.equals(0.0, f.w);
+ f = f.withX(4.0);
+ Expect.equals(4.0, f.x);
+ f = f.withY(3.0);
+ Expect.equals(3.0, f.y);
+ f = f.withZ(2.0);
+ Expect.equals(2.0, f.z);
+ f = f.withW(1.0);
+ Expect.equals(1.0, f.w);
+ f = new Float32x4.zero();
+ f = f.withX(4.0).withZ(2.0).withW(1.0).withY(3.0);
+ Expect.equals(4.0, f.x);
+ Expect.equals(3.0, f.y);
+ Expect.equals(2.0, f.z);
+ Expect.equals(1.0, f.w);
+ var m = new Uint32x4.bool(false, false, false, false);
+ Expect.equals(false, m.flagX);
+ Expect.equals(false, m.flagY);
+ Expect.equals(false, m.flagZ);
+ Expect.equals(false, m.flagW);
+ m = m.withFlagX(true);
+ Expect.equals(true, m.flagX);
+ Expect.equals(false, m.flagY);
+ Expect.equals(false, m.flagZ);
+ Expect.equals(false, m.flagW);
+ m = m.withFlagY(true);
+ Expect.equals(true, m.flagX);
+ Expect.equals(true, m.flagY);
+ Expect.equals(false, m.flagZ);
+ Expect.equals(false, m.flagW);
+ m = m.withFlagZ(true);
+ Expect.equals(true, m.flagX);
+ Expect.equals(true, m.flagY);
+ Expect.equals(true, m.flagZ);
+ Expect.equals(false, m.flagW);
+ m = m.withFlagW(true);
+ Expect.equals(true, m.flagX);
+ Expect.equals(true, m.flagY);
+ Expect.equals(true, m.flagZ);
+ Expect.equals(true, m.flagW);
+}
+
+testGetters() {
+ var f = new Float32x4(1.0, 2.0, 3.0, 4.0);
+ Expect.equals(1.0, f.x);
+ Expect.equals(2.0, f.y);
+ Expect.equals(3.0, f.z);
+ Expect.equals(4.0, f.w);
+ var m = new Uint32x4.bool(false, true, true, false);
+ Expect.equals(false, m.flagX);
+ Expect.equals(true, m.flagY);
+ Expect.equals(true, m.flagZ);
+ Expect.equals(false, m.flagW);
+}
+
+main() {
+ for (int i = 0; i < 3000; i++) {
+ testGetters();
+ testSetters();
+ testBitOperators();
+ testConversions();
+ testSelect();
+ testShuffle();
+ testAdd();
+ testSub();
+ testNegate();
+ testMul();
+ testDiv();
+ testComparison();
+ testScale();
+ testClamp();
+ testAbs();
+ testMin();
+ testMax();
+ testSqrt();
+ testReciprocal();
+ testReciprocalSqrt();
+ }
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index c4537b6..86c53f32 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -13,6 +13,10 @@
cc/SNPrint_BadArgs: Skip
+# These tests are skipped because of the workaround to open issue 8594.
+cc/Debug_StackTraceDump1: Skip
+cc/Debug_StackTraceDump2: Skip
+
[ $arch == x64 ]
cc/IsolateInterrupt: Skip
@@ -33,6 +37,8 @@
dart/isolate_mirror*: Skip # compilers not aware of dart:mirrors
dart/byte_array_test: Skip # compilers not aware of byte arrays
dart/byte_array_optimized_test: Skip # compilers not aware of byte arrays
+dart/simd128float32_array_test: Skip # compilers not aware of Simd128
+dart/simd128float32_test: Skip # compilers not aware of Simd128
dart/isolate_unhandled*: Skip
[ $compiler == dart2js ]
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 2bd4737..3331a6f 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -7,6 +7,7 @@
#include "vm/assembler.h"
+#include "vm/runtime_entry.h"
#include "vm/stub_code.h"
namespace dart {
@@ -23,6 +24,7 @@
W = 1 << 21, // writeback base register (or leave unchanged)
A = 1 << 21, // accumulate in multiply instruction (or not)
B = 1 << 22, // unsigned byte (or word)
+ D = 1 << 22, // high/lo bit of start of s/d register range
N = 1 << 22, // long (or short)
U = 1 << 23, // positive (or negative) offset/index
P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing)
@@ -64,6 +66,7 @@
uint32_t Address::encoding3() const {
+ ASSERT(kind_ == Immediate);
const uint32_t offset_mask = (1 << 12) - 1;
uint32_t offset = encoding_ & offset_mask;
ASSERT(offset < 256);
@@ -72,6 +75,7 @@
uint32_t Address::vencoding() const {
+ ASSERT(kind_ == Immediate);
const uint32_t offset_mask = (1 << 12) - 1;
uint32_t offset = encoding_ & offset_mask;
ASSERT(offset < (1 << 10)); // In the range 0 to +1020.
@@ -140,7 +144,7 @@
ASSERT(rd != kNoRegister);
ASSERT(cond != kNoCondition);
int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
- B26 |
+ B26 | (ad.kind() == Address::Immediate ? 0 : B25) |
(load ? L : 0) |
(byte ? B : 0) |
(static_cast<int32_t>(rd) << kRdShift) |
@@ -702,6 +706,83 @@
Emit(encoding);
}
+void Assembler::EmitMultiVSMemOp(Condition cond,
+ BlockAddressMode am,
+ bool load,
+ Register base,
+ SRegister start,
+ uint32_t count) {
+ ASSERT(base != kNoRegister);
+ ASSERT(cond != kNoCondition);
+ ASSERT(start != kNoSRegister);
+ ASSERT(static_cast<int32_t>(start) + count <= kNumberOfSRegisters);
+
+ int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+ B27 | B26 | B11 | B9 |
+ am |
+ (load ? L : 0) |
+ (static_cast<int32_t>(base) << kRnShift) |
+ ((static_cast<int32_t>(start) & 0x1) ? D : 0) |
+ ((static_cast<int32_t>(start) >> 1) << 12) |
+ count;
+ Emit(encoding);
+}
+
+
+void Assembler::EmitMultiVDMemOp(Condition cond,
+ BlockAddressMode am,
+ bool load,
+ Register base,
+ DRegister start,
+ int32_t count) {
+ ASSERT(base != kNoRegister);
+ ASSERT(cond != kNoCondition);
+ ASSERT(start != kNoDRegister);
+ ASSERT(static_cast<int32_t>(start) + count <= kNumberOfDRegisters);
+
+ int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+ B27 | B26 | B11 | B9 | B8 |
+ am |
+ (load ? L : 0) |
+ (static_cast<int32_t>(base) << kRnShift) |
+ ((static_cast<int32_t>(start) & 0x10) ? D : 0) |
+ ((static_cast<int32_t>(start) & 0xf) << 12) |
+ (count << 1);
+ Emit(encoding);
+}
+
+
+void Assembler::vldms(BlockAddressMode am, Register base,
+ SRegister first, SRegister last, Condition cond) {
+ ASSERT((am == IA) || (am == IA_W) || (am == DB_W));
+ ASSERT(last > first);
+ EmitMultiVSMemOp(cond, am, true, base, first, last - first + 1);
+}
+
+
+void Assembler::vstms(BlockAddressMode am, Register base,
+ SRegister first, SRegister last, Condition cond) {
+ ASSERT((am == IA) || (am == IA_W) || (am == DB_W));
+ ASSERT(last > first);
+ EmitMultiVSMemOp(cond, am, false, base, first, last - first + 1);
+}
+
+
+void Assembler::vldmd(BlockAddressMode am, Register base,
+ DRegister first, DRegister last, Condition cond) {
+ ASSERT((am == IA) || (am == IA_W) || (am == DB_W));
+ ASSERT(last > first);
+ EmitMultiVDMemOp(cond, am, true, base, first, last - first + 1);
+}
+
+
+void Assembler::vstmd(BlockAddressMode am, Register base,
+ DRegister first, DRegister last, Condition cond) {
+ ASSERT((am == IA) || (am == IA_W) || (am == DB_W));
+ ASSERT(last > first);
+ EmitMultiVDMemOp(cond, am, false, base, first, last - first + 1);
+}
+
void Assembler::EmitVFPsss(Condition cond, int32_t opcode,
SRegister sd, SRegister sn, SRegister sm) {
@@ -990,15 +1071,17 @@
}
-void Assembler::svc(uint32_t imm24) {
+void Assembler::svc(uint32_t imm24, Condition cond) {
+ ASSERT(cond != kNoCondition);
ASSERT(imm24 < (1 << 24));
- int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
+ int32_t encoding = (cond << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
Emit(encoding);
}
-void Assembler::bkpt(uint16_t imm16) {
- int32_t encoding = (AL << kConditionShift) | B24 | B21 |
+void Assembler::bkpt(uint16_t imm16, Condition cond) {
+ ASSERT(cond != kNoCondition);
+ int32_t encoding = (cond << kConditionShift) | B24 | B21 |
((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
Emit(encoding);
}
@@ -1014,6 +1097,16 @@
}
+void Assembler::bx(Register rm, Condition cond) {
+ ASSERT(rm != kNoRegister);
+ ASSERT(cond != kNoCondition);
+ int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+ B24 | B21 | (0xfff << 8) | B4 |
+ (static_cast<int32_t>(rm) << kRmShift);
+ Emit(encoding);
+}
+
+
void Assembler::blx(Register rm, Condition cond) {
ASSERT(rm != kNoRegister);
ASSERT(cond != kNoCondition);
@@ -1033,9 +1126,23 @@
}
+void Assembler::Drop(intptr_t stack_elements) {
+ ASSERT(stack_elements >= 0);
+ if (stack_elements > 0) {
+ AddImmediate(SP, SP, stack_elements * kWordSize);
+ }
+}
+
+
void Assembler::LoadObject(Register rd, const Object& object) {
- // TODO(regis): If the object is never relocated (null, true, false, ...),
- // load as immediate.
+ if (object.IsNull() ||
+ object.IsSmi() ||
+ (object.raw() == Bool::True().raw()) ||
+ (object.raw() == Bool::False().raw())) {
+ // This object is never relocated; do not use object pool.
+ LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()));
+ return;
+ }
const int32_t offset =
Array::data_offset() + 4*AddObject(object) - kHeapObjectTag;
if (Address::CanHoldLoadOffset(kLoadWord, offset)) {
@@ -1043,7 +1150,7 @@
} else {
int32_t offset12_hi = offset & ~kOffset12Mask; // signed
uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
- AddConstant(rd, PP, offset12_hi);
+ AddImmediate(rd, PP, offset12_hi);
ldr(rd, Address(rd, offset12_lo));
}
}
@@ -1163,9 +1270,9 @@
}
-void Assembler::Branch(const ExternalLabel* label) {
- LoadImmediate(IP, label->address()); // Target address is never patched.
- mov(PC, ShifterOperand(IP));
+void Assembler::Branch(const ExternalLabel* label, Condition cond) {
+ LoadImmediate(IP, label->address(), cond); // Address is never patched.
+ mov(PC, ShifterOperand(IP), cond);
}
@@ -1187,7 +1294,7 @@
} else {
int32_t offset12_hi = offset & ~kOffset12Mask; // signed
uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
- // Inline a simplified version of AddConstant(LR, CP, offset12_hi).
+ // Inline a simplified version of AddImmediate(LR, CP, offset12_hi).
ShifterOperand shifter_op;
if (ShifterOperand::CanHold(offset12_hi, &shifter_op)) {
add(LR, PP, shifter_op);
@@ -1412,12 +1519,12 @@
}
-void Assembler::AddConstant(Register rd, int32_t value, Condition cond) {
- AddConstant(rd, rd, value, cond);
+void Assembler::AddImmediate(Register rd, int32_t value, Condition cond) {
+ AddImmediate(rd, rd, value, cond);
}
-void Assembler::AddConstant(Register rd, Register rn, int32_t value,
+void Assembler::AddImmediate(Register rd, Register rn, int32_t value,
Condition cond) {
if (value == 0) {
if (rd != rn) {
@@ -1453,7 +1560,7 @@
}
-void Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
+void Assembler::AddImmediateSetFlags(Register rd, Register rn, int32_t value,
Condition cond) {
ShifterOperand shifter_op;
if (ShifterOperand::CanHold(value, &shifter_op)) {
@@ -1480,7 +1587,7 @@
}
-void Assembler::AddConstantWithCarry(Register rd, Register rn, int32_t value,
+void Assembler::AddImmediateWithCarry(Register rd, Register rn, int32_t value,
Condition cond) {
ShifterOperand shifter_op;
if (ShifterOperand::CanHold(value, &shifter_op)) {
@@ -1507,6 +1614,102 @@
}
+void Assembler::CompareImmediate(Register rn, int32_t value, Condition cond) {
+ ShifterOperand shifter_op;
+ if (ShifterOperand::CanHold(value, &shifter_op)) {
+ cmp(rn, shifter_op, cond);
+ } else {
+ ASSERT(rn != IP);
+ LoadImmediate(IP, cond);
+ cmp(rn, ShifterOperand(IP), cond);
+ }
+}
+
+
+static int NumRegsBelowFP(RegList regs) {
+ int count = 0;
+ for (int i = 0; i < FP; i++) {
+ if ((regs & (1 << i)) != 0) {
+ count++;
+ }
+ }
+ return count;
+}
+
+
+void Assembler::EnterFrame(RegList regs, intptr_t frame_size) {
+ if (prologue_offset_ == -1) {
+ prologue_offset_ = CodeSize();
+ }
+ PushList(regs);
+ if ((regs & (1 << FP)) != 0) {
+ // Set FP to the saved previous FP.
+ add(FP, SP, ShifterOperand(4 * NumRegsBelowFP(regs)));
+ }
+ AddImmediate(SP, -frame_size);
+}
+
+
+void Assembler::LeaveFrame(RegList regs) {
+ ASSERT((regs & (1 << PC)) == 0); // Must not pop PC.
+ if ((regs & (1 << FP)) != 0) {
+ // Use FP to set SP.
+ sub(SP, FP, ShifterOperand(4 * NumRegsBelowFP(regs)));
+ }
+ PopList(regs);
+}
+
+
+void Assembler::Ret() {
+ bx(LR);
+}
+
+
+void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
+ // Reserve space for arguments and align frame before entering
+ // the C++ world.
+ AddImmediate(SP, -frame_space);
+ if (OS::ActivationFrameAlignment() > 0) {
+ bic(SP, SP, ShifterOperand(OS::ActivationFrameAlignment() - 1));
+ }
+}
+
+
+void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) {
+ // Preserve volatile CPU registers.
+ EnterFrame(kDartVolatileCpuRegs | (1 << FP), 0);
+
+ // Preserve all volatile FPU registers.
+ // TODO(regis): Use vstmd instruction once supported.
+ // vstmd(DB_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg);
+
+ ReserveAlignedFrameSpace(frame_space);
+}
+
+
+void Assembler::LeaveCallRuntimeFrame() {
+ // SP might have been modified to reserve space for arguments
+ // and ensure proper alignment of the stack frame.
+ // We need to restore it before restoring registers.
+ const intptr_t kPushedRegistersSize =
+ kDartVolatileCpuRegCount * kWordSize;
+ // TODO(regis): + kDartVolatileFpuRegCount * 2 * kWordSize;
+ AddImmediate(SP, FP, -kPushedRegistersSize);
+
+ // Restore all volatile FPU registers.
+ // TODO(regis): Use vldmd instruction once supported.
+ // vldmd(IA_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg);
+
+ // Restore volatile CPU registers.
+ LeaveFrame(kDartVolatileCpuRegs | (1 << FP));
+}
+
+
+void Assembler::CallRuntime(const RuntimeEntry& entry) {
+ entry.Call(this);
+}
+
+
void Assembler::Stop(const char* message) {
if (FLAG_print_stop_message) {
PushList((1 << R0) | (1 << IP) | (1 << LR)); // Preserve R0, IP, LR.
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 76f20a1..f2203d6 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -15,6 +15,9 @@
namespace dart {
+// Forward declarations.
+class RuntimeEntry;
+
class Label : public ValueObject {
public:
Label() : position_(0) { }
@@ -159,6 +162,7 @@
uint32_t encoding_;
friend class Assembler;
+ friend class Address;
};
@@ -200,6 +204,11 @@
class Address : public ValueObject {
public:
+ enum OffsetKind {
+ Immediate,
+ ShiftedRegister,
+ };
+
// Memory operand addressing mode
enum Mode {
// bit encoding P U W
@@ -211,15 +220,19 @@
NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
};
- Address(const Address& other) : ValueObject(), encoding_(other.encoding_) { }
+ Address(const Address& other)
+ : ValueObject(), encoding_(other.encoding_), kind_(other.kind_) {
+ }
Address& operator=(const Address& other) {
encoding_ = other.encoding_;
+ kind_ = other.kind_;
return *this;
}
explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
ASSERT(Utils::IsAbsoluteUint(12, offset));
+ kind_ = Immediate;
if (offset < 0) {
encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign.
} else {
@@ -228,6 +241,14 @@
encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
}
+ explicit Address(Register rn, Register rm, Shift shift = LSL,
+ uint32_t shift_imm = 0, Mode am = Offset) {
+ ShifterOperand so(rm, shift, shift_imm);
+
+ kind_ = ShiftedRegister;
+ encoding_ = so.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift);
+ }
+
static bool CanHoldLoadOffset(LoadOperandType type, int offset);
static bool CanHoldStoreOffset(StoreOperandType type, int offset);
@@ -240,8 +261,12 @@
// Encoding for vfp load/store addressing.
uint32_t vencoding() const;
+ OffsetKind kind() const { return kind_; }
+
uint32_t encoding_;
+ OffsetKind kind_;
+
friend class Assembler;
};
@@ -391,8 +416,8 @@
void nop(Condition cond = AL);
// Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
- void bkpt(uint16_t imm16);
- void svc(uint32_t imm24);
+ void bkpt(uint16_t imm16, Condition cond = AL);
+ void svc(uint32_t imm24, Condition cond = AL);
// Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
void vmovsr(SRegister sn, Register rt, Condition cond = AL);
@@ -413,6 +438,16 @@
void vldrd(DRegister dd, Address ad, Condition cond = AL);
void vstrd(DRegister dd, Address ad, Condition cond = AL);
+ void vldms(BlockAddressMode am, Register base,
+ SRegister first, SRegister last, Condition cond = AL);
+ void vstms(BlockAddressMode am, Register base,
+ SRegister first, SRegister last, Condition cond = AL);
+
+ void vldmd(BlockAddressMode am, Register base,
+ DRegister first, DRegister last, Condition cond = AL);
+ void vstmd(BlockAddressMode am, Register base,
+ DRegister first, DRegister last, Condition cond = AL);
+
void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
@@ -453,11 +488,12 @@
// Branch instructions.
void b(Label* label, Condition cond = AL);
void bl(Label* label, Condition cond = AL);
+ void bx(Register rm, Condition cond = AL);
void blx(Register rm, Condition cond = AL);
// Macros.
// Branch to an entry address. Call sequence is never patched.
- void Branch(const ExternalLabel* label);
+ void Branch(const ExternalLabel* label, Condition cond = AL);
// Branch and link to an entry address. Call sequence is never patched.
void BranchLink(const ExternalLabel* label);
@@ -472,14 +508,17 @@
// Branch and link to [base + offset]. Call sequence is never patched.
void BranchLinkOffset(Register base, int offset);
- // Add signed constant value to rd. May clobber IP.
- void AddConstant(Register rd, int32_t value, Condition cond = AL);
- void AddConstant(Register rd, Register rn, int32_t value,
- Condition cond = AL);
- void AddConstantSetFlags(Register rd, Register rn, int32_t value,
- Condition cond = AL);
- void AddConstantWithCarry(Register rd, Register rn, int32_t value,
+ // Add signed immediate value to rd. May clobber IP.
+ void AddImmediate(Register rd, int32_t value, Condition cond = AL);
+ void AddImmediate(Register rd, Register rn, int32_t value,
+ Condition cond = AL);
+ void AddImmediateSetFlags(Register rd, Register rn, int32_t value,
Condition cond = AL);
+ void AddImmediateWithCarry(Register rd, Register rn, int32_t value,
+ Condition cond = AL);
+
+ // Compare rn with signed immediate value. May clobber IP.
+ void CompareImmediate(Register rn, int32_t value, Condition cond = AL);
// Load and Store. May clobber IP.
void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
@@ -487,6 +526,7 @@
void LoadDImmediate(DRegister dd, double value,
Register scratch, Condition cond = AL);
void MarkExceptionHandler(Label* label);
+ void Drop(intptr_t stack_elements);
void LoadObject(Register rd, const Object& object);
void LoadFromOffset(LoadOperandType type,
Register reg,
@@ -531,6 +571,28 @@
void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
void Rrx(Register rd, Register rm, Condition cond = AL);
+ void SmiTag(Register reg, Condition cond = AL) {
+ Lsl(reg, reg, kSmiTagSize, cond);
+ }
+
+ void SmiUntag(Register reg, Condition cond = AL) {
+ Asr(reg, reg, kSmiTagSize, cond);
+ }
+
+ // Function frame setup and tear down.
+ void EnterFrame(RegList regs, intptr_t frame_space);
+ void LeaveFrame(RegList regs);
+ void Ret();
+ void ReserveAlignedFrameSpace(intptr_t frame_space);
+
+ // Create a frame for calling into runtime that preserves all volatile
+ // registers. Frame's SP is guaranteed to be correctly aligned and
+ // frame_space bytes are reserved under it.
+ void EnterCallRuntimeFrame(intptr_t frame_space);
+ void LeaveCallRuntimeFrame();
+
+ void CallRuntime(const RuntimeEntry& entry);
+
// Emit data (e.g encoded instruction or immediate) in instruction stream.
void Emit(int32_t value);
@@ -605,6 +667,20 @@
Register rm,
Register rs);
+ void EmitMultiVSMemOp(Condition cond,
+ BlockAddressMode am,
+ bool load,
+ Register base,
+ SRegister start,
+ uint32_t count);
+
+ void EmitMultiVDMemOp(Condition cond,
+ BlockAddressMode am,
+ bool load,
+ Register base,
+ DRegister start,
+ int32_t count);
+
void EmitVFPsss(Condition cond,
int32_t opcode,
SRegister sd,
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index 1c6297e..bdd0837 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -130,6 +130,31 @@
}
+ASSEMBLER_TEST_GENERATE(SingleVShiftLoadStore, assembler) {
+ __ LoadImmediate(R0, bit_cast<int32_t, float>(12.3f));
+ __ mov(R2, ShifterOperand(SP));
+ // Expressing __str(R0, Address(SP, (-kWordSize * 32), Address::PreIndex));
+ // as:
+ __ mov(R1, ShifterOperand(kWordSize));
+ __ str(R0, Address(SP, R1, LSL, 5, Address::NegPreIndex));
+ __ vldrs(S0, Address(R2, (-kWordSize * 32)));
+ __ vadds(S0, S0, S0);
+ __ vstrs(S0, Address(R2, (-kWordSize * 32)));
+ // Expressing __ldr(R0, Address(SP, (kWordSize * 32), Address::PostIndex));
+ // as:
+ __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(SingleVShiftLoadStore, test) {
+ EXPECT(test != NULL);
+ typedef float (*SingleVLoadStore)();
+ float res = EXECUTE_TEST_CODE_FLOAT(SingleVLoadStore, test->entry());
+ EXPECT_FLOAT_EQ(2*12.3f, res, 0.001f);
+}
+
+
ASSEMBLER_TEST_GENERATE(DoubleVLoadStore, assembler) {
int64_t value = bit_cast<int64_t, double>(12.3);
__ LoadImmediate(R0, Utils::Low32Bits(value));
@@ -917,6 +942,425 @@
}
+ASSEMBLER_TEST_GENERATE(AddressShiftStrLSL1NegOffset, assembler) {
+ __ mov(R2, ShifterOperand(42));
+ __ mov(R1, ShifterOperand(kWordSize));
+ __ str(R2, Address(SP, R1, LSL, 1, Address::NegOffset));
+ __ ldr(R0, Address(SP, (-kWordSize * 2), Address::Offset));
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftStrLSL1NegOffset, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftLdrLSL5NegOffset, assembler) {
+ __ mov(R2, ShifterOperand(42));
+ __ mov(R1, ShifterOperand(kWordSize));
+ __ str(R2, Address(SP, (-kWordSize * 32), Address::Offset));
+ __ ldr(R0, Address(SP, R1, LSL, 5, Address::NegOffset));
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftLdrLSL5NegOffset, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftStrLRS1NegOffset, assembler) {
+ __ mov(R2, ShifterOperand(42));
+ __ mov(R1, ShifterOperand(kWordSize * 2));
+ __ str(R2, Address(SP, R1, LSR, 1, Address::NegOffset));
+ __ ldr(R0, Address(SP, -kWordSize, Address::Offset));
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftStrLRS1NegOffset, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftLdrLRS1NegOffset, assembler) {
+ __ mov(R2, ShifterOperand(42));
+ __ mov(R1, ShifterOperand(kWordSize * 2));
+ __ str(R2, Address(SP, -kWordSize, Address::Offset));
+ __ ldr(R0, Address(SP, R1, LSR, 1, Address::NegOffset));
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftLdrLRS1NegOffset, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftStrLSLNegPreIndex, assembler) {
+ __ mov(R2, ShifterOperand(42));
+ __ mov(R1, ShifterOperand(kWordSize));
+ __ mov(R3, ShifterOperand(SP));
+ __ str(R2, Address(SP, R1, LSL, 5, Address::NegPreIndex));
+ __ ldr(R0, Address(R3, (-kWordSize * 32), Address::Offset));
+ __ mov(SP, ShifterOperand(R3));
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftStrLSLNegPreIndex, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftLdrLSLNegPreIndex, assembler) {
+ __ mov(R2, ShifterOperand(42));
+ __ mov(R1, ShifterOperand(kWordSize));
+ __ str(R2, Address(SP, (-kWordSize * 32), Address::PreIndex));
+ __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftLdrLSLNegPreIndex, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can store and reload the D registers using vstmd and vldmd
+ASSEMBLER_TEST_GENERATE(VstmdVldmd, assembler) {
+ __ LoadDImmediate(D0, 0.0, R0);
+ __ LoadDImmediate(D1, 1.0, R0);
+ __ LoadDImmediate(D2, 2.0, R0);
+ __ LoadDImmediate(D3, 3.0, R0);
+ __ LoadDImmediate(D4, 4.0, R0);
+ __ vstmd(DB_W, SP, D0, D4); // Push D0 - D4 onto the stack, dec SP
+ __ LoadDImmediate(D0, 0.0, R0);
+ __ LoadDImmediate(D1, 0.0, R0);
+ __ LoadDImmediate(D2, 0.0, R0);
+ __ LoadDImmediate(D3, 0.0, R0);
+ __ LoadDImmediate(D4, 0.0, R0);
+ __ vldmd(IA_W, SP, D0, D4); // Pop stack into D0 - D4, inc SP
+
+ // Load success value into R0
+ __ mov(R0, ShifterOperand(42));
+
+ // Check that 4.0 is back in D4
+ __ LoadDImmediate(D5, 4.0, R1);
+ __ vcmpd(D4, D5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ // Check that 3.0 is back in D3
+ __ LoadDImmediate(D5, 3.0, R1);
+ __ vcmpd(D3, D5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+
+ // Check that 2.0 is back in D2
+ __ LoadDImmediate(D5, 2.0, R1);
+ __ vcmpd(D2, D5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ // Check that 1.0 is back in D1
+ __ LoadDImmediate(D5, 1.0, R1);
+ __ vcmpd(D1, D5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmdVldmd, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can store and reload the S registers using vstms and vldms
+ASSEMBLER_TEST_GENERATE(VstmsVldms, assembler) {
+ __ LoadSImmediate(S0, 0.0);
+ __ LoadSImmediate(S1, 1.0);
+ __ LoadSImmediate(S2, 2.0);
+ __ LoadSImmediate(S3, 3.0);
+ __ LoadSImmediate(S4, 4.0);
+ __ vstms(DB_W, SP, S0, S4); // Push S0 - S4 onto the stack, dec SP
+ __ LoadSImmediate(S0, 0.0);
+ __ LoadSImmediate(S1, 0.0);
+ __ LoadSImmediate(S2, 0.0);
+ __ LoadSImmediate(S3, 0.0);
+ __ LoadSImmediate(S4, 0.0);
+ __ vldms(IA_W, SP, S0, S4); // Pop stack into S0 - S4, inc SP
+
+ // Load success value into R0
+ __ mov(R0, ShifterOperand(42));
+
+ // Check that 4.0 is back in S4
+ __ LoadSImmediate(S5, 4.0);
+ __ vcmps(S4, S5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 3.0 is back in S3
+ __ LoadSImmediate(S5, 3.0);
+ __ vcmps(S3, S5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 2.0 is back in S2
+ __ LoadSImmediate(S5, 2.0);
+ __ vcmps(S2, S5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 1.0 is back in S1
+ __ LoadSImmediate(S5, 1.0);
+ __ vcmps(S1, S5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmsVldms, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can start somewhere other than D0
+ASSEMBLER_TEST_GENERATE(VstmdVldmd1, assembler) {
+ __ LoadDImmediate(D1, 1.0, R0);
+ __ LoadDImmediate(D2, 2.0, R0);
+ __ LoadDImmediate(D3, 3.0, R0);
+ __ LoadDImmediate(D4, 4.0, R0);
+ __ vstmd(DB_W, SP, D1, D4); // Push D1 - D4 onto the stack, dec SP
+ __ LoadDImmediate(D1, 0.0, R0);
+ __ LoadDImmediate(D2, 0.0, R0);
+ __ LoadDImmediate(D3, 0.0, R0);
+ __ LoadDImmediate(D4, 0.0, R0);
+ __ vldmd(IA_W, SP, D1, D4); // Pop stack into D1 - D4, inc SP
+
+ // Load success value into R0
+ __ mov(R0, ShifterOperand(42));
+
+ // Check that 4.0 is back in D4
+ __ LoadDImmediate(D5, 4.0, R1);
+ __ vcmpd(D4, D5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ // Check that 3.0 is back in D3
+ __ LoadDImmediate(D5, 3.0, R1);
+ __ vcmpd(D3, D5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+
+ // Check that 2.0 is back in D2
+ __ LoadDImmediate(D5, 2.0, R1);
+ __ vcmpd(D2, D5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ // Check that 1.0 is back in D1
+ __ LoadDImmediate(D5, 1.0, R1);
+ __ vcmpd(D1, D5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmdVldmd1, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can start somewhere other than S0
+ASSEMBLER_TEST_GENERATE(VstmsVldms1, assembler) {
+ __ LoadSImmediate(S1, 1.0);
+ __ LoadSImmediate(S2, 2.0);
+ __ LoadSImmediate(S3, 3.0);
+ __ LoadSImmediate(S4, 4.0);
+ __ vstms(DB_W, SP, S1, S4); // Push S0 - S4 onto the stack, dec SP
+ __ LoadSImmediate(S1, 0.0);
+ __ LoadSImmediate(S2, 0.0);
+ __ LoadSImmediate(S3, 0.0);
+ __ LoadSImmediate(S4, 0.0);
+ __ vldms(IA_W, SP, S1, S4); // Pop stack into S0 - S4, inc SP
+
+ // Load success value into R0
+ __ mov(R0, ShifterOperand(42));
+
+ // Check that 4.0 is back in S4
+ __ LoadSImmediate(S5, 4.0);
+ __ vcmps(S4, S5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 3.0 is back in S3
+ __ LoadSImmediate(S5, 3.0);
+ __ vcmps(S3, S5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 2.0 is back in S2
+ __ LoadSImmediate(S5, 2.0);
+ __ vcmps(S2, S5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 1.0 is back in S1
+ __ LoadSImmediate(S5, 1.0);
+ __ vcmps(S1, S5);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmsVldms1, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can store the D registers using vstmd and
+// load them into a different set using vldmd
+ASSEMBLER_TEST_GENERATE(VstmdVldmd_off, assembler) {
+ __ LoadDImmediate(D0, 0.0, R0);
+ __ LoadDImmediate(D1, 1.0, R0);
+ __ LoadDImmediate(D2, 2.0, R0);
+ __ LoadDImmediate(D3, 3.0, R0);
+ __ LoadDImmediate(D4, 4.0, R0);
+ __ LoadDImmediate(D5, 5.0, R0);
+ __ vstmd(DB_W, SP, D0, D4); // Push D0 - D4 onto the stack, dec SP
+ __ vldmd(IA_W, SP, D5, D9); // Pop stack into D5 - D9, inc SP
+
+ // Load success value into R0
+ __ mov(R0, ShifterOperand(42));
+
+ // Check that 4.0 is in D9
+ __ LoadDImmediate(D10, 4.0, R1);
+ __ vcmpd(D9, D10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ // Check that 3.0 is in D8
+ __ LoadDImmediate(D10, 3.0, R1);
+ __ vcmpd(D8, D10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+
+ // Check that 2.0 is in D7
+ __ LoadDImmediate(D10, 2.0, R1);
+ __ vcmpd(D7, D10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ // Check that 1.0 is in D6
+ __ LoadDImmediate(D10, 1.0, R1);
+ __ vcmpd(D6, D10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ // Check that 0.0 is in D5
+ __ LoadDImmediate(D10, 0.0, R1);
+ __ vcmpd(D5, D10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure into R0 if NE
+
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmdVldmd_off, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can start somewhere other than S0
+ASSEMBLER_TEST_GENERATE(VstmsVldms_off, assembler) {
+ __ LoadSImmediate(S0, 0.0);
+ __ LoadSImmediate(S1, 1.0);
+ __ LoadSImmediate(S2, 2.0);
+ __ LoadSImmediate(S3, 3.0);
+ __ LoadSImmediate(S4, 4.0);
+ __ LoadSImmediate(S5, 5.0);
+ __ vstms(DB_W, SP, S0, S4); // Push S0 - S4 onto the stack, dec SP
+ __ vldms(IA_W, SP, S5, S9); // Pop stack into S5 - S9, inc SP
+
+ // Load success value into R0
+ __ mov(R0, ShifterOperand(42));
+
+ // Check that 4.0 is in S9
+ __ LoadSImmediate(S10, 4.0);
+ __ vcmps(S9, S10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 3.0 is in S8
+ __ LoadSImmediate(S10, 3.0);
+ __ vcmps(S8, S10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 2.0 is in S7
+ __ LoadSImmediate(S10, 2.0);
+ __ vcmps(S7, S10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 1.0 is back in S6
+ __ LoadSImmediate(S10, 1.0);
+ __ vcmps(S6, S10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ // Check that 0.0 is back in S5
+ __ LoadSImmediate(S10, 0.0);
+ __ vcmps(S5, S10);
+ __ vmstat();
+ __ mov(R0, ShifterOperand(0), NE); // Put failure value into R0 if NE
+
+ __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmsVldms_off, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index bef0afb..824b592 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -1979,38 +1979,6 @@
}
-void Assembler::DoubleRound(XmmRegister dst, XmmRegister src, XmmRegister tmp) {
- ASSERT(tmp != src);
- static double kZeroFiveConst = 0.5;
- static double kNegZeroFiveConst = -0.5;
- static double kOneConst = 1.0;
- static double kNegOneConst = -1.0;
- Label is_negative, round;
- if (src != dst) {
- movsd(dst, src);
- }
- // Special handling: 0.5 -> 1.0, -0.5 -> -1.0;
- Label done, equal_point5, equal_neg_point5;
- movsd(tmp, Address::Absolute(reinterpret_cast<intptr_t>(&kZeroFiveConst)));
- comisd(tmp, dst);
- j(EQUAL, &equal_point5, Assembler::kNearJump);
- movsd(tmp, Address::Absolute(reinterpret_cast<intptr_t>(&kNegZeroFiveConst)));
- comisd(tmp, dst);
- j(EQUAL, &equal_neg_point5, Assembler::kNearJump);
-
- roundsd(dst, dst, Assembler::kRoundToNearest);
- jmp(&done, Assembler::kNearJump);
-
- Bind(&equal_point5);
- movsd(dst, Address::Absolute(reinterpret_cast<intptr_t>(&kOneConst)));
- jmp(&done);
-
- Bind(&equal_neg_point5);
- movsd(dst, Address::Absolute(reinterpret_cast<intptr_t>(&kNegOneConst)));
- Bind(&done);
-}
-
-
void Assembler::EnterFrame(intptr_t frame_size) {
if (prologue_offset_ == -1) {
prologue_offset_ = CodeSize();
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 8ab5b0c..adc9494 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -628,7 +628,6 @@
void FloatNegate(XmmRegister f);
void DoubleAbs(XmmRegister reg);
- void DoubleRound(XmmRegister dst, XmmRegister src, XmmRegister tmp);
void LockCmpxchgl(const Address& address, Register reg) {
lock();
diff --git a/runtime/vm/assembler_ia32_test.cc b/runtime/vm/assembler_ia32_test.cc
index f3da046..7933061 100644
--- a/runtime/vm/assembler_ia32_test.cc
+++ b/runtime/vm/assembler_ia32_test.cc
@@ -1675,48 +1675,6 @@
}
-ASSEMBLER_TEST_GENERATE(DoubleToDoubleRound, assembler) {
- __ movsd(XMM3, Address(ESP, kWordSize));
- __ DoubleRound(XMM2, XMM3, XMM0);
- __ pushl(EAX);
- __ pushl(EAX);
- __ movsd(Address(ESP, 0), XMM2);
- __ fldl(Address(ESP, 0));
- __ popl(EAX);
- __ popl(EAX);
- __ ret();
-}
-
-
-ASSEMBLER_TEST_RUN(DoubleToDoubleRound, test) {
- typedef double (*DoubleToDoubleRoundCode)(double d);
- double res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(12.3);
- EXPECT_EQ(12.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(12.8);
- EXPECT_EQ(13.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(0.5);
- EXPECT_EQ(1.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-12.3);
- EXPECT_EQ(-12.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-12.8);
- EXPECT_EQ(-13.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-0.5);
- EXPECT_EQ(-1.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(
- test->entry())(0.49999999999999994);
- EXPECT_EQ(0.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(
- test->entry())(-0.49999999999999994);
- EXPECT_EQ(-0.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(
- test->entry())(9007199254740991.0);
- EXPECT_EQ(9007199254740991.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(
- test->entry())(-9007199254740991.0);
- EXPECT_EQ(-9007199254740991.0, res);
-}
-
-
static const double kDoubleConst = 3.226;
ASSEMBLER_TEST_GENERATE(GlobalAddress, assembler) {
diff --git a/runtime/vm/assembler_macros_arm.cc b/runtime/vm/assembler_macros_arm.cc
index f2266c2..38cd6a5 100644
--- a/runtime/vm/assembler_macros_arm.cc
+++ b/runtime/vm/assembler_macros_arm.cc
@@ -7,8 +7,13 @@
#include "vm/assembler_macros.h"
+#include "vm/assembler.h"
+
namespace dart {
+#define __ assembler->
+
+
void AssemblerMacros::TryAllocate(Assembler* assembler,
const Class& cls,
Label* failure,
@@ -20,12 +25,49 @@
void AssemblerMacros::EnterDartFrame(Assembler* assembler,
intptr_t frame_size) {
- UNIMPLEMENTED();
+ const intptr_t offset = assembler->CodeSize();
+ // Save PC in frame for fast identification of corresponding code.
+ // Note that callee-saved registers can be added to the register list.
+ __ EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0);
+
+ if (offset != 0) {
+ // Adjust saved PC for any intrinsic code that could have been generated
+ // before a frame is created. Use PP as temp register.
+ __ ldr(PP, Address(FP, 2 * kWordSize));
+ __ AddImmediate(PP, PP, -offset);
+ __ str(PP, Address(FP, 2 * kWordSize));
+ }
+
+ // Setup pool pointer for this dart function.
+ const intptr_t object_pool_pc_dist =
+ Instructions::HeaderSize() - Instructions::object_pool_offset() +
+ assembler->CodeSize() + Instr::kPCReadOffset;
+ __ ldr(PP, Address(PC, -object_pool_pc_dist));
+
+ // Reserve space for locals.
+ __ AddImmediate(SP, -frame_size);
+}
+
+
+void AssemblerMacros::LeaveDartFrame(Assembler* assembler) {
+ __ LeaveFrame((1 << PP) | (1 << FP) | (1 << LR));
+ // Adjust SP for PC pushed in EnterDartFrame.
+ __ AddImmediate(SP, kWordSize);
}
void AssemblerMacros::EnterStubFrame(Assembler* assembler) {
- UNIMPLEMENTED();
+ // Push 0 as saved PC for stub frames.
+ __ mov(IP, ShifterOperand(LR));
+ __ mov(LR, ShifterOperand(0));
+ __ EnterFrame((1 << FP) | (1 << IP) | (1 << LR), 0);
+}
+
+
+void AssemblerMacros::LeaveStubFrame(Assembler* assembler) {
+ __ LeaveFrame((1 << FP) | (1 << LR));
+ // Adjust SP for null PC pushed in EnterStubFrame.
+ __ AddImmediate(SP, kWordSize);
}
} // namespace dart
diff --git a/runtime/vm/assembler_macros_arm.h b/runtime/vm/assembler_macros_arm.h
index 5bf1427..0a5119b 100644
--- a/runtime/vm/assembler_macros_arm.h
+++ b/runtime/vm/assembler_macros_arm.h
@@ -37,15 +37,17 @@
// enable easy access to the RawInstruction object of code corresponding
// to this frame.
static void EnterDartFrame(Assembler* assembler, intptr_t frame_size);
+ static void LeaveDartFrame(Assembler* assembler);
// Set up a stub frame so that the stack traversal code can easily identify
// a stub frame.
static void EnterStubFrame(Assembler* assembler);
+ static void LeaveStubFrame(Assembler* assembler);
// Instruction pattern from entrypoint is used in dart frame prologs
// to set up the frame and save a PC which can be used to figure out the
// RawInstruction object corresponding to the code running in the frame.
- static const intptr_t kOffsetOfSavedPCfromEntrypoint = -1; // UNIMPLEMENTED.
+ static const intptr_t kOffsetOfSavedPCfromEntrypoint = Instr::kPCReadOffset;
};
} // namespace dart.
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 8afb003..2db5f67 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -2081,42 +2081,6 @@
}
-void Assembler::DoubleRound(XmmRegister dst, XmmRegister src, XmmRegister tmp) {
- ASSERT(tmp != src);
- static double kZeroFiveConst = 0.5;
- static double kNegZeroFiveConst = -0.5;
- static double kOneConst = 1.0;
- static double kNegOneConst = -1.0;
- Label is_negative, round;
- if (src != dst) {
- movsd(dst, src);
- }
- // Special handling: 0.5 -> 1.0, -0.5 -> -1.0;
- Label done, equal_point5, equal_neg_point5;
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&kZeroFiveConst)));
- movsd(tmp, Address(TMP, 0));
- comisd(tmp, dst);
- j(EQUAL, &equal_point5, Assembler::kNearJump);
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&kNegZeroFiveConst)));
- movsd(tmp, Address(TMP, 0));
- comisd(tmp, dst);
- j(EQUAL, &equal_neg_point5, Assembler::kNearJump);
-
- roundsd(dst, dst, Assembler::kRoundToNearest);
- jmp(&done, Assembler::kNearJump);
-
- Bind(&equal_point5);
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&kOneConst)));
- movsd(dst, Address(TMP, 0));
- jmp(&done);
-
- Bind(&equal_neg_point5);
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&kNegOneConst)));
- movsd(dst, Address(TMP, 0));
- Bind(&done);
-}
-
-
void Assembler::Stop(const char* message) {
int64_t message_address = reinterpret_cast<int64_t>(message);
if (FLAG_print_stop_message) {
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 64add15..61894c0 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -642,7 +642,6 @@
void FloatNegate(XmmRegister f);
void DoubleAbs(XmmRegister reg);
- void DoubleRound(XmmRegister dst, XmmRegister src, XmmRegister tmp);
void LockCmpxchgl(const Address& address, Register reg) {
lock();
diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc
index b035b6e..ba99591 100644
--- a/runtime/vm/assembler_x64_test.cc
+++ b/runtime/vm/assembler_x64_test.cc
@@ -2226,41 +2226,6 @@
}
-ASSEMBLER_TEST_GENERATE(DoubleToDoubleRound, assembler) {
- __ DoubleRound(XMM0, XMM0, XMM1);
- __ ret();
-}
-
-
-ASSEMBLER_TEST_RUN(DoubleToDoubleRound, test) {
- typedef double (*DoubleToDoubleRoundCode)(double d);
- double res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(12.3);
- EXPECT_EQ(12.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(12.8);
- EXPECT_EQ(13.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(0.5);
- EXPECT_EQ(1.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-12.3);
- EXPECT_EQ(-12.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-12.8);
- EXPECT_EQ(-13.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-0.5);
- EXPECT_EQ(-1.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(
- test->entry())(0.49999999999999994);
- EXPECT_EQ(0.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(
- test->entry())(-0.49999999999999994);
- EXPECT_EQ(-0.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(
- test->entry())(9007199254740991.0);
- EXPECT_EQ(9007199254740991.0, res);
- res = reinterpret_cast<DoubleToDoubleRoundCode>(
- test->entry())(-9007199254740991.0);
- EXPECT_EQ(-9007199254740991.0, res);
-}
-
-
ASSEMBLER_TEST_GENERATE(ExtractSignBits, assembler) {
__ movmskpd(RAX, XMM0);
__ andq(RAX, Immediate(0x1));
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index dbe70d9..4ac570b 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -429,7 +429,7 @@
return NULL;
}
const Object& result = Object::Handle(
- DartEntry::InvokeStatic(getter_func, Object::empty_array()));
+ DartEntry::InvokeFunction(getter_func, Object::empty_array()));
if (result.IsError() || result.IsNull()) {
// TODO(turnidge): We could get better error messages by returning
// the Error object directly to the parser. This will involve
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 1b1d8d0..4ff0081 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -22,11 +22,11 @@
bool patch) {
return Script::New(String::Handle(String::New(url, Heap::kOld)),
String::Handle(String::New(source, Heap::kOld)),
- patch ? RawScript::kPatchTag : RawScript::kSourceTag);
+ patch ? RawScript::kPatchTag : RawScript::kLibraryTag);
}
-RawScript* Bootstrap::LoadASyncScript(bool patch) {
+RawScript* Bootstrap::LoadAsyncScript(bool patch) {
const char* url = patch ? "dart:async-patch" : "dart:async";
const char* source = patch ? async_patch_ : async_source_;
return LoadScript(url, source, patch);
@@ -72,7 +72,7 @@
RawScript* Bootstrap::LoadJsonScript(bool patch) {
const char* url = patch ? "dart:json-patch" : "dart:json";
- const char* source = patch ? json_source_ : json_source_;
+ const char* source = patch ? json_patch_ : json_source_;
return LoadScript(url, source, patch);
}
diff --git a/runtime/vm/bootstrap.h b/runtime/vm/bootstrap.h
index 275c27d..56fdc8c 100644
--- a/runtime/vm/bootstrap.h
+++ b/runtime/vm/bootstrap.h
@@ -17,7 +17,7 @@
class Bootstrap : public AllStatic {
public:
- static RawScript* LoadASyncScript(bool patch);
+ static RawScript* LoadAsyncScript(bool patch);
static RawScript* LoadCoreScript(bool patch);
static RawScript* LoadCollectionScript(bool patch);
static RawScript* LoadCollectionDevScript(bool patch);
@@ -45,6 +45,7 @@
static const char isolate_source_[];
static const char isolate_patch_[];
static const char json_source_[];
+ static const char json_patch_[];
static const char math_source_[];
static const char math_patch_[];
static const char mirrors_source_[];
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index 3b65e03..2f9ade3 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -56,7 +56,7 @@
Dart_NativeEntryResolver resolver =
reinterpret_cast<Dart_NativeEntryResolver>(BootstrapNatives::Lookup);
- library = Library::ASyncLibrary();
+ library = Library::AsyncLibrary();
ASSERT(!library.IsNull());
library.set_native_entry_resolver(resolver);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index dd21318..9f0db00 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -83,7 +83,7 @@
V(String_getHashCode, 1) \
V(String_getLength, 1) \
V(String_charAt, 2) \
- V(String_charCodeAt, 2) \
+ V(String_codeUnitAt, 2) \
V(String_concat, 2) \
V(String_toLowerCase, 1) \
V(String_toUpperCase, 1) \
@@ -106,8 +106,68 @@
V(TypeError_throwNew, 5) \
V(FallThroughError_throwNew, 1) \
V(AbstractClassInstantiationError_throwNew, 2) \
+ V(Stacktrace_getFullStacktrace, 1) \
+ V(Stacktrace_getStacktrace, 1) \
+ V(Stacktrace_setupFullStacktrace, 1) \
V(Stopwatch_now, 0) \
V(Stopwatch_frequency, 0) \
+ V(Float32x4_fromDoubles, 5) \
+ V(Float32x4_zero, 1) \
+ V(Float32x4_add, 2) \
+ V(Float32x4_negate, 1) \
+ V(Float32x4_sub, 2) \
+ V(Float32x4_mul, 2) \
+ V(Float32x4_div, 2) \
+ V(Float32x4_cmplt, 2) \
+ V(Float32x4_cmplte, 2) \
+ V(Float32x4_cmpgt, 2) \
+ V(Float32x4_cmpgte, 2) \
+ V(Float32x4_cmpequal, 2) \
+ V(Float32x4_cmpnequal, 2) \
+ V(Float32x4_scale, 2) \
+ V(Float32x4_abs, 1) \
+ V(Float32x4_clamp, 3) \
+ V(Float32x4_getX, 1) \
+ V(Float32x4_getY, 1) \
+ V(Float32x4_getZ, 1) \
+ V(Float32x4_getW, 1) \
+ V(Float32x4_getXXXX, 1) \
+ V(Float32x4_getYYYY, 1) \
+ V(Float32x4_getZZZZ, 1) \
+ V(Float32x4_getWWWW, 1) \
+ V(Float32x4_setX, 2) \
+ V(Float32x4_setY, 2) \
+ V(Float32x4_setZ, 2) \
+ V(Float32x4_setW, 2) \
+ V(Float32x4_min, 2) \
+ V(Float32x4_max, 2) \
+ V(Float32x4_sqrt, 1) \
+ V(Float32x4_reciprocal, 1) \
+ V(Float32x4_reciprocalSqrt, 1) \
+ V(Float32x4_toUint32x4, 1) \
+ V(Uint32x4_fromInts, 5) \
+ V(Uint32x4_fromBools, 5) \
+ V(Uint32x4_or, 2) \
+ V(Uint32x4_and, 2) \
+ V(Uint32x4_xor, 2) \
+ V(Uint32x4_getX, 1) \
+ V(Uint32x4_getY, 1) \
+ V(Uint32x4_getZ, 1) \
+ V(Uint32x4_getW, 1) \
+ V(Uint32x4_setX, 2) \
+ V(Uint32x4_setY, 2) \
+ V(Uint32x4_setZ, 2) \
+ V(Uint32x4_setW, 2) \
+ V(Uint32x4_getFlagX, 1) \
+ V(Uint32x4_getFlagY, 1) \
+ V(Uint32x4_getFlagZ, 1) \
+ V(Uint32x4_getFlagW, 1) \
+ V(Uint32x4_setFlagX, 2) \
+ V(Uint32x4_setFlagY, 2) \
+ V(Uint32x4_setFlagZ, 2) \
+ V(Uint32x4_setFlagW, 2) \
+ V(Uint32x4_select, 3) \
+ V(Uint32x4_toFloat32x4, 1) \
V(ByteArray_getLength, 1) \
V(ByteArray_getInt8, 2) \
V(ByteArray_setInt8, 3) \
@@ -125,6 +185,8 @@
V(ByteArray_setInt64, 3) \
V(ByteArray_getUint64, 2) \
V(ByteArray_setUint64, 3) \
+ V(ByteArray_getFloat32x4, 2) \
+ V(ByteArray_setFloat32x4, 3) \
V(ByteArray_getFloat32, 2) \
V(ByteArray_setFloat32, 3) \
V(ByteArray_getFloat64, 2) \
@@ -166,6 +228,10 @@
V(Uint64List_newTransferable, 1) \
V(Uint64Array_getIndexed, 2) \
V(Uint64Array_setIndexed, 3) \
+ V(Float32x4Array_new, 1) \
+ V(Float32x4List_newTransferable, 1) \
+ V(Float32x4Array_getIndexed, 2) \
+ V(Float32x4Array_setIndexed, 3) \
V(Float32Array_new, 1) \
V(Float32List_newTransferable, 1) \
V(Float32Array_getIndexed, 2) \
@@ -192,6 +258,8 @@
V(ExternalInt64Array_setIndexed, 3) \
V(ExternalUint64Array_getIndexed, 2) \
V(ExternalUint64Array_setIndexed, 3) \
+ V(ExternalFloat32x4Array_getIndexed, 2) \
+ V(ExternalFloat32x4Array_setIndexed, 3) \
V(ExternalFloat32Array_getIndexed, 2) \
V(ExternalFloat32Array_setIndexed, 3) \
V(ExternalFloat64Array_getIndexed, 2) \
diff --git a/runtime/vm/bootstrap_nocorelib.cc b/runtime/vm/bootstrap_nocorelib.cc
index d838fc2..1e6799a 100644
--- a/runtime/vm/bootstrap_nocorelib.cc
+++ b/runtime/vm/bootstrap_nocorelib.cc
@@ -15,7 +15,7 @@
DEFINE_FLAG(bool, print_bootstrap, false, "Print the bootstrap source.");
-RawScript* Bootstrap::LoadASyncScript(bool is_patch) {
+RawScript* Bootstrap::LoadAsyncScript(bool is_patch) {
UNREACHABLE();
return Script::null();
}
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index b2253ee..81c7c87 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -771,11 +771,7 @@
// Self referencing types may get finalized indirectly.
if (!parameterized_type.IsFinalized()) {
// Mark the type as finalized.
- if (parameterized_type.IsInstantiated()) {
- parameterized_type.set_is_finalized_instantiated();
- } else {
- parameterized_type.set_is_finalized_uninstantiated();
- }
+ parameterized_type.SetIsFinalized();
}
// Upper bounds of the finalized type arguments are only verified in checked
@@ -1121,6 +1117,31 @@
class_name.ToCString());
}
+ // Copy the type parameters of the mixin class to the mixin
+ // application class.
+ const int num_type_parameters = mixin_cls.NumTypeParameters();
+ if (num_type_parameters > 0) {
+ ASSERT(cls.NumTypeParameters() == 0);
+ const TypeArguments& type_params =
+ TypeArguments::Handle(mixin_cls.type_parameters());
+ const TypeArguments& cloned_type_params =
+ TypeArguments::Handle(TypeArguments::New(num_type_parameters));
+ ASSERT(!type_params.IsNull());
+ TypeParameter& param = TypeParameter::Handle();
+ TypeParameter& cloned_param = TypeParameter::Handle();
+ String& param_name = String::Handle();
+ AbstractType& param_bound = AbstractType::Handle();
+ for (int i = 0; i < num_type_parameters; i++) {
+ param ^= type_params.TypeAt(i);
+ param_name = param.name();
+ param_bound = param.bound();
+ cloned_param = TypeParameter::New(
+ cls, i, param_name, param_bound, param.token_pos());
+ cloned_type_params.SetTypeAt(i, cloned_param);
+ }
+ cls.set_type_parameters(cloned_type_params);
+ }
+
const GrowableObjectArray& cloned_funcs =
GrowableObjectArray::Handle(GrowableObjectArray::New());
Array& functions = Array::Handle();
@@ -1194,6 +1215,12 @@
if (!super_class.IsNull()) {
FinalizeClass(super_class);
}
+ if (cls.mixin() != Type::null()) {
+ // Copy instance methods and fields from the mixin class.
+ // This has to happen before the check whether the methods of
+ // the class conflict with inherited methods.
+ ApplyMixin(cls);
+ }
// Finalize type parameters before finalizing the super type.
FinalizeTypeParameters(cls);
// Finalize super type.
@@ -1227,12 +1254,6 @@
FinalizeType(cls, sig_type, kCanonicalizeWellFormed);
return;
}
- if (cls.mixin() != Type::null()) {
- // Copy instance methods and fields from the mixin class.
- // This has to happen before the check whether the methods of
- // the class conflict with inherited methods.
- ApplyMixin(cls);
- }
// Finalize interface types (but not necessarily interface classes).
Array& interface_types = Array::Handle(cls.interfaces());
AbstractType& interface_type = AbstractType::Handle();
@@ -1607,7 +1628,7 @@
}
ASSERT(type.HasResolvedTypeClass());
if (!type.IsFinalized()) {
- type.set_is_finalized_instantiated();
+ type.SetIsFinalized();
// Do not canonicalize malformed types, since they may not be resolved.
} else {
// The only case where the malformed type was already finalized is when its
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index 261b0dd..e4fc7b8 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -278,7 +278,7 @@
// is called, this should then cause the stack map of function 'A.foo'
// to be traversed and the appropriate objects visited.
const Object& result = Object::Handle(
- DartEntry::InvokeStatic(function_foo, Object::empty_array()));
+ DartEntry::InvokeFunction(function_foo, Object::empty_array()));
EXPECT(!result.IsError());
}
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 75e1a03..94ff500 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1109,20 +1109,16 @@
// A non-closure object was invoked as a closure, so call the "call" method
// on it.
-// Arg0: non-closure object.
-// Arg1: arguments descriptor.
-// Arg2: arguments array, including non-closure object.
-DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) {
+// Arg0: arguments descriptor.
+// Arg1: arguments array, including non-closure object.
+DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 2) {
ASSERT(arguments.ArgCount() ==
kInvokeNonClosureRuntimeEntry.argument_count());
- const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0));
- const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1));
- const Array& function_args = Array::CheckedHandle(arguments.ArgAt(2));
+ const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(0));
+ const Array& function_args = Array::CheckedHandle(arguments.ArgAt(1));
const Object& result = Object::Handle(
- DartEntry::InvokeClosure(instance,
- function_args,
- args_descriptor));
+ DartEntry::InvokeClosure(function_args, args_descriptor));
CheckResultError(result);
arguments.SetReturn(result);
}
@@ -1154,7 +1150,7 @@
// 2. Invoke the getter.
const Array& args = Array::Handle(Array::New(kNumArguments));
args.SetAt(0, receiver);
- const Object& value = Object::Handle(DartEntry::InvokeDynamic(getter, args));
+ const Object& value = Object::Handle(DartEntry::InvokeFunction(getter, args));
// 3. If the getter threw an exception, treat it as no such method.
if (value.IsUnhandledException()) return false;
@@ -1166,9 +1162,7 @@
Instance& instance = Instance::Handle();
instance ^= value.raw();
arguments.SetAt(0, instance);
- *result = DartEntry::InvokeClosure(instance,
- arguments,
- arguments_descriptor);
+ *result = DartEntry::InvokeClosure(arguments, arguments_descriptor);
CheckResultError(*result);
return true;
}
diff --git a/runtime/vm/code_generator_test.cc b/runtime/vm/code_generator_test.cc
index f2b4c62..cb86ed0 100644
--- a/runtime/vm/code_generator_test.cc
+++ b/runtime/vm/code_generator_test.cc
@@ -4,7 +4,9 @@
#include "platform/assert.h"
#include "vm/globals.h"
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
+#if defined(TARGET_ARCH_IA32) || \
+ defined(TARGET_ARCH_X64) || \
+ defined(TARGET_ARCH_ARM)
#include "vm/ast.h"
#include "vm/assembler.h"
@@ -23,14 +25,6 @@
static const intptr_t kPos = Scanner::kDummyTokenIndex;
-// Helper to allocate and return a LocalVariable.
-static LocalVariable* NewTestLocalVariable(const char* name) {
- const String& variable_name = String::ZoneHandle(Symbols::New(name));
- const Type& variable_type = Type::ZoneHandle(Type::DynamicType());
- return new LocalVariable(kPos, variable_name, variable_type);
-}
-
-
CODEGEN_TEST_GENERATE(SimpleReturnCodegen, test) {
test->node_sequence()->Add(new ReturnNode(kPos));
}
@@ -53,6 +47,17 @@
CODEGEN_TEST2_RUN(SimpleStaticCallCodegen, SmiReturnCodegen, Smi::New(3))
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
+
+
+// Helper to allocate and return a LocalVariable.
+static LocalVariable* NewTestLocalVariable(const char* name) {
+ const String& variable_name = String::ZoneHandle(Symbols::New(name));
+ const Type& variable_type = Type::ZoneHandle(Type::DynamicType());
+ return new LocalVariable(kPos, variable_name, variable_type);
+}
+
+
CODEGEN_TEST_GENERATE(ReturnParameterCodegen, test) {
SequenceNode* node_seq = test->node_sequence();
const int num_params = 1;
@@ -545,7 +550,7 @@
CODEGEN_TEST_RAW_RUN(AllocateNewObjectCodegen, function) {
const Object& result = Object::Handle(
- DartEntry::InvokeStatic(function, Object::empty_array()));
+ DartEntry::InvokeFunction(function, Object::empty_array()));
EXPECT(!result.IsError());
const GrowableObjectArray& libs = GrowableObjectArray::Handle(
Isolate::Current()->object_store()->libraries());
@@ -560,6 +565,8 @@
EXPECT_EQ(cls.raw(), result.clazz());
}
+#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
+
} // namespace dart
-#endif // defined TARGET_ARCH_IA32 || defined(TARGET_ARCH_X64)
+#endif // defined(TARGET_ARCH_IA32) || ..._ARCH_X64) || ..._ARCH_ARM)
diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc
index 90582f8..8f75660 100644
--- a/runtime/vm/code_patcher_arm.cc
+++ b/runtime/vm/code_patcher_arm.cc
@@ -7,6 +7,7 @@
#include "vm/code_patcher.h"
+#include "vm/instructions.h"
#include "vm/object.h"
namespace dart {
@@ -14,8 +15,8 @@
uword CodePatcher::GetStaticCallTargetAt(uword return_address,
const Code& code) {
ASSERT(code.ContainsInstructionAt(return_address));
- UNIMPLEMENTED();
- return 0;
+ CallPattern call(return_address, code);
+ return call.TargetAddress();
}
@@ -23,7 +24,8 @@
const Code& code,
uword new_target) {
ASSERT(code.ContainsInstructionAt(return_address));
- UNIMPLEMENTED();
+ CallPattern call(return_address, code);
+ call.SetTargetAddress(new_target);
}
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 149691b..4e19724 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -164,9 +164,7 @@
if (FLAG_print_flow_graph ||
(optimized && FLAG_print_flow_graph_optimized)) {
- OS::Print("Before Optimizations\n");
- FlowGraphPrinter printer(*flow_graph);
- printer.PrintBlocks();
+ FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
}
if (optimized) {
@@ -183,6 +181,7 @@
// TODO(srdjan): Moved before inlining until environment use list can
// be used to detect when shift-left is outside the scope of bit-and.
optimizer.TryOptimizeLeftShiftWithBitAndPattern();
+ DEBUG_ASSERT(flow_graph->VerifyUseLists());
// Inlining (mutates the flow graph)
if (FLAG_use_inlining) {
@@ -217,6 +216,13 @@
DEBUG_ASSERT(flow_graph->VerifyUseLists());
}
+ // Propagate types and eliminate even more type tests.
+ if (FLAG_propagate_types) {
+ FlowGraphTypePropagator propagator(flow_graph);
+ propagator.Propagate();
+ DEBUG_ASSERT(flow_graph->VerifyUseLists());
+ }
+
// Unbox doubles. Performed after constant propagation to minimize
// interference from phis merging double values and tagged
// values comming from dead paths.
@@ -236,7 +242,8 @@
if (FLAG_loop_invariant_code_motion &&
(parsed_function.function().deoptimization_counter() <
(FLAG_deoptimization_counter_threshold - 1))) {
- LICM::Optimize(flow_graph);
+ LICM licm(flow_graph);
+ licm.Optimize();
DEBUG_ASSERT(flow_graph->VerifyUseLists());
}
@@ -257,9 +264,7 @@
allocator.AllocateRegisters();
if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
- OS::Print("After Optimizations:\n");
- FlowGraphPrinter printer(*flow_graph);
- printer.PrintBlocks();
+ FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph);
}
}
@@ -513,7 +518,9 @@
DisassembleCode(function, optimized);
} else if (FLAG_disassemble_optimized && optimized) {
// TODO(fschneider): Print unoptimized code along with the optimized code.
+ OS::Print("*** BEGIN CODE\n");
DisassembleCode(function, true);
+ OS::Print("*** END CODE\n");
}
isolate->set_long_jump_base(base);
@@ -550,6 +557,9 @@
if (setjmp(*jump.Set()) == 0) {
// Non-optimized code generator.
CompileParsedFunctionHelper(parsed_function, false);
+ if (FLAG_disassemble) {
+ DisassembleCode(parsed_function.function(), false);
+ }
isolate->set_long_jump_base(base);
return Error::null();
} else {
@@ -640,7 +650,7 @@
CompileParsedFunctionHelper(*parsed_function, false);
const Object& result = Object::Handle(
- DartEntry::InvokeStatic(func, Object::empty_array()));
+ DartEntry::InvokeFunction(func, Object::empty_array()));
isolate->set_long_jump_base(base);
return result.raw();
} else {
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 1ba6550..0a0c928 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -16,6 +16,7 @@
enum Register {
+ kFirstFreeCpuRegister = 0,
R0 = 0,
R1 = 1,
R2 = 2,
@@ -25,6 +26,7 @@
R6 = 6,
R7 = 7,
R8 = 8,
+ kLastFreeCpuRegister = 8,
R9 = 9,
R10 = 10,
R11 = 11,
@@ -132,11 +134,11 @@
// Register aliases.
-const Register TMP = kNoRegister; // No scratch register used by assembler.
+const Register TMP = IP; // Used as scratch register by assembler.
const Register CTX = R9; // Caches current context in generated code.
const Register PP = R10; // Caches object pool pointer in generated code.
-const Register SPREG = SP;
-const Register FPREG = FP;
+const Register SPREG = SP; // Stack pointer register.
+const Register FPREG = FP; // Frame pointer register.
// Exception object is passed in this register to the catch handlers when an
@@ -146,13 +148,32 @@
// List of registers used in load/store multiple.
typedef uint16_t RegList;
-const RegList kAllCoreRegistersList = 0xFFFF;
+const RegList kAllCpuRegistersList = 0xFFFF;
-// C++ ABI call registers
-const int kAbiRegisterCount = 4;
-const Register kAbiRegisters[kAbiRegisterCount] = { R0, R1, R2, R3 };
-const RegList kAbiRegisterList = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3);
+// C++ ABI call registers.
+const RegList kAbiArgumentCpuRegs =
+ (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3);
+const RegList kAbiPreservedCpuRegs =
+ (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) |
+ (1 << R8) | (1 << R9) | (1 << R10);
+const int kAbiPreservedCpuRegCount = 7;
+const DRegister kAbiFirstPreservedFpuReg = D8;
+const DRegister kAbiLastPreservedFpuReg =
+ static_cast<DRegister>(kNumberOfDRegisters - 1);
+
+// CPU registers available to Dart allocator.
+const RegList kDartAvailableCpuRegs =
+ (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) |
+ (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8);
+
+// Registers available to Dart that are not preserved by runtime calls.
+const RegList kDartVolatileCpuRegs =
+ kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
+const int kDartVolatileCpuRegCount = 4;
+const DRegister kDartFirstVolatileFpuReg = D0;
+const DRegister kDartLastVolatileFpuReg = D7;
+const int kDartVolatileFpuRegCount = 8;
// Values for the condition field as defined in section A3.2.
@@ -431,12 +452,12 @@
// Test for Supervisor Call instruction.
inline bool IsSvc() const {
- return ((InstructionBits() & 0xff000000) == 0xef000000);
+ return ((InstructionBits() & 0x0f000000) == 0x0f000000);
}
// Test for Breakpoint instruction.
inline bool IsBkpt() const {
- return ((InstructionBits() & 0xfff000f0) == 0xe1200070);
+ return ((InstructionBits() & 0x0ff000f0) == 0x01200070);
}
// VFP register fields.
@@ -483,6 +504,14 @@
return ((Bits(20, 5) & 0x12) == 0x10) && (Bits(9, 3) == 5);
}
+ // Test for VFP multiple load and store instructions of type 6.
+ inline bool IsVFPMultipleLoadStore() const {
+ ASSERT(ConditionField() != kSpecialCondition);
+ ASSERT(TypeField() == 6);
+ int32_t puw = (PUField() << 1) | Bit(21); // don't care about D bit
+ return (Bits(9, 3) == 5) && ((puw == 2) || (puw == 3) || (puw == 5));
+ }
+
// Special accessors that test for existence of a value.
inline bool HasS() const { return SField() == 1; }
inline bool HasB() const { return BField() == 1; }
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 467cdac..ad3f3c6 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -10,6 +10,7 @@
namespace dart {
enum Register {
+ kFirstFreeCpuRegister = 0,
EAX = 0,
ECX = 1,
EDX = 2,
@@ -18,8 +19,8 @@
EBP = 5,
ESI = 6,
EDI = 7,
+ kLastFreeCpuRegister = 7,
kNumberOfCpuRegisters = 8,
- kFirstByteUnsafeRegister = 4,
kNoRegister = -1 // Signals an illegal register.
};
@@ -59,9 +60,10 @@
// Register aliases.
const Register TMP = kNoRegister; // No scratch register used by assembler.
-const Register CTX = ESI; // Caches current context in generated code.
-const Register SPREG = ESP;
-const Register FPREG = EBP;
+const Register CTX = ESI; // Caches current context in generated code.
+const Register PP = kNoRegister; // No object pool pointer.
+const Register SPREG = ESP; // Stack pointer register.
+const Register FPREG = EBP; // Frame pointer register.
// Exception object is passed in this register to the catch handlers when an
// exception is thrown.
diff --git a/runtime/vm/constants_mips.h b/runtime/vm/constants_mips.h
index 6ff56ba..ea670bc 100644
--- a/runtime/vm/constants_mips.h
+++ b/runtime/vm/constants_mips.h
@@ -10,6 +10,7 @@
enum Register {
ZR = 0,
AT = 1,
+ kFirstFreeCpuRegister = 2,
V0 = 2,
V1 = 3,
A0 = 4,
@@ -34,6 +35,7 @@
S7 = 23,
T8 = 24,
T9 = 25,
+ kLastFreeCpuRegister = 25,
K0 = 26,
K1 = 27,
GP = 28,
@@ -91,10 +93,11 @@
// Register aliases.
-const Register TMP = AT;
-const Register CTX = S7; // Caches current context in generated code.
-const Register SPREG = SP;
-const Register FPREG = FP;
+const Register TMP = AT; // Used as scratch register by assembler.
+const Register CTX = S6; // Caches current context in generated code.
+const Register PP = S7; // Caches object pool pointer in generated code.
+const Register SPREG = SP; // Stack pointer register.
+const Register FPREG = FP; // Frame pointer register.
// Values for the condition field. // UNIMPLEMENTED.
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 31b00b1..38a8793 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -8,6 +8,7 @@
namespace dart {
enum Register {
+ kFirstFreeCpuRegister = 0,
RAX = 0,
RCX = 1,
RDX = 2,
@@ -24,6 +25,7 @@
R13 = 13,
R14 = 14,
R15 = 15,
+ kLastFreeCpuRegister = 15,
kNumberOfCpuRegisters = 16,
kNoRegister = -1 // Signals an illegal register.
};
@@ -83,8 +85,9 @@
// Register aliases.
const Register TMP = R11; // Used as scratch register by the assembler.
const Register CTX = R15; // Caches current context in generated code.
-const Register SPREG = RSP;
-const Register FPREG = RBP;
+const Register PP = kNoRegister; // No object pool pointer.
+const Register SPREG = RSP; // Stack pointer register.
+const Register FPREG = RBP; // Frame pointer register.
// Exception object is passed in this register to the catch handlers when an
// exception is thrown.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index f4a9fa8..d8ba637 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1131,7 +1131,7 @@
ASSERT(!function.IsNull());
const Array& args = Array::Handle(isolate, Array::New(kNumArguments));
args.SetAt(0, Integer::Handle(isolate, Integer::New(port_id)));
- return Api::NewHandle(isolate, DartEntry::InvokeStatic(function, args));
+ return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
}
@@ -1924,7 +1924,7 @@
const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
args.SetAt(0, instance); // Set up the receiver as the first argument.
const Object& retval =
- Object::Handle(isolate, DartEntry::InvokeDynamic(function, args));
+ Object::Handle(isolate, DartEntry::InvokeFunction(function, args));
if (retval.IsSmi()) {
*len = Smi::Cast(retval).Value();
return Api::Success(isolate);
@@ -1989,8 +1989,8 @@
const Integer& indexobj = Integer::Handle(isolate, Integer::New(index));
args.SetAt(0, instance);
args.SetAt(1, indexobj);
- return Api::NewHandle(isolate, DartEntry::InvokeDynamic(function,
- args));
+ return Api::NewHandle(isolate, DartEntry::InvokeFunction(function,
+ args));
}
}
return Api::NewError("Object does not implement the 'List' interface");
@@ -2051,8 +2051,8 @@
args.SetAt(0, instance);
args.SetAt(1, index_obj);
args.SetAt(2, value_obj);
- return Api::NewHandle(isolate, DartEntry::InvokeDynamic(function,
- args));
+ return Api::NewHandle(isolate, DartEntry::InvokeFunction(function,
+ args));
}
}
return Api::NewError("Object does not implement the 'List' interface");
@@ -2110,7 +2110,7 @@
args.SetAt(1,
Smi::Handle(isolate, Smi::New(Function::kCtorPhaseAll)));
args.SetAt(2, String::Handle(String::New(exception_message)));
- result = DartEntry::InvokeStatic(constructor, args);
+ result = DartEntry::InvokeFunction(constructor, args);
if (result.IsError()) return result.raw();
ASSERT(result.IsNull());
@@ -2211,7 +2211,7 @@
for (int i = 0; i < length; i++) {
intobj = Integer::New(offset + i);
args.SetAt(1, intobj);
- result = DartEntry::InvokeDynamic(function, args);
+ result = DartEntry::InvokeFunction(function, args);
if (result.IsError()) {
return Api::NewHandle(isolate, result.raw());
}
@@ -2306,7 +2306,7 @@
args.SetAt(1, indexobj);
args.SetAt(2, valueobj);
const Object& result = Object::Handle(
- isolate, DartEntry::InvokeDynamic(function, args));
+ isolate, DartEntry::InvokeFunction(function, args));
if (result.IsError()) {
return Api::NewHandle(isolate, result.raw());
}
@@ -2664,7 +2664,7 @@
args.SetAt(i + 1, obj);
}
// Now try to invoke the closure.
- return Api::NewHandle(isolate, DartEntry::InvokeClosure(closure_obj, args));
+ return Api::NewHandle(isolate, DartEntry::InvokeClosure(args));
}
@@ -3570,7 +3570,7 @@
}
// Invoke the constructor and return the new object.
- result = DartEntry::InvokeStatic(constructor, args);
+ result = DartEntry::InvokeFunction(constructor, args);
if (result.IsError()) {
return Api::NewHandle(isolate, result.raw());
}
@@ -3644,7 +3644,7 @@
function_name.ToCString());
}
args.SetAt(0, instance);
- return Api::NewHandle(isolate, DartEntry::InvokeDynamic(function, args));
+ return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
} else if (obj.IsClass()) {
// Finalize all classes.
@@ -3668,7 +3668,7 @@
cls_name.ToCString(),
function_name.ToCString());
}
- return Api::NewHandle(isolate, DartEntry::InvokeStatic(function, args));
+ return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
} else if (obj.IsLibrary()) {
// Check whether class finalization is needed.
@@ -3709,7 +3709,7 @@
function_name.ToCString(),
error_message.ToCString());
}
- return Api::NewHandle(isolate, DartEntry::InvokeStatic(function, args));
+ return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
} else {
return Api::NewError(
@@ -3773,7 +3773,7 @@
const int kNumArgs = 1;
const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
args.SetAt(0, instance);
- return Api::NewHandle(isolate, DartEntry::InvokeDynamic(getter, args));
+ return Api::NewHandle(isolate, DartEntry::InvokeFunction(getter, args));
} else if (obj.IsClass()) {
// Finalize all classes.
@@ -3794,7 +3794,7 @@
if (!getter.IsNull()) {
// Invoke the getter and return the result.
return Api::NewHandle(
- isolate, DartEntry::InvokeStatic(getter, Object::empty_array()));
+ isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
} else if (!field.IsNull()) {
return Api::NewHandle(isolate, field.value());
} else {
@@ -3826,7 +3826,7 @@
if (!getter.IsNull()) {
// Invoke the getter and return the result.
return Api::NewHandle(
- isolate, DartEntry::InvokeStatic(getter, Object::empty_array()));
+ isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
} else if (!field.IsNull()) {
return Api::NewHandle(isolate, field.value());
} else {
@@ -3901,7 +3901,7 @@
const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
args.SetAt(0, instance);
args.SetAt(1, value_instance);
- return Api::NewHandle(isolate, DartEntry::InvokeDynamic(setter, args));
+ return Api::NewHandle(isolate, DartEntry::InvokeFunction(setter, args));
} else if (obj.IsClass()) {
// To access a static field we may need to use the Field or the
@@ -3920,7 +3920,7 @@
const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
args.SetAt(0, value_instance);
const Object& result =
- Object::Handle(isolate, DartEntry::InvokeStatic(setter, args));
+ Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
if (result.IsError()) {
return Api::NewHandle(isolate, result.raw());
} else {
@@ -3957,7 +3957,7 @@
const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
args.SetAt(0, value_instance);
const Object& result =
- Object::Handle(isolate, DartEntry::InvokeStatic(setter, args));
+ Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
if (result.IsError()) {
return Api::NewHandle(isolate, result.raw());
} else {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index ea91a9e..77860db 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -7410,7 +7410,7 @@
" var result = 0;\n"
" for (var i = 0; i < s.length; i++) {\n"
" if (b && i == 0) A.change_str(str);\n"
- " result += s.charCodeAt(i);"
+ " result += s.codeUnitAt(i);"
" }\n"
" return result;\n"
"}\n"
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 66ae155..c6b5dc3 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -8,6 +8,7 @@
#include "vm/compiler.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
+#include "vm/simulator.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
@@ -17,17 +18,28 @@
RawArray* ArgumentsDescriptor::cached_args_descriptors_[kCachedDescriptorCount];
-RawObject* DartEntry::InvokeDynamic(const Function& function,
- const Array& arguments) {
- const Array& arg_desc =
+RawObject* DartEntry::InvokeFunction(const Function& function,
+ const Array& arguments) {
+ const Array& arguments_descriptor =
Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
- return InvokeDynamic(function, arguments, arg_desc);
+ return InvokeFunction(function, arguments, arguments_descriptor);
}
-RawObject* DartEntry::InvokeDynamic(const Function& function,
- const Array& arguments,
- const Array& arguments_descriptor) {
+RawObject* DartEntry::InvokeFunction(const Function& function,
+ const Array& arguments,
+ const Array& arguments_descriptor) {
+ const Context& context =
+ Context::ZoneHandle(Isolate::Current()->object_store()->empty_context());
+ ASSERT(context.isolate() == Isolate::Current());
+ return InvokeFunction(function, arguments, arguments_descriptor, context);
+}
+
+
+RawObject* DartEntry::InvokeFunction(const Function& function,
+ const Array& arguments,
+ const Array& arguments_descriptor,
+ const Context& context) {
// Get the entrypoint corresponding to the function specified, this
// will result in a compilation of the function if it is not already
// compiled.
@@ -37,72 +49,40 @@
return error.raw();
}
}
-
// Now Call the invoke stub which will invoke the dart function.
invokestub entrypoint = reinterpret_cast<invokestub>(
StubCode::InvokeDartCodeEntryPoint());
- const Context& context =
- Context::ZoneHandle(Isolate::Current()->object_store()->empty_context());
- ASSERT(context.isolate() == Isolate::Current());
const Code& code = Code::Handle(function.CurrentCode());
ASSERT(!code.IsNull());
ASSERT(Isolate::Current()->no_callback_scope_depth() == 0);
- return entrypoint(code.EntryPoint(),
- arguments_descriptor,
- arguments,
- context);
+#ifdef USING_SIMULATOR
+ return bit_copy<RawObject*, int64_t>(Simulator::Current()->Call(
+ reinterpret_cast<int32_t>(entrypoint),
+ static_cast<int32_t>(code.EntryPoint()),
+ reinterpret_cast<int32_t>(&arguments_descriptor),
+ reinterpret_cast<int32_t>(&arguments),
+ reinterpret_cast<int32_t>(&context),
+ 0));
+#else
+ return entrypoint(code.EntryPoint(),
+ arguments_descriptor,
+ arguments,
+ context);
+#endif
}
-RawObject* DartEntry::InvokeStatic(const Function& function,
- const Array& arguments) {
+RawObject* DartEntry::InvokeClosure(const Array& arguments) {
const Array& arguments_descriptor =
Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
- return InvokeStatic(function, arguments, arguments_descriptor);
+ return InvokeClosure(arguments, arguments_descriptor);
}
-RawObject* DartEntry::InvokeStatic(const Function& function,
- const Array& arguments,
- const Array& arguments_descriptor) {
- // Get the entrypoint corresponding to the function specified, this
- // will result in a compilation of the function if it is not already
- // compiled.
- ASSERT(!function.IsNull());
- if (!function.HasCode()) {
- const Error& error = Error::Handle(Compiler::CompileFunction(function));
- if (!error.IsNull()) {
- return error.raw();
- }
- }
- // Now Call the invoke stub which will invoke the dart function.
- invokestub entrypoint = reinterpret_cast<invokestub>(
- StubCode::InvokeDartCodeEntryPoint());
- const Context& context =
- Context::ZoneHandle(Isolate::Current()->object_store()->empty_context());
- ASSERT(context.isolate() == Isolate::Current());
- const Code& code = Code::Handle(function.CurrentCode());
- ASSERT(!code.IsNull());
- ASSERT(Isolate::Current()->no_callback_scope_depth() == 0);
- return entrypoint(code.EntryPoint(),
- arguments_descriptor,
- arguments,
- context);
-}
-
-
-RawObject* DartEntry::InvokeClosure(const Instance& closure,
- const Array& arguments) {
- const Array& arguments_descriptor =
- Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
- return InvokeClosure(closure, arguments, arguments_descriptor);
-}
-
-
-RawObject* DartEntry::InvokeClosure(const Instance& instance,
- const Array& arguments,
+RawObject* DartEntry::InvokeClosure(const Array& arguments,
const Array& arguments_descriptor) {
- ASSERT(instance.raw() == arguments.At(0));
+ Instance& instance = Instance::Handle();
+ instance ^= arguments.At(0);
// Get the entrypoint corresponding to the closure function or to the call
// method of the instance. This will result in a compilation of the function
// if it is not already compiled.
@@ -114,26 +94,9 @@
if (function.AreValidArgumentCounts(args_desc.Count(),
args_desc.NamedCount(),
NULL)) {
- if (!function.HasCode()) {
- const Error& error = Error::Handle(Compiler::CompileFunction(function));
- if (!error.IsNull()) {
- return error.raw();
- }
- }
- // Now call the invoke stub which will invoke the closure function or
- // 'call' function.
// The closure or non-closure object (receiver) is passed as implicit
// first argument. It is already included in the arguments array.
- invokestub entrypoint = reinterpret_cast<invokestub>(
- StubCode::InvokeDartCodeEntryPoint());
- ASSERT(context.isolate() == Isolate::Current());
- const Code& code = Code::Handle(function.CurrentCode());
- ASSERT(!code.IsNull());
- ASSERT(Isolate::Current()->no_callback_scope_depth() == 0);
- return entrypoint(code.EntryPoint(),
- arguments_descriptor,
- arguments,
- context);
+ return InvokeFunction(function, arguments, arguments_descriptor, context);
}
}
// There is no compatible 'call' method, so invoke noSuchMethod.
@@ -169,7 +132,7 @@
allocation_args.SetAt(1, arguments_descriptor);
allocation_args.SetAt(2, arguments);
const Object& invocation_mirror = Object::Handle(
- InvokeStatic(allocation_function, allocation_args));
+ InvokeFunction(allocation_function, allocation_args));
// Now use the invocation mirror object and invoke NoSuchMethod.
const int kNumArguments = 2;
@@ -183,7 +146,7 @@
const Array& args = Array::Handle(Array::New(kNumArguments));
args.SetAt(0, receiver);
args.SetAt(1, invocation_mirror);
- return InvokeDynamic(function, args);
+ return InvokeFunction(function, args);
}
@@ -350,7 +313,8 @@
Function::Handle(cls.LookupConstructorAllowPrivate(function_name));
ASSERT(!constructor.IsNull());
const Object& retval =
- Object::Handle(DartEntry::InvokeStatic(constructor, constructor_arguments));
+ Object::Handle(DartEntry::InvokeFunction(constructor,
+ constructor_arguments));
ASSERT(retval.IsNull() || retval.IsError());
if (retval.IsError()) {
return retval.raw();
@@ -370,8 +334,8 @@
ASSERT(!function.IsNull());
const Array& args = Array::Handle(Array::New(kNumArguments));
args.SetAt(0, receiver);
- const Object& result = Object::Handle(DartEntry::InvokeDynamic(function,
- args));
+ const Object& result = Object::Handle(DartEntry::InvokeFunction(function,
+ args));
ASSERT(result.IsInstance() || result.IsError());
return result.raw();
}
@@ -391,8 +355,8 @@
const Array& args = Array::Handle(Array::New(kNumArguments));
args.SetAt(0, left);
args.SetAt(1, right);
- const Object& result = Object::Handle(DartEntry::InvokeDynamic(function,
- args));
+ const Object& result = Object::Handle(DartEntry::InvokeFunction(function,
+ args));
ASSERT(result.IsInstance() || result.IsError());
return result.raw();
}
@@ -422,7 +386,7 @@
const Array& args = Array::Handle(Array::New(kNumArguments));
args.SetAt(0, Integer::Handle(Integer::New(port_id)));
const Object& result =
- Object::Handle(DartEntry::InvokeStatic(function, args));
+ Object::Handle(DartEntry::InvokeFunction(function, args));
return result.raw();
}
@@ -455,7 +419,7 @@
args.SetAt(1, Integer::Handle(isolate, Integer::New(reply_port_id)));
args.SetAt(2, message);
const Object& result =
- Object::Handle(isolate, DartEntry::InvokeStatic(function, args));
+ Object::Handle(isolate, DartEntry::InvokeFunction(function, args));
ASSERT(result.IsNull() || result.IsError());
return result.raw();
}
@@ -478,7 +442,7 @@
Resolver::kIsQualified));
const Array& args = Array::Handle(Array::New(kNumArguments));
args.SetAt(0, Integer::Handle(Integer::New(port_id)));
- return DartEntry::InvokeStatic(function, args);
+ return DartEntry::InvokeFunction(function, args);
}
@@ -496,8 +460,8 @@
args.SetAt(0, map);
args.SetAt(1, key);
args.SetAt(2, value);
- const Object& result = Object::Handle(DartEntry::InvokeDynamic(function,
- args));
+ const Object& result = Object::Handle(DartEntry::InvokeFunction(function,
+ args));
return result.raw();
}
@@ -512,7 +476,7 @@
ASSERT(!func.IsNull());
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0, port);
- return DartEntry::InvokeDynamic(func, args);
+ return DartEntry::InvokeFunction(func, args);
}
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index e4c6d5c..aeab904 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -105,43 +105,37 @@
const Array& arguments,
const Context& context);
- // Invokes the specified instance function on the receiver.
+ // Invokes the specified instance function or static function.
+ // The first argument of an instance function is the receiver.
// On success, returns a RawInstance. On failure, a RawError.
// This is used when there are no named arguments in the call.
- static RawObject* InvokeDynamic(const Function& function,
- const Array& arguments);
+ static RawObject* InvokeFunction(const Function& function,
+ const Array& arguments);
- // Invokes the specified instance function on the receiver.
+ // Invokes the specified instance or static function.
// On success, returns a RawInstance. On failure, a RawError.
- static RawObject* InvokeDynamic(const Function& function,
- const Array& arguments,
+ static RawObject* InvokeFunction(const Function& function,
+ const Array& arguments,
+ const Array& arguments_descriptor);
+
+ // Invokes the specified instance, static, or closure function.
+ // On success, returns a RawInstance. On failure, a RawError.
+ static RawObject* InvokeFunction(const Function& function,
+ const Array& arguments,
+ const Array& arguments_descriptor,
+ const Context& context);
+
+ // Invokes the closure object given as the first argument.
+ // On success, returns a RawInstance. On failure, a RawError.
+ // This is used when there are no named arguments in the call.
+ static RawObject* InvokeClosure(const Array& arguments);
+
+ // Invokes the closure object given as the first argument.
+ // On success, returns a RawInstance. On failure, a RawError.
+ static RawObject* InvokeClosure(const Array& arguments,
const Array& arguments_descriptor);
- // Invoke the specified static function.
- // On success, returns a RawInstance. On failure, a RawError.
- // This is used when there are no named arguments in the call.
- static RawObject* InvokeStatic(const Function& function,
- const Array& arguments);
-
- // Invoke the specified static function.
- // On success, returns a RawInstance. On failure, a RawError.
- static RawObject* InvokeStatic(const Function& function,
- const Array& arguments,
- const Array& arguments_descriptor);
-
- // Invoke the specified closure object.
- // On success, returns a RawInstance. On failure, a RawError.
- // This is used when there are no named arguments in the call.
- static RawObject* InvokeClosure(const Instance& closure,
- const Array& arguments);
-
- // Invoke the specified closure object.
- // On success, returns a RawInstance. On failure, a RawError.
- static RawObject* InvokeClosure(const Instance& closure,
- const Array& arguments,
- const Array& arguments_descriptor);
-
- // Invoke the noSuchMethod instance function on the receiver.
+ // Invokes the noSuchMethod instance function on the receiver.
// On success, returns a RawInstance. On failure, a RawError.
static RawObject* InvokeNoSuchMethod(const Instance& receiver,
const String& target_name,
diff --git a/runtime/vm/dart_entry_test.cc b/runtime/vm/dart_entry_test.cc
index 65a629f..f067736 100644
--- a/runtime/vm/dart_entry_test.cc
+++ b/runtime/vm/dart_entry_test.cc
@@ -40,7 +40,7 @@
EXPECT(CompilerTest::TestCompileFunction(function));
EXPECT(function.HasCode());
const Smi& retval = Smi::Handle(reinterpret_cast<RawSmi*>(
- DartEntry::InvokeStatic(function, Object::empty_array())));
+ DartEntry::InvokeFunction(function, Object::empty_array())));
EXPECT_EQ(Smi::New(42), retval.raw());
}
@@ -66,7 +66,7 @@
EXPECT(!function.IsNull());
GrowableArray<const Object*> arguments;
const Object& retval = Object::Handle(
- DartEntry::InvokeStatic(function, Object::empty_array()));
+ DartEntry::InvokeFunction(function, Object::empty_array()));
EXPECT(retval.IsError());
EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
}
@@ -99,7 +99,7 @@
Function& constructor =
Function::Handle(cls.LookupConstructor(constructor_name));
ASSERT(!constructor.IsNull());
- DartEntry::InvokeStatic(constructor, constructor_arguments);
+ DartEntry::InvokeFunction(constructor, constructor_arguments);
// Call foo.
String& name = String::Handle(String::New("foo"));
@@ -107,8 +107,8 @@
EXPECT(!function.IsNull());
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0, instance);
- const Object& retval = Object::Handle(DartEntry::InvokeDynamic(function,
- args));
+ const Object& retval = Object::Handle(DartEntry::InvokeFunction(function,
+ args));
EXPECT(retval.IsError());
EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
}
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index d75d5c0..dd814b7 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -218,7 +218,7 @@
WriteByte(static_cast<uint8_t>(v + kEndByteMarker));
}
- void WriteByte(uint8_t value) {
+ DART_FORCE_INLINE void WriteByte(uint8_t value) {
if (current_ >= end_) {
Resize(1);
}
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 61a9f69..388db67 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -493,6 +493,9 @@
if (var_info.kind == RawLocalVarDescriptors::kStackVar) {
*value = GetLocalVarValue(var_info.index);
} else {
+ // TODO(tball): enable context variables once problem with VariableAt() is
+ // fixed, where frame_ctx_level is sometimes off by 1 (issues 8593 and 8594)
+ /*
ASSERT(var_info.kind == RawLocalVarDescriptors::kContextVar);
ASSERT(!ctx_.IsNull());
// The context level at the PC/token index of this activation frame.
@@ -513,7 +516,8 @@
}
ASSERT(!ctx.IsNull());
*value = ctx.At(ctx_slot);
- }
+ } */
+ *value = Symbols::New("<unknown>");
}
}
@@ -881,7 +885,7 @@
frame->fp(),
frame->sp(),
code);
- if (get_saved_context) {
+ if (get_saved_context && !activation->code().is_optimized()) {
ctx = activation->GetSavedContext();
}
activation->SetContext(ctx);
@@ -1223,7 +1227,7 @@
if (setjmp(*jump.Set()) == 0) {
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0, object);
- result = DartEntry::InvokeDynamic(getter_func, args);
+ result = DartEntry::InvokeFunction(getter_func, args);
} else {
result = isolate_->object_store()->sticky_error();
}
@@ -1260,7 +1264,7 @@
bool saved_ignore_flag = ignore_breakpoints_;
ignore_breakpoints_ = true;
if (setjmp(*jump.Set()) == 0) {
- result = DartEntry::InvokeStatic(getter_func, Object::empty_array());
+ result = DartEntry::InvokeFunction(getter_func, Object::empty_array());
} else {
result = isolate_->object_store()->sticky_error();
}
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 4a10822..b096c82 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -751,4 +751,12 @@
return Api::CastIsolate(isolate);
}
+
+DART_EXPORT char* Dart_GetVmStatus(const char* request) {
+ if (strncmp(request, "/isolate/", 9) == 0) {
+ return Isolate::GetStatus(request);
+ }
+ return NULL;
+}
+
} // namespace dart
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index b4e862e..9e098cc 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -101,10 +101,11 @@
// These register names are defined in a way to match the native disassembler
-// formatting. See for example the command "objdump -d <binary file>".
+// formatting, except for register aliases ctx (r9) and pp (r10).
+// See for example the command "objdump -d <binary file>".
static const char* reg_names[kNumberOfCpuRegisters] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
+ "r8", "ctx", "pp", "fp", "ip", "sp", "lr", "pc",
};
@@ -296,6 +297,19 @@
PrintSRegister(reg);
return 2;
}
+ } else if (format[1] == 'l') {
+ ASSERT(STRING_STARTS_WITH(format, "slist"));
+ int reg_count = instr->Bits(0, 8);
+ int start = instr->Bit(22) | (instr->Bits(12, 4) << 1);
+ Print("{");
+ for (int i = start; i < start + reg_count; i++) {
+ PrintSRegister(i);
+ if (i != start + reg_count - 1) {
+ Print(", ");
+ }
+ }
+ Print("}");
+ return 5;
}
UNREACHABLE();
return -1;
@@ -316,6 +330,19 @@
int reg = instr->DmField();
PrintDRegister(reg);
return 2;
+ } else if (format[1] == 'l') {
+ ASSERT(STRING_STARTS_WITH(format, "dlist"));
+ int reg_count = instr->Bits(0, 8) >> 1;
+ int start = (instr->Bit(22) << 4) | instr->Bits(12, 4);
+ Print("{");
+ for (int i = start; i < start + reg_count; i++) {
+ PrintDRegister(i);
+ if (i != start + reg_count - 1) {
+ Print(", ");
+ }
+ }
+ Print("}");
+ return 5;
}
UNREACHABLE();
return -1;
@@ -555,6 +582,8 @@
case 1: {
if (instr->Bits(21, 2) == 0x3) {
Format(instr, "clz'cond 'rd, 'rm");
+ } else if (instr->Bits(21, 2) == 0x1) {
+ Format(instr, "bx'cond 'rm");
} else {
Unknown(instr);
}
@@ -571,7 +600,7 @@
}
case 7: {
if (instr->Bits(21, 2) == 0x1) {
- Format(instr, "bkpt #'imm12_4");
+ Format(instr, "bkpt'cond #'imm12_4");
} else {
// Format(instr, "smc'cond");
Unknown(instr); // Not used.
@@ -918,6 +947,20 @@
}
}
}
+ } else if (instr->IsVFPMultipleLoadStore()) {
+ if (instr->HasL()) { // vldm
+ if (instr->Bit(8)) { // vldmd
+ Format(instr, "vldmd'cond'pu 'rn'w, 'dlist");
+ } else { // vldms
+ Format(instr, "vldms'cond'pu 'rn'w, 'slist");
+ }
+ } else { // vstm
+ if (instr->Bit(8)) { // vstmd
+ Format(instr, "vstmd'cond'pu 'rn'w, 'dlist");
+ } else { // vstms
+ Format(instr, "vstms'cond'pu 'rn'w, 'slist");
+ }
+ }
} else {
Unknown(instr);
}
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index f6413ba..b05dd6d 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -26,6 +26,106 @@
const char* Exceptions::kCastErrorDstName = "type cast";
+class StacktraceBuilder : public ValueObject {
+ public:
+ StacktraceBuilder() { }
+ virtual ~StacktraceBuilder() { }
+
+ virtual void AddFrame(const Function& func,
+ const Code& code,
+ const Smi& offset) = 0;
+};
+
+
+class RegularStacktraceBuilder : public StacktraceBuilder {
+ public:
+ RegularStacktraceBuilder()
+ : func_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
+ code_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
+ pc_offset_list_(
+ GrowableObjectArray::Handle(GrowableObjectArray::New())) { }
+ ~RegularStacktraceBuilder() { }
+
+ const GrowableObjectArray& func_list() const { return func_list_; }
+ const GrowableObjectArray& code_list() const { return code_list_; }
+ const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; }
+
+ virtual void AddFrame(const Function& func,
+ const Code& code,
+ const Smi& offset) {
+ func_list_.Add(func);
+ code_list_.Add(code);
+ pc_offset_list_.Add(offset);
+ }
+
+ private:
+ const GrowableObjectArray& func_list_;
+ const GrowableObjectArray& code_list_;
+ const GrowableObjectArray& pc_offset_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(RegularStacktraceBuilder);
+};
+
+
+class PreallocatedStacktraceBuilder : public StacktraceBuilder {
+ public:
+ explicit PreallocatedStacktraceBuilder(const Stacktrace& stacktrace)
+ : stacktrace_(stacktrace),
+ cur_index_(0) {
+ ASSERT(stacktrace_.raw() ==
+ Isolate::Current()->object_store()->preallocated_stack_trace());
+ }
+ ~PreallocatedStacktraceBuilder() { }
+
+ virtual void AddFrame(const Function& func,
+ const Code& code,
+ const Smi& offset);
+
+ private:
+ static const int kNumTopframes = 3;
+
+ const Stacktrace& stacktrace_;
+ intptr_t cur_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(PreallocatedStacktraceBuilder);
+};
+
+
+void PreallocatedStacktraceBuilder::AddFrame(const Function& func,
+ const Code& code,
+ const Smi& offset) {
+ if (cur_index_ >= Stacktrace::kPreallocatedStackdepth) {
+ // The number of frames is overflowing the preallocated stack trace object.
+ Function& frame_func = Function::Handle();
+ Code& frame_code = Code::Handle();
+ Smi& frame_offset = Smi::Handle();
+ intptr_t start = Stacktrace::kPreallocatedStackdepth - (kNumTopframes - 1);
+ intptr_t null_slot = start - 2;
+ // Add an empty slot to indicate the overflow so that the toString
+ // method can account for the overflow.
+ if (stacktrace_.FunctionAtFrame(null_slot) != Function::null()) {
+ stacktrace_.SetFunctionAtFrame(null_slot, frame_func);
+ stacktrace_.SetCodeAtFrame(null_slot, frame_code);
+ }
+ // Move frames one slot down so that we can accomadate the new frame.
+ for (intptr_t i = start; i < Stacktrace::kPreallocatedStackdepth; i++) {
+ intptr_t prev = (i - 1);
+ frame_func = stacktrace_.FunctionAtFrame(i);
+ frame_code = stacktrace_.CodeAtFrame(i);
+ frame_offset = stacktrace_.PcOffsetAtFrame(i);
+ stacktrace_.SetFunctionAtFrame(prev, frame_func);
+ stacktrace_.SetCodeAtFrame(prev, frame_code);
+ stacktrace_.SetPcOffsetAtFrame(prev, frame_offset);
+ }
+ cur_index_ = (Stacktrace::kPreallocatedStackdepth - 1);
+ }
+ stacktrace_.SetFunctionAtFrame(cur_index_, func);
+ stacktrace_.SetCodeAtFrame(cur_index_, code);
+ stacktrace_.SetPcOffsetAtFrame(cur_index_, offset);
+ cur_index_ += 1;
+}
+
+
static bool ShouldShowFunction(const Function& function) {
if (FLAG_verbose_stacktrace) {
return true;
@@ -40,9 +140,7 @@
static bool FindExceptionHandler(uword* handler_pc,
uword* handler_sp,
uword* handler_fp,
- const GrowableObjectArray& func_list,
- const GrowableObjectArray& code_list,
- const GrowableObjectArray& pc_offset_list) {
+ StacktraceBuilder* builder) {
StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
StackFrame* frame = frames.NextFrame();
ASSERT(frame != NULL); // We expect to find a dart invocation frame.
@@ -64,18 +162,14 @@
ASSERT(pc < (code.EntryPoint() + code.Size()));
if (ShouldShowFunction(func)) {
offset = Smi::New(pc - code.EntryPoint());
- func_list.Add(func);
- code_list.Add(code);
- pc_offset_list.Add(offset);
+ builder->AddFrame(func, code, offset);
}
}
} else {
offset = Smi::New(frame->pc() - code.EntryPoint());
func = code.function();
if (ShouldShowFunction(func)) {
- func_list.Add(func);
- code_list.Add(code);
- pc_offset_list.Add(offset);
+ builder->AddFrame(func, code, offset);
}
}
if (frame->FindExceptionHandler(handler_pc)) {
@@ -171,46 +265,74 @@
static void ThrowExceptionHelper(const Instance& incoming_exception,
const Instance& existing_stacktrace) {
- Instance& exception = Instance::Handle(incoming_exception.raw());
+ bool use_preallocated_stacktrace = false;
+ Isolate* isolate = Isolate::Current();
+ Instance& exception = Instance::Handle(isolate, incoming_exception.raw());
if (exception.IsNull()) {
exception ^= Exceptions::Create(Exceptions::kNullThrown,
Object::empty_array());
+ } else if (exception.raw() == isolate->object_store()->out_of_memory() ||
+ exception.raw() == isolate->object_store()->stack_overflow()) {
+ use_preallocated_stacktrace = true;
}
uword handler_pc = 0;
uword handler_sp = 0;
uword handler_fp = 0;
- const GrowableObjectArray& func_list =
- GrowableObjectArray::Handle(GrowableObjectArray::New());
- const GrowableObjectArray& code_list =
- GrowableObjectArray::Handle(GrowableObjectArray::New());
- const GrowableObjectArray& pc_offset_list =
- GrowableObjectArray::Handle(GrowableObjectArray::New());
- bool handler_exists = FindExceptionHandler(&handler_pc,
- &handler_sp,
- &handler_fp,
- func_list,
- code_list,
- pc_offset_list);
+ Stacktrace& stacktrace = Stacktrace::Handle(isolate);
+ bool handler_exists = false;
+ if (use_preallocated_stacktrace) {
+ stacktrace ^= isolate->object_store()->preallocated_stack_trace();
+ PreallocatedStacktraceBuilder frame_builder(stacktrace);
+ handler_exists = FindExceptionHandler(&handler_pc,
+ &handler_sp,
+ &handler_fp,
+ &frame_builder);
+ } else {
+ RegularStacktraceBuilder frame_builder;
+ handler_exists = FindExceptionHandler(&handler_pc,
+ &handler_sp,
+ &handler_fp,
+ &frame_builder);
+ // TODO(5411263): At some point we can optimize by figuring out if a
+ // stack trace is needed based on whether the catch code specifies a
+ // stack trace object or there is a rethrow in the catch clause.
+ if (frame_builder.pc_offset_list().Length() != 0) {
+ // Create arrays for function, code and pc_offset triplet for each frame.
+ const Array& func_array =
+ Array::Handle(isolate, Array::MakeArray(frame_builder.func_list()));
+ const Array& code_array =
+ Array::Handle(isolate, Array::MakeArray(frame_builder.code_list()));
+ const Array& pc_offset_array =
+ Array::Handle(isolate,
+ Array::MakeArray(frame_builder.pc_offset_list()));
+ if (existing_stacktrace.IsNull()) {
+ stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array);
+ } else {
+ stacktrace ^= existing_stacktrace.raw();
+ stacktrace.Append(func_array, code_array, pc_offset_array);
+ // Since we are re throwing and appending to the existing stack trace
+ // we clear out the catch trace collected in the existing stack trace
+ // as that trace will not be valid anymore.
+ stacktrace.SetCatchStacktrace(Object::empty_array(),
+ Object::empty_array(),
+ Object::empty_array());
+ }
+ } else {
+ stacktrace ^= existing_stacktrace.raw();
+ // Since we are re throwing and appending to the existing stack trace
+ // we clear out the catch trace collected in the existing stack trace
+ // as that trace will not be valid anymore.
+ stacktrace.SetCatchStacktrace(Object::empty_array(),
+ Object::empty_array(),
+ Object::empty_array());
+ }
+ }
// We expect to find a handler_pc, if the exception is unhandled
// then we expect to at least have the dart entry frame on the
// stack as Exceptions::Throw should happen only after a dart
// invocation has been done.
ASSERT(handler_pc != 0);
- // TODO(5411263): At some point we can optimize by figuring out if a
- // stack trace is needed based on whether the catch code specifies a
- // stack trace object or there is a rethrow in the catch clause.
- Stacktrace& stacktrace = Stacktrace::Handle();
- if (pc_offset_list.Length() != 0) {
- if (existing_stacktrace.IsNull()) {
- stacktrace = Stacktrace::New(func_list, code_list, pc_offset_list);
- } else {
- stacktrace ^= existing_stacktrace.raw();
- stacktrace.Append(func_list, code_list, pc_offset_list);
- }
- } else {
- stacktrace ^= existing_stacktrace.raw();
- }
if (FLAG_print_stacktrace_at_throw) {
OS::Print("Exception '%s' thrown:\n", exception.ToCString());
OS::Print("%s\n", stacktrace.ToCString());
@@ -224,7 +346,6 @@
stacktrace);
} else {
if (FLAG_heap_profile_out_of_memory) {
- Isolate* isolate = Isolate::Current();
if (exception.raw() == isolate->object_store()->out_of_memory()) {
isolate->heap()->ProfileToFile("out-of-memory");
}
@@ -466,10 +587,6 @@
library = Library::CoreLibrary();
class_name = &Symbols::NullThrownError();
break;
- case kIllegalJSRegExp:
- library = Library::CoreLibrary();
- class_name = &Symbols::IllegalJSRegExpException();
- break;
case kIsolateSpawn:
library = Library::IsolateLibrary();
class_name = &Symbols::IsolateSpawnException();
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 9582034..6015369 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -58,7 +58,6 @@
kOutOfMemory,
kInternalError,
kNullThrown,
- kIllegalJSRegExp,
kIsolateSpawn,
kIsolateUnhandledException
};
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index e7598ac..fe14079 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -72,19 +72,13 @@
Instruction* instr,
Environment* env,
Definition::UseKind use_kind) {
- for (intptr_t i = instr->InputCount() - 1; i >= 0; --i) {
- Value* input = instr->InputAt(i);
- input->definition()->AddInputUse(input);
- input->set_instruction(instr);
- input->set_use_index(i);
- }
- ASSERT(instr->env() == NULL);
- if (env != NULL) env->DeepCopyTo(instr);
if (use_kind == Definition::kValue) {
ASSERT(instr->IsDefinition());
instr->AsDefinition()->set_ssa_temp_index(alloc_ssa_temp_index());
}
instr->InsertAfter(prev);
+ ASSERT(instr->env() == NULL);
+ if (env != NULL) env->DeepCopyTo(instr);
}
@@ -151,18 +145,18 @@
}
Definition* defn = instr->AsDefinition();
if (defn != NULL) {
+ // Used definitions must have an SSA name. We use the name to index
+ // into bit vectors during analyses. Some definitions without SSA names
+ // (e.g., PushArgument) have environment uses.
+ ASSERT((defn->input_use_list() == NULL) || defn->HasSSATemp());
Value* prev = NULL;
Value* curr = defn->input_use_list();
while (curr != NULL) {
ASSERT(prev == curr->previous_use());
ASSERT(defn == curr->definition());
Instruction* instr = curr->instruction();
- // The instruction should not be removed from the graph. Removed
- // instructions have a NULL previous link. Phis are not removed until
- // register allocation. Comparisons used only in a branch will have a
- // NULL previous link though they are still in the graph.
- ASSERT(instr->IsPhi() ||
- (instr->IsDefinition() && instr->AsDefinition()->IsComparison()) ||
+ // The instruction should not be removed from the graph.
+ ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) ||
(instr->previous() != NULL));
ASSERT(curr == instr->InputAt(curr->use_index()));
prev = curr;
@@ -176,8 +170,7 @@
ASSERT(defn == curr->definition());
Instruction* instr = curr->instruction();
ASSERT(curr == instr->env()->ValueAtUseIndex(curr->use_index()));
- ASSERT(instr->IsPhi() ||
- (instr->IsDefinition() && instr->AsDefinition()->IsComparison()) ||
+ ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) ||
(instr->previous() != NULL));
prev = curr;
curr = curr->next_use();
@@ -196,10 +189,11 @@
for (intptr_t i = 0; i < preorder_.length(); ++i) {
BlockEntryInstr* entry = preorder_[i];
JoinEntryInstr* join = entry->AsJoinEntry();
- if (join != NULL && join->phis() != NULL) {
- for (intptr_t i = 0; i < join->phis()->length(); ++i) {
- PhiInstr* phi = (*join->phis())[i];
- if (phi != NULL) VerifyUseListsInInstruction(phi);
+ if (join != NULL) {
+ for (PhiIterator it(join); !it.Done(); it.Advance()) {
+ PhiInstr* phi = it.Current();
+ ASSERT(phi != NULL);
+ VerifyUseListsInInstruction(phi);
}
}
for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
@@ -222,8 +216,9 @@
// Rename uses to reference inserted phis where appropriate.
// Collect phis that reach a non-environment use.
Rename(&live_phis, inlining_parameters);
- // Propagate alive mark transitively from alive phis.
- MarkLivePhis(&live_phis);
+ // Propagate alive mark transitively from alive phis and then remove
+ // non-live ones.
+ RemoveDeadPhis(&live_phis);
}
@@ -474,12 +469,9 @@
Environment::From(*env,
num_non_copied_params_,
parsed_function_.function());
- current->set_env(deopt_env);
- intptr_t use_index = 0;
+ current->SetEnvironment(deopt_env);
for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
Value* use = it.CurrentValue();
- use->set_instruction(current);
- use->set_use_index(use_index++);
use->definition()->AddEnvUse(use);
}
}
@@ -501,15 +493,12 @@
Definition* input_defn = v->definition();
if (input_defn->IsLoadLocal() || input_defn->IsStoreLocal()) {
// Remove the load/store from the graph.
- input_defn->UnuseAllInputs();
input_defn->RemoveFromGraph();
// Assert we are not referencing nulls in the initial environment.
ASSERT(reaching_defn->ssa_temp_index() != -1);
v->set_definition(reaching_defn);
input_defn = reaching_defn;
}
- v->set_instruction(current);
- v->set_use_index(i);
input_defn->AddInputUse(v);
}
@@ -548,7 +537,6 @@
env->Add((*env)[index]);
// We remove load/store instructions when we find their use in 2a.
} else {
- definition->UnuseAllInputs();
it.RemoveCurrentFromGraph();
}
} else {
@@ -591,9 +579,6 @@
// Rename input operand.
Value* use = new Value((*env)[i]);
phi->SetInputAt(pred_index, use);
- use->set_instruction(phi);
- use->set_use_index(pred_index);
- use->definition()->AddInputUse(use);
}
}
}
@@ -601,7 +586,7 @@
}
-void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) {
+void FlowGraph::RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis) {
while (!live_phis->is_empty()) {
PhiInstr* phi = live_phis->RemoveLast();
for (intptr_t i = 0; i < phi->InputCount(); i++) {
@@ -613,6 +598,11 @@
}
}
}
+
+ for (BlockIterator it(postorder_iterator()); !it.Done(); it.Advance()) {
+ JoinEntryInstr* join = it.Current()->AsJoinEntry();
+ if (join != NULL) join->RemoveDeadPhis(constant_null());
+ }
}
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index 59c0c0d..fa8c796 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -167,7 +167,7 @@
const GrowableArray<BitVector*>& assigned_vars,
const GrowableArray<BitVector*>& dom_frontier);
- void MarkLivePhis(GrowableArray<PhiInstr*>* live_phis);
+ void RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis);
void ReplacePredecessor(BlockEntryInstr* old_block,
BlockEntryInstr* new_block);
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index a2b0c36..02704b2 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -78,10 +78,21 @@
cpu_spill_slot_count_(0) {
for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL);
+ // All registers are marked as "not blocked" (array initialized to false).
+ // Mark the unavailable ones as "blocked" (true).
+ for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) {
+ blocked_cpu_registers_[i] = true;
+ }
+ for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) {
+ blocked_cpu_registers_[i] = true;
+ }
blocked_cpu_registers_[CTX] = true;
if (TMP != kNoRegister) {
blocked_cpu_registers_[TMP] = true;
}
+ if (PP != kNoRegister) {
+ blocked_cpu_registers_[PP] = true;
+ }
blocked_cpu_registers_[SPREG] = true;
blocked_cpu_registers_[FPREG] = true;
@@ -91,37 +102,12 @@
// Remove environments from the instructions which can't deoptimize.
-// Replace dead phis uses with null values in environments.
-void FlowGraphAllocator::EliminateEnvironmentUses() {
- ConstantInstr* constant_null =
- postorder_.Last()->AsGraphEntry()->constant_null();
+void FlowGraphAllocator::EliminateEnvironments() {
for (intptr_t i = 0; i < block_order_.length(); ++i) {
BlockEntryInstr* block = block_order_[i];
- if (block->IsJoinEntry()) block->AsJoinEntry()->RemoveDeadPhis();
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
Instruction* current = it.Current();
- if (current->CanDeoptimize()) {
- ASSERT(current->env() != NULL);
- for (Environment::DeepIterator it(current->env());
- !it.Done();
- it.Advance()) {
- Value* use = it.CurrentValue();
- Definition* def = use->definition();
- PushArgumentInstr* push_argument = def->AsPushArgument();
- if ((push_argument != NULL) && push_argument->WasEliminated()) {
- it.SetCurrentValue(push_argument->value()->Copy());
- continue;
- }
-
- PhiInstr* phi = def->AsPhi();
- if ((phi != NULL) && !phi->is_alive()) {
- it.SetCurrentValue(new Value(constant_null));
- continue;
- }
- }
- } else {
- current->set_env(NULL);
- }
+ if (!current->CanDeoptimize()) current->RemoveEnvironment();
}
}
}
@@ -177,25 +163,22 @@
// Handle phis.
if (block->IsJoinEntry()) {
JoinEntryInstr* join = block->AsJoinEntry();
- if (join->phis() != NULL) {
- for (intptr_t j = 0; j < join->phis()->length(); j++) {
- PhiInstr* phi = (*join->phis())[j];
- if (phi == NULL) continue;
+ for (PhiIterator it(join); !it.Done(); it.Advance()) {
+ PhiInstr* phi = it.Current();
+ ASSERT(phi != NULL);
+ kill->Add(phi->ssa_temp_index());
+ live_in->Remove(phi->ssa_temp_index());
- kill->Add(phi->ssa_temp_index());
- live_in->Remove(phi->ssa_temp_index());
+ // If a phi input is not defined by the corresponding predecessor it
+ // must be marked live-in for that predecessor.
+ for (intptr_t k = 0; k < phi->InputCount(); k++) {
+ Value* val = phi->InputAt(k);
+ if (val->BindsToConstant()) continue;
- // If phi-operand is not defined by a predecessor it must be marked
- // live-in for a predecessor.
- for (intptr_t k = 0; k < phi->InputCount(); k++) {
- Value* val = phi->InputAt(k);
- if (val->BindsToConstant()) continue;
-
- BlockEntryInstr* pred = block->PredecessorAt(k);
- const intptr_t use = val->definition()->ssa_temp_index();
- if (!kill_[pred->postorder_number()]->Contains(use)) {
- live_in_[pred->postorder_number()]->Add(use);
- }
+ BlockEntryInstr* pred = block->PredecessorAt(k);
+ const intptr_t use = val->definition()->ssa_temp_index();
+ if (!kill_[pred->postorder_number()]->Contains(use)) {
+ live_in_[pred->postorder_number()]->Add(use);
}
}
}
@@ -696,12 +679,9 @@
const intptr_t pred_idx = join->IndexOfPredecessor(block);
// Record the corresponding phi input use for each phi.
- ZoneGrowableArray<PhiInstr*>* phis = join->phis();
intptr_t move_idx = 0;
- for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) {
- PhiInstr* phi = (*phis)[phi_idx];
- if (phi == NULL) continue;
-
+ for (PhiIterator it(join); !it.Done(); it.Advance()) {
+ PhiInstr* phi = it.Current();
Value* val = phi->InputAt(pred_idx);
MoveOperands* move = parallel_move->MoveOperandsAt(move_idx);
@@ -744,19 +724,13 @@
// All uses are recorded at the start position in the block.
const intptr_t pos = join->start_pos();
-
- ZoneGrowableArray<PhiInstr*>* phis = join->phis();
- if (phis == NULL) return;
-
const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header();
-
intptr_t move_idx = 0;
- for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) {
- PhiInstr* phi = (*phis)[phi_idx];
- if (phi == NULL) continue;
-
+ for (PhiIterator it(join); !it.Done(); it.Advance()) {
+ PhiInstr* phi = it.Current();
+ ASSERT(phi != NULL);
const intptr_t vreg = phi->ssa_temp_index();
- ASSERT(vreg != -1);
+ ASSERT(vreg >= 0);
// Expected shape of live range:
//
@@ -1183,8 +1157,10 @@
// For join entry predecessors create phi resolution moves if
// necessary. They will be populated by the register allocator.
JoinEntryInstr* join = block->AsJoinEntry();
- if ((join != NULL) && (join->phi_count() > 0)) {
- const intptr_t phi_count = join->phi_count();
+ if ((join != NULL) &&
+ (join->phis() != NULL) &&
+ !join->phis()->is_empty()) {
+ const intptr_t phi_count = join->phis()->length();
for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
// Insert the move between the last two instructions of the
// predecessor block (all such blocks have at least two instructions:
@@ -1756,15 +1732,14 @@
!it.Done();
it.Advance()) {
PhiInstr* phi = it.Current();
- if (phi->is_alive()) {
- const intptr_t phi_vreg = phi->ssa_temp_index();
- LiveRange* range = GetLiveRange(phi_vreg);
- if (range->assigned_location().kind() == register_kind_) {
- const intptr_t reg = range->assigned_location().register_code();
+ ASSERT(phi->is_alive());
+ const intptr_t phi_vreg = phi->ssa_temp_index();
+ LiveRange* range = GetLiveRange(phi_vreg);
+ if (range->assigned_location().kind() == register_kind_) {
+ const intptr_t reg = range->assigned_location().register_code();
- if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
- used_on_backedge[reg] = true;
- }
+ if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
+ used_on_backedge[reg] = true;
}
}
}
@@ -2446,7 +2421,7 @@
void FlowGraphAllocator::AllocateRegisters() {
CollectRepresentations();
- EliminateEnvironmentUses();
+ EliminateEnvironments();
AnalyzeLiveness();
diff --git a/runtime/vm/flow_graph_allocator.h b/runtime/vm/flow_graph_allocator.h
index 2c2447f..b191758 100644
--- a/runtime/vm/flow_graph_allocator.h
+++ b/runtime/vm/flow_graph_allocator.h
@@ -54,7 +54,7 @@
void CollectRepresentations();
// Eliminate unnecessary environments from the IL.
- void EliminateEnvironmentUses();
+ void EliminateEnvironments();
// Compute initial values for live-out, kill and live-in sets.
void ComputeInitialSets();
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 8bcba37..f06d426 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -197,19 +197,14 @@
}
// If the call has uses, create a phi of the returns.
if (call->HasUses()) {
- // Environment count: length before call - argument count (+ return)
- intptr_t env_count = call->env()->Length() - call->ArgumentCount();
// Add a phi of the return values.
- join->InsertPhi(env_count, env_count + 1);
- PhiInstr* phi = join->phis()->Last();
+ PhiInstr* phi = new PhiInstr(join, num_exits);
phi->set_ssa_temp_index(caller_graph->alloc_ssa_temp_index());
phi->mark_alive();
for (intptr_t i = 0; i < num_exits; ++i) {
- Value* value = ValueAt(i);
- phi->SetInputAt(i, value);
- value->set_instruction(phi);
- value->set_use_index(i);
+ phi->SetInputAt(i, ValueAt(i));
}
+ join->InsertPhi(phi);
// Replace uses of the call with the phi.
call->ReplaceUsesWith(phi);
} else {
@@ -1686,7 +1681,10 @@
node->ElementAt(i)->Visit(&for_value);
Append(for_value);
// No store barrier needed for constants.
- const bool emit_store_barrier = !for_value.value()->BindsToConstant();
+ const StoreBarrierType emit_store_barrier =
+ for_value.value()->BindsToConstant()
+ ? kNoStoreBarrier
+ : kEmitStoreBarrier;
StoreIndexedInstr* store = new StoreIndexedInstr(
array, index, for_value.value(),
emit_store_barrier, class_id, deopt_id);
@@ -1978,22 +1976,40 @@
}
-static bool IsRecognizedConstructor(const Function& function,
- const String& expected) {
- const Class& clazz = Class::Handle(function.Owner());
- const Library& lib = Library::Handle(clazz.library());
+// List of recognized factories in core lib (factories with known result-cid):
+// (factory-name-symbol, result-cid, fingerprint).
+#define RECOGNIZED_FACTORY_LIST(V) \
+ V(ObjectArrayDot, kArrayCid, 97987288) \
+ V(GrowableObjectArrayWithData, kGrowableObjectArrayCid, 816132033) \
+ V(GrowableObjectArrayDot, kGrowableObjectArrayCid, 1896741574) \
- const String& expected_class_name =
- String::Handle(lib.PrivateName(expected));
- if (!String::Handle(clazz.Name()).Equals(expected_class_name)) {
- return false;
+
+// Class that recognizes factories and returns corresponding result cid.
+class FactoryRecognizer : public AllStatic {
+ public:
+ // Return kDynamicCid if factory is not recognized.
+ static intptr_t ResultCid(const Function& factory) {
+ ASSERT(factory.IsFactory());
+ const Class& function_class = Class::Handle(factory.Owner());
+ const Library& lib = Library::Handle(function_class.library());
+ if (lib.raw() != Library::CoreLibrary()) {
+ // Only core library factories recognized.
+ return kDynamicCid;
+ }
+ const String& factory_name = String::Handle(factory.name());
+#define RECOGNIZE_FACTORY(test_factory_symbol, cid, fp) \
+ if (String::EqualsIgnoringPrivateKey( \
+ factory_name, Symbols::test_factory_symbol())) { \
+ ASSERT(factory.CheckSourceFingerprint(fp)); \
+ return cid; \
+ } \
+
+RECOGNIZED_FACTORY_LIST(RECOGNIZE_FACTORY);
+#undef RECOGNIZE_FACTORY
+
+ return kDynamicCid;
}
-
- const String& function_name = String::Handle(function.name());
- const String& expected_function_name = String::Handle(
- String::Concat(expected_class_name, Symbols::Dot()));
- return function_name.Equals(expected_function_name);
-}
+};
static intptr_t GetResultCidOfConstructor(ConstructorCallNode* node) {
@@ -2008,20 +2024,13 @@
if (node->constructor().IsFactory()) {
if ((function_class.Name() == Symbols::List().raw()) &&
(function.name() == Symbols::ListFactory().raw())) {
- return kGrowableObjectArrayCid;
- } else if ((function_class.Name() == Symbols::List().raw()) &&
- (function.name() == Symbols::ListFixedLengthFactory().raw())) {
- return kArrayCid;
- } else {
- if (IsRecognizedConstructor(function, Symbols::ObjectArray()) &&
- (node->arguments()->length() == 1)) {
- return kArrayCid;
- } else if (IsRecognizedConstructor(function,
- Symbols::GrowableObjectArray()) &&
- (node->arguments()->length() == 0)) {
+ // Special recognition of 'new List()' vs 'new List(n)'.
+ if (node->arguments()->length() == 0) {
return kGrowableObjectArrayCid;
}
+ return kArrayCid;
}
+ return FactoryRecognizer::ResultCid(function);
}
return kDynamicCid; // Result cid not known.
}
@@ -2569,7 +2578,6 @@
type,
dst_name);
}
- const bool kEmitStoreBarrier = true;
StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr(
node->field(), for_instance.value(), store_value, kEmitStoreBarrier);
ReturnDefinition(store);
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 8319dd5..dc6d4ab 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -674,9 +674,15 @@
bool blocked_registers[kNumberOfCpuRegisters];
// Mark all available registers free.
- for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+ for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) {
+ blocked_registers[i] = true;
+ }
+ for (intptr_t i = kFirstFreeCpuRegister; i <= kLastFreeCpuRegister; i++) {
blocked_registers[i] = false;
}
+ for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) {
+ blocked_registers[i] = true;
+ }
// Mark all fixed input, temp and output registers as used.
for (intptr_t i = 0; i < locs->input_count(); i++) {
@@ -708,6 +714,9 @@
if (TMP != kNoRegister) {
blocked_registers[TMP] = true;
}
+ if (PP != kNoRegister) {
+ blocked_registers[PP] = true;
+ }
// Allocate all unallocated input locations.
const bool should_pop = !instr->IsPushArgument();
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index d8b220c..502de90 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -7,10 +7,24 @@
#include "vm/flow_graph_compiler.h"
-#include "vm/longjump.h"
+#include "lib/error.h"
+#include "vm/ast_printer.h"
+#include "vm/dart_entry.h"
+#include "vm/il_printer.h"
+#include "vm/locations.h"
+#include "vm/object_store.h"
+#include "vm/parser.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
namespace dart {
+DECLARE_FLAG(int, optimization_counter_threshold);
+DECLARE_FLAG(bool, print_ast);
+DECLARE_FLAG(bool, print_scopes);
+DECLARE_FLAG(bool, enable_type_checks);
+
+
FlowGraphCompiler::~FlowGraphCompiler() {
// BlockInfos are zone-allocated, so their destructors are not called.
// Verify the labels explicitly here.
@@ -31,6 +45,9 @@
}
+#define __ assembler()->
+
+
void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
Label* is_true,
Label* is_false) {
@@ -128,12 +145,24 @@
void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) {
- UNIMPLEMENTED();
+ if (!is_optimizing()) {
+ if (FLAG_enable_type_checks && instr->IsAssertAssignable()) {
+ AssertAssignableInstr* assert = instr->AsAssertAssignable();
+ AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
+ assert->deopt_id(),
+ assert->token_pos());
+ }
+ AllocateRegistersLocally(instr);
+ }
}
void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
- UNIMPLEMENTED();
+ if (is_optimizing()) return;
+ Definition* defn = instr->AsDefinition();
+ if ((defn != NULL) && defn->is_used()) {
+ __ Push(defn->locs()->out().reg());
+ }
}
@@ -153,12 +182,191 @@
void FlowGraphCompiler::EmitFrameEntry() {
- UNIMPLEMENTED();
+ const Function& function = parsed_function().function();
+ if (CanOptimizeFunction() && function.is_optimizable()) {
+ const bool can_optimize = !is_optimizing() || may_reoptimize();
+ const Register function_reg = R6;
+ if (can_optimize) {
+ __ LoadObject(function_reg, function);
+ }
+ // Patch point is after the eventually inlined function object.
+ AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ if (can_optimize) {
+ // Reoptimization of optimized function is triggered by counting in
+ // IC stubs, but not at the entry of the function.
+ if (!is_optimizing()) {
+ __ ldr(R7, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ __ add(R7, R7, ShifterOperand(1));
+ __ str(R7, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ } else {
+ __ ldr(R7, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ }
+ __ CompareImmediate(R7, FLAG_optimization_counter_threshold);
+ ASSERT(function_reg == R6);
+ __ Branch(&StubCode::OptimizeFunctionLabel(), GE);
+ }
+ } else {
+ AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ }
+ __ Comment("Enter frame");
+ AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize));
}
void FlowGraphCompiler::CompileGraph() {
- UNIMPLEMENTED();
+ InitCompiler();
+ if (TryIntrinsify()) {
+ // Although this intrinsified code will never be patched, it must satisfy
+ // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum
+ // code size.
+ __ bkpt(0);
+ __ Branch(&StubCode::FixCallersTargetLabel());
+ return;
+ }
+
+ EmitFrameEntry();
+
+ const Function& function = parsed_function().function();
+
+ const int num_fixed_params = function.num_fixed_parameters();
+ const int num_copied_params = parsed_function().num_copied_params();
+ const int num_locals = parsed_function().num_stack_locals();
+
+ // For optimized code, keep a bitmap of the frame in order to build
+ // stackmaps for GC safepoints in the prologue.
+ LocationSummary* prologue_locs = NULL;
+ if (is_optimizing()) {
+ // Spill slots are allocated but not initialized.
+ prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall);
+ prologue_locs->stack_bitmap()->SetLength(StackSize());
+ }
+
+ // We check the number of passed arguments when we have to copy them due to
+ // the presence of optional parameters.
+ // No such checking code is generated if only fixed parameters are declared,
+ // unless we are in debug mode or unless we are compiling a closure.
+ LocalVariable* saved_args_desc_var =
+ parsed_function().GetSavedArgumentsDescriptorVar();
+ if (num_copied_params == 0) {
+#ifdef DEBUG
+ ASSERT(!parsed_function().function().HasOptionalParameters());
+ const bool check_arguments = true;
+#else
+ const bool check_arguments = function.IsClosureFunction();
+#endif
+ if (check_arguments) {
+ __ Comment("Check argument count");
+ // Check that exactly num_fixed arguments are passed in.
+ Label correct_num_arguments, wrong_num_arguments;
+ __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+ __ CompareImmediate(R0, Smi::RawValue(num_fixed_params));
+ __ b(&wrong_num_arguments, NE);
+ __ ldr(R1, FieldAddress(R4,
+ ArgumentsDescriptor::positional_count_offset()));
+ __ cmp(R0, ShifterOperand(R1));
+ __ b(&correct_num_arguments, EQ);
+ __ Bind(&wrong_num_arguments);
+ if (function.IsClosureFunction()) {
+ if (StackSize() != 0) {
+ // We need to unwind the space we reserved for locals and copied
+ // parameters. The NoSuchMethodFunction stub does not expect to see
+ // that area on the stack.
+ __ AddImmediate(SP, StackSize() * kWordSize);
+ }
+ // The call below has an empty stackmap because we have just
+ // dropped the spill slots.
+ BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
+
+ // Invoke noSuchMethod function passing "call" as the function name.
+ const int kNumArgsChecked = 1;
+ const ICData& ic_data = ICData::ZoneHandle(
+ ICData::New(function, Symbols::Call(),
+ Isolate::kNoDeoptId, kNumArgsChecked));
+ __ LoadObject(R5, ic_data);
+ // FP - 4 : saved PP, object pool pointer of caller.
+ // FP + 0 : previous frame pointer.
+ // FP + 4 : return address.
+ // FP + 8 : PC marker, for easy identification of RawInstruction obj.
+ // FP + 12: last argument (arg n-1).
+ // SP + 0 : saved PP.
+ // SP + 16 + 4*(n-1) : first argument (arg 0).
+ // R5 : ic-data.
+ // R4 : arguments descriptor array.
+ __ BranchLink(&StubCode::CallNoSuchMethodFunctionLabel());
+ if (is_optimizing()) {
+ stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
+ empty_stack_bitmap,
+ 0); // No registers.
+ }
+ // The noSuchMethod call may return.
+ AssemblerMacros::LeaveDartFrame(assembler());
+ __ Ret();
+ } else {
+ __ Stop("Wrong number of arguments");
+ }
+ __ Bind(&correct_num_arguments);
+ }
+ // The arguments descriptor is never saved in the absence of optional
+ // parameters, since any argument definition test would always yield true.
+ ASSERT(saved_args_desc_var == NULL);
+ } else {
+ if (saved_args_desc_var != NULL) {
+ __ Comment("Save arguments descriptor");
+ const Register kArgumentsDescriptorReg = R4;
+ // The saved_args_desc_var is allocated one slot before the first local.
+ const intptr_t slot = parsed_function().first_stack_local_index() + 1;
+ // If the saved_args_desc_var is captured, it is first moved to the stack
+ // and later to the context, once the context is allocated.
+ ASSERT(saved_args_desc_var->is_captured() ||
+ (saved_args_desc_var->index() == slot));
+ __ str(kArgumentsDescriptorReg, Address(FP, slot * kWordSize));
+ }
+ CopyParameters();
+ }
+
+ // In unoptimized code, initialize (non-argument) stack allocated slots to
+ // null. This does not cover the saved_args_desc_var slot.
+ if (!is_optimizing() && (num_locals > 0)) {
+ __ Comment("Initialize spill slots");
+ const intptr_t slot_base = parsed_function().first_stack_local_index();
+ __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ for (intptr_t i = 0; i < num_locals; ++i) {
+ // Subtract index i (locals lie at lower addresses than FP).
+ __ str(R0, Address(FP, (slot_base - i) * kWordSize));
+ }
+ }
+
+ if (FLAG_print_scopes) {
+ // Print the function scope (again) after generating the prologue in order
+ // to see annotations such as allocation indices of locals.
+ if (FLAG_print_ast) {
+ // Second printing.
+ OS::Print("Annotated ");
+ }
+ AstPrinter::PrintFunctionScope(parsed_function());
+ }
+
+ VisitBlocks();
+
+ __ bkpt(0);
+ GenerateDeferredCode();
+ // Emit function patching code. This will be swapped with the first 5 bytes
+ // at entry point.
+ AddCurrentDescriptor(PcDescriptors::kPatchCode,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ __ Branch(&StubCode::FixCallersTargetLabel());
+ AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ __ Branch(&StubCode::DeoptimizeLazyLabel());
}
@@ -175,7 +383,20 @@
const ExternalLabel* label,
PcDescriptors::Kind kind,
LocationSummary* locs) {
- UNIMPLEMENTED();
+ __ BranchLinkPatchable(label);
+ AddCurrentDescriptor(kind, deopt_id, token_pos);
+ RecordSafepoint(locs);
+ // Marks either the continuation point in unoptimized code or the
+ // deoptimization point in optimized code, after call.
+ if (is_optimizing()) {
+ AddDeoptIndexAtCall(deopt_id, token_pos);
+ } else {
+ // Add deoptimization continuation point after the call and before the
+ // arguments are removed.
+ AddCurrentDescriptor(PcDescriptors::kDeoptAfter,
+ deopt_id,
+ token_pos);
+ }
}
@@ -183,7 +404,7 @@
intptr_t deopt_id,
const RuntimeEntry& entry,
LocationSummary* locs) {
- UNIMPLEMENTED();
+ __ Unimplemented("call runtime");
}
@@ -227,7 +448,16 @@
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
- UNIMPLEMENTED();
+ __ LoadObject(R4, arguments_descriptor);
+ // Do not use the code from the function, but let the code be patched so that
+ // we can record the outgoing edges to other code.
+ GenerateDartCall(deopt_id,
+ token_pos,
+ &StubCode::CallStaticFunctionLabel(),
+ PcDescriptors::kFuncCall,
+ locs);
+ AddStaticCallTarget(function);
+ __ Drop(argument_count);
}
@@ -252,12 +482,31 @@
void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
- UNIMPLEMENTED();
+ // TODO(vegorov): consider saving only caller save (volatile) registers.
+ const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
+ if (fpu_registers > 0) {
+ UNIMPLEMENTED();
+ }
+
+ // Store general purpose registers with the lowest register number at the
+ // lowest address.
+ const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
+ ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
+ __ PushList(cpu_registers);
}
void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
- UNIMPLEMENTED();
+ // General purpose registers have the lowest register number at the
+ // lowest address.
+ const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
+ ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
+ __ PopList(cpu_registers);
+
+ const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
+ if (fpu_registers > 0) {
+ UNIMPLEMENTED();
+ }
}
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 3fc75b3..ebc2053 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -573,7 +573,6 @@
for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
PushArgumentInstr* push = call->PushArgumentAt(i);
push->ReplaceUsesWith(push->value()->definition());
- push->UnuseAllInputs();
push->RemoveFromGraph();
}
@@ -645,12 +644,27 @@
return parsed_function;
}
+ // Include special handling for List. factory: inlining it is not helpful
+ // if the incoming argument is a non-constant value.
+ // TODO(srdjan): Fix inlining of List. factory.
void InlineStaticCalls() {
const GrowableArray<StaticCallInstr*>& calls =
inlining_call_sites_->static_calls();
TRACE_INLINING(OS::Print(" Static Calls (%d)\n", calls.length()));
for (intptr_t i = 0; i < calls.length(); ++i) {
StaticCallInstr* call = calls[i];
+ if (call->function().name() == Symbols::ListFactory().raw()) {
+ // Inline only if no arguments or a constant was passed.
+ ASSERT(call->function().NumImplicitParameters() == 1);
+ ASSERT(call->ArgumentCount() <= 2);
+ // Arg 0: Instantiator type arguments.
+ // Arg 1: Length (optional).
+ if ((call->ArgumentCount() == 2) &&
+ (!call->PushArgumentAt(1)->value()->BindsToConstant())) {
+ // Do not inline since a non-constant argument was passed.
+ continue;
+ }
+ }
GrowableArray<Value*> arguments(call->ArgumentCount());
for (int i = 0; i < call->ArgumentCount(); ++i) {
arguments.Add(call->PushArgumentAt(i)->value());
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 58cf837..522dee1 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -290,7 +290,6 @@
OS::Print("Removing v%"Pd".\n", current_defn->ssa_temp_index());
}
}
- current->UnuseAllInputs();
iterator->RemoveCurrentFromGraph();
}
@@ -333,9 +332,7 @@
// Convert by boxing/unboxing.
// TODO(fschneider): Implement direct unboxed mint-to-double conversion.
BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType());
- use->RemoveFromUseList();
- use->set_definition(boxed);
- boxed->AddInputUse(use);
+ use->BindTo(boxed);
InsertBefore(insert_before, boxed, NULL, Definition::kValue);
const intptr_t deopt_id = (deopt_target != NULL) ?
@@ -363,9 +360,7 @@
}
}
ASSERT(converted != NULL);
- use->RemoveFromUseList();
- use->set_definition(converted);
- converted->AddInputUse(use);
+ use->BindTo(converted);
InsertBefore(insert_before, converted, use->instruction()->env(),
Definition::kValue);
}
@@ -388,8 +383,7 @@
Instruction* deopt_target;
PhiInstr* phi = use->instruction()->AsPhi();
if (phi != NULL) {
- if (!phi->is_alive()) continue;
-
+ ASSERT(phi->is_alive());
// For phis conversions have to be inserted in the predecessor.
insert_before =
phi->block()->PredecessorAt(use->use_index())->last_instruction();
@@ -407,12 +401,10 @@
// Convervatively unbox all phis that were proven to be of type Double.
for (intptr_t i = 0; i < block_order_.length(); ++i) {
JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry();
- if (join_entry == NULL) continue;
-
- if (join_entry->phis() != NULL) {
- for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) {
- PhiInstr* phi = (*join_entry->phis())[i];
- if (phi == NULL) continue;
+ if (join_entry != NULL) {
+ for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
+ PhiInstr* phi = it.Current();
+ ASSERT(phi != NULL);
if (phi->Type()->ToCid() == kDoubleCid) {
phi->set_representation(kUnboxedDouble);
}
@@ -430,17 +422,15 @@
for (intptr_t i = 0; i < block_order_.length(); ++i) {
BlockEntryInstr* entry = block_order_[i];
-
JoinEntryInstr* join_entry = entry->AsJoinEntry();
- if ((join_entry != NULL) && (join_entry->phis() != NULL)) {
- for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) {
- PhiInstr* phi = (*join_entry->phis())[i];
- if ((phi != NULL) && (phi->is_alive())) {
- InsertConversionsFor(phi);
- }
+ if (join_entry != NULL) {
+ for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
+ PhiInstr* phi = it.Current();
+ ASSERT(phi != NULL);
+ ASSERT(phi->is_alive());
+ InsertConversionsFor(phi);
}
}
-
for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
Definition* def = it.Current()->AsDefinition();
if (def != NULL) {
@@ -565,7 +555,6 @@
for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
PushArgumentInstr* push = call->PushArgumentAt(i);
push->ReplaceUsesWith(push->value()->definition());
- push->UnuseAllInputs();
push->RemoveFromGraph();
}
call->ReplaceWith(replacement, current_iterator());
@@ -893,10 +882,15 @@
}
intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index);
- // Check if store barrier is needed.
- bool needs_store_barrier = !RawObject::IsByteArrayClassId(array_cid);
+ // Check if store barrier is needed. Byte arrays don't need a store barrier.
+ StoreBarrierType needs_store_barrier =
+ RawObject::IsByteArrayClassId(array_cid)
+ ? kNoStoreBarrier
+ : kEmitStoreBarrier;
if (!value_check.IsNull()) {
- needs_store_barrier = false;
+ // No store barrier needed because checked value is a smi, an unboxed mint
+ // or unboxed double.
+ needs_store_barrier = kNoStoreBarrier;
AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
call);
}
@@ -1240,12 +1234,9 @@
field.Offset(),
AbstractType::ZoneHandle(field.type()),
field.is_final());
- // Detach environment from the original instruction because it can't
- // deoptimize.
- for (Environment::DeepIterator it(call->env()); !it.Done(); it.Advance()) {
- it.CurrentValue()->RemoveFromUseList();
- }
- call->set_env(NULL);
+ // Discard the environment from the original instruction because the load
+ // can't deoptimize.
+ call->RemoveEnvironment();
ReplaceCall(call, load);
}
@@ -1414,7 +1405,7 @@
}
-LoadIndexedInstr* FlowGraphOptimizer::BuildStringCharCodeAt(
+LoadIndexedInstr* FlowGraphOptimizer::BuildStringCodeUnitAt(
InstanceCallInstr* call,
intptr_t cid) {
Definition* str = call->ArgumentAt(0);
@@ -1536,11 +1527,11 @@
break;
}
- if ((recognized_kind == MethodRecognizer::kStringBaseCharCodeAt) &&
+ if ((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) &&
(ic_data.NumberOfChecks() == 1) &&
((class_ids[0] == kOneByteStringCid) ||
(class_ids[0] == kTwoByteStringCid))) {
- LoadIndexedInstr* instr = BuildStringCharCodeAt(call, class_ids[0]);
+ LoadIndexedInstr* instr = BuildStringCodeUnitAt(call, class_ids[0]);
ReplaceCall(call, instr);
return true;
}
@@ -1549,7 +1540,7 @@
(class_ids[0] == kOneByteStringCid)) {
// TODO(fschneider): Handle TwoByteString.
LoadIndexedInstr* load_char_code =
- BuildStringCharCodeAt(call, class_ids[0]);
+ BuildStringCodeUnitAt(call, class_ids[0]);
InsertBefore(call, load_char_code, NULL, Definition::kValue);
StringFromCharCodeInstr* char_at =
new StringFromCharCodeInstr(new Value(load_char_code),
@@ -1587,10 +1578,10 @@
}
case MethodRecognizer::kDoubleMod:
case MethodRecognizer::kDoublePow:
+ case MethodRecognizer::kDoubleRound:
ReplaceWithMathCFunction(call, recognized_kind);
return true;
case MethodRecognizer::kDoubleTruncate:
- case MethodRecognizer::kDoubleRound:
case MethodRecognizer::kDoubleFloor:
case MethodRecognizer::kDoubleCeil:
if (!CPUFeatures::double_truncate_round_supported()) {
@@ -1906,26 +1897,23 @@
if (InstanceCallNeedsClassCheck(instr)) {
AddReceiverCheck(instr);
}
- bool needs_store_barrier = true;
+ StoreBarrierType needs_store_barrier = kEmitStoreBarrier;
if (ArgIsAlwaysSmi(*instr->ic_data(), 1)) {
InsertBefore(instr,
new CheckSmiInstr(new Value(instr->ArgumentAt(1)),
instr->deopt_id()),
instr->env(),
Definition::kEffect);
- needs_store_barrier = false;
+ needs_store_barrier = kNoStoreBarrier;
}
StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr(
field,
new Value(instr->ArgumentAt(0)),
new Value(instr->ArgumentAt(1)),
needs_store_barrier);
- // Detach environment from the original instruction because it can't
- // deoptimize.
- for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
- it.CurrentValue()->RemoveFromUseList();
- }
- instr->set_env(NULL);
+ // Discard the environment from the original instruction because the store
+ // can't deoptimize.
+ instr->RemoveEnvironment();
ReplaceCall(instr, store);
return true;
}
@@ -2268,12 +2256,9 @@
// Skip dead phis.
PhiInstr* phi = use->instruction()->AsPhi();
- if ((phi != NULL) && !phi->is_alive()) continue;
-
+ ASSERT((phi == NULL) || phi->is_alive());
if (IsDominatedUse(dom, use)) {
- use->RemoveFromUseList();
- use->set_definition(other);
- other->AddInputUse(use);
+ use->BindTo(other);
}
}
}
@@ -2618,7 +2603,6 @@
RangeBoundary array_length =
RangeBoundary::FromDefinition(check->length()->definition());
if (check->IsRedundant(array_length)) {
- current->UnuseAllInputs();
it.RemoveCurrentFromGraph();
}
}
@@ -2660,7 +2644,6 @@
def = def->AsConstraint()->value()->definition();
}
constraints_[i]->ReplaceUsesWith(def);
- constraints_[i]->UnuseAllInputs();
constraints_[i]->RemoveFromGraph();
}
}
@@ -2683,6 +2666,10 @@
}
+LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) {
+}
+
+
void LICM::Hoist(ForwardInstructionIterator* it,
BlockEntryInstr* pre_header,
Instruction* current) {
@@ -2696,13 +2683,11 @@
pre_header->block_id());
}
// Move the instruction out of the loop.
+ current->RemoveEnvironment();
it->RemoveCurrentFromGraph();
GotoInstr* last = pre_header->last_instruction()->AsGoto();
- current->InsertBefore(last);
- // Attach the environment of the Goto instruction to the hoisted
- // instruction and set the correct deopt_id.
- ASSERT(last->env() != NULL);
- last->env()->DeepCopyTo(current);
+ // Using kind kEffect will not assign a fresh ssa temporary index.
+ flow_graph()->InsertBefore(last, current, last->env(), Definition::kEffect);
current->deopt_id_ = last->GetDeoptId();
}
@@ -2717,7 +2702,6 @@
}
if (phi->Type()->ToCid() == kSmiCid) {
- current->UnuseAllInputs();
it->RemoveCurrentFromGraph();
return;
}
@@ -2748,19 +2732,16 @@
// Host CheckSmi instruction and make this phi smi one.
Hoist(it, pre_header, current);
- // Replace value we are checking with phi's input. Maintain use lists.
- Definition* non_smi_input_defn = phi->InputAt(non_smi_input)->definition();
- current->value()->RemoveFromUseList();
- current->value()->set_definition(non_smi_input_defn);
- non_smi_input_defn->AddInputUse(current->value());
+ // Replace value we are checking with phi's input.
+ current->value()->BindTo(phi->InputAt(non_smi_input)->definition());
phi->UpdateType(CompileType::FromCid(kSmiCid));
}
-void LICM::Optimize(FlowGraph* flow_graph) {
+void LICM::Optimize() {
GrowableArray<BlockEntryInstr*> loop_headers;
- flow_graph->ComputeLoops(&loop_headers);
+ flow_graph()->ComputeLoops(&loop_headers);
for (intptr_t i = 0; i < loop_headers.length(); ++i) {
BlockEntryInstr* header = loop_headers[i];
@@ -2771,7 +2752,7 @@
for (BitVector::Iterator loop_it(header->loop_info());
!loop_it.Done();
loop_it.Advance()) {
- BlockEntryInstr* block = flow_graph->preorder()[loop_it.Current()];
+ BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()];
for (ForwardInstructionIterator it(block);
!it.Done();
it.Advance()) {
@@ -3127,7 +3108,6 @@
}
defn->ReplaceUsesWith(replacement);
- defn->UnuseAllInputs();
instr_it.RemoveCurrentFromGraph();
continue;
} else if (!kill->Contains(expr_id)) {
@@ -3289,10 +3269,6 @@
Definition* replacement = (*pred_out_values)[expr_id]->Replacement();
Value* input = new Value(replacement);
phi->SetInputAt(i, input);
-
- // TODO(vegorov): add a helper function to handle input insertion.
- input->set_instruction(phi);
- input->set_use_index(i);
replacement->AddInputUse(input);
}
@@ -3339,7 +3315,6 @@
}
load->ReplaceUsesWith(replacement);
- load->UnuseAllInputs();
load->RemoveFromGraph();
load->SetReplacement(replacement);
}
@@ -3400,13 +3375,19 @@
return true;
}
- // Emit non-redundant phis created during ComputeOutValues and ForwardLoads.
+ // Phis have not yet been inserted into the graph but they have uses of
+ // their inputs. Insert the non-redundant ones and clear the input uses
+ // of the redundant ones.
void EmitPhis() {
for (intptr_t i = 0; i < phis_.length(); i++) {
PhiInstr* phi = phis_[i];
- if ((phi->input_use_list() != NULL) && !EliminateRedundantPhi(phi)) {
+ if (phi->HasUses() && !EliminateRedundantPhi(phi)) {
phi->mark_alive();
phi->block()->InsertPhi(phi);
+ } else {
+ for (intptr_t j = phi->InputCount() - 1; j >= 0; --j) {
+ phi->InputAt(j)->RemoveFromUseList();
+ }
}
}
}
@@ -4275,43 +4256,47 @@
// Predecessors will be recomputed (in block id order) after removing
// unreachable code so we merely have to keep the phi inputs in order.
ZoneGrowableArray<PhiInstr*>* phis = join->phis();
- if (phis != NULL) {
+ if ((phis != NULL) && !phis->is_empty()) {
intptr_t pred_count = join->PredecessorCount();
intptr_t live_count = 0;
for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) {
if (reachable_->Contains(
join->PredecessorAt(pred_idx)->preorder_number())) {
if (live_count < pred_idx) {
- for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
- PhiInstr* phi = (*phis)[phi_idx];
- if (phi == NULL) continue;
- Value* input = phi->inputs_[pred_idx];
- input->set_use_index(live_count);
- phi->inputs_[live_count] = input;
+ for (PhiIterator it(join); !it.Done(); it.Advance()) {
+ PhiInstr* phi = it.Current();
+ ASSERT(phi != NULL);
+ phi->SetInputAt(live_count, phi->InputAt(pred_idx));
}
}
++live_count;
} else {
- for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
- PhiInstr* phi = (*phis)[phi_idx];
- if (phi == NULL) continue;
- phi->inputs_[pred_idx]->RemoveFromUseList();
+ for (PhiIterator it(join); !it.Done(); it.Advance()) {
+ PhiInstr* phi = it.Current();
+ ASSERT(phi != NULL);
+ phi->InputAt(pred_idx)->RemoveFromUseList();
}
}
}
if (live_count < pred_count) {
- for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
- PhiInstr* phi = (*phis)[phi_idx];
- if (phi == NULL) continue;
+ intptr_t to_idx = 0;
+ for (intptr_t from_idx = 0; from_idx < phis->length(); ++from_idx) {
+ PhiInstr* phi = (*phis)[from_idx];
+ ASSERT(phi != NULL);
if (FLAG_remove_redundant_phis && (live_count == 1)) {
Value* input = phi->InputAt(0);
phi->ReplaceUsesWith(input->definition());
input->RemoveFromUseList();
- (*phis)[phi_idx] = NULL;
} else {
phi->inputs_.TruncateTo(live_count);
+ (*phis)[to_idx++] = phi;
}
}
+ if (to_idx == 0) {
+ join->phis_ = NULL;
+ } else {
+ phis->TruncateTo(to_idx);
+ }
}
}
}
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 6ec0e35..83515bc 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -84,7 +84,7 @@
bool TryInlineInstanceMethod(InstanceCallInstr* call);
void ReplaceWithInstanceOf(InstanceCallInstr* instr);
- LoadIndexedInstr* BuildStringCharCodeAt(InstanceCallInstr* call,
+ LoadIndexedInstr* BuildStringCodeUnitAt(InstanceCallInstr* call,
intptr_t cid);
LoadIndexedInstr* BuildByteArrayViewLoad(InstanceCallInstr* call,
@@ -162,19 +162,25 @@
// Loop invariant code motion.
-class LICM : public AllStatic {
+class LICM : public ValueObject {
public:
- static void Optimize(FlowGraph* flow_graph);
+ explicit LICM(FlowGraph* flow_graph);
+
+ void Optimize();
private:
- static void Hoist(ForwardInstructionIterator* it,
- BlockEntryInstr* pre_header,
- Instruction* current);
+ FlowGraph* flow_graph() const { return flow_graph_; }
- static void TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it,
- BlockEntryInstr* header,
- BlockEntryInstr* pre_header,
- CheckSmiInstr* current);
+ void Hoist(ForwardInstructionIterator* it,
+ BlockEntryInstr* pre_header,
+ Instruction* current);
+
+ void TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it,
+ BlockEntryInstr* header,
+ BlockEntryInstr* pre_header,
+ CheckSmiInstr* current);
+
+ FlowGraph* const flow_graph_;
};
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 8810fbc..09d6171 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -42,22 +42,21 @@
void FlowGraphTypePropagator::Propagate() {
if (FLAG_trace_type_propagation) {
- OS::Print("Before type propagation:\n");
- FlowGraphPrinter printer(*flow_graph_);
- printer.PrintBlocks();
+ FlowGraphPrinter::PrintGraph("Before type propagation", flow_graph_);
}
// Walk the dominator tree and propagate reaching types to all Values.
// Collect all phis for a fixed point iteration.
PropagateRecursive(flow_graph_->graph_entry());
-#ifdef DEBUG
// Initially the worklist contains only phis.
+ // Reset compile type of all phis to None to ensure that
+ // types are correctly propagated through the cycles of
+ // phis.
for (intptr_t i = 0; i < worklist_.length(); i++) {
ASSERT(worklist_[i]->IsPhi());
- ASSERT(worklist_[i]->Type()->IsNone());
+ *worklist_[i]->Type() = CompileType::None();
}
-#endif
// Iterate until a fixed point is reached, updating the types of
// definitions.
@@ -84,9 +83,7 @@
}
if (FLAG_trace_type_propagation) {
- OS::Print("After type propagation:\n");
- FlowGraphPrinter printer(*flow_graph_);
- printer.PrintBlocks();
+ FlowGraphPrinter::PrintGraph("After type propagation", flow_graph_);
}
}
@@ -176,9 +173,7 @@
void FlowGraphTypePropagator::VisitJoinEntry(JoinEntryInstr* join) {
for (PhiIterator it(join); !it.Done(); it.Advance()) {
- if (it.Current()->is_alive()) {
- worklist_.Add(it.Current());
- }
+ worklist_.Add(it.Current());
}
}
@@ -289,14 +284,8 @@
}
ASSERT(check_clone != NULL);
ASSERT(assert->deopt_id() == assert->env()->deopt_id());
-
- Value* use = check_clone->InputAt(0);
- use->set_instruction(check_clone);
- use->set_use_index(0);
- use->definition()->AddInputUse(use);
-
- assert->env()->DeepCopyTo(check_clone);
check_clone->InsertBefore(assert);
+ assert->env()->DeepCopyTo(check_clone);
(*asserts_)[defn->ssa_temp_index()] = kStrengthenedAssertMarker;
}
@@ -352,7 +341,7 @@
CompileType CompileType::FromAbstractType(const AbstractType& type,
- bool is_nullable) {
+ bool is_nullable) {
return CompileType(is_nullable, kIllegalCid, &type);
}
@@ -400,9 +389,10 @@
} else if (type_->IsVoidType()) {
cid_ = kNullCid;
} else if (FLAG_use_cha && type_->HasResolvedTypeClass()) {
- const intptr_t cid = Class::Handle(type_->type_class()).id();
- if (!CHA::HasSubclasses(cid)) {
- cid_ = cid;
+ const Class& type_class = Class::Handle(type_->type_class());
+ if (!type_class.is_implemented() &&
+ !CHA::HasSubclasses(type_class.id())) {
+ cid_ = type_class.id();
} else {
cid_ = kDynamicCid;
}
@@ -538,12 +528,7 @@
bool PhiInstr::RecomputeType() {
- if (!is_alive()) {
- return false;
- }
-
CompileType result = CompileType::None();
-
for (intptr_t i = 0; i < InputCount(); i++) {
if (FLAG_trace_type_propagation) {
OS::Print(" phi %"Pd" input %"Pd": v%"Pd" has reaching type %s\n",
@@ -564,17 +549,6 @@
}
-static bool CanTrustParameterType(const Function& function, intptr_t index) {
- // Parameter is receiver.
- if (index == 0) {
- return function.IsDynamicFunction() || function.IsConstructor();
- }
-
- // Parameter is the constructor phase.
- return (index == 1) && function.IsConstructor();
-}
-
-
CompileType ParameterInstr::ComputeType() const {
// Note that returning the declared type of the formal parameter would be
// incorrect, because ParameterInstr is used as input to the type check
@@ -582,14 +556,36 @@
// always be wrongly eliminated.
// However there are parameters that are known to match their declared type:
// for example receiver and construction phase.
- if (!CanTrustParameterType(block_->parsed_function().function(),
- index())) {
- return CompileType::Dynamic();
+ const Function& function = block_->parsed_function().function();
+ LocalScope* scope = block_->parsed_function().node_sequence()->scope();
+ const AbstractType& type = scope->VariableAt(index())->type();
+
+ // Parameter is the constructor phase.
+ if ((index() == 1) && function.IsConstructor()) {
+ return CompileType::FromAbstractType(type, CompileType::kNonNullable);
}
- LocalScope* scope = block_->parsed_function().node_sequence()->scope();
- return CompileType::FromAbstractType(scope->VariableAt(index())->type(),
- CompileType::kNonNullable);
+ // Parameter is the receiver.
+ if ((index() == 0) &&
+ (function.IsDynamicFunction() || function.IsConstructor())) {
+ if (type.IsObjectType() || type.IsNullType()) {
+ // Receiver can be null.
+ return CompileType::FromAbstractType(type, CompileType::kNullable);
+ }
+
+ // Receiver can't be null but can be an instance of a subclass.
+ intptr_t cid = kDynamicCid;
+ if (FLAG_use_cha && type.HasResolvedTypeClass()) {
+ const Class& type_class = Class::Handle(type.type_class());
+ if (!CHA::HasSubclasses(type_class.id())) {
+ cid = type_class.id();
+ }
+ }
+
+ return CompileType(CompileType::kNonNullable, cid, &type);
+ }
+
+ return CompileType::Dynamic();
}
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index c4d74e5..d938145 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -32,6 +32,14 @@
}
+void FlowGraphPrinter::PrintGraph(const char* phase, FlowGraph* flow_graph) {
+ OS::Print("*** BEGIN CFG\n%s\n", phase);
+ FlowGraphPrinter printer(*flow_graph);
+ printer.PrintBlocks();
+ OS::Print("*** END CFG\n");
+}
+
+
void FlowGraphPrinter::PrintBlocks() {
if (!function_.IsNull()) {
OS::Print("==== %s\n", function_.ToFullyQualifiedCString());
diff --git a/runtime/vm/il_printer.h b/runtime/vm/il_printer.h
index 3da0191..aaa62b7 100644
--- a/runtime/vm/il_printer.h
+++ b/runtime/vm/il_printer.h
@@ -54,6 +54,8 @@
const String& dst_name,
bool eliminated);
+ static void PrintGraph(const char* phase, FlowGraph* flow_graph);
+
private:
const Function& function_;
const GrowableArray<BlockEntryInstr*>& block_order_;
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index ba7ec59..8dab5d9 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -60,14 +60,15 @@
uword CallPattern::TargetAddress() const {
const Object& target_address = Object::Handle(object_pool_.At(pool_index_));
ASSERT(target_address.IsSmi());
- return Smi::Cast(target_address).Value() << kSmiTagShift;
+ // The address is stored in the object array as a RawSmi.
+ return reinterpret_cast<uword>(target_address.raw());
}
void CallPattern::SetTargetAddress(uword target_address) const {
ASSERT(Utils::IsAligned(target_address, 4));
// The address is stored in the object array as a RawSmi.
- const Smi& smi = Smi::Handle(Smi::New(target_address >> kSmiTagShift));
+ const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target_address));
object_pool_.SetAt(pool_index_, smi);
}
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 2b10211..dcb64cc 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -70,13 +70,12 @@
intptr_t deopt_id,
const ICData& unary_checks)
: unary_checks_(unary_checks) {
- ASSERT(value != NULL);
ASSERT(unary_checks.IsZoneHandle());
// Expected useful check data.
- ASSERT(!unary_checks_.IsNull() &&
- (unary_checks_.NumberOfChecks() > 0) &&
- (unary_checks_.num_args_tested() == 1));
- inputs_[0] = value;
+ ASSERT(!unary_checks_.IsNull());
+ ASSERT(unary_checks_.NumberOfChecks() > 0);
+ ASSERT(unary_checks_.num_args_tested() == 1);
+ SetInputAt(0, value);
deopt_id_ = deopt_id;
// Otherwise use CheckSmiInstr.
ASSERT((unary_checks_.NumberOfChecks() != 1) ||
@@ -319,6 +318,25 @@
#undef DEFINE_ACCEPT
+void Instruction::SetEnvironment(Environment* deopt_env) {
+ intptr_t use_index = 0;
+ for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
+ Value* use = it.CurrentValue();
+ use->set_instruction(this);
+ use->set_use_index(use_index++);
+ }
+ env_ = deopt_env;
+}
+
+
+void Instruction::RemoveEnvironment() {
+ for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) {
+ it.CurrentValue()->RemoveFromUseList();
+ }
+ env_ = NULL;
+}
+
+
Instruction* Instruction::RemoveFromGraph(bool return_previous) {
ASSERT(!IsBlockEntry());
ASSERT(!IsControl());
@@ -327,29 +345,23 @@
ASSERT(!IsReThrow());
ASSERT(!IsGoto());
ASSERT(previous() != NULL);
+ // We cannot assert that the instruction, if it is a definition, has no
+ // uses. This function is used to remove instructions from the graph and
+ // reinsert them elsewhere (e.g., hoisting).
Instruction* prev_instr = previous();
Instruction* next_instr = next();
ASSERT(next_instr != NULL);
ASSERT(!next_instr->IsBlockEntry());
prev_instr->LinkTo(next_instr);
- // Reset successor and previous instruction to indicate
- // that the instruction is removed from the graph.
+ UnuseAllInputs();
+ // Reset the successor and previous instruction to indicate that the
+ // instruction is removed from the graph.
set_previous(NULL);
set_next(NULL);
return return_previous ? prev_instr : next_instr;
}
-void Instruction::InsertBefore(Instruction* next) {
- ASSERT(previous_ == NULL);
- ASSERT(next_ == NULL);
- next_ = next;
- previous_ = next->previous_;
- next->previous_ = this;
- previous_->next_ = this;
-}
-
-
void Instruction::InsertAfter(Instruction* prev) {
ASSERT(previous_ == NULL);
ASSERT(next_ == NULL);
@@ -357,6 +369,13 @@
next_ = prev->next_;
next_->previous_ = this;
previous_->next_ = this;
+
+ // Update def-use chains whenever instructions are added to the graph
+ // after initial graph construction.
+ for (intptr_t i = InputCount() - 1; i >= 0; --i) {
+ Value* input = InputAt(i);
+ input->definition()->AddInputUse(input);
+ }
}
@@ -473,7 +492,6 @@
if (next != NULL) next->set_previous_use(prev);
}
- set_definition(NULL);
set_previous_use(NULL);
set_next_use(NULL);
}
@@ -535,28 +553,18 @@
for (intptr_t i = other->InputCount() - 1; i >= 0; --i) {
Value* input = other->InputAt(i);
input->definition()->AddInputUse(input);
- input->set_instruction(other);
- input->set_use_index(i);
}
// Take other's environment from this definition.
ASSERT(other->env() == NULL);
- intptr_t use_index = 0;
- for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) {
- Value* use = it.CurrentValue();
- use->set_instruction(other);
- use->set_use_index(use_index++);
- }
- other->set_env(env());
- set_env(NULL);
+ other->SetEnvironment(env());
+ env_ = NULL;
// Replace all uses of this definition with other.
ReplaceUsesWith(other);
// Reuse this instruction's SSA name for other.
ASSERT(!other->HasSSATemp());
if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index());
- // Remove this definition's input uses.
- UnuseAllInputs();
- // Finally remove this definition from the graph.
+ // Finally insert the other definition in place of this one in the graph.
previous()->LinkTo(other);
if ((iterator != NULL) && (this == iterator->Current())) {
// Remove through the iterator.
@@ -564,34 +572,42 @@
iterator->RemoveCurrentFromGraph();
} else {
other->LinkTo(next());
+ // Remove this definition's input uses.
+ UnuseAllInputs();
}
set_previous(NULL);
set_next(NULL);
}
+BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked)
+ : comparison_(comparison), is_checked_(is_checked) {
+ for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
+ comparison->InputAt(i)->set_instruction(this);
+ }
+}
+
+
+void BranchInstr::RawSetInputAt(intptr_t i, Value* value) {
+ comparison()->RawSetInputAt(i, value);
+}
+
+
// A misleadingly named function for use in template functions that replace
// both definitions with definitions and branch comparisons with
// comparisons. In the branch case, leave the branch intact and replace its
-// comparison with another comparison.
+// comparison with a new comparison not currently in the graph.
void BranchInstr::ReplaceWith(ComparisonInstr* other,
ForwardInstructionIterator* ignored) {
- // Record the new comparison's input uses.
- for (intptr_t i = other->InputCount() - 1; i >= 0; --i) {
- Value* input = other->InputAt(i);
- input->definition()->AddInputUse(input);
- }
SetComparison(other);
}
void BranchInstr::SetComparison(ComparisonInstr* comp) {
- // The new comparison's input uses are already recorded in their
- // definition's use lists.
for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) {
Value* input = comp->InputAt(i);
+ input->definition()->AddInputUse(input);
input->set_instruction(this);
- input->set_use_index(i);
}
// There should be no need to copy or unuse an environment.
ASSERT(comparison()->env() == NULL);
@@ -744,9 +760,9 @@
// If the new and old predecessor index match there is nothing to update.
if ((join->phis() == NULL) || (old_index == new_index)) return;
// Otherwise, reorder the predecessor uses in each phi.
- for (intptr_t i = 0; i < join->phis()->length(); ++i) {
- PhiInstr* phi = (*join->phis())[i];
- if (phi == NULL) continue;
+ for (PhiIterator it(join); !it.Done(); it.Advance()) {
+ PhiInstr* phi = it.Current();
+ ASSERT(phi != NULL);
ASSERT(pred_count == phi->InputCount());
// Save the predecessor use.
Value* pred_use = phi->InputAt(old_index);
@@ -755,13 +771,10 @@
for (intptr_t use_idx = old_index;
use_idx != new_index;
use_idx += step) {
- Value* use = phi->InputAt(use_idx + step);
- phi->SetInputAt(use_idx, use);
- use->set_use_index(use_idx);
+ phi->SetInputAt(use_idx, phi->InputAt(use_idx + step));
}
// Write the predecessor use.
phi->SetInputAt(new_index, pred_use);
- pred_use->set_use_index(new_index);
}
}
}
@@ -780,7 +793,6 @@
}
ASSERT((*phis_)[var_index] == NULL);
(*phis_)[var_index] = new PhiInstr(this, PredecessorCount());
- phi_count_++;
}
@@ -790,23 +802,32 @@
phis_ = new ZoneGrowableArray<PhiInstr*>(1);
}
phis_->Add(phi);
- phi_count_++;
}
-void JoinEntryInstr::RemoveDeadPhis() {
+void JoinEntryInstr::RemoveDeadPhis(Definition* replacement) {
if (phis_ == NULL) return;
- for (intptr_t i = 0; i < phis_->length(); i++) {
- PhiInstr* phi = (*phis_)[i];
- if ((phi != NULL) && !phi->is_alive()) {
- (*phis_)[i] = NULL;
- phi_count_--;
+ intptr_t to_index = 0;
+ for (intptr_t from_index = 0; from_index < phis_->length(); ++from_index) {
+ PhiInstr* phi = (*phis_)[from_index];
+ if (phi != NULL) {
+ if (phi->is_alive()) {
+ (*phis_)[to_index++] = phi;
+ for (intptr_t i = phi->InputCount() - 1; i >= 0; --i) {
+ Value* input = phi->InputAt(i);
+ input->definition()->AddInputUse(input);
+ }
+ } else {
+ phi->ReplaceUsesWith(replacement);
+ }
}
}
-
- // Check if we removed all phis.
- if (phi_count_ == 0) phis_ = NULL;
+ if (to_index == 0) {
+ phis_ = NULL;
+ } else {
+ phis_->TruncateTo(to_index);
+ }
}
@@ -1169,9 +1190,7 @@
// It is ok to insert instructions before the current during
// forward iteration.
optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue);
- instantiator_type_arguments()->RemoveFromUseList();
- instantiator_type_arguments()->set_definition(null_constant);
- null_constant->AddInputUse(instantiator_type_arguments());
+ instantiator_type_arguments()->BindTo(null_constant);
}
return this;
}
@@ -1200,9 +1219,6 @@
(comp->input_use_list()->next_use() == NULL) &&
(comp->env_use_list() == NULL)) {
comp->RemoveFromGraph();
- // It is safe to pass a NULL iterator because we're replacing the
- // comparison wrapped in a BranchInstr which does not modify the
- // linked list of instructions.
SetComparison(comp);
if (FLAG_trace_optimization) {
OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index());
@@ -1536,14 +1552,11 @@
}
Environment* copy = DeepCopy();
- intptr_t use_index = 0;
+ instr->SetEnvironment(copy);
for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
Value* value = it.CurrentValue();
- value->set_instruction(instr);
- value->set_use_index(use_index++);
value->definition()->AddEnvUse(value);
}
- instr->set_env(copy);
}
@@ -1555,6 +1568,7 @@
ASSERT(instr->env()->outer() == NULL);
intptr_t argument_count = instr->env()->fixed_parameter_count();
Environment* copy = DeepCopy(values_.length() - argument_count);
+ instr->env()->outer_ = copy;
intptr_t use_index = instr->env()->Length(); // Start index after inner.
for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
Value* value = it.CurrentValue();
@@ -1562,7 +1576,6 @@
value->set_use_index(use_index++);
value->definition()->AddEnvUse(value);
}
- instr->env()->outer_ = copy;
}
@@ -2171,16 +2184,34 @@
}
+InvokeMathCFunctionInstr::InvokeMathCFunctionInstr(
+ ZoneGrowableArray<Value*>* inputs,
+ InstanceCallInstr* instance_call,
+ MethodRecognizer::Kind recognized_kind)
+ : inputs_(inputs),
+ locs_(NULL),
+ recognized_kind_(recognized_kind) {
+ ASSERT(inputs_->length() == ArgumentCountFor(recognized_kind_));
+ for (intptr_t i = 0; i < inputs_->length(); ++i) {
+ ASSERT((*inputs)[i] != NULL);
+ (*inputs)[i]->set_instruction(this);
+ (*inputs)[i]->set_use_index(i);
+ }
+ deopt_id_ = instance_call->deopt_id();
+}
+
+
intptr_t InvokeMathCFunctionInstr::ArgumentCountFor(
MethodRecognizer::Kind kind) {
switch (kind) {
case MethodRecognizer::kDoubleTruncate:
- case MethodRecognizer::kDoubleRound:
case MethodRecognizer::kDoubleFloor:
case MethodRecognizer::kDoubleCeil: {
ASSERT(!CPUFeatures::double_truncate_round_supported());
return 1;
}
+ case MethodRecognizer::kDoubleRound:
+ return 1;
case MethodRecognizer::kDoubleMod:
case MethodRecognizer::kDoublePow:
return 2;
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 4d25a91..976fa13 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -73,7 +73,7 @@
V(_GrowableObjectArray, get:_capacity, GrowableArrayCapacity, 725548050) \
V(_StringBase, get:length, StringBaseLength, 320803993) \
V(_StringBase, get:isEmpty, StringBaseIsEmpty, 711547329) \
- V(_StringBase, charCodeAt, StringBaseCharCodeAt, 984449525) \
+ V(_StringBase, codeUnitAt, StringBaseCodeUnitAt, 984449525) \
V(_StringBase, [], StringBaseCharAt, 1062366987) \
V(_IntegerImplementation, toDouble, IntegerToDouble, 733149324) \
V(_Double, toInt, DoubleToInteger, 362666636) \
@@ -113,11 +113,27 @@
// Values of CompileType form a lattice with a None type as a bottom and a
// nullable Dynamic type as a top element. Method Union provides a join
// operation for the lattice.
-class CompileType {
+class CompileType : public ValueObject {
public:
static const bool kNullable = true;
static const bool kNonNullable = false;
+ CompileType(bool is_nullable, intptr_t cid, const AbstractType* type)
+ : is_nullable_(is_nullable), cid_(cid), type_(type) { }
+
+ CompileType(const CompileType& other)
+ : ValueObject(),
+ is_nullable_(other.is_nullable_),
+ cid_(other.cid_),
+ type_(other.type_) { }
+
+ CompileType& operator=(const CompileType& other) {
+ is_nullable_ = other.is_nullable_;
+ cid_ = other.cid_;
+ type_ = other.type_;
+ return *this;
+ }
+
// Return type such that concrete value's type in runtime is guaranteed to
// be subtype of it.
const AbstractType* ToAbstractType();
@@ -197,9 +213,6 @@
const char* ToCString() const;
private:
- CompileType(bool is_nullable, intptr_t cid, const AbstractType* type)
- : is_nullable_(is_nullable), cid_(cid), type_(type) { }
-
bool CanComputeIsInstanceOf(const AbstractType& type,
bool is_nullable,
bool* is_instance);
@@ -274,6 +287,9 @@
static void AddToList(Value* value, Value** list);
void RemoveFromUseList();
+ // Change the definition after use lists have been computed.
+ inline void BindTo(Definition* definition);
+
Value* Copy() { return new Value(definition_); }
// This function must only be used when the new Value is dominated by
@@ -336,9 +352,7 @@
template<typename T, intptr_t N>
class EmbeddedArray {
public:
- EmbeddedArray() {
- for (intptr_t i = 0; i < N; i++) elements_[i] = NULL;
- }
+ EmbeddedArray() : elements_() { }
intptr_t length() const { return N; }
@@ -510,7 +524,12 @@
virtual intptr_t InputCount() const = 0;
virtual Value* InputAt(intptr_t i) const = 0;
- virtual void SetInputAt(intptr_t i, Value* value) = 0;
+ void SetInputAt(intptr_t i, Value* value) {
+ ASSERT(value != NULL);
+ value->set_instruction(this);
+ value->set_use_index(i);
+ RawSetInputAt(i, value);
+ }
// Remove all inputs (including in the environment) from their
// definition's use lists.
@@ -561,7 +580,9 @@
next->set_previous(this);
}
- // Removed this instruction from the graph.
+ // Removed this instruction from the graph, after use lists have been
+ // computed. If the instruction is a definition with uses, those uses are
+ // unaffected (so the instruction can be reinserted, e.g., hoisting).
Instruction* RemoveFromGraph(bool return_previous = true);
// Normal instructions can have 0 (inside a block) or 1 (last instruction in
@@ -607,7 +628,8 @@
}
Environment* env() const { return env_; }
- void set_env(Environment* env) { env_ = env; }
+ void SetEnvironment(Environment* deopt_env);
+ void RemoveEnvironment();
intptr_t lifetime_position() const { return lifetime_position_; }
void set_lifetime_position(intptr_t pos) {
@@ -641,10 +663,12 @@
// change.
virtual Instruction* Canonicalize(FlowGraphOptimizer* optimizer);
- // Insert this instruction before 'next'.
- void InsertBefore(Instruction* next);
+ // Insert this instruction before 'next' after use lists are computed.
+ // Instructions cannot be inserted before a block entry or any other
+ // instruction without a previous instruction.
+ void InsertBefore(Instruction* next) { InsertAfter(next->previous()); }
- // Insert this instruction after 'prev'.
+ // Insert this instruction after 'prev' after use lists are computed.
void InsertAfter(Instruction* prev);
// Returns true if the instruction is affected by side effects.
@@ -708,6 +732,8 @@
friend class FlowGraphOptimizer;
friend class LoadIndexedInstr;
+ virtual void RawSetInputAt(intptr_t i, Value* value) = 0;
+
intptr_t deopt_id_;
intptr_t lifetime_position_; // Position used by register allocator.
Instruction* previous_;
@@ -726,10 +752,6 @@
virtual intptr_t InputCount() const { return N; }
virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
- virtual void SetInputAt(intptr_t i, Value* value) {
- ASSERT(value != NULL);
- inputs_[i] = value;
- }
virtual LocationSummary* locs() {
if (locs_ == NULL) {
@@ -742,6 +764,10 @@
EmbeddedArray<Value*, N> inputs_;
private:
+ virtual void RawSetInputAt(intptr_t i, Value* value) {
+ inputs_[i] = value;
+ }
+
LocationSummary* locs_;
};
@@ -923,7 +949,6 @@
UNREACHABLE();
return NULL;
}
- virtual void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
virtual intptr_t ArgumentCount() const { return 0; }
@@ -960,6 +985,8 @@
loop_info_(NULL) { }
private:
+ virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
+
virtual void ClearPredecessors() = 0;
virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0;
@@ -1092,8 +1119,7 @@
JoinEntryInstr(intptr_t block_id, intptr_t try_index)
: BlockEntryInstr(block_id, try_index),
predecessors_(2), // Two is the assumed to be the common case.
- phis_(NULL),
- phi_count_(0) { }
+ phis_(NULL) { }
DECLARE_INSTRUCTION(JoinEntry)
@@ -1110,12 +1136,10 @@
virtual void PrepareEntry(FlowGraphCompiler* compiler);
void InsertPhi(intptr_t var_index, intptr_t var_count);
- void RemoveDeadPhis();
+ void RemoveDeadPhis(Definition* replacement);
void InsertPhi(PhiInstr* phi);
- intptr_t phi_count() const { return phi_count_; }
-
virtual void PrintTo(BufferFormatter* f) const;
private:
@@ -1123,12 +1147,14 @@
friend class BlockEntryInstr;
friend class ValueInliningContext;
+ // Direct access to phis_ in order to resize it due to phi elimination.
+ friend class ConstantPropagator;
+
virtual void ClearPredecessors() { predecessors_.Clear(); }
virtual void AddPredecessor(BlockEntryInstr* predecessor);
GrowableArray<BlockEntryInstr*> predecessors_;
ZoneGrowableArray<PhiInstr*>* phis_;
- intptr_t phi_count_;
DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr);
};
@@ -1137,15 +1163,11 @@
class PhiIterator : public ValueObject {
public:
explicit PhiIterator(JoinEntryInstr* join)
- : phis_(join->phis()), index_(-1) {
- if (!Done()) Advance(); // Advance to the first phi.
- }
+ : phis_(join->phis()), index_(0) { }
void Advance() {
ASSERT(!Done());
- do {
- index_++;
- } while (!Done() && (Current() == NULL));
+ index_++;
}
bool Done() const {
@@ -1369,9 +1391,17 @@
};
+// Change a value's definition after use lists have been computed.
+inline void Value::BindTo(Definition* def) {
+ RemoveFromUseList();
+ set_definition(def);
+ def->AddInputUse(this);
+}
+
+
class PhiInstr : public Definition {
public:
- explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
+ PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
: block_(block),
inputs_(num_inputs),
is_alive_(false),
@@ -1395,8 +1425,6 @@
Value* InputAt(intptr_t i) const { return inputs_[i]; }
- void SetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
-
virtual bool CanDeoptimize() const { return false; }
virtual bool HasSideEffect() const { return false; }
@@ -1437,7 +1465,11 @@
}
private:
- friend class ConstantPropagator; // Direct access to inputs_.
+ // Direct access to inputs_ in order to resize it due to unreachable
+ // predecessors.
+ friend class ConstantPropagator;
+
+ void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
JoinEntryInstr* block_;
GrowableArray<Value*> inputs_;
@@ -1452,7 +1484,7 @@
class ParameterInstr : public Definition {
public:
- explicit ParameterInstr(intptr_t index, GraphEntryInstr* block)
+ ParameterInstr(intptr_t index, GraphEntryInstr* block)
: index_(index), block_(block) { }
DECLARE_INSTRUCTION(Parameter)
@@ -1469,7 +1501,6 @@
UNREACHABLE();
return NULL;
}
- void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
virtual bool CanDeoptimize() const { return false; }
@@ -1485,6 +1516,8 @@
virtual CompileType ComputeType() const;
private:
+ virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
+
const intptr_t index_;
GraphEntryInstr* block_;
@@ -1494,8 +1527,8 @@
class PushArgumentInstr : public Definition {
public:
- explicit PushArgumentInstr(Value* value) : value_(value), locs_(NULL) {
- ASSERT(value != NULL);
+ explicit PushArgumentInstr(Value* value) : locs_(NULL) {
+ SetInputAt(0, value);
set_use_kind(kEffect); // Override the default.
}
@@ -1506,10 +1539,6 @@
ASSERT(i == 0);
return value_;
}
- void SetInputAt(intptr_t i, Value* value) {
- ASSERT(i == 0);
- value_ = value;
- }
virtual intptr_t ArgumentCount() const { return 0; }
@@ -1536,6 +1565,11 @@
virtual void PrintOperandsTo(BufferFormatter* f) const;
private:
+ virtual void RawSetInputAt(intptr_t i, Value* value) {
+ ASSERT(i == 0);
+ value_ = value;
+ }
+
Value* value_;
LocationSummary* locs_;
@@ -1552,8 +1586,7 @@
public:
ReturnInstr(intptr_t token_pos, Value* value)
: token_pos_(token_pos) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
}
DECLARE_INSTRUCTION(Return)
@@ -1691,15 +1724,13 @@
class BranchInstr : public ControlInstruction {
public:
- explicit BranchInstr(ComparisonInstr* comparison, bool is_checked = false)
- : comparison_(comparison), is_checked_(is_checked) { }
+ explicit BranchInstr(ComparisonInstr* comparison, bool is_checked = false);
DECLARE_INSTRUCTION(Branch)
virtual intptr_t ArgumentCount() const;
intptr_t InputCount() const;
Value* InputAt(intptr_t i) const;
- void SetInputAt(intptr_t i, Value* value);
virtual bool CanDeoptimize() const;
virtual bool HasSideEffect() const;
@@ -1726,6 +1757,8 @@
virtual void PrintTo(BufferFormatter* f) const;
private:
+ virtual void RawSetInputAt(intptr_t i, Value* value);
+
ComparisonInstr* comparison_;
const bool is_checked_;
@@ -1736,8 +1769,7 @@
class StoreContextInstr : public TemplateInstruction<1> {
public:
explicit StoreContextInstr(Value* value) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
}
DECLARE_INSTRUCTION(StoreContext);
@@ -1762,10 +1794,6 @@
virtual intptr_t InputCount() const { return N; }
virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
- virtual void SetInputAt(intptr_t i, Value* value) {
- ASSERT(value != NULL);
- inputs_[i] = value;
- }
// Returns a structure describing the location constraints required
// to emit native code for this definition.
@@ -1782,6 +1810,10 @@
private:
friend class BranchInstr;
+ virtual void RawSetInputAt(intptr_t i, Value* value) {
+ inputs_[i] = value;
+ }
+
LocationSummary* locs_;
};
@@ -1949,8 +1981,7 @@
public:
ConstraintInstr(Value* value, Range* constraint)
: constraint_(constraint) {
- inputs_[0] = value;
- inputs_[1] = NULL; // Dependency.
+ SetInputAt(0, value);
}
DECLARE_INSTRUCTION(Constraint)
@@ -1979,10 +2010,8 @@
void AddDependency(Definition* defn) {
Value* val = new Value(defn);
- val->set_use_index(1);
- val->set_instruction(this);
defn->AddInputUse(val);
- set_dependency(val);
+ SetInputAt(1, val);
}
private:
@@ -1990,10 +2019,6 @@
return inputs_[1];
}
- void set_dependency(Value* value) {
- inputs_[1] = value;
- }
-
Range* constraint_;
DISALLOW_COPY_AND_ASSIGN(ConstraintInstr);
@@ -2039,14 +2064,11 @@
: token_pos_(token_pos),
dst_type_(AbstractType::ZoneHandle(dst_type.raw())),
dst_name_(dst_name) {
- ASSERT(value != NULL);
- ASSERT(instantiator != NULL);
- ASSERT(instantiator_type_arguments != NULL);
ASSERT(!dst_type.IsNull());
ASSERT(!dst_name.IsNull());
- inputs_[0] = value;
- inputs_[1] = instantiator;
- inputs_[2] = instantiator_type_arguments;
+ SetInputAt(0, value);
+ SetInputAt(1, instantiator);
+ SetInputAt(2, instantiator_type_arguments);
}
DECLARE_INSTRUCTION(AssertAssignable)
@@ -2088,8 +2110,7 @@
public:
AssertBooleanInstr(intptr_t token_pos, Value* value)
: token_pos_(token_pos) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
}
DECLARE_INSTRUCTION(AssertBoolean)
@@ -2121,8 +2142,7 @@
ArgumentDefinitionTestInstr(ArgumentDefinitionTestNode* node,
Value* saved_arguments_descriptor)
: ast_node_(*node) {
- ASSERT(saved_arguments_descriptor != NULL);
- inputs_[0] = saved_arguments_descriptor;
+ SetInputAt(0, saved_arguments_descriptor);
}
DECLARE_INSTRUCTION(ArgumentDefinitionTest)
@@ -2314,10 +2334,8 @@
public:
ComparisonInstr(Token::Kind kind, Value* left, Value* right)
: kind_(kind) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
+ SetInputAt(0, left);
+ SetInputAt(1, right);
}
Value* left() const { return inputs_[0]; }
@@ -2351,11 +2369,6 @@
}
-inline void BranchInstr::SetInputAt(intptr_t i, Value* value) {
- comparison()->SetInputAt(i, value);
-}
-
-
inline bool BranchInstr::CanDeoptimize() const {
// Branches need a deoptimization info in checked mode if they
// can throw a type check error.
@@ -2657,8 +2670,7 @@
intptr_t context_level)
: local_(local),
context_level_(context_level) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
}
DECLARE_INSTRUCTION(StoreLocal)
@@ -2720,17 +2732,21 @@
};
+enum StoreBarrierType {
+ kNoStoreBarrier,
+ kEmitStoreBarrier
+};
+
+
class StoreInstanceFieldInstr : public TemplateDefinition<2> {
public:
StoreInstanceFieldInstr(const Field& field,
Value* instance,
Value* value,
- bool emit_store_barrier)
+ StoreBarrierType emit_store_barrier)
: field_(field), emit_store_barrier_(emit_store_barrier) {
- ASSERT(instance != NULL);
- ASSERT(value != NULL);
- inputs_[0] = instance;
- inputs_[1] = value;
+ SetInputAt(0, instance);
+ SetInputAt(1, value);
}
DECLARE_INSTRUCTION(StoreInstanceField)
@@ -2741,7 +2757,8 @@
Value* instance() const { return inputs_[0]; }
Value* value() const { return inputs_[1]; }
bool ShouldEmitStoreBarrier() const {
- return value()->NeedsStoreBuffer() && emit_store_barrier_;
+ return value()->NeedsStoreBuffer()
+ && (emit_store_barrier_ == kEmitStoreBarrier);
}
virtual void PrintOperandsTo(BufferFormatter* f) const;
@@ -2752,7 +2769,7 @@
private:
const Field& field_;
- const bool emit_store_barrier_;
+ const StoreBarrierType emit_store_barrier_;
DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldInstr);
};
@@ -2788,8 +2805,7 @@
StoreStaticFieldInstr(const Field& field, Value* value)
: field_(field) {
ASSERT(field.IsZoneHandle());
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
}
DECLARE_INSTRUCTION(StoreStaticField);
@@ -2819,10 +2835,8 @@
intptr_t class_id,
intptr_t deopt_id)
: index_scale_(index_scale), class_id_(class_id) {
- ASSERT(array != NULL);
- ASSERT(index != NULL);
- inputs_[0] = array;
- inputs_[1] = index;
+ SetInputAt(0, array);
+ SetInputAt(1, index);
deopt_id_ = deopt_id;
}
@@ -2858,13 +2872,12 @@
class StringFromCharCodeInstr : public TemplateDefinition<1> {
public:
- explicit StringFromCharCodeInstr(Value* char_code,
- intptr_t cid) : cid_(cid) {
+ StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) {
ASSERT(char_code != NULL);
ASSERT(char_code->definition()->IsLoadIndexed() &&
(char_code->definition()->AsLoadIndexed()->class_id() ==
kOneByteStringCid));
- inputs_[0] = char_code;
+ SetInputAt(0, char_code);
}
DECLARE_INSTRUCTION(StringFromCharCode)
@@ -2892,18 +2905,15 @@
StoreIndexedInstr(Value* array,
Value* index,
Value* value,
- bool emit_store_barrier,
+ StoreBarrierType emit_store_barrier,
intptr_t class_id,
intptr_t deopt_id)
: emit_store_barrier_(emit_store_barrier),
class_id_(class_id),
deopt_id_(deopt_id) {
- ASSERT(array != NULL);
- ASSERT(index != NULL);
- ASSERT(value != NULL);
- inputs_[0] = array;
- inputs_[1] = index;
- inputs_[2] = value;
+ SetInputAt(0, array);
+ SetInputAt(1, index);
+ SetInputAt(2, value);
}
DECLARE_INSTRUCTION(StoreIndexed)
@@ -2914,7 +2924,8 @@
intptr_t class_id() const { return class_id_; }
bool ShouldEmitStoreBarrier() const {
- return value()->NeedsStoreBuffer() && emit_store_barrier_;
+ return value()->NeedsStoreBuffer()
+ && (emit_store_barrier_ == kEmitStoreBarrier);
}
virtual bool CanDeoptimize() const { return false; }
@@ -2930,7 +2941,7 @@
}
private:
- const bool emit_store_barrier_;
+ const StoreBarrierType emit_store_barrier_;
const intptr_t class_id_;
const intptr_t deopt_id_;
@@ -2942,8 +2953,7 @@
class BooleanNegateInstr : public TemplateDefinition<1> {
public:
explicit BooleanNegateInstr(Value* value) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
}
DECLARE_INSTRUCTION(BooleanNegate)
@@ -2971,13 +2981,10 @@
: token_pos_(token_pos),
type_(type),
negate_result_(negate_result) {
- ASSERT(value != NULL);
- ASSERT(instantiator != NULL);
- ASSERT(instantiator_type_arguments != NULL);
ASSERT(!type.IsNull());
- inputs_[0] = value;
- inputs_[1] = instantiator;
- inputs_[2] = instantiator_type_arguments;
+ SetInputAt(0, value);
+ SetInputAt(1, instantiator);
+ SetInputAt(2, instantiator_type_arguments);
}
DECLARE_INSTRUCTION(InstanceOf)
@@ -3052,10 +3059,8 @@
Value* type_arguments,
Value* instantiator)
: ast_node_(*node) {
- ASSERT(type_arguments != NULL);
- ASSERT(instantiator != NULL);
- inputs_[0] = type_arguments;
- inputs_[1] = instantiator;
+ SetInputAt(0, type_arguments);
+ SetInputAt(1, instantiator);
}
DECLARE_INSTRUCTION(AllocateObjectWithBoundsCheck)
@@ -3085,13 +3090,10 @@
: token_pos_(token_pos),
num_elements_(num_elements),
type_(type) {
-#if defined(DEBUG)
- ASSERT(element_type != NULL);
ASSERT(type_.IsZoneHandle());
ASSERT(!type_.IsNull());
ASSERT(type_.IsFinalized());
-#endif
- inputs_[0] = element_type;
+ SetInputAt(0, element_type);
}
DECLARE_INSTRUCTION(CreateArray)
@@ -3164,9 +3166,8 @@
result_cid_(kDynamicCid),
immutable_(immutable),
recognized_kind_(MethodRecognizer::kUnknown) {
- ASSERT(value != NULL);
ASSERT(type.IsZoneHandle()); // May be null if field is not an instance.
- inputs_[0] = value;
+ SetInputAt(0, value);
}
DECLARE_INSTRUCTION(LoadField)
@@ -3222,11 +3223,9 @@
Value* value,
const AbstractType& type)
: offset_in_bytes_(offset_in_bytes), type_(type) {
- ASSERT(value != NULL);
- ASSERT(dest != NULL);
ASSERT(type.IsZoneHandle()); // May be null if field is not an instance.
- inputs_[0] = value;
- inputs_[1] = dest;
+ SetInputAt(0, value);
+ SetInputAt(1, dest);
}
DECLARE_INSTRUCTION(StoreVMField)
@@ -3259,8 +3258,7 @@
: token_pos_(token_pos),
type_arguments_(type_arguments) {
ASSERT(type_arguments.IsZoneHandle());
- ASSERT(instantiator != NULL);
- inputs_[0] = instantiator;
+ SetInputAt(0, instantiator);
}
DECLARE_INSTRUCTION(InstantiateTypeArguments)
@@ -3293,8 +3291,7 @@
Value* instantiator)
: token_pos_(token_pos),
type_arguments_(type_arguments) {
- ASSERT(instantiator != NULL);
- inputs_[0] = instantiator;
+ SetInputAt(0, instantiator);
}
DECLARE_INSTRUCTION(ExtractConstructorTypeArguments)
@@ -3324,8 +3321,7 @@
ExtractConstructorInstantiatorInstr(ConstructorCallNode* ast_node,
Value* instantiator)
: ast_node_(*ast_node) {
- ASSERT(instantiator != NULL);
- inputs_[0] = instantiator;
+ SetInputAt(0, instantiator);
}
DECLARE_INSTRUCTION(ExtractConstructorInstantiator)
@@ -3378,8 +3374,7 @@
class ChainContextInstr : public TemplateInstruction<1> {
public:
explicit ChainContextInstr(Value* context_value) {
- ASSERT(context_value != NULL);
- inputs_[0] = context_value;
+ SetInputAt(0, context_value);
}
DECLARE_INSTRUCTION(ChainContext)
@@ -3401,8 +3396,7 @@
public:
CloneContextInstr(intptr_t token_pos, Value* context_value)
: token_pos_(token_pos) {
- ASSERT(context_value != NULL);
- inputs_[0] = context_value;
+ SetInputAt(0, context_value);
}
intptr_t token_pos() const { return token_pos_; }
@@ -3454,10 +3448,8 @@
CheckEitherNonSmiInstr(Value* left,
Value* right,
InstanceCallInstr* instance_call) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
+ SetInputAt(0, left);
+ SetInputAt(1, right);
deopt_id_ = instance_call->deopt_id();
}
@@ -3488,8 +3480,7 @@
public:
BoxDoubleInstr(Value* value, InstanceCallInstr* instance_call)
: token_pos_((instance_call != NULL) ? instance_call->token_pos() : 0) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
}
Value* value() const { return inputs_[0]; }
@@ -3521,8 +3512,7 @@
class BoxIntegerInstr : public TemplateDefinition<1> {
public:
explicit BoxIntegerInstr(Value* value) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
}
Value* value() const { return inputs_[0]; }
@@ -3550,8 +3540,7 @@
class UnboxDoubleInstr : public TemplateDefinition<1> {
public:
UnboxDoubleInstr(Value* value, intptr_t deopt_id) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
deopt_id_ = deopt_id;
}
@@ -3582,8 +3571,7 @@
class UnboxIntegerInstr : public TemplateDefinition<1> {
public:
UnboxIntegerInstr(Value* value, intptr_t deopt_id) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
deopt_id_ = deopt_id;
}
@@ -3616,8 +3604,7 @@
class MathSqrtInstr : public TemplateDefinition<1> {
public:
MathSqrtInstr(Value* value, StaticCallInstr* instance_call) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
deopt_id_ = instance_call->deopt_id();
}
@@ -3661,10 +3648,8 @@
Value* right,
InstanceCallInstr* instance_call)
: op_kind_(op_kind) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
+ SetInputAt(0, left);
+ SetInputAt(1, right);
deopt_id_ = instance_call->deopt_id();
}
@@ -3720,10 +3705,8 @@
InstanceCallInstr* instance_call)
: op_kind_(op_kind),
instance_call_(instance_call) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
+ SetInputAt(0, left);
+ SetInputAt(1, right);
deopt_id_ = instance_call->deopt_id();
}
@@ -3785,11 +3768,9 @@
Value* right,
InstanceCallInstr* instance_call)
: op_kind_(op_kind) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
ASSERT(op_kind == Token::kSHR || op_kind == Token::kSHL);
- inputs_[0] = left;
- inputs_[1] = right;
+ SetInputAt(0, left);
+ SetInputAt(1, right);
deopt_id_ = instance_call->deopt_id();
}
@@ -3842,9 +3823,8 @@
Value* value,
InstanceCallInstr* instance_call)
: op_kind_(op_kind) {
- ASSERT(value != NULL);
ASSERT(op_kind == Token::kBIT_NOT);
- inputs_[0] = value;
+ SetInputAt(0, value);
deopt_id_ = instance_call->deopt_id();
}
@@ -3900,10 +3880,8 @@
instance_call_(instance_call),
overflow_(true),
is_truncating_(false) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
+ SetInputAt(0, left);
+ SetInputAt(1, right);
deopt_id_ = instance_call->deopt_id();
}
@@ -3966,8 +3944,7 @@
Value* value)
: op_kind_(op_kind) {
ASSERT((op_kind == Token::kNEGATE) || (op_kind == Token::kBIT_NOT));
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
deopt_id_ = instance_call->deopt_id();
}
@@ -4039,8 +4016,7 @@
public:
DoubleToIntegerInstr(Value* value, InstanceCallInstr* instance_call)
: instance_call_(instance_call) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
}
Value* value() const { return inputs_[0]; }
@@ -4067,8 +4043,7 @@
class DoubleToSmiInstr : public TemplateDefinition<1> {
public:
DoubleToSmiInstr(Value* value, InstanceCallInstr* instance_call) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
deopt_id_ = instance_call->deopt_id();
}
@@ -4099,8 +4074,7 @@
InstanceCallInstr* instance_call,
MethodRecognizer::Kind recognized_kind)
: recognized_kind_(recognized_kind) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ SetInputAt(0, value);
deopt_id_ = instance_call->deopt_id();
}
@@ -4137,11 +4111,7 @@
public:
InvokeMathCFunctionInstr(ZoneGrowableArray<Value*>* inputs,
InstanceCallInstr* instance_call,
- MethodRecognizer::Kind recognized_kind)
- : inputs_(inputs), locs_(NULL), recognized_kind_(recognized_kind) {
- ASSERT(inputs_->length() == ArgumentCountFor(recognized_kind_));
- deopt_id_ = instance_call->deopt_id();
- }
+ MethodRecognizer::Kind recognized_kind);
static intptr_t ArgumentCountFor(MethodRecognizer::Kind recognized_kind_);
@@ -4176,11 +4146,6 @@
return (*inputs_)[i];
}
- virtual void SetInputAt(intptr_t i, Value* value) {
- ASSERT(value != NULL);
- (*inputs_)[i] = value;
- }
-
// Returns a structure describing the location constraints required
// to emit native code for this definition.
LocationSummary* locs() {
@@ -4191,6 +4156,10 @@
}
private:
+ virtual void RawSetInputAt(intptr_t i, Value* value) {
+ (*inputs_)[i] = value;
+ }
+
ZoneGrowableArray<Value*>* inputs_;
LocationSummary* locs_;
@@ -4237,9 +4206,8 @@
class CheckSmiInstr : public TemplateInstruction<1> {
public:
CheckSmiInstr(Value* value, intptr_t original_deopt_id) {
- ASSERT(value != NULL);
ASSERT(original_deopt_id != Isolate::kNoDeoptId);
- inputs_[0] = value;
+ SetInputAt(0, value);
deopt_id_ = original_deopt_id;
}
@@ -4271,10 +4239,8 @@
intptr_t array_type,
InstanceCallInstr* instance_call)
: array_type_(array_type) {
- ASSERT(length != NULL);
- ASSERT(index != NULL);
- inputs_[0] = length;
- inputs_[1] = index;
+ SetInputAt(0, length);
+ SetInputAt(1, index);
deopt_id_ = instance_call->deopt_id();
}
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index f35ed33..6ca6c8f 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -16,14 +16,19 @@
#include "vm/stub_code.h"
#include "vm/symbols.h"
+#define __ compiler->assembler()->
+
namespace dart {
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, propagate_ic_data);
+// Generic summary for call instructions that have all arguments pushed
+// on the stack and return the result in a fixed register R0.
LocationSummary* Instruction::MakeCallSummary() {
- UNIMPLEMENTED();
- return NULL;
+ LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall);
+ result->set_out(Location::RegisterLocation(R0));
+ return result;
}
@@ -39,13 +44,43 @@
LocationSummary* ReturnInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* locs =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+ locs->set_in(0, Location::RegisterLocation(R0));
+ return locs;
}
+// Attempt optimized compilation at return instruction instead of at the entry.
+// The entry needs to be patchable, no inlined objects are allowed in the area
+// that will be overwritten by the patch instructions: a branch macro sequence.
void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Register result = locs()->in(0).reg();
+ ASSERT(result == R0);
+#if defined(DEBUG)
+ // TODO(srdjan): Fix for functions with finally clause.
+ // A finally clause may leave a previously pushed return value if it
+ // has its own return instruction. Method that have finally are currently
+ // not optimized.
+ if (!compiler->HasFinally()) {
+ __ sub(R2, FP, ShifterOperand(SP));
+ // + 1 for saved PP.
+ __ CompareImmediate(R2, (compiler->StackSize() + 1) * kWordSize);
+ __ bkpt(0, NE);
+ }
+#endif
+ AssemblerMacros::LeaveDartFrame(compiler->assembler());
+ __ Ret();
+
+ // Generate 2 NOP instructions so that the debugger can patch the return
+ // pattern (1 instruction) with a call to the debug stub (3 instructions).
+ __ nop();
+ __ nop();
+ compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
+ Isolate::kNoDeoptId,
+ token_pos());
}
@@ -78,13 +113,18 @@
LocationSummary* ConstantInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ return LocationSummary::Make(0,
+ Location::RequiresRegister(),
+ LocationSummary::kNoCall);
}
void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ // The register allocator drops constant definitions that have no uses.
+ if (!locs()->out().IsInvalid()) {
+ Register result = locs()->out().reg();
+ __ LoadObject(result, value());
+ }
}
@@ -364,13 +404,52 @@
LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 0;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs,
+ kNumTemps,
+ LocationSummary::kCallOnSlowPath);
+ return summary;
}
+class CheckStackOverflowSlowPath : public SlowPathCode {
+ public:
+ explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction)
+ : instruction_(instruction) { }
+
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Comment("CheckStackOverflowSlowPath");
+ __ Bind(entry_label());
+ compiler->SaveLiveRegisters(instruction_->locs());
+ // pending_deoptimization_env_ is needed to generate a runtime call that
+ // may throw an exception.
+ ASSERT(compiler->pending_deoptimization_env_ == NULL);
+ compiler->pending_deoptimization_env_ = instruction_->env();
+ compiler->GenerateCallRuntime(instruction_->token_pos(),
+ instruction_->deopt_id(),
+ kStackOverflowRuntimeEntry,
+ instruction_->locs());
+ compiler->pending_deoptimization_env_ = NULL;
+ compiler->RestoreLiveRegisters(instruction_->locs());
+ __ b(exit_label());
+ }
+
+ private:
+ CheckStackOverflowInstr* instruction_;
+};
+
+
void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
+ compiler->AddSlowPathCode(slow_path);
+
+ __ LoadImmediate(IP, Isolate::Current()->stack_limit_address());
+ __ ldr(IP, Address(IP));
+ __ cmp(SP, ShifterOperand(IP));
+ __ b(slow_path->entry_label(), LS);
+ __ Bind(slow_path->exit_label());
}
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 50a4972..776f6dc 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -2714,15 +2714,11 @@
LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps =
- (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0;
+ const intptr_t kNumTemps = 0;
LocationSummary* result =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
result->set_in(0, Location::RequiresFpuRegister());
result->set_out(Location::RequiresFpuRegister());
- if (recognized_kind() == MethodRecognizer::kDoubleRound) {
- result->set_temp(0, Location::RequiresFpuRegister());
- }
return result;
}
@@ -2740,11 +2736,6 @@
case MethodRecognizer::kDoubleCeil:
__ roundsd(result, value, Assembler::kRoundUp);
break;
- case MethodRecognizer::kDoubleRound: {
- XmmRegister temp = locs()->temp(0).fpu_reg();
- __ DoubleRound(result, value, temp);
- break;
- }
default:
UNREACHABLE();
}
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 7b8f669..7d023f8 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -2561,15 +2561,11 @@
LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps =
- (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0;
+ const intptr_t kNumTemps = 0;
LocationSummary* result =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
result->set_in(0, Location::RequiresFpuRegister());
result->set_out(Location::RequiresFpuRegister());
- if (recognized_kind() == MethodRecognizer::kDoubleRound) {
- result->set_temp(0, Location::RequiresFpuRegister());
- }
return result;
}
@@ -2587,11 +2583,6 @@
case MethodRecognizer::kDoubleCeil:
__ roundsd(result, value, Assembler::kRoundUp);
break;
- case MethodRecognizer::kDoubleRound: {
- XmmRegister temp = locs()->temp(0).fpu_reg();
- __ DoubleRound(result, value, temp);
- break;
- }
default:
UNREACHABLE();
}
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 379c6c1..16b3893 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -60,7 +60,7 @@
V(_Double, _mulFromInteger, Double_mulFromInteger, 815838159) \
V(_Double, .fromInteger, Double_fromInteger, 842078193) \
V(_Double, toInt, Double_toInt, 362666636) \
- V(_ObjectArray, ., ObjectArray_Allocate, 577949617) \
+ V(_ObjectArray, ., ObjectArray_Allocate, 97987288) \
V(_ObjectArray, get:length, Array_getLength, 405297088) \
V(_ObjectArray, [], Array_getIndexed, 71937385) \
V(_ObjectArray, []=, Array_setIndexed, 255863719) \
@@ -78,7 +78,8 @@
V(_StringBase, get:hashCode, String_getHashCode, 320803993) \
V(_StringBase, get:isEmpty, String_getIsEmpty, 711547329) \
V(_StringBase, get:length, String_getLength, 320803993) \
- V(_StringBase, charCodeAt, String_charCodeAt, 984449525) \
+ V(_StringBase, codeUnitAt, String_codeUnitAt, 984449525) \
+ V(_OneByteString, get:hashCode, OneByteString_getHashCode, 682660413) \
#define MATH_LIB_INTRINSIC_LIST(V) \
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index c2b7c2b..2905a38 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -374,7 +374,7 @@
}
-bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
+bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
return false;
}
@@ -383,6 +383,11 @@
return false;
}
+
+bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
+ return false;
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 7bd0c89..c25075d 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -1435,7 +1435,7 @@
// TODO(srdjan): Implement for two and four byte strings as well.
-bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
+bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
Label fall_through;
__ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index.
__ movl(EAX, Address(ESP, + 2 * kWordSize)); // String.
@@ -1471,6 +1471,76 @@
return true;
}
+
+bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
+ Label compute_hash;
+ __ movl(EBX, Address(ESP, + 1 * kWordSize)); // OneByteString object.
+ __ movl(EAX, FieldAddress(EBX, String::hash_offset()));
+ __ cmpl(EAX, Immediate(0));
+ __ j(EQUAL, &compute_hash, Assembler::kNearJump);
+ __ ret();
+
+ __ Bind(&compute_hash);
+ // Hash not yet computed, use algorithm of class StringHasher.
+ __ movl(ECX, FieldAddress(EBX, String::length_offset()));
+ __ SmiUntag(ECX);
+ __ xorl(EAX, EAX);
+ __ xorl(EDI, EDI);
+ // EBX: Instance of OneByteString.
+ // ECX: String length, untagged integer.
+ // EDI: Loop counter, untagged integer.
+ // EAX: Hash code, untagged integer.
+ Label loop, done, set_hash_code;
+ __ Bind(&loop);
+ __ cmpl(EDI, ECX);
+ __ j(EQUAL, &done, Assembler::kNearJump);
+ // Add to hash code: (hash_ is uint32)
+ // hash_ += ch;
+ // hash_ += hash_ << 10;
+ // hash_ ^= hash_ >> 6;
+ // Get one characters (ch).
+ __ movzxb(EDX, FieldAddress(EBX, EDI, TIMES_1, OneByteString::data_offset()));
+ // EDX: ch and temporary.
+ __ addl(EAX, EDX);
+ __ movl(EDX, EAX);
+ __ shll(EDX, Immediate(10));
+ __ addl(EAX, EDX);
+ __ movl(EDX, EAX);
+ __ shrl(EDX, Immediate(6));
+ __ xorl(EAX, EDX);
+
+ __ incl(EDI);
+ __ jmp(&loop, Assembler::kNearJump);
+
+ __ Bind(&done);
+ // Finalize:
+ // hash_ += hash_ << 3;
+ // hash_ ^= hash_ >> 11;
+ // hash_ += hash_ << 15;
+ __ movl(EDX, EAX);
+ __ shll(EDX, Immediate(3));
+ __ addl(EAX, EDX);
+ __ movl(EDX, EAX);
+ __ shrl(EDX, Immediate(11));
+ __ xorl(EAX, EDX);
+ __ movl(EDX, EAX);
+ __ shll(EDX, Immediate(15));
+ __ addl(EAX, EDX);
+ // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
+ __ andl(EAX,
+ Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1)));
+
+ // return hash_ == 0 ? 1 : hash_;
+ __ cmpl(EAX, Immediate(0));
+ __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump);
+ __ incl(EAX);
+ __ Bind(&set_hash_code);
+ __ SmiTag(EAX);
+ __ movl(FieldAddress(EBX, String::hash_offset()), EAX);
+ __ ret();
+ return true;
+}
+
#undef __
} // namespace dart
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 70540a6..08a298c 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -374,7 +374,7 @@
}
-bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
+bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
return false;
}
@@ -383,6 +383,11 @@
return false;
}
+
+bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
+ return false;
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_MIPS
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 694c384..b72beb0 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -1358,7 +1358,7 @@
// TODO(srdjan): Implement for two and four byte strings as well.
-bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
+bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
Label fall_through;
__ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index.
__ movq(RAX, Address(RSP, + 2 * kWordSize)); // String.
@@ -1394,6 +1394,77 @@
return true;
}
+
+bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
+ Label compute_hash;
+ __ movq(RBX, Address(RSP, + 1 * kWordSize)); // OneByteString object.
+ __ movq(RAX, FieldAddress(RBX, String::hash_offset()));
+ __ cmpq(RAX, Immediate(0));
+ __ j(EQUAL, &compute_hash, Assembler::kNearJump);
+ __ ret();
+
+ __ Bind(&compute_hash);
+ // Hash not yet computed, use algorithm of class StringHasher.
+ __ movq(RCX, FieldAddress(RBX, String::length_offset()));
+ __ SmiUntag(RCX);
+ __ xorq(RAX, RAX);
+ __ xorq(RDI, RDI);
+ // RBX: Instance of OneByteString.
+ // RCX: String length, untagged integer.
+ // RDI: Loop counter, untagged integer.
+ // RAX: Hash code, untagged integer.
+ Label loop, done, set_hash_code;
+ __ Bind(&loop);
+ __ cmpq(RDI, RCX);
+ __ j(EQUAL, &done, Assembler::kNearJump);
+ // Add to hash code: (hash_ is uint32)
+ // hash_ += ch;
+ // hash_ += hash_ << 10;
+ // hash_ ^= hash_ >> 6;
+ // Get one characters (ch).
+ __ movzxb(RDX, FieldAddress(RBX, RDI, TIMES_1, OneByteString::data_offset()));
+ // RDX: ch and temporary.
+ __ addl(RAX, RDX);
+ __ movq(RDX, RAX);
+ __ shll(RDX, Immediate(10));
+ __ addl(RAX, RDX);
+ __ movq(RDX, RAX);
+ __ shrl(RDX, Immediate(6));
+ __ xorl(RAX, RDX);
+
+ __ incq(RDI);
+ __ jmp(&loop, Assembler::kNearJump);
+
+ __ Bind(&done);
+ // Finalize:
+ // hash_ += hash_ << 3;
+ // hash_ ^= hash_ >> 11;
+ // hash_ += hash_ << 15;
+ __ movq(RDX, RAX);
+ __ shll(RDX, Immediate(3));
+ __ addl(RAX, RDX);
+ __ movq(RDX, RAX);
+ __ shrl(RDX, Immediate(11));
+ __ xorl(RAX, RDX);
+ __ movq(RDX, RAX);
+ __ shll(RDX, Immediate(15));
+ __ addl(RAX, RDX);
+ // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
+ __ andl(RAX,
+ Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1)));
+
+ // return hash_ == 0 ? 1 : hash_;
+ __ cmpq(RAX, Immediate(0));
+ __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump);
+ __ incq(RAX);
+ __ Bind(&set_hash_code);
+ __ SmiTag(RAX);
+ __ movq(FieldAddress(RBX, String::hash_offset()), RAX);
+ __ ret();
+ return true;
+}
+
+
#undef __
} // namespace dart
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 06ca69e..31e909b 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -191,8 +191,8 @@
const Array& callback_args = Array::Handle(Array::New(1));
callback_args.SetAt(0, exception);
const Object& result =
- Object::Handle(DartEntry::InvokeStatic(Function::Cast(function),
- callback_args));
+ Object::Handle(DartEntry::InvokeFunction(Function::Cast(function),
+ callback_args));
if (result.IsError()) {
const Error& err = Error::Cast(result);
OS::PrintErr("failed calling unhandled exception callback: %s\n",
@@ -388,6 +388,13 @@
void Isolate::SetStackLimitFromCurrentTOS(uword stack_top_value) {
+#ifdef USING_SIMULATOR
+ // Ignore passed-in native stack top and use Simulator stack top.
+ Simulator* sim = Simulator::Current(); // May allocate a simulator.
+ ASSERT(simulator() == sim); // This isolate's simulator is the current one.
+ stack_top_value = sim->StackTop();
+ // The overflow area is accounted for by the simulator.
+#endif
SetStackLimit(stack_top_value - GetSpecifiedStackSize());
}
@@ -627,4 +634,61 @@
}
}
+
+char* Isolate::GetStatus(const char* request) {
+ char* p = const_cast<char*>(request);
+ const char* service_type = "/isolate/";
+ ASSERT(strncmp(p, service_type, strlen(service_type)) == 0);
+ p += strlen(service_type);
+
+ // Extract isolate handle.
+ int64_t addr;
+ OS::StringToInt64(p, &addr);
+ Isolate* isolate = reinterpret_cast<Isolate*>(addr);
+ Heap* heap = isolate->heap();
+
+ char buffer[256];
+ int64_t port = isolate->main_port();
+ int64_t start_time = (isolate->start_time() / 1000L);
+#if defined(TARGET_ARCH_X64)
+ const char* format = "{\n"
+ " \"name\": \"%s\",\n"
+ " \"port\": %ld,\n"
+ " \"starttime\": %ld,\n"
+ " \"stacklimit\": %ld,\n"
+ " \"newspace\": {\n"
+ " \"used\": %ld,\n"
+ " \"capacity\": %ld\n"
+ " },\n"
+ " \"oldspace\": {\n"
+ " \"used\": %ld,\n"
+ " \"capacity\": %ld\n"
+ " }\n"
+ "}";
+#else
+ const char* format = "{\n"
+ " \"name\": \"%s\",\n"
+ " \"port\": %lld,\n"
+ " \"starttime\": %lld,\n"
+ " \"stacklimit\": %d,\n"
+ " \"newspace\": {\n"
+ " \"used\": %d,\n"
+ " \"capacity\": %d\n"
+ " },\n"
+ " \"oldspace\": {\n"
+ " \"used\": %d,\n"
+ " \"capacity\": %d\n"
+ " }\n"
+ "}";
+#endif
+ int n = OS::SNPrint(buffer, 256, format, isolate->name(), port, start_time,
+ isolate->saved_stack_limit(),
+ heap->Used(Heap::kNew) / KB,
+ heap->Capacity(Heap::kNew) / KB,
+ heap->Used(Heap::kOld) / KB,
+ heap->Capacity(Heap::kOld) / KB);
+ ASSERT(n < 256);
+ return strdup(buffer);
+}
+
} // namespace dart
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index b8f03b5..2e6735f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -344,6 +344,8 @@
return list;
}
+ static char* GetStatus(const char* request);
+
private:
Isolate();
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index f8b7f6c..6a8dda8 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -366,15 +366,15 @@
}
}
- bool ContainsRegister(Register reg) {
+ bool ContainsRegister(Register reg) const {
return (cpu_registers_ & (1 << reg)) != 0;
}
- bool ContainsFpuRegister(FpuRegister fpu_reg) {
+ bool ContainsFpuRegister(FpuRegister fpu_reg) const {
return (fpu_registers_ & (1 << fpu_reg)) != 0;
}
- intptr_t fpu_regs_count() {
+ intptr_t fpu_regs_count() const {
intptr_t count = 0;
for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; reg_idx++) {
if (ContainsFpuRegister(static_cast<FpuRegister>(reg_idx))) {
@@ -384,6 +384,9 @@
return count;
}
+ intptr_t cpu_registers() const { return cpu_registers_; }
+ intptr_t fpu_registers() const { return fpu_registers_; }
+
private:
intptr_t cpu_registers_;
intptr_t fpu_registers_;
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index de192a2..1027e3f 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -7,6 +7,7 @@
#include "platform/assert.h"
#include "vm/globals.h"
+#include "vm/simulator.h"
#include "vm/stub_code.h"
namespace dart {
@@ -21,7 +22,13 @@
#if defined(TESTING) || defined(DEBUG)
-#if defined(TARGET_OS_WINDOWS)
+#if defined(USING_SIMULATOR)
+#define CHECK_STACK_ALIGNMENT { \
+ uword current_sp = Simulator::Current()->get_register(SPREG); \
+ ASSERT((OS::ActivationFrameAlignment() == 0) || \
+ (Utils::IsAligned(current_sp, OS::ActivationFrameAlignment()))); \
+}
+#elif defined(TARGET_OS_WINDOWS)
// The compiler may dynamically align the stack on Windows, so do not check.
#define CHECK_STACK_ALIGNMENT { }
#else
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b2dba5a..5bceca2 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -125,7 +125,7 @@
// (Library, class name, method name)
#define INVISIBLE_LIST(V) \
V(CoreLibrary, Object, _noSuchMethod) \
- V(CoreLibrary, List, _throwArgumentError) \
+ V(CoreLibrary, _ObjectArray, _ObjectArray.) \
V(CoreLibrary, AssertionErrorImplementation, _throwNew) \
V(CoreLibrary, TypeErrorImplementation, _throwNew) \
V(CoreLibrary, FallThroughErrorImplementation, _throwNew) \
@@ -133,6 +133,7 @@
V(CoreLibrary, NoSuchMethodError, _throwNew) \
V(CoreLibrary, int, _throwFormatException) \
V(CoreLibrary, int, _parse) \
+ V(CoreLibrary, StackTrace, _setupFullStackTrace) \
static void MarkFunctionAsInvisible(const Library& lib,
@@ -140,7 +141,7 @@
const char* function_name) {
ASSERT(!lib.IsNull());
const Class& cls = Class::Handle(
- lib.LookupClass(String::Handle(String::New(class_name))));
+ lib.LookupClassAllowPrivate(String::Handle(String::New(class_name))));
ASSERT(!cls.IsNull());
const Function& function =
Function::Handle(
@@ -631,15 +632,30 @@
lib.AddClass(cls);
}
-#define INIT_LIBRARY(name, raw_script, raw_lib) \
- script ^= raw_script; \
- Library::Init##name##Library(isolate); \
- lib ^= raw_lib; \
- ASSERT(!lib.IsNull()); \
+
+#define LOAD_LIBRARY(name, raw_name) \
+ url = Symbols::Dart##name().raw(); \
+ lib = Library::LookupLibrary(url); \
+ if (lib.IsNull()) { \
+ lib = Library::NewLibraryHelper(url, true); \
+ lib.Register(); \
+ } \
+ isolate->object_store()->set_##raw_name##_library(lib); \
+
+#define INIT_LIBRARY(name, raw_name, has_patch) \
+ LOAD_LIBRARY(name, raw_name) \
+ script = Bootstrap::Load##name##Script(false); \
error = Bootstrap::Compile(lib, script); \
if (!error.IsNull()) { \
return error.raw(); \
} \
+ if (has_patch) { \
+ script = Bootstrap::Load##name##Script(true); \
+ error = lib.Patch(script); \
+ if (!error.IsNull()) { \
+ return error.raw(); \
+ } \
+ } \
RawError* Object::Init(Isolate* isolate) {
@@ -649,6 +665,10 @@
Class& cls = Class::Handle();
Type& type = Type::Handle();
Array& array = Array::Handle();
+ String& url = String::Handle();
+ Library& lib = Library::Handle();
+ Script& script = Script::Handle();
+ Error& error = Error::Handle();
// All RawArray fields will be initialized to an empty array, therefore
// initialize array class first.
@@ -698,8 +718,10 @@
GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld));
object_store->set_libraries(libraries);
- // Basic infrastructure has been setup, initialize the class dictionary.
+ // Pre-register the core library.
Library::InitCoreLibrary(isolate);
+
+ // Basic infrastructure has been setup, initialize the class dictionary.
Library& core_lib = Library::Handle(Library::CoreLibrary());
ASSERT(!core_lib.IsNull());
@@ -726,7 +748,7 @@
type ^= Type::New(Object::Handle(cls.raw()),
TypeArguments::Handle(),
Scanner::kDummyTokenIndex);
- type.set_is_finalized_instantiated();
+ type.SetIsFinalized();
type ^= type.Canonicalize();
object_store->set_array_type(type);
@@ -761,7 +783,7 @@
cls = Class::New<Stacktrace>();
object_store->set_stacktrace_class(cls);
- RegisterClass(cls, Symbols::Stacktrace(), core_lib);
+ RegisterClass(cls, Symbols::StackTrace(), core_lib);
pending_classes.Add(cls, Heap::kOld);
// Super type set below, after Object is allocated.
@@ -771,7 +793,7 @@
pending_classes.Add(cls, Heap::kOld);
// Initialize the base interfaces used by the core VM classes.
- Script& script = Script::Handle(Bootstrap::LoadCoreScript(false));
+ script = Bootstrap::LoadCoreScript(false);
// Allocate and initialize the pre-allocated classes in the core library.
cls = Class::New<Instance>(kInstanceCid);
@@ -821,8 +843,25 @@
object_store->set_weak_property_class(cls);
RegisterPrivateClass(cls, Symbols::_WeakProperty(), core_lib);
- Library::InitScalarlistLibrary(isolate);
+ // Setup some default native field classes which can be extended for
+ // specifying native fields in dart classes.
+ Library::InitNativeWrappersLibrary(isolate);
+ ASSERT(isolate->object_store()->native_wrappers_library() != Library::null());
+
+ // Pre-register the scalarlist library so the native class implementations
+ // can be hooked up before compiling it.
+ LOAD_LIBRARY(Scalarlist, scalarlist);
+
Library& scalarlist_lib = Library::Handle(Library::ScalarlistLibrary());
+ ASSERT(!scalarlist_lib.IsNull());
+
+ cls = Class::New<Float32x4>();
+ object_store->set_float32x4_class(cls);
+ RegisterPrivateClass(cls, Symbols::_Float32x4(), scalarlist_lib);
+
+ cls = Class::New<Uint32x4>();
+ object_store->set_uint32x4_class(cls);
+ RegisterPrivateClass(cls, Symbols::_Uint32x4(), scalarlist_lib);
cls = Class::New<Int8Array>();
object_store->set_int8_array_class(cls);
@@ -860,6 +899,10 @@
object_store->set_uint64_array_class(cls);
RegisterPrivateClass(cls, Symbols::_Uint64Array(), scalarlist_lib);
+ cls = Class::New<Float32x4Array>();
+ object_store->set_float32x4_array_class(cls);
+ RegisterPrivateClass(cls, Symbols::_Float32x4Array(), scalarlist_lib);
+
cls = Class::New<Float32Array>();
object_store->set_float32_array_class(cls);
RegisterPrivateClass(cls, Symbols::_Float32Array(), scalarlist_lib);
@@ -906,6 +949,11 @@
object_store->set_external_uint64_array_class(cls);
RegisterPrivateClass(cls, Symbols::_ExternalUint64Array(), scalarlist_lib);
+ cls = Class::New<ExternalFloat32x4Array>();
+ object_store->set_external_float32x4_array_class(cls);
+ RegisterPrivateClass(cls, Symbols::_ExternalFloat32x4Array(),
+ scalarlist_lib);
+
cls = Class::New<ExternalFloat32Array>();
object_store->set_external_float32_array_class(cls);
RegisterPrivateClass(cls, Symbols::_ExternalFloat32Array(), scalarlist_lib);
@@ -993,120 +1041,22 @@
type = Type::NewNonParameterizedType(cls);
object_store->set_dynamic_type(type);
- // Setup some default native field classes which can be extended for
- // specifying native fields in dart classes.
- Library::InitNativeWrappersLibrary(isolate);
- ASSERT(isolate->object_store()->native_wrappers_library() != Library::null());
-
// Finish the initialization by compiling the bootstrap scripts containing the
// base interfaces and the implementation of the internal classes.
- Error& error = Error::Handle();
- error = Bootstrap::Compile(core_lib, script);
- if (!error.IsNull()) {
- return error.raw();
- }
- Script& patch_script = Script::Handle(Bootstrap::LoadCoreScript(true));
- error = core_lib.Patch(patch_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- Library::InitASyncLibrary(isolate);
- const Script& async_script =
- Script::Handle(Bootstrap::LoadASyncScript(false));
- const Library& async_lib = Library::Handle(Library::ASyncLibrary());
- ASSERT(!async_lib.IsNull());
- error = Bootstrap::Compile(async_lib, async_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- patch_script = Bootstrap::LoadASyncScript(true);
- error = async_lib.Patch(patch_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- const Script& collection_script =
- Script::Handle(Bootstrap::LoadCollectionScript(false));
- const Library& collection_lib =
- Library::Handle(Library::CollectionLibrary());
- ASSERT(!collection_lib.IsNull());
- error = Bootstrap::Compile(collection_lib, collection_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- const Script& collection_dev_script =
- Script::Handle(Bootstrap::LoadCollectionDevScript(false));
- const Library& collection_dev_lib =
- Library::Handle(Library::CollectionDevLibrary());
- ASSERT(!collection_dev_lib.IsNull());
- error = Bootstrap::Compile(collection_dev_lib, collection_dev_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- const Script& math_script = Script::Handle(Bootstrap::LoadMathScript(false));
- const Library& math_lib = Library::Handle(Library::MathLibrary());
- ASSERT(!math_lib.IsNull());
- error = Bootstrap::Compile(math_lib, math_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- patch_script = Bootstrap::LoadMathScript(true);
- error = math_lib.Patch(patch_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- const Script& isolate_script = Script::Handle(
- Bootstrap::LoadIsolateScript(false));
- Library::InitIsolateLibrary(isolate);
- const Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
- ASSERT(!isolate_lib.IsNull());
- error = Bootstrap::Compile(isolate_lib, isolate_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- patch_script = Bootstrap::LoadIsolateScript(true);
- error = isolate_lib.Patch(patch_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- const Script& mirrors_script = Script::Handle(
- Bootstrap::LoadMirrorsScript(false));
- Library::InitMirrorsLibrary(isolate);
- const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary());
- ASSERT(!mirrors_lib.IsNull());
- error = Bootstrap::Compile(mirrors_lib, mirrors_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- patch_script = Bootstrap::LoadMirrorsScript(true);
- error = mirrors_lib.Patch(patch_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- const Script& scalarlist_script = Script::Handle(
- Bootstrap::LoadScalarlistScript(false));
- ASSERT(!scalarlist_lib.IsNull());
- error = Bootstrap::Compile(scalarlist_lib, scalarlist_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- patch_script = Bootstrap::LoadScalarlistScript(true);
- error = scalarlist_lib.Patch(patch_script);
- if (!error.IsNull()) {
- return error.raw();
- }
- Library& lib = Library::Handle();
- INIT_LIBRARY(Crypto,
- Bootstrap::LoadCryptoScript(false),
- Library::CryptoLibrary());
- INIT_LIBRARY(Json,
- Bootstrap::LoadJsonScript(false),
- Library::JsonLibrary());
- INIT_LIBRARY(Utf,
- Bootstrap::LoadUtfScript(false),
- Library::UtfLibrary());
- INIT_LIBRARY(Uri,
- Bootstrap::LoadUriScript(false),
- Library::UriLibrary());
+ INIT_LIBRARY(Core, core, true);
+
+ INIT_LIBRARY(Async, async, true);
+ INIT_LIBRARY(Collection, collection, false);
+ INIT_LIBRARY(CollectionDev, collection_dev, false);
+ INIT_LIBRARY(Crypto, crypto, false);
+ INIT_LIBRARY(Isolate, isolate, true);
+ INIT_LIBRARY(Json, json, true);
+ INIT_LIBRARY(Math, math, true);
+ INIT_LIBRARY(Mirrors, mirrors, true);
+ INIT_LIBRARY(Scalarlist, scalarlist, true);
+ INIT_LIBRARY(Utf, utf, false);
+ INIT_LIBRARY(Uri, uri, false);
+
Bootstrap::SetupNativeResolver();
// Remove the Object superclass cycle by setting the super type to null (not
@@ -1151,6 +1101,12 @@
cls = Class::New<GrowableObjectArray>();
object_store->set_growable_object_array_class(cls);
+ cls = Class::New<Float32x4>();
+ object_store->set_float32x4_class(cls);
+
+ cls = Class::New<Uint32x4>();
+ object_store->set_uint32x4_class(cls);
+
cls = Class::New<Int8Array>();
object_store->set_int8_array_class(cls);
@@ -1178,6 +1134,9 @@
cls = Class::New<Uint64Array>();
object_store->set_uint64_array_class(cls);
+ cls = Class::New<Float32x4Array>();
+ object_store->set_float32x4_array_class(cls);
+
cls = Class::New<Float32Array>();
object_store->set_float32_array_class(cls);
@@ -1211,6 +1170,9 @@
cls = Class::New<ExternalUint64Array>();
object_store->set_external_uint64_array_class(cls);
+ cls = Class::New<ExternalFloat32x4Array>();
+ object_store->set_external_float32x4_array_class(cls);
+
cls = Class::New<ExternalFloat32Array>();
object_store->set_external_float32_array_class(cls);
@@ -1413,6 +1375,10 @@
case kImmutableArrayCid:
case kGrowableObjectArrayCid:
return Symbols::List().raw();
+ case kFloat32x4Cid:
+ return Symbols::Float32x4().raw();
+ case kUint32x4Cid:
+ return Symbols::Uint32x4().raw();
case kInt8ArrayCid:
case kExternalInt8ArrayCid:
return Symbols::Int8List().raw();
@@ -1440,6 +1406,9 @@
case kUint64ArrayCid:
case kExternalUint64ArrayCid:
return Symbols::Uint64List().raw();
+ case kFloat32x4ArrayCid:
+ case kExternalFloat32x4ArrayCid:
+ return Symbols::Float32x4List().raw();
case kFloat32ArrayCid:
case kExternalFloat32ArrayCid:
return Symbols::Float32List().raw();
@@ -6340,37 +6309,12 @@
}
-void Library::InitASyncLibrary(Isolate* isolate) {
- const String& url = Symbols::DartAsync();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- isolate->object_store()->set_async_library(lib);
-}
-
-
void Library::InitCoreLibrary(Isolate* isolate) {
const String& core_lib_url = Symbols::DartCore();
const Library& core_lib =
Library::Handle(Library::NewLibraryHelper(core_lib_url, false));
core_lib.Register();
isolate->object_store()->set_core_library(core_lib);
- Library::InitMathLibrary(isolate);
- const Library& math_lib = Library::Handle(Library::MathLibrary());
- const Namespace& math_ns = Namespace::Handle(
- Namespace::New(math_lib, Array::Handle(), Array::Handle()));
- Library::InitCollectionDevLibrary(isolate);
- const Library& collection_dev_lib =
- Library::Handle(Library::CollectionDevLibrary());
- const Namespace& collection_dev_ns = Namespace::Handle(
- Namespace::New(collection_dev_lib, Array::Handle(), Array::Handle()));
- Library::InitCollectionLibrary(isolate);
- const Library& collection_lib =
- Library::Handle(Library::CollectionLibrary());
- const Namespace& collection_ns = Namespace::Handle(
- Namespace::New(collection_lib, Array::Handle(), Array::Handle()));
- core_lib.AddImport(math_ns);
- core_lib.AddImport(collection_ns);
- core_lib.AddImport(collection_dev_ns);
isolate->object_store()->set_root_library(Library::Handle());
// Hook up predefined classes without setting their library pointers. These
@@ -6381,92 +6325,6 @@
}
-void Library::InitCollectionLibrary(Isolate* isolate) {
- const String& url = Symbols::DartCollection();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- const Library& math_lib = Library::Handle(Library::MathLibrary());
- const Namespace& math_ns = Namespace::Handle(
- Namespace::New(math_lib, Array::Handle(), Array::Handle()));
- const Library& collection_dev_lib =
- Library::Handle(Library::CollectionDevLibrary());
- const Namespace& collection_dev_ns = Namespace::Handle(
- Namespace::New(collection_dev_lib, Array::Handle(), Array::Handle()));
- lib.AddImport(math_ns);
- lib.AddImport(collection_dev_ns);
- isolate->object_store()->set_collection_library(lib);
-}
-
-
-void Library::InitCollectionDevLibrary(Isolate* isolate) {
- const String& url = Symbols::DartCollectionDev();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- isolate->object_store()->set_collection_dev_library(lib);
-}
-
-
-void Library::InitCryptoLibrary(Isolate* isolate) {
- const String& url = Symbols::DartCrypto();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- const Library& math_lib = Library::Handle(Library::MathLibrary());
- const Namespace& math_ns = Namespace::Handle(
- Namespace::New(math_lib, Array::Handle(), Array::Handle()));
- lib.AddImport(math_ns);
- isolate->object_store()->set_crypto_library(lib);
-}
-
-
-void Library::InitIsolateLibrary(Isolate* isolate) {
- const String& url = Symbols::DartIsolate();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- const Library& async_lib = Library::Handle(Library::ASyncLibrary());
- const Namespace& async_ns = Namespace::Handle(
- Namespace::New(async_lib, Array::Handle(), Array::Handle()));
- lib.AddImport(async_ns);
- isolate->object_store()->set_isolate_library(lib);
-}
-
-
-void Library::InitJsonLibrary(Isolate* isolate) {
- const String& url = Symbols::DartJson();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- isolate->object_store()->set_json_library(lib);
-}
-
-
-void Library::InitMathLibrary(Isolate* isolate) {
- const String& url = Symbols::DartMath();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- isolate->object_store()->set_math_library(lib);
-}
-
-
-void Library::InitMirrorsLibrary(Isolate* isolate) {
- const String& url = Symbols::DartMirrors();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- const Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
- const Namespace& isolate_ns = Namespace::Handle(
- Namespace::New(isolate_lib, Array::Handle(), Array::Handle()));
- lib.AddImport(isolate_ns);
- const Library& async_lib = Library::Handle(Library::ASyncLibrary());
- const Namespace& async_ns = Namespace::Handle(
- Namespace::New(async_lib, Array::Handle(), Array::Handle()));
- lib.AddImport(async_ns);
- const Library& wrappers_lib =
- Library::Handle(Library::NativeWrappersLibrary());
- const Namespace& wrappers_ns = Namespace::Handle(
- Namespace::New(wrappers_lib, Array::Handle(), Array::Handle()));
- lib.AddImport(wrappers_ns);
- isolate->object_store()->set_mirrors_library(lib);
-}
-
-
void Library::InitNativeWrappersLibrary(Isolate* isolate) {
static const int kNumNativeWrappersClasses = 4;
ASSERT(kNumNativeWrappersClasses > 0 && kNumNativeWrappersClasses < 10);
@@ -6492,47 +6350,6 @@
}
-void Library::InitScalarlistLibrary(Isolate* isolate) {
- const String& url = Symbols::DartScalarlist();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- const Library& collection_lib =
- Library::Handle(Library::CollectionLibrary());
- const Namespace& collection_ns = Namespace::Handle(
- Namespace::New(collection_lib, Array::Handle(), Array::Handle()));
- lib.AddImport(collection_ns);
- isolate->object_store()->set_scalarlist_library(lib);
-}
-
-
-void Library::InitUriLibrary(Isolate* isolate) {
- const String& url = Symbols::DartUri();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- const Library& math_lib = Library::Handle(Library::MathLibrary());
- const Namespace& math_ns = Namespace::Handle(
- Namespace::New(math_lib, Array::Handle(), Array::Handle()));
- const Library& utf_lib = Library::Handle(Library::UtfLibrary());
- const Namespace& utf_ns = Namespace::Handle(
- Namespace::New(utf_lib, Array::Handle(), Array::Handle()));
- lib.AddImport(math_ns);
- lib.AddImport(utf_ns);
- isolate->object_store()->set_uri_library(lib);
-}
-
-
-void Library::InitUtfLibrary(Isolate* isolate) {
- const String& url = Symbols::DartUtf();
- const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
- lib.Register();
- const Library& async_lib = Library::Handle(Library::ASyncLibrary());
- const Namespace& async_ns = Namespace::Handle(
- Namespace::New(async_lib, Array::Handle(), Array::Handle()));
- lib.AddImport(async_ns);
- isolate->object_store()->set_utf_library(lib);
-}
-
-
RawLibrary* Library::LookupLibrary(const String &url) {
Isolate* isolate = Isolate::Current();
Library& lib = Library::Handle(isolate, Library::null());
@@ -6626,7 +6443,7 @@
}
-RawLibrary* Library::ASyncLibrary() {
+RawLibrary* Library::AsyncLibrary() {
return Isolate::Current()->object_store()->async_library();
}
@@ -7263,8 +7080,38 @@
const char* LocalVarDescriptors::ToCString() const {
- UNIMPLEMENTED();
- return "LocalVarDescriptors";
+ intptr_t len = 1; // Trailing '\0'.
+ const char* kFormat =
+ "%2"Pd" kind=%d scope=0x%04x begin=%"Pd" end=%"Pd" name=%s\n";
+ for (intptr_t i = 0; i < Length(); i++) {
+ String& var_name = String::Handle(GetName(i));
+ RawLocalVarDescriptors::VarInfo info;
+ GetInfo(i, &info);
+ len += OS::SNPrint(NULL, 0, kFormat,
+ i,
+ info.kind,
+ info.scope_id,
+ info.begin_pos,
+ info.end_pos,
+ var_name.ToCString());
+ }
+ char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len);
+ intptr_t num_chars = 0;
+ for (intptr_t i = 0; i < Length(); i++) {
+ String& var_name = String::Handle(GetName(i));
+ RawLocalVarDescriptors::VarInfo info;
+ GetInfo(i, &info);
+ num_chars += OS::SNPrint((buffer + num_chars),
+ (len - num_chars),
+ kFormat,
+ i,
+ info.kind,
+ info.scope_id,
+ info.begin_pos,
+ info.end_pos,
+ var_name.ToCString());
+ }
+ return buffer;
}
@@ -8912,7 +8759,7 @@
}
const Type& type = Type::Handle(
Type::New(cls, type_arguments, Scanner::kDummyTokenIndex));
- type.set_is_finalized_instantiated();
+ type.SetIsFinalized();
return type.raw();
}
@@ -9475,21 +9322,19 @@
type ^= Type::New(Object::Handle(type_class.raw()),
no_type_arguments,
Scanner::kDummyTokenIndex);
- type.set_is_finalized_instantiated();
+ type.SetIsFinalized();
type ^= type.Canonicalize();
return type.raw();
}
-void Type::set_is_finalized_instantiated() const {
+void Type::SetIsFinalized() const {
ASSERT(!IsFinalized());
- set_type_state(RawType::kFinalizedInstantiated);
-}
-
-
-void Type::set_is_finalized_uninstantiated() const {
- ASSERT(!IsFinalized());
- set_type_state(RawType::kFinalizedUninstantiated);
+ if (IsInstantiated()) {
+ set_type_state(RawType::kFinalizedInstantiated);
+ } else {
+ set_type_state(RawType::kFinalizedUninstantiated);
+ }
}
@@ -9603,7 +9448,7 @@
Type::New(cls, type_arguments, token_pos()));
ASSERT(type_arguments.IsNull() ||
(type_arguments.Length() == cls.NumTypeArguments()));
- instantiated_type.set_is_finalized_instantiated();
+ instantiated_type.SetIsFinalized();
return instantiated_type.raw();
}
@@ -10655,6 +10500,7 @@
}
+// Synchronize with implementation in compiler (intrinsifier).
class StringHasher : ValueObject {
public:
StringHasher() : hash_(0) {}
@@ -10683,9 +10529,15 @@
ASSERT(len >= 0);
ASSERT((begin_index + len) <= str.Length());
StringHasher hasher;
- CodePointIterator it(str, begin_index, len);
- while (it.Next()) {
- hasher.Add(it.Current());
+ if (str.IsOneByteString()) {
+ for (intptr_t i = 0; i < len; i++) {
+ hasher.Add(*OneByteString::CharAddr(str, i + begin_index));
+ }
+ } else {
+ CodePointIterator it(str, begin_index, len);
+ while (it.Next()) {
+ hasher.Add(it.Current());
+ }
}
return hasher.Finalize(String::kHashBits);
}
@@ -10727,13 +10579,13 @@
ASSERT(RawObject::IsStringClassId(class_id));
NoGCScope no_gc;
if (class_id == kOneByteStringCid) {
- return *OneByteString::CharAddr(*this, index);
+ return *OneByteString::CharAddr(*this, index);
}
if (class_id == kTwoByteStringCid) {
- return *TwoByteString::CharAddr(*this, index);
+ return *TwoByteString::CharAddr(*this, index);
}
if (class_id == kExternalOneByteStringCid) {
- return *ExternalOneByteString::CharAddr(*this, index);
+ return *ExternalOneByteString::CharAddr(*this, index);
}
ASSERT(class_id == kExternalTwoByteStringCid);
return *ExternalTwoByteString::CharAddr(*this, index);
@@ -11206,7 +11058,30 @@
const char* String::ToCString() const {
- intptr_t len = Utf8::Length(*this);
+ if (IsOneByteString()) {
+ // Quick conversion if OneByteString contains only ASCII characters.
+ intptr_t len = Length();
+ if (len == 0) {
+ return "";
+ }
+ Zone* zone = Isolate::Current()->current_zone();
+ uint8_t* result = zone->Alloc<uint8_t>(len + 1);
+ NoGCScope no_gc;
+ const uint8_t* original_str = OneByteString::CharAddr(*this, 0);
+ for (intptr_t i = 0; i < len; i++) {
+ if (original_str[i] <= Utf8::kMaxOneByteChar) {
+ result[i] = original_str[i];
+ } else {
+ len = -1;
+ break;
+ }
+ }
+ if (len > 0) {
+ result[len] = 0;
+ return reinterpret_cast<const char*>(result);
+ }
+ }
+ const intptr_t len = Utf8::Length(*this);
Zone* zone = Isolate::Current()->current_zone();
uint8_t* result = zone->Alloc<uint8_t>(len + 1);
ToUTF8(result, len);
@@ -11508,17 +11383,16 @@
// This should be caught before we reach here.
FATAL1("Fatal error in OneByteString::New: invalid len %"Pd"\n", len);
}
- String& result = String::Handle();
{
RawObject* raw = Object::Allocate(OneByteString::kClassId,
OneByteString::InstanceSize(len),
space);
NoGCScope no_gc;
- result ^= raw;
- result.SetLength(len);
- result.SetHash(0);
+ RawOneByteString* result = reinterpret_cast<RawOneByteString*>(raw);
+ result->ptr()->length_ = Smi::New(len);
+ result->ptr()->hash_ = 0;
+ return result;
}
- return OneByteString::raw(result);
}
@@ -12149,6 +12023,206 @@
}
+RawFloat32x4* Float32x4::New(float v0, float v1, float v2, float v3,
+ Heap::Space space) {
+ ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
+ Class::null());
+ Float32x4& result = Float32x4::Handle();
+ {
+ RawObject* raw = Object::Allocate(Float32x4::kClassId,
+ Float32x4::InstanceSize(),
+ space);
+ NoGCScope no_gc;
+ result ^= raw;
+ }
+ result.set_x(v0);
+ result.set_y(v1);
+ result.set_z(v2);
+ result.set_w(v3);
+ return result.raw();
+}
+
+
+RawFloat32x4* Float32x4::New(simd_value_t value, Heap::Space space) {
+ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
+ Class::null());
+ Float32x4& result = Float32x4::Handle();
+ {
+ RawObject* raw = Object::Allocate(Float32x4::kClassId,
+ Float32x4::InstanceSize(),
+ space);
+ NoGCScope no_gc;
+ result ^= raw;
+ }
+ result.set_value(value);
+ return result.raw();
+}
+
+
+simd_value_t Float32x4::value() const {
+ return simd_value_safe_load(&raw_ptr()->value_[0]);
+}
+
+
+void Float32x4::set_value(simd_value_t value) const {
+ simd_value_safe_store(&raw_ptr()->value_[0], value);
+}
+
+
+void Float32x4::set_x(float value) const {
+ raw_ptr()->value_[0] = value;
+}
+
+
+void Float32x4::set_y(float value) const {
+ raw_ptr()->value_[1] = value;
+}
+
+
+void Float32x4::set_z(float value) const {
+ raw_ptr()->value_[2] = value;
+}
+
+
+void Float32x4::set_w(float value) const {
+ raw_ptr()->value_[3] = value;
+}
+
+
+float Float32x4::x() const {
+ return raw_ptr()->value_[0];
+}
+
+
+float Float32x4::y() const {
+ return raw_ptr()->value_[1];
+}
+
+
+float Float32x4::z() const {
+ return raw_ptr()->value_[2];
+}
+
+
+float Float32x4::w() const {
+ return raw_ptr()->value_[3];
+}
+
+
+const char* Float32x4::ToCString() const {
+ const char* kFormat = "[%f, %f, %f, %f]";
+ float _x = x();
+ float _y = y();
+ float _z = z();
+ float _w = w();
+ // Calculate the size of the string.
+ intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y, _z, _w) + 1;
+ char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+ OS::SNPrint(chars, len, kFormat, _x, _y, _z, _w);
+ return chars;
+}
+
+
+RawUint32x4* Uint32x4::New(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3,
+ Heap::Space space) {
+ ASSERT(Isolate::Current()->object_store()->uint32x4_class() !=
+ Class::null());
+ Uint32x4& result = Uint32x4::Handle();
+ {
+ RawObject* raw = Object::Allocate(Uint32x4::kClassId,
+ Uint32x4::InstanceSize(),
+ space);
+ NoGCScope no_gc;
+ result ^= raw;
+ }
+ result.set_x(v0);
+ result.set_y(v1);
+ result.set_z(v2);
+ result.set_w(v3);
+ return result.raw();
+}
+
+
+RawUint32x4* Uint32x4::New(simd_value_t value, Heap::Space space) {
+ ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
+ Class::null());
+ Uint32x4& result = Uint32x4::Handle();
+ {
+ RawObject* raw = Object::Allocate(Uint32x4::kClassId,
+ Uint32x4::InstanceSize(),
+ space);
+ NoGCScope no_gc;
+ result ^= raw;
+ }
+ result.set_value(value);
+ return result.raw();
+}
+
+
+void Uint32x4::set_x(uint32_t value) const {
+ raw_ptr()->value_[0] = value;
+}
+
+
+void Uint32x4::set_y(uint32_t value) const {
+ raw_ptr()->value_[1] = value;
+}
+
+
+void Uint32x4::set_z(uint32_t value) const {
+ raw_ptr()->value_[2] = value;
+}
+
+
+void Uint32x4::set_w(uint32_t value) const {
+ raw_ptr()->value_[3] = value;
+}
+
+
+uint32_t Uint32x4::x() const {
+ return raw_ptr()->value_[0];
+}
+
+
+uint32_t Uint32x4::y() const {
+ return raw_ptr()->value_[1];
+}
+
+
+uint32_t Uint32x4::z() const {
+ return raw_ptr()->value_[2];
+}
+
+
+uint32_t Uint32x4::w() const {
+ return raw_ptr()->value_[3];
+}
+
+
+simd_value_t Uint32x4::value() const {
+ return simd_value_safe_load(&raw_ptr()->value_[0]);
+}
+
+
+void Uint32x4::set_value(simd_value_t value) const {
+ simd_value_safe_store(&raw_ptr()->value_[0], value);
+}
+
+
+const char* Uint32x4::ToCString() const {
+ const char* kFormat = "[%08x, %08x, %08x, %08x]";
+ uint32_t _x = x();
+ uint32_t _y = y();
+ uint32_t _z = z();
+ uint32_t _w = w();
+ // Calculate the size of the string.
+ intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y, _z, _w) + 1;
+ char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+ OS::SNPrint(chars, len, kFormat, _x, _y, _z, _w);
+ return chars;
+}
+
+
void ByteArray::Copy(void* dst,
const ByteArray& src,
intptr_t src_offset,
@@ -12481,6 +12555,30 @@
}
+RawFloat32x4Array* Float32x4Array::New(intptr_t len,
+ Heap::Space space) {
+ ASSERT(Isolate::Current()->object_store()->float32x4_array_class() !=
+ Class::null());
+ return NewImpl<Float32x4Array, RawFloat32x4Array>(kClassId, len,
+ space);
+}
+
+
+RawFloat32x4Array* Float32x4Array::New(const simd_value_t* data,
+ intptr_t len,
+ Heap::Space space) {
+ ASSERT(Isolate::Current()->object_store()->float32_array_class() !=
+ Class::null());
+ return NewImpl<Float32x4Array, RawFloat32x4Array>(kClassId, data,
+ len, space);
+}
+
+
+const char* Float32x4Array::ToCString() const {
+ return "_Float32x4Array";
+}
+
+
RawFloat32Array* Float32Array::New(intptr_t len, Heap::Space space) {
ASSERT(Isolate::Current()->object_store()->float32_array_class() !=
Class::null());
@@ -12661,6 +12759,24 @@
}
+RawExternalFloat32x4Array* ExternalFloat32x4Array::New(
+ simd_value_t* data,
+ intptr_t len,
+ Heap::Space space) {
+ RawClass* cls =
+ Isolate::Current()->object_store()->external_float32x4_array_class();
+ ASSERT(cls != Class::null());
+ return NewExternalImpl<ExternalFloat32x4Array,
+ RawExternalFloat32x4Array>(kClassId, data, len,
+ space);
+}
+
+
+const char* ExternalFloat32x4Array::ToCString() const {
+ return "_ExternalFloat32x4Array";
+}
+
+
RawExternalFloat32Array* ExternalFloat32Array::New(float* data,
intptr_t len,
Heap::Space space) {
@@ -12742,18 +12858,39 @@
}
+void Stacktrace::SetFunctionAtFrame(intptr_t frame_index,
+ const Function& func) const {
+ const Array& function_array = Array::Handle(raw_ptr()->function_array_);
+ function_array.SetAt(frame_index, func);
+}
+
+
RawCode* Stacktrace::CodeAtFrame(intptr_t frame_index) const {
const Array& code_array = Array::Handle(raw_ptr()->code_array_);
return reinterpret_cast<RawCode*>(code_array.At(frame_index));
}
+void Stacktrace::SetCodeAtFrame(intptr_t frame_index,
+ const Code& code) const {
+ const Array& code_array = Array::Handle(raw_ptr()->code_array_);
+ code_array.SetAt(frame_index, code);
+}
+
+
RawSmi* Stacktrace::PcOffsetAtFrame(intptr_t frame_index) const {
const Array& pc_offset_array = Array::Handle(raw_ptr()->pc_offset_array_);
return reinterpret_cast<RawSmi*>(pc_offset_array.At(frame_index));
}
+void Stacktrace::SetPcOffsetAtFrame(intptr_t frame_index,
+ const Smi& pc_offset) const {
+ const Array& pc_offset_array = Array::Handle(raw_ptr()->pc_offset_array_);
+ pc_offset_array.SetAt(frame_index, pc_offset);
+}
+
+
void Stacktrace::set_function_array(const Array& function_array) const {
StorePointer(&raw_ptr()->function_array_, function_array.raw());
}
@@ -12769,9 +12906,24 @@
}
-RawStacktrace* Stacktrace::New(const GrowableObjectArray& func_list,
- const GrowableObjectArray& code_list,
- const GrowableObjectArray& pc_offset_list,
+void Stacktrace::set_catch_func_array(const Array& function_array) const {
+ StorePointer(&raw_ptr()->catch_func_array_, function_array.raw());
+}
+
+
+void Stacktrace::set_catch_code_array(const Array& code_array) const {
+ StorePointer(&raw_ptr()->catch_code_array_, code_array.raw());
+}
+
+
+void Stacktrace::set_catch_pc_offset_array(const Array& pc_offset_array) const {
+ StorePointer(&raw_ptr()->catch_pc_offset_array_, pc_offset_array.raw());
+}
+
+
+RawStacktrace* Stacktrace::New(const Array& func_array,
+ const Array& code_array,
+ const Array& pc_offset_array,
Heap::Space space) {
ASSERT(Isolate::Current()->object_store()->stacktrace_class() !=
Class::null());
@@ -12783,21 +12935,19 @@
NoGCScope no_gc;
result ^= raw;
}
- // Create arrays for the function, code and pc_offset triplet for each frame.
- const Array& function_array = Array::Handle(Array::MakeArray(func_list));
- const Array& code_array = Array::Handle(Array::MakeArray(code_list));
- const Array& pc_offset_array =
- Array::Handle(Array::MakeArray(pc_offset_list));
- result.set_function_array(function_array);
+ result.set_function_array(func_array);
result.set_code_array(code_array);
result.set_pc_offset_array(pc_offset_array);
+ result.SetCatchStacktrace(Object::empty_array(),
+ Object::empty_array(),
+ Object::empty_array());
return result.raw();
}
-void Stacktrace::Append(const GrowableObjectArray& func_list,
- const GrowableObjectArray& code_list,
- const GrowableObjectArray& pc_offset_list) const {
+void Stacktrace::Append(const Array& func_list,
+ const Array& code_list,
+ const Array& pc_offset_list) const {
intptr_t old_length = Length();
intptr_t new_length = old_length + pc_offset_list.Length();
ASSERT(pc_offset_list.Length() == func_list.Length());
@@ -12828,7 +12978,42 @@
}
+void Stacktrace::SetCatchStacktrace(const Array& func_array,
+ const Array& code_array,
+ const Array& pc_offset_array) const {
+ StorePointer(&raw_ptr()->catch_func_array_, func_array.raw());
+ StorePointer(&raw_ptr()->catch_code_array_, code_array.raw());
+ StorePointer(&raw_ptr()->catch_pc_offset_array_, pc_offset_array.raw());
+}
+
+
+RawString* Stacktrace::FullStacktrace() const {
+ const Array& func_array = Array::Handle(raw_ptr()->catch_func_array_);
+ if (!func_array.IsNull() && (func_array.Length() > 0)) {
+ const Array& code_array = Array::Handle(raw_ptr()->catch_code_array_);
+ const Array& pc_offset_array =
+ Array::Handle(raw_ptr()->catch_pc_offset_array_);
+ const Stacktrace& catch_trace = Stacktrace::Handle(
+ Stacktrace::New(func_array, code_array, pc_offset_array));
+ intptr_t idx = Length();
+ const String& trace =
+ String::Handle(String::New(catch_trace.ToCStringInternal(idx)));
+ const String& throw_trace =
+ String::Handle(String::New(ToCStringInternal(0)));
+ return String::Concat(throw_trace, trace);
+ }
+ return String::New(ToCStringInternal(0));
+}
+
+
const char* Stacktrace::ToCString() const {
+ const String& trace = String::Handle(FullStacktrace());
+ return trace.ToCString();
+}
+
+
+const char* Stacktrace::ToCStringInternal(intptr_t frame_index) const {
+ Isolate* isolate = Isolate::Current();
Function& function = Function::Handle();
Code& code = Code::Handle();
Script& script = Script::Handle();
@@ -12840,8 +13025,21 @@
intptr_t total_len = 0;
const char* kFormat = "#%-6d %s (%s:%d:%d)\n";
GrowableArray<char*> frame_strings;
+ char* chars;
for (intptr_t i = 0; i < Length(); i++) {
function = FunctionAtFrame(i);
+ if (function.IsNull()) {
+ // Check if null function object indicates a stack trace overflow.
+ if ((i < (Length() - 1)) &&
+ (FunctionAtFrame(i + 1) != Function::null())) {
+ const char* kTruncated = "...\n...\n";
+ intptr_t truncated_len = strlen(kTruncated) + 1;
+ chars = isolate->current_zone()->Alloc<char>(truncated_len);
+ OS::SNPrint(chars, truncated_len, "%s", kTruncated);
+ frame_strings.Add(chars);
+ }
+ continue;
+ }
code = CodeAtFrame(i);
uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i));
intptr_t token_pos = code.GetTokenIndexOfPC(pc);
@@ -12854,22 +13052,22 @@
script.GetTokenLocation(token_pos, &line, &column);
}
intptr_t len = OS::SNPrint(NULL, 0, kFormat,
- i,
+ (frame_index + i),
function_name.ToCString(),
url.ToCString(),
line, column);
total_len += len;
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+ chars = isolate->current_zone()->Alloc<char>(len + 1);
OS::SNPrint(chars, (len + 1), kFormat,
- i,
+ (frame_index + i),
function_name.ToCString(),
url.ToCString(),
line, column);
frame_strings.Add(chars);
}
- // Now concatentate the frame descriptions into a single C string.
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(total_len + 1);
+ // Now concatenate the frame descriptions into a single C string.
+ chars = isolate->current_zone()->Alloc<char>(total_len + 1);
intptr_t index = 0;
for (intptr_t i = 0; i < frame_strings.length(); i++) {
index += OS::SNPrint((chars + index),
@@ -12877,6 +13075,7 @@
"%s",
frame_strings[i]);
}
+ chars[total_len] = '\0';
return chars;
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index a0ba8ae..e2ed725 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2113,21 +2113,10 @@
static RawLibrary* GetLibrary(intptr_t index);
static bool IsKeyUsed(intptr_t key);
- static void InitASyncLibrary(Isolate* isolate);
static void InitCoreLibrary(Isolate* isolate);
- static void InitCollectionLibrary(Isolate* isolate);
- static void InitCollectionDevLibrary(Isolate* isolate);
- static void InitCryptoLibrary(Isolate* isolate);
- static void InitIsolateLibrary(Isolate* isolate);
- static void InitJsonLibrary(Isolate* isolate);
- static void InitMathLibrary(Isolate* isolate);
- static void InitMirrorsLibrary(Isolate* isolate);
static void InitNativeWrappersLibrary(Isolate* isolate);
- static void InitScalarlistLibrary(Isolate* isolate);
- static void InitUriLibrary(Isolate* isolate);
- static void InitUtfLibrary(Isolate* isolate);
- static RawLibrary* ASyncLibrary();
+ static RawLibrary* AsyncLibrary();
static RawLibrary* CoreLibrary();
static RawLibrary* CollectionLibrary();
static RawLibrary* CollectionDevLibrary();
@@ -2165,6 +2154,8 @@
RawObject* LookupEntry(const String& name, intptr_t *index) const;
FINAL_HEAP_OBJECT_IMPLEMENTATION(Library, Object);
+
+ friend class Object;
friend class Class;
friend class Debugger;
friend class DictionaryIterator;
@@ -2236,6 +2227,9 @@
intptr_t size() const { return raw_ptr()->size_; } // Excludes HeaderSize().
RawCode* code() const { return raw_ptr()->code_; }
RawArray* object_pool() const { return raw_ptr()->object_pool_; }
+ static intptr_t object_pool_offset() {
+ return OFFSET_OF(RawInstructions, object_pool_);
+ }
uword EntryPoint() const {
return reinterpret_cast<uword>(raw_ptr()) + HeaderSize();
@@ -3512,8 +3506,7 @@
(raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) ||
(raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated);
}
- void set_is_finalized_instantiated() const;
- void set_is_finalized_uninstantiated() const;
+ void SetIsFinalized() const;
virtual bool IsBeingFinalized() const {
return raw_ptr()->type_state_ == RawType::kBeingFinalized;
}
@@ -4770,6 +4763,72 @@
};
+class Float32x4 : public Instance {
+ public:
+ static RawFloat32x4* New(float value0, float value1, float value2,
+ float value3, Heap::Space space = Heap::kNew);
+ static RawFloat32x4* New(simd_value_t value, Heap::Space space = Heap::kNew);
+
+ float x() const;
+ float y() const;
+ float z() const;
+ float w() const;
+
+ void set_x(float x) const;
+ void set_y(float y) const;
+ void set_z(float z) const;
+ void set_w(float w) const;
+
+ simd_value_t value() const;
+ void set_value(simd_value_t value) const;
+
+ static intptr_t InstanceSize() {
+ return RoundedAllocationSize(sizeof(RawFloat32x4));
+ }
+
+ static intptr_t value_offset() {
+ return OFFSET_OF(RawFloat32x4, value_);
+ }
+
+ private:
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Float32x4, Instance);
+ friend class Class;
+};
+
+
+class Uint32x4 : public Instance {
+ public:
+ static RawUint32x4* New(uint32_t value0, uint32_t value1, uint32_t value2,
+ uint32_t value3, Heap::Space space = Heap::kNew);
+ static RawUint32x4* New(simd_value_t value, Heap::Space space = Heap::kNew);
+
+ uint32_t x() const;
+ uint32_t y() const;
+ uint32_t z() const;
+ uint32_t w() const;
+
+ void set_x(uint32_t x) const;
+ void set_y(uint32_t y) const;
+ void set_z(uint32_t z) const;
+ void set_w(uint32_t w) const;
+
+ simd_value_t value() const;
+ void set_value(simd_value_t value) const;
+
+ static intptr_t InstanceSize() {
+ return RoundedAllocationSize(sizeof(RawUint32x4));
+ }
+
+ static intptr_t value_offset() {
+ return OFFSET_OF(RawUint32x4, value_);
+ }
+
+ private:
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Uint32x4, Instance);
+ friend class Class;
+};
+
+
class ByteArray : public Instance {
public:
intptr_t Length() const {
@@ -5310,6 +5369,61 @@
};
+class Float32x4Array : public ByteArray {
+ public:
+ intptr_t ByteLength() const {
+ return Length() * kBytesPerElement;
+ }
+
+ simd_value_t At(intptr_t index) const {
+ ASSERT((index >= 0) && (index < Length()));
+ simd_value_t* load_ptr = &raw_ptr()->data_[index];
+ return simd_value_safe_load(load_ptr);
+ }
+
+ void SetAt(intptr_t index, simd_value_t value) const {
+ ASSERT((index >= 0) && (index < Length()));
+ simd_value_t* store_ptr = &raw_ptr()->data_[index];
+ simd_value_safe_store(store_ptr, value);
+ }
+
+ static const intptr_t kBytesPerElement = 16;
+ static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
+
+ static intptr_t data_offset() {
+ return OFFSET_OF(RawFloat32x4Array, data_);
+ }
+
+ static intptr_t InstanceSize() {
+ ASSERT(sizeof(RawFloat32x4Array) ==
+ OFFSET_OF(RawFloat32x4Array, data_));
+ return 0;
+ }
+
+ static intptr_t InstanceSize(intptr_t len) {
+ ASSERT(0 <= len && len <= kMaxElements);
+ return RoundedAllocationSize(
+ sizeof(RawFloat32x4Array) + (len * kBytesPerElement));
+ }
+
+ static RawFloat32x4Array* New(intptr_t len,
+ Heap::Space space = Heap::kNew);
+ static RawFloat32x4Array* New(const simd_value_t* data,
+ intptr_t len,
+ Heap::Space space = Heap::kNew);
+
+ private:
+ uint8_t* ByteAddr(intptr_t byte_offset) const {
+ ASSERT((byte_offset >= 0) && (byte_offset < ByteLength()));
+ return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
+ }
+
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Float32x4Array, ByteArray);
+ friend class ByteArray;
+ friend class Class;
+};
+
+
class Float32Array : public ByteArray {
public:
intptr_t ByteLength() const {
@@ -5909,6 +6023,68 @@
};
+class ExternalFloat32x4Array : public ByteArray {
+ public:
+ intptr_t ByteLength() const {
+ return Length() * kBytesPerElement;
+ }
+
+ simd_value_t At(intptr_t index) const {
+ ASSERT((index >= 0) && (index < Length()));
+ simd_value_t* load_ptr = &raw_ptr()->data_[index];
+ return simd_value_safe_load(load_ptr);
+ }
+
+ void SetAt(intptr_t index, simd_value_t value) const {
+ ASSERT((index >= 0) && (index < Length()));
+ simd_value_t* store_ptr = &raw_ptr()->data_[index];
+ simd_value_safe_store(store_ptr, value);
+ }
+
+
+ simd_value_t* GetData() const {
+ return raw_ptr()->data_;
+ }
+
+ void* GetPeer() const {
+ return raw_ptr()->peer_;
+ }
+
+ static const intptr_t kBytesPerElement = 16;
+
+ // Since external arrays may be serialized to non-external ones,
+ // enforce the same maximum element count.
+ static const intptr_t kMaxElements = Float32x4Array::kMaxElements;
+
+ static intptr_t InstanceSize() {
+ return RoundedAllocationSize(sizeof(RawExternalFloat32x4Array));
+ }
+
+ static RawExternalFloat32x4Array* New(simd_value_t* data,
+ intptr_t len,
+ Heap::Space space = Heap::kNew);
+
+ private:
+ uint8_t* ByteAddr(intptr_t byte_offset) const {
+ ASSERT((byte_offset >= 0) && (byte_offset < ByteLength()));
+ uint8_t* data = reinterpret_cast<uint8_t*>(raw_ptr()->data_);
+ return data + byte_offset;
+ }
+
+ void SetData(simd_value_t* data) const {
+ raw_ptr()->data_ = data;
+ }
+
+ void SetPeer(void* peer) const {
+ raw_ptr()->peer_ = peer;
+ }
+
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32x4Array, ByteArray);
+ friend class ByteArray;
+ friend class Class;
+};
+
+
class ExternalFloat32Array : public ByteArray {
public:
intptr_t ByteLength() const {
@@ -6112,28 +6288,44 @@
// Internal stacktrace object used in exceptions for printing stack traces.
class Stacktrace : public Instance {
public:
+ static const int kPreallocatedStackdepth = 10;
+
intptr_t Length() const;
+
RawFunction* FunctionAtFrame(intptr_t frame_index) const;
+ void SetFunctionAtFrame(intptr_t frame_index, const Function& func) const;
+
RawCode* CodeAtFrame(intptr_t frame_index) const;
+ void SetCodeAtFrame(intptr_t frame_index, const Code& code) const;
+
RawSmi* PcOffsetAtFrame(intptr_t frame_index) const;
- void Append(const GrowableObjectArray& func_list,
- const GrowableObjectArray& code_list,
- const GrowableObjectArray& pc_offset_list) const;
+ void SetPcOffsetAtFrame(intptr_t frame_index, const Smi& pc_offset) const;
+ void SetCatchStacktrace(const Array& func_array,
+ const Array& code_array,
+ const Array& pc_offset_array) const;
+
+ void Append(const Array& func_list,
+ const Array& code_list,
+ const Array& pc_offset_list) const;
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(RawStacktrace));
}
- static RawStacktrace* New(const GrowableObjectArray& func_list,
- const GrowableObjectArray& code_list,
- const GrowableObjectArray& pc_offset_list,
+ static RawStacktrace* New(const Array& func_array,
+ const Array& code_array,
+ const Array& pc_offset_array,
Heap::Space space = Heap::kNew);
- const char* ToCStringInternal(bool verbose) const;
+ RawString* FullStacktrace() const;
+ const char* ToCStringInternal(intptr_t frame_index) const;
private:
void set_function_array(const Array& function_array) const;
void set_code_array(const Array& code_array) const;
void set_pc_offset_array(const Array& pc_offset_array) const;
+ void set_catch_func_array(const Array& function_array) const;
+ void set_catch_code_array(const Array& code_array) const;
+ void set_catch_pc_offset_array(const Array& pc_offset_array) const;
FINAL_HEAP_OBJECT_IMPLEMENTATION(Stacktrace, Instance);
friend class Class;
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 5343c42..31b9ccc 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -87,6 +87,7 @@
empty_context_(Context::null()),
stack_overflow_(Instance::null()),
out_of_memory_(Instance::null()),
+ preallocated_stack_trace_(Stacktrace::null()),
keyword_symbols_(Array::null()),
receive_port_create_function_(Function::null()),
lookup_receive_port_function_(Function::null()),
@@ -114,12 +115,14 @@
bool ObjectStore::PreallocateObjects() {
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL && isolate->object_store() == this);
- if (this->stack_overflow() != Instance::null() &&
- this->out_of_memory() != Instance::null()) {
+ if (this->stack_overflow() != Instance::null()) {
+ ASSERT(this->out_of_memory() != Instance::null());
+ ASSERT(this->preallocated_stack_trace() != Stacktrace::null());
return true;
}
ASSERT(this->stack_overflow() == Instance::null());
ASSERT(this->out_of_memory() == Instance::null());
+ ASSERT(this->preallocated_stack_trace() == Stacktrace::null());
// TODO(regis): Reenable this code for arm and mips when possible.
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
Object& result = Object::Handle();
@@ -136,6 +139,17 @@
return false;
}
set_out_of_memory(Instance::Cast(result));
+ const Array& func_array = Array::Handle(
+ isolate,
+ Array::New(Stacktrace::kPreallocatedStackdepth, Heap::kOld));
+ const Array& code_array = Array::Handle(
+ isolate,
+ Array::New(Stacktrace::kPreallocatedStackdepth, Heap::kOld));
+ const Array& pc_offset_array = Array::Handle(
+ isolate,
+ Array::New(Stacktrace::kPreallocatedStackdepth, Heap::kOld));
+ result = Stacktrace::New(func_array, code_array, pc_offset_array);
+ set_preallocated_stack_trace(Stacktrace::Cast(result));
#endif
return true;
}
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 8bc26cf..1811803 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -164,6 +164,20 @@
return OFFSET_OF(ObjectStore, growable_object_array_class_);
}
+ RawClass* float32x4_class() const {
+ return float32x4_class_;
+ }
+ void set_float32x4_class(const Class& value) {
+ float32x4_class_ = value.raw();
+ }
+
+ RawClass* uint32x4_class() const {
+ return uint32x4_class_;
+ }
+ void set_uint32x4_class(const Class& value) {
+ uint32x4_class_ = value.raw();
+ }
+
RawClass* int8_array_class() const {
return int8_array_class_;
}
@@ -227,6 +241,13 @@
uint64_array_class_ = value.raw();
}
+ RawClass* float32x4_array_class() const {
+ return float32x4_array_class_;
+ }
+ void set_float32x4_array_class(const Class& value) {
+ float32x4_array_class_ = value.raw();
+ }
+
RawClass* float32_array_class() const {
return float32_array_class_;
}
@@ -304,6 +325,13 @@
external_uint64_array_class_ = value.raw();
}
+ RawClass* external_float32x4_array_class() const {
+ return external_float32x4_array_class_;
+ }
+ void set_external_float32x4_array_class(const Class& value) {
+ external_float32x4_array_class_ = value.raw();
+ }
+
RawClass* external_float32_array_class() const {
return external_float32_array_class_;
}
@@ -497,6 +525,13 @@
out_of_memory_ = value.raw();
}
+ RawStacktrace* preallocated_stack_trace() const {
+ return preallocated_stack_trace_;
+ }
+ void set_preallocated_stack_trace(const Stacktrace& value) {
+ preallocated_stack_trace_ = value.raw();
+ }
+
RawArray* keyword_symbols() const { return keyword_symbols_; }
void set_keyword_symbols(const Array& value) {
keyword_symbols_ = value.raw();
@@ -568,6 +603,8 @@
RawType* array_type_;
RawClass* immutable_array_class_;
RawClass* growable_object_array_class_;
+ RawClass* float32x4_class_;
+ RawClass* uint32x4_class_;
RawClass* int8_array_class_;
RawClass* uint8_array_class_;
RawClass* uint8_clamped_array_class_;
@@ -577,6 +614,7 @@
RawClass* uint32_array_class_;
RawClass* int64_array_class_;
RawClass* uint64_array_class_;
+ RawClass* float32x4_array_class_;
RawClass* float32_array_class_;
RawClass* float64_array_class_;
RawClass* external_int8_array_class_;
@@ -588,6 +626,7 @@
RawClass* external_uint32_array_class_;
RawClass* external_int64_array_class_;
RawClass* external_uint64_array_class_;
+ RawClass* external_float32x4_array_class_;
RawClass* external_float32_array_class_;
RawClass* external_float64_array_class_;
RawClass* stacktrace_class_;
@@ -618,6 +657,7 @@
RawContext* empty_context_;
RawInstance* stack_overflow_;
RawInstance* out_of_memory_;
+ RawStacktrace* preallocated_stack_trace_;
RawArray* keyword_symbols_;
RawFunction* receive_port_create_function_;
RawFunction* lookup_receive_port_function_;
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index a9dcfd9..ab50b27 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -32,9 +32,95 @@
"Generate symbols of generated dart functions for debugging with GDB");
DEFINE_FLAG(bool, generate_perf_events_symbols, false,
"Generate events symbols for profiling with perf");
+DEFINE_FLAG(bool, ll_prof, false,
+ "Generate compiled code log file for processing with ll_prof.py.");
DEFINE_FLAG(charp, generate_pprof_symbols, NULL,
"Writes pprof events symbols to the provided file");
+class LowLevelProfileCodeObserver : public CodeObserver {
+ public:
+ LowLevelProfileCodeObserver() {
+ Dart_FileOpenCallback file_open = Isolate::file_open_callback();
+ if (file_open == NULL) {
+ return;
+ }
+ const char* filename = "v8.log.ll";
+ log_file_ = (*file_open)(filename);
+#if defined(TARGET_ARCH_IA32)
+ const char arch[] = "ia32";
+#elif defined(TARGET_ARCH_X64)
+ const char arch[] = "x64";
+#elif defined(TARGET_ARCH_ARM)
+ const char arch[] = "arm";
+#elif defined(TARGET_ARCH_MIPS)
+ const char arch[] = "mips";
+#else
+ const char arch[] = "unknown";
+#endif
+ LowLevelLogWriteBytes(arch, sizeof(arch));
+ }
+
+ ~LowLevelProfileCodeObserver() {
+ Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+ if (file_close == NULL) {
+ return;
+ }
+ ASSERT(log_file_ != NULL);
+ (*file_close)(log_file_);
+ }
+
+ virtual bool IsActive() const {
+ return FLAG_ll_prof;
+ }
+
+ struct LowLevelCodeCreateStruct {
+ static const char kTag = 'C';
+
+ int32_t name_size;
+ uword code_address;
+ int32_t code_size;
+ };
+
+ template <typename T>
+ void LowLevelLogWriteStruct(const T& s) {
+ char tag = T::kTag;
+ LowLevelLogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
+ LowLevelLogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
+ }
+
+ void LowLevelLogWriteBytes(const char* bytes, int size) {
+ Dart_FileWriteCallback file_write = Isolate::file_write_callback();
+ ASSERT(file_write != NULL);
+ (file_write)(bytes, size, log_file_);
+ }
+
+ virtual void Notify(const char* name,
+ uword base,
+ uword prologue_offset,
+ uword size,
+ bool optimized) {
+ const char* marker = optimized ? "*" : "";
+ char* name_buffer =
+ Isolate::Current()->current_zone()->PrintToString("%s%s", marker, name);
+ intptr_t len = strlen(name_buffer);
+
+ LowLevelCodeCreateStruct event;
+ event.name_size = len;
+ event.code_address = base;
+ event.code_size = size;
+
+ LowLevelLogWriteStruct(event);
+ LowLevelLogWriteBytes(name_buffer, len);
+ LowLevelLogWriteBytes(reinterpret_cast<char*>(base), size);
+ }
+
+ private:
+ void* log_file_;
+
+ DISALLOW_COPY_AND_ASSIGN(LowLevelProfileCodeObserver);
+};
+
+
class PerfCodeObserver : public CodeObserver {
public:
PerfCodeObserver() {
@@ -378,6 +464,9 @@
void OS::RegisterCodeObservers() {
+ if (FLAG_ll_prof) {
+ CodeObservers::Register(new LowLevelProfileCodeObserver);
+ }
if (FLAG_generate_perf_events_symbols) {
CodeObservers::Register(new PerfCodeObserver);
}
diff --git a/runtime/vm/os_test.cc b/runtime/vm/os_test.cc
index a64fc82..ff577b4 100644
--- a/runtime/vm/os_test.cc
+++ b/runtime/vm/os_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -15,7 +15,7 @@
int64_t sleep_time = 702;
OS::Sleep(sleep_time);
int64_t delta = OS::GetCurrentTimeMillis() - start_time;
- const int kAcceptableSleepWakeupJitter = 100; // Measured in milliseconds.
+ const int kAcceptableSleepWakeupJitter = 200; // Measured in milliseconds.
EXPECT_GE(delta, sleep_time - kAcceptableSleepWakeupJitter);
EXPECT_LE(delta, sleep_time + kAcceptableSleepWakeupJitter);
}
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 4740688..47c8b1e 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -3415,6 +3415,13 @@
library_.AddClass(mixin_application);
set_current_class(mixin_application);
ParseTypeParameters(mixin_application);
+
+ // TODO(hausner): Handle mixin application aliases with generics.
+ if (mixin_application.NumTypeParameters() > 0) {
+ ErrorMsg(classname_pos,
+ "type parameters on mixin applications not yet supported");
+ }
+
ExpectToken(Token::kASSIGN);
if (CurrentToken() == Token::kABSTRACT) {
@@ -3438,8 +3445,15 @@
ErrorMsg("mixin application 'with Type' expected");
}
- Type& mixin_application_type = Type::Handle(ParseMixins(mixin_super_type));
- // The result of ParseMixins() is a chain of super classes that is the
+ const Type& mixin_application_type =
+ Type::Handle(ParseMixins(mixin_super_type));
+ // TODO(hausner): Implement generic mixin support.
+ if (mixin_application_type.arguments() != AbstractTypeArguments::null()) {
+ ErrorMsg(mixin_application_type.token_pos(),
+ "mixin class with type arguments not yet supported");
+ }
+
+ // The result of ParseMixins() is a chain of super types that is the
// result of the mixin composition 'S with M1, M2, ...'. The mixin
// application classes are anonymous (i.e. not registered in the current
// library). We steal the super type and mixin type from the bottom of
@@ -3838,7 +3852,7 @@
// TODO(hausner): Remove this restriction.
if (super_type.arguments() != AbstractTypeArguments::null()) {
ErrorMsg(super_type.token_pos(),
- "super class of mixin may not have type arguments");
+ "super class in mixin application may not have type arguments");
}
AbstractType& mixin_type = AbstractType::Handle();
@@ -3848,7 +3862,6 @@
Type& mixin_application_type = Type::Handle();
Type& mixin_super_type = Type::Handle(super_type.raw());
Array& mixin_application_interfaces = Array::Handle();
- const TypeArguments& no_type_arguments = TypeArguments::Handle();
do {
ConsumeToken();
const intptr_t mixin_pos = TokenPos();
@@ -3858,22 +3871,14 @@
"mixin type '%s' may not be a type parameter",
String::Handle(mixin_type.UserVisibleName()).ToCString());
}
- // TODO(hausner): Remove this check once we handle mixins with type
- // arguments.
- mixin_type_arguments = mixin_type.arguments();
- if (!mixin_type_arguments.IsNull()) {
- ErrorMsg(mixin_pos,
- "mixin type '%s' may not have type arguments",
- String::Handle(mixin_type.UserVisibleName()).ToCString());
- }
// The name of the mixin application class is a combination of
// the superclass and mixin class.
String& mixin_app_name = String::Handle();
- mixin_app_name = mixin_super_type.Name();
+ mixin_app_name = mixin_super_type.ClassName();
mixin_app_name = String::Concat(mixin_app_name, Symbols::Ampersand());
mixin_app_name = String::Concat(mixin_app_name,
- String::Handle(mixin_type.Name()));
+ String::Handle(mixin_type.ClassName()));
mixin_app_name = Symbols::New(mixin_app_name);
mixin_application = Class::New(mixin_app_name, script_, mixin_pos);
@@ -3887,10 +3892,17 @@
mixin_application_interfaces.SetAt(0, mixin_type);
mixin_application.set_interfaces(mixin_application_interfaces);
- // TODO(hausner): Need to support type arguments.
+ // For the type arguments of the mixin application type, we need
+ // a copy of the type arguments to the mixin type. The simplest way
+ // to get the copy is to rewind the parser, parse the mixin type
+ // again and steal its type arguments.
+ SetPosition(mixin_pos);
+ mixin_type = ParseType(ClassFinalizer::kTryResolve);
+ mixin_type_arguments = mixin_type.arguments();
+
mixin_application_type = Type::New(mixin_application,
- no_type_arguments,
- Scanner::kDummyTokenIndex);
+ mixin_type_arguments,
+ mixin_pos);
mixin_super_type = mixin_application_type.raw();
} while (CurrentToken() == Token::kCOMMA);
return mixin_application_type.raw();
@@ -4252,23 +4264,36 @@
}
-Dart_Handle Parser::CallLibraryTagHandler(Dart_LibraryTag tag,
+RawObject* Parser::CallLibraryTagHandler(Dart_LibraryTag tag,
intptr_t token_pos,
const String& url) {
Isolate* isolate = Isolate::Current();
Dart_LibraryTagHandler handler = isolate->library_tag_handler();
if (handler == NULL) {
+ if (url.StartsWith(Symbols::DartScheme())) {
+ if (tag == kCanonicalizeUrl) {
+ return url.raw();
+ }
+ return Object::null();
+ }
ErrorMsg(token_pos, "no library handler registered");
}
Dart_Handle result = handler(tag,
Api::NewHandle(isolate, library_.raw()),
Api::NewHandle(isolate, url.raw()));
if (Dart_IsError(result)) {
+ // In case of an error we append an explanatory error message to the
+ // error obtained from the library tag handler.
Error& prev_error = Error::Handle();
prev_error ^= Api::UnwrapHandle(result);
AppendErrorMsg(prev_error, token_pos, "library handler failed");
}
- return result;
+ if (tag == kCanonicalizeUrl) {
+ if (!Dart_IsString(result)) {
+ ErrorMsg(token_pos, "library handler failed URI canonicalization");
+ }
+ }
+ return Api::UnwrapHandle(result);
}
@@ -4303,10 +4328,8 @@
}
ExpectToken(Token::kRPAREN);
ExpectToken(Token::kSEMICOLON);
- Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl,
- import_pos,
- url);
- const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
+ const String& canon_url = String::CheckedHandle(
+ CallLibraryTagHandler(kCanonicalizeUrl, import_pos, url));
// Lookup the library URL.
Library& library = Library::Handle(Library::LookupLibrary(canon_url));
if (library.IsNull()) {
@@ -4352,10 +4375,8 @@
ConsumeToken();
ExpectToken(Token::kRPAREN);
ExpectToken(Token::kSEMICOLON);
- Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl,
- source_pos,
- url);
- const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
+ const String& canon_url = String::CheckedHandle(
+ CallLibraryTagHandler(kCanonicalizeUrl, source_pos, url));
CallLibraryTagHandler(kSourceTag, source_pos, canon_url);
}
}
@@ -4442,9 +4463,8 @@
ExpectSemicolon();
// Canonicalize library URL.
- Dart_Handle handle =
- CallLibraryTagHandler(kCanonicalizeUrl, import_pos, url);
- const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
+ const String& canon_url = String::CheckedHandle(
+ CallLibraryTagHandler(kCanonicalizeUrl, import_pos, url));
// Lookup the library URL.
Library& library = Library::Handle(Library::LookupLibrary(canon_url));
if (library.IsNull()) {
@@ -4496,9 +4516,8 @@
const String& url = *CurrentLiteral();
ConsumeToken();
ExpectSemicolon();
- Dart_Handle handle =
- CallLibraryTagHandler(kCanonicalizeUrl, source_pos, url);
- const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
+ const String& canon_url = String::CheckedHandle(
+ CallLibraryTagHandler(kCanonicalizeUrl, source_pos, url));
CallLibraryTagHandler(kSourceTag, source_pos, canon_url);
}
@@ -4531,8 +4550,6 @@
return;
}
- const bool is_script = (script_.kind() == RawScript::kScriptTag);
- const bool is_library = (script_.kind() == RawScript::kLibraryTag);
ASSERT(script_.kind() != RawScript::kSourceTag);
// We may read metadata tokens that are part of the toplevel
@@ -4542,17 +4559,15 @@
intptr_t metadata_pos = TokenPos();
SkipMetadata();
if (CurrentToken() == Token::kLIBRARY) {
+ if (is_patch_source()) {
+ ErrorMsg("patch cannot override library name");
+ }
ParseLibraryName();
metadata_pos = TokenPos();
SkipMetadata();
- } else if (is_library) {
- ErrorMsg("library name definition expected");
}
while ((CurrentToken() == Token::kIMPORT) ||
(CurrentToken() == Token::kEXPORT)) {
- if (is_script && (CurrentToken() == Token::kEXPORT)) {
- ErrorMsg("export not allowed in scripts");
- }
ParseLibraryImportExport();
metadata_pos = TokenPos();
SkipMetadata();
@@ -4617,7 +4632,7 @@
Class::New(Symbols::TopLevel(), script_, TokenPos()));
toplevel_class.set_library(library_);
- if (is_library_source()) {
+ if (is_library_source() || is_patch_source()) {
ParseLibraryDefinition();
} else if (is_part_source()) {
ParsePartHeader();
@@ -5082,7 +5097,7 @@
Type::Handle(Type::Function()).type_class());
function_type = Type::New(
unknown_signature_class, TypeArguments::Handle(), ident_pos);
- function_type.set_is_finalized_instantiated(); // No finalization needed.
+ function_type.SetIsFinalized(); // No finalization needed.
// Add the function variable to the scope before parsing the function in
// order to allow self reference from inside the function.
@@ -6278,11 +6293,18 @@
// A stack trace variable is specified in this block, so generate code
// to load the stack trace object (:stacktrace_var) into the stack trace
// variable specified in this block.
+ ArgumentListNode* no_args = new ArgumentListNode(catch_pos);
LocalVariable* trace = LookupLocalScope(*stack_trace_param.var);
ASSERT(catch_trace_var != NULL);
current_block_->statements->Add(
new StoreLocalNode(catch_pos, trace,
new LoadLocalNode(catch_pos, catch_trace_var)));
+ current_block_->statements->Add(
+ new InstanceCallNode(
+ catch_pos,
+ new LoadLocalNode(catch_pos, trace),
+ PrivateCoreLibName(Symbols::_setupFullStackTrace()),
+ no_args));
}
ParseStatementSequence(); // Parse the catch handler code.
@@ -8185,7 +8207,7 @@
ASSERT(!func.IsNull());
ASSERT(func.kind() == RawFunction::kConstImplicitGetter);
Object& const_value = Object::Handle(
- DartEntry::InvokeStatic(func, Object::empty_array()));
+ DartEntry::InvokeFunction(func, Object::empty_array()));
if (const_value.IsError()) {
const Error& error = Error::Cast(const_value);
if (error.IsUnhandledException()) {
@@ -8248,9 +8270,9 @@
Array::Handle(ArgumentsDescriptor::New(num_arguments,
arguments->names()));
const Object& result =
- Object::Handle(DartEntry::InvokeStatic(constructor,
- arg_values,
- arg_descriptor));
+ Object::Handle(DartEntry::InvokeFunction(constructor,
+ arg_values,
+ arg_descriptor));
if (result.IsError()) {
if (result.IsUnhandledException()) {
return result.raw();
@@ -9459,7 +9481,7 @@
// Call interpolation function.
String& concatenated = String::ZoneHandle();
- concatenated ^= DartEntry::InvokeStatic(func, interpolate_arg);
+ concatenated ^= DartEntry::InvokeFunction(func, interpolate_arg);
if (concatenated.IsUnhandledException()) {
ErrorMsg("Exception thrown in Parser::Interpolate");
}
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index ba83c47..5dd2aa6 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -336,9 +336,9 @@
void ParseTopLevelAccessor(TopLevel* top_level);
// Support for parsing libraries.
- Dart_Handle CallLibraryTagHandler(Dart_LibraryTag tag,
- intptr_t token_pos,
- const String& url);
+ RawObject* CallLibraryTagHandler(Dart_LibraryTag tag,
+ intptr_t token_pos,
+ const String& url);
void ParseIdentList(GrowableObjectArray* names);
void ParseLibraryDefinition();
void ParseLibraryName();
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index ecf2a79..0e47312 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -182,6 +182,13 @@
instance_size = Uint64Array::InstanceSize(byte_array_length);
break;
}
+ case kFloat32x4ArrayCid: {
+ const RawFloat32x4Array* raw_byte_array =
+ reinterpret_cast<const RawFloat32x4Array*>(this);
+ intptr_t byte_array_length = Smi::Value(raw_byte_array->ptr()->length_);
+ instance_size = Float32x4Array::InstanceSize(byte_array_length);
+ break;
+ }
case kFloat32ArrayCid: {
const RawFloat32Array* raw_byte_array =
reinterpret_cast<const RawFloat32Array*>(this);
@@ -761,6 +768,22 @@
}
+intptr_t RawFloat32x4::VisitFloat32x4Pointers(
+ RawFloat32x4* raw_obj,
+ ObjectPointerVisitor* visitor) {
+ ASSERT(raw_obj->IsHeapObject());
+ return Float32x4::InstanceSize();
+}
+
+
+intptr_t RawUint32x4::VisitUint32x4Pointers(
+ RawUint32x4* raw_obj,
+ ObjectPointerVisitor* visitor) {
+ ASSERT(raw_obj->IsHeapObject());
+ return Uint32x4::InstanceSize();
+}
+
+
intptr_t RawByteArray::VisitByteArrayPointers(RawByteArray* raw_obj,
ObjectPointerVisitor* visitor) {
// ByteArray is an abstract class.
@@ -859,6 +882,15 @@
}
+intptr_t RawFloat32x4Array::VisitFloat32x4ArrayPointers(
+ RawFloat32x4Array *raw_obj, ObjectPointerVisitor* visitor) {
+ // Make sure that we got here with the tagged pointer as this.
+ ASSERT(raw_obj->IsHeapObject());
+ intptr_t length = Smi::Value(raw_obj->ptr()->length_);
+ visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+ return Float32x4Array::InstanceSize(length);
+}
+
intptr_t RawFloat32Array::VisitFloat32ArrayPointers(
RawFloat32Array *raw_obj, ObjectPointerVisitor* visitor) {
// Make sure that we got here with the tagged pointer as this.
@@ -960,6 +992,16 @@
}
+intptr_t
+ RawExternalFloat32x4Array::VisitExternalFloat32x4ArrayPointers(
+ RawExternalFloat32x4Array* raw_obj, ObjectPointerVisitor* visitor) {
+ // Make sure that we got here with the tagged pointer as this.
+ ASSERT(raw_obj->IsHeapObject());
+ visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+ return ExternalFloat32x4Array::InstanceSize();
+}
+
+
intptr_t RawExternalFloat32Array::VisitExternalFloat32ArrayPointers(
RawExternalFloat32Array* raw_obj, ObjectPointerVisitor* visitor) {
// Make sure that we got here with the tagged pointer as this.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 2889ff9..6d829fe 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -71,6 +71,7 @@
V(Uint32Array) \
V(Int64Array) \
V(Uint64Array) \
+ V(Float32x4Array) \
V(Float32Array) \
V(Float64Array) \
V(ExternalInt8Array) \
@@ -82,12 +83,16 @@
V(ExternalUint32Array) \
V(ExternalInt64Array) \
V(ExternalUint64Array) \
+ V(ExternalFloat32x4Array) \
V(ExternalFloat32Array) \
V(ExternalFloat64Array) \
V(Stacktrace) \
V(JSRegExp) \
V(WeakProperty) \
V(DartFunction) \
+ V(Float32x4) \
+ V(Uint32x4) \
+
#define CLASS_LIST_STRINGS(V) \
V(String) \
@@ -1301,6 +1306,24 @@
};
+class RawFloat32x4 : public RawInstance {
+ RAW_HEAP_OBJECT_IMPLEMENTATION(Float32x4);
+
+ float value_[4];
+
+ friend class SnapshotReader;
+};
+
+
+class RawUint32x4 : public RawInstance {
+ RAW_HEAP_OBJECT_IMPLEMENTATION(Uint32x4);
+
+ uint32_t value_[4];
+
+ friend class SnapshotReader;
+};
+
+
// Define an aliases for intptr_t.
#if defined(ARCH_IS_32_BIT)
#define RawIntPtrArray RawInt32Array
@@ -1401,6 +1424,13 @@
};
+class RawFloat32x4Array : public RawByteArray {
+ RAW_HEAP_OBJECT_IMPLEMENTATION(Float32x4Array);
+
+ // Variable length data follows here.
+ simd_value_t data_[0];
+};
+
class RawFloat32Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Float32Array);
@@ -1490,6 +1520,14 @@
};
+class RawExternalFloat32x4Array : public RawByteArray {
+ RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32x4Array);
+
+ simd_value_t* data_;
+ void* peer_;
+};
+
+
class RawExternalFloat32Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32Array);
@@ -1524,8 +1562,11 @@
RawArray* function_array_; // Function for each frame in the stack trace.
RawArray* code_array_; // Code object for each frame in the stack trace.
RawArray* pc_offset_array_; // Offset of PC for each frame.
+ RawArray* catch_func_array_; // Func for each frame in catch stack trace.
+ RawArray* catch_code_array_; // Code for each frame in catch stack trace.
+ RawArray* catch_pc_offset_array_; // Offset of PC for each catch stack frame.
RawObject** to() {
- return reinterpret_cast<RawObject**>(&ptr()->pc_offset_array_);
+ return reinterpret_cast<RawObject**>(&ptr()->catch_pc_offset_array_);
}
};
@@ -1670,20 +1711,22 @@
kUint32ArrayCid == kByteArrayCid + 7 &&
kInt64ArrayCid == kByteArrayCid + 8 &&
kUint64ArrayCid == kByteArrayCid + 9 &&
- kFloat32ArrayCid == kByteArrayCid + 10 &&
- kFloat64ArrayCid == kByteArrayCid + 11 &&
- kExternalInt8ArrayCid == kByteArrayCid + 12 &&
- kExternalUint8ArrayCid == kByteArrayCid + 13 &&
- kExternalUint8ClampedArrayCid == kByteArrayCid + 14 &&
- kExternalInt16ArrayCid == kByteArrayCid + 15 &&
- kExternalUint16ArrayCid == kByteArrayCid + 16 &&
- kExternalInt32ArrayCid == kByteArrayCid + 17 &&
- kExternalUint32ArrayCid == kByteArrayCid + 18 &&
- kExternalInt64ArrayCid == kByteArrayCid + 19 &&
- kExternalUint64ArrayCid == kByteArrayCid + 20 &&
- kExternalFloat32ArrayCid == kByteArrayCid + 21 &&
- kExternalFloat64ArrayCid == kByteArrayCid + 22 &&
- kStacktraceCid == kByteArrayCid + 23);
+ kFloat32x4ArrayCid == kByteArrayCid + 10 &&
+ kFloat32ArrayCid == kByteArrayCid + 11 &&
+ kFloat64ArrayCid == kByteArrayCid + 12 &&
+ kExternalInt8ArrayCid == kByteArrayCid + 13 &&
+ kExternalUint8ArrayCid == kByteArrayCid + 14 &&
+ kExternalUint8ClampedArrayCid == kByteArrayCid + 15 &&
+ kExternalInt16ArrayCid == kByteArrayCid + 16 &&
+ kExternalUint16ArrayCid == kByteArrayCid + 17 &&
+ kExternalInt32ArrayCid == kByteArrayCid + 18 &&
+ kExternalUint32ArrayCid == kByteArrayCid + 19 &&
+ kExternalInt64ArrayCid == kByteArrayCid + 20 &&
+ kExternalUint64ArrayCid == kByteArrayCid + 21 &&
+ kExternalFloat32x4ArrayCid == kByteArrayCid + 22 &&
+ kExternalFloat32ArrayCid == kByteArrayCid + 23 &&
+ kExternalFloat64ArrayCid == kByteArrayCid + 24 &&
+ kStacktraceCid == kByteArrayCid + 25);
return (index >= kByteArrayCid && index <= kExternalFloat64ArrayCid);
}
@@ -1697,9 +1740,10 @@
kExternalUint32ArrayCid == kExternalInt8ArrayCid + 6 &&
kExternalInt64ArrayCid == kExternalInt8ArrayCid + 7 &&
kExternalUint64ArrayCid == kExternalInt8ArrayCid + 8 &&
- kExternalFloat32ArrayCid == kExternalInt8ArrayCid + 9 &&
- kExternalFloat64ArrayCid == kExternalInt8ArrayCid + 10 &&
- kStacktraceCid == kExternalInt8ArrayCid + 11);
+ kExternalFloat32x4ArrayCid == kExternalInt8ArrayCid + 9 &&
+ kExternalFloat32ArrayCid == kExternalInt8ArrayCid + 10 &&
+ kExternalFloat64ArrayCid == kExternalInt8ArrayCid + 11 &&
+ kStacktraceCid == kExternalInt8ArrayCid + 12);
return (index >= kExternalInt8ArrayCid && index <= kExternalFloat64ArrayCid);
}
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 2b4011d..99370a2 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -2045,6 +2045,98 @@
}
+RawFloat32x4* Float32x4::ReadFrom(SnapshotReader* reader,
+ intptr_t object_id,
+ intptr_t tags,
+ Snapshot::Kind kind) {
+ ASSERT(reader != NULL);
+ // Read the values.
+ float value0 = reader->Read<float>();
+ float value1 = reader->Read<float>();
+ float value2 = reader->Read<float>();
+ float value3 = reader->Read<float>();
+
+ // Create a Float32x4 object.
+ Float32x4& simd = Float32x4::ZoneHandle(reader->isolate(),
+ Float32x4::null());
+ if (kind == Snapshot::kFull) {
+ simd = reader->NewFloat32x4(value0, value1, value2, value3);
+ } else {
+ simd = Float32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
+ }
+ reader->AddBackRef(object_id, &simd, kIsDeserialized);
+ // Set the object tags.
+ simd.set_tags(tags);
+ return simd.raw();
+}
+
+
+void RawFloat32x4::WriteTo(SnapshotWriter* writer,
+ intptr_t object_id,
+ Snapshot::Kind kind) {
+ ASSERT(writer != NULL);
+
+ // Write out the serialization header value for this object.
+ writer->WriteInlinedObjectHeader(object_id);
+
+ // Write out the class and tags information.
+ writer->WriteIndexedObject(kFloat32x4Cid);
+ writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+ // Write out the float values.
+ writer->Write<float>(ptr()->value_[0]);
+ writer->Write<float>(ptr()->value_[1]);
+ writer->Write<float>(ptr()->value_[2]);
+ writer->Write<float>(ptr()->value_[3]);
+}
+
+
+RawUint32x4* Uint32x4::ReadFrom(SnapshotReader* reader,
+ intptr_t object_id,
+ intptr_t tags,
+ Snapshot::Kind kind) {
+ ASSERT(reader != NULL);
+ // Read the values.
+ uint32_t value0 = reader->Read<uint32_t>();
+ uint32_t value1 = reader->Read<uint32_t>();
+ uint32_t value2 = reader->Read<uint32_t>();
+ uint32_t value3 = reader->Read<uint32_t>();
+
+ // Create a Float32x4 object.
+ Uint32x4& simd = Uint32x4::ZoneHandle(reader->isolate(), Uint32x4::null());
+
+ if (kind == Snapshot::kFull) {
+ simd = reader->NewUint32x4(value0, value1, value2, value3);
+ } else {
+ simd = Uint32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
+ }
+ reader->AddBackRef(object_id, &simd, kIsDeserialized);
+ // Set the object tags.
+ simd.set_tags(tags);
+ return simd.raw();
+}
+
+
+void RawUint32x4::WriteTo(SnapshotWriter* writer,
+ intptr_t object_id,
+ Snapshot::Kind kind) {
+ ASSERT(writer != NULL);
+
+ // Write out the serialization header value for this object.
+ writer->WriteInlinedObjectHeader(object_id);
+
+ // Write out the class and tags information.
+ writer->WriteIndexedObject(kUint32x4Cid);
+ writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+ // Write out the mask values.
+ writer->Write<uint32_t>(ptr()->value_[0]);
+ writer->Write<uint32_t>(ptr()->value_[1]);
+ writer->Write<uint32_t>(ptr()->value_[2]);
+ writer->Write<uint32_t>(ptr()->value_[3]);
+}
+
+
RawByteArray* ByteArray::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
@@ -2106,6 +2198,32 @@
BYTEARRAY_TYPE_LIST(BYTEARRAY_READ_FROM)
#undef BYTEARRAY_READ_FROM
+RawFloat32x4Array* Float32x4Array::ReadFrom(SnapshotReader* reader,
+ intptr_t object_id,
+ intptr_t tags,
+ Snapshot::Kind kind) {
+ ASSERT(reader != NULL);
+
+ intptr_t len = reader->ReadSmiValue();
+ Float32x4Array& result = Float32x4Array::ZoneHandle(
+ reader->isolate(), Float32x4Array::New(len, HEAP_SPACE(kind)));
+ reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+ // Set the object tags.
+ result.set_tags(tags);
+
+ // Setup the array elements.
+ float v[4];
+ for (intptr_t i = 0; i < len; ++i) {
+ v[0] = reader->Read<float>();
+ v[1] = reader->Read<float>();
+ v[2] = reader->Read<float>();
+ v[3] = reader->Read<float>();
+ result.SetAt(i, simd_value_safe_load(&v[0]));
+ }
+ return result.raw();
+}
+
#define EXTERNALARRAY_READ_FROM(name, lname, type) \
RawExternal##name##Array* External##name##Array::ReadFrom( \
@@ -2126,8 +2244,8 @@
return obj.raw(); \
} \
-
BYTEARRAY_TYPE_LIST(EXTERNALARRAY_READ_FROM)
+EXTERNALARRAY_READ_FROM(Float32x4, Float32x4, simd_value_t)
#undef EXTERNALARRAY_READ_FROM
@@ -2183,6 +2301,28 @@
BYTEARRAY_TYPE_LIST(BYTEARRAY_WRITE_TO)
#undef BYTEARRAY_WRITE_TO
+void RawFloat32x4Array::WriteTo(SnapshotWriter* writer, intptr_t object_id,
+ Snapshot::Kind kind) {
+ ASSERT(writer != NULL);
+ RawSmi* length = ptr()->length_;
+ float* data = reinterpret_cast<float*>(&ptr()->data_[0]);
+
+ // Write out the serialization header value for this object.
+ writer->WriteInlinedObjectHeader(object_id);
+
+ // Write out the class and tags information.
+ writer->WriteIndexedObject(kFloat32x4ArrayCid);
+ writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+ // Write out the length field.
+ writer->Write<RawObject*>(length);
+
+ // Write out the array elements as floats.
+ intptr_t len = Smi::Value(length)*4;
+ for (intptr_t i = 0; i < len; i++) {
+ writer->Write(data[i]);
+ }
+}
#define EXTERNALARRAY_WRITE_TO(name, lname, type) \
void RawExternal##name##Array::WriteTo(SnapshotWriter* writer, \
@@ -2200,6 +2340,30 @@
BYTEARRAY_TYPE_LIST(EXTERNALARRAY_WRITE_TO)
#undef BYTEARRAY_WRITE_TO
+void RawExternalFloat32x4Array::WriteTo(SnapshotWriter* writer,
+ intptr_t object_id,
+ Snapshot::Kind kind) {
+ ASSERT(writer != NULL);
+ RawSmi* length = ptr()->length_;
+ float* data = reinterpret_cast<float*>(&ptr()->data_[0]);
+
+ // Write out the serialization header value for this object.
+ writer->WriteInlinedObjectHeader(object_id);
+
+ // Write out the class and tags information.
+ writer->WriteIndexedObject(kExternalFloat32x4ArrayCid);
+ writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+ // Write out the length field.
+ writer->Write<RawObject*>(length);
+
+ // Write out the array elements as floats.
+ intptr_t len = Smi::Value(length)*4;
+ for (intptr_t i = 0; i < len; i++) {
+ writer->Write(data[i]);
+ }
+}
+
#undef BYTEARRAY_TYPE_LIST
@@ -2223,7 +2387,32 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNIMPLEMENTED();
+ if (kind == Snapshot::kFull) {
+ Stacktrace& result = Stacktrace::ZoneHandle(reader->isolate(),
+ reader->NewStacktrace());
+ reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+ // There are no non object pointer fields.
+
+ // Read all the object pointer fields.
+ Array& array = Array::Handle(reader->isolate());
+ array ^= reader->ReadObjectRef();
+ result.set_function_array(array);
+ array ^= reader->ReadObjectRef();
+ result.set_code_array(array);
+ array ^= reader->ReadObjectRef();
+ result.set_pc_offset_array(array);
+
+ array ^= reader->ReadObjectRef();
+ result.set_catch_func_array(array);
+ array ^= reader->ReadObjectRef();
+ result.set_catch_code_array(array);
+ array ^= reader->ReadObjectRef();
+ result.set_catch_pc_offset_array(array);
+
+ return result.raw();
+ }
+ UNREACHABLE(); // Stacktraces are not sent in a snapshot.
return Stacktrace::null();
}
@@ -2231,7 +2420,26 @@
void RawStacktrace::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
- UNIMPLEMENTED();
+ if (kind == Snapshot::kFull) {
+ ASSERT(writer != NULL);
+ ASSERT(this == Isolate::Current()->object_store()->
+ preallocated_stack_trace());
+
+ // Write out the serialization header value for this object.
+ writer->WriteInlinedObjectHeader(object_id);
+
+ // Write out the class and tags information.
+ writer->WriteIndexedObject(kStacktraceCid);
+ writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+ // There are no non object pointer fields.
+
+ // Write out all the object pointer fields.
+ SnapshotWriterVisitor visitor(writer);
+ visitor.VisitPointers(from(), to());
+ } else {
+ UNREACHABLE(); // Stacktraces are not supported for other snapshot forms.
+ }
}
diff --git a/runtime/vm/resolver_test.cc b/runtime/vm/resolver_test.cc
index 6e97d71..8b5499b 100644
--- a/runtime/vm/resolver_test.cc
+++ b/runtime/vm/resolver_test.cc
@@ -113,7 +113,7 @@
const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
args.SetAt(1, arg1);
const Smi& retval = Smi::Handle(
- reinterpret_cast<RawSmi*>(DartEntry::InvokeStatic(function, args)));
+ reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
EXPECT_EQ(kTestValue, retval.Value());
}
@@ -188,7 +188,7 @@
const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
args.SetAt(2, arg1);
const Smi& retval = Smi::Handle(
- reinterpret_cast<RawSmi*>(DartEntry::InvokeDynamic(function, args)));
+ reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
EXPECT_EQ(kTestValue, retval.Value());
}
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index e7119b8..77e6b54 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -7,10 +7,36 @@
#include "vm/runtime_entry.h"
+#include "vm/assembler.h"
+#include "vm/simulator.h"
+#include "vm/stub_code.h"
+
namespace dart {
+#define __ assembler->
+
+
+// Generate code to call into the stub which will call the runtime
+// function. Input for the stub is as follows:
+// SP : points to the arguments and return value array.
+// R5 : address of the runtime function to call.
+// R4 : number of arguments to the call.
void RuntimeEntry::Call(Assembler* assembler) const {
- UNIMPLEMENTED();
+ // Compute the effective address. When running under the simulator,
+ // this is a redirection address that forces the simulator to call
+ // into the runtime system.
+ uword entry = GetEntryPoint();
+#if defined(USING_SIMULATOR)
+ entry = Simulator::RedirectExternalReference(entry, argument_count());
+#endif
+ if (is_leaf()) {
+ ExternalLabel label(name(), entry);
+ __ BranchLink(&label);
+ } else {
+ __ LoadImmediate(R5, entry);
+ __ LoadImmediate(R4, argument_count());
+ __ BranchLink(&StubCode::CallToRuntimeLabel());
+ }
}
} // namespace dart
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 952ab88..5d14e41 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -135,14 +135,14 @@
}
-static Register LookupCoreRegisterByName(const char* name) {
+static Register LookupCpuRegisterByName(const char* name) {
static const char* kNames[] = {
"r0", "r1", "r2", "r3",
"r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15",
"pc", "lr", "sp", "ip",
- "fp", "sl"
+ "fp", "pp", "ctx"
};
static const Register kRegisters[] = {
R0, R1, R2, R3,
@@ -150,7 +150,7 @@
R8, R9, R10, R11,
R12, R13, R14, R15,
PC, LR, SP, IP,
- FP, R10
+ FP, R10, R9
};
ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters));
for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) {
@@ -183,7 +183,7 @@
bool SimulatorDebugger::GetValue(char* desc, uint32_t* value) {
- Register reg = LookupCoreRegisterByName(desc);
+ Register reg = LookupCpuRegisterByName(desc);
if (reg != kNoRegister) {
if (reg == PC) {
*value = sim_->get_pc();
@@ -195,6 +195,9 @@
if ((desc[0] == '*')) {
uint32_t addr;
if (GetValue(desc + 1, &addr)) {
+ if (Simulator::IsIllegalAddress(addr)) {
+ return false;
+ }
*value = *(reinterpret_cast<uint32_t*>(addr));
return true;
}
@@ -216,6 +219,9 @@
if ((desc[0] == '*')) {
uint32_t addr;
if (GetValue(desc + 1, &addr)) {
+ if (Simulator::IsIllegalAddress(addr)) {
+ return false;
+ }
*value = *(reinterpret_cast<float*>(addr));
return true;
}
@@ -233,6 +239,9 @@
if ((desc[0] == '*')) {
uint32_t addr;
if (GetValue(desc + 1, &addr)) {
+ if (Simulator::IsIllegalAddress(addr)) {
+ return false;
+ }
*value = *(reinterpret_cast<double*>(addr));
return true;
}
@@ -671,11 +680,11 @@
return reinterpret_cast<uword>(&svc_instruction_);
}
- void* external_function() const { return external_function_; }
+ uword external_function() const { return external_function_; }
uint32_t argument_count() const { return argument_count_; }
- static Redirection* Get(void* external_function, uint32_t argument_count) {
+ static Redirection* Get(uword external_function, uint32_t argument_count) {
Redirection* current;
for (current = list_; current != NULL; current = current->next_) {
if (current->external_function_ == external_function) return current;
@@ -693,7 +702,7 @@
private:
static const int32_t kRedirectSvcInstruction =
((AL << kConditionShift) | (0xf << 24) | kRedirectionSvcCode);
- Redirection(void* external_function, uint32_t argument_count)
+ Redirection(uword external_function, uint32_t argument_count)
: external_function_(external_function),
argument_count_(argument_count),
svc_instruction_(kRedirectSvcInstruction),
@@ -701,7 +710,7 @@
list_ = this;
}
- void* external_function_;
+ uword external_function_;
const uint32_t argument_count_;
uint32_t svc_instruction_;
Redirection* next_;
@@ -712,7 +721,7 @@
Redirection* Redirection::list_ = NULL;
-uword Simulator::RedirectExternalReference(void* function,
+uword Simulator::RedirectExternalReference(uword function,
uint32_t argument_count) {
Redirection* redirection = Redirection::Get(function, argument_count);
return redirection->address_of_svc_instruction();
@@ -956,10 +965,10 @@
// Returns the top of the stack area to enable checking for stack pointer
// validity.
-uintptr_t Simulator::StackTop() const {
+uword Simulator::StackTop() const {
// To be safe in potential stack underflows we leave some buffer above and
// set the stack top.
- return reinterpret_cast<uintptr_t>(stack_) +
+ return reinterpret_cast<uword>(stack_) +
(Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
}
@@ -1316,8 +1325,7 @@
int32_t saved_lr = get_register(LR);
Redirection* redirection = Redirection::FromSvcInstruction(instr);
- intptr_t external =
- reinterpret_cast<intptr_t>(redirection->external_function());
+ uword external = redirection->external_function();
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
if (FLAG_trace_sim) {
@@ -1391,21 +1399,28 @@
if (instr->IsMiscellaneous()) {
switch (instr->Bits(4, 3)) {
case 1: {
- ASSERT(instr->Bits(21, 2) == 0x3);
- // Format(instr, "clz'cond 'rd, 'rm");
- Register rm = instr->RmField();
- Register rd = instr->RdField();
- int32_t rm_val = get_register(rm);
- int32_t rd_val = 0;
- if (rm_val != 0) {
- while (rm_val > 0) {
- rd_val++;
- rm_val <<= 1;
+ if (instr->Bits(21, 2) == 0x3) {
+ // Format(instr, "clz'cond 'rd, 'rm");
+ Register rm = instr->RmField();
+ Register rd = instr->RdField();
+ int32_t rm_val = get_register(rm);
+ int32_t rd_val = 0;
+ if (rm_val != 0) {
+ while (rm_val > 0) {
+ rd_val++;
+ rm_val <<= 1;
+ }
+ } else {
+ rd_val = 32;
}
+ set_register(rd, rd_val);
} else {
- rd_val = 32;
+ ASSERT(instr->Bits(21, 2) == 0x1);
+ // Format(instr, "bx'cond 'rm");
+ Register rm = instr->RmField();
+ int32_t rm_val = get_register(rm);
+ set_pc(rm_val);
}
- set_register(rd, rd_val);
break;
}
case 3: {
@@ -1420,7 +1435,7 @@
}
case 7: {
if (instr->Bits(21, 2) == 0x1) {
- // Format(instr, "bkpt #'imm12_4");
+ // Format(instr, "bkpt'cond #'imm12_4");
SimulatorDebugger dbg(this);
set_pc(get_pc() + Instr::kInstrSize);
char buffer[32];
@@ -2144,6 +2159,57 @@
}
}
}
+ } else if (instr->IsVFPMultipleLoadStore()) {
+ Register rn = instr->RnField();
+ int32_t addr = get_register(rn);
+ int32_t imm_val = instr->Bits(0, 8);
+ if (instr->Bit(23) == 0) {
+ addr -= (imm_val << 2);
+ }
+ if (instr->HasW()) {
+ if (instr->Bit(23) == 1) {
+ set_register(rn, addr + (imm_val << 2));
+ } else {
+ set_register(rn, addr); // already subtracted from addr
+ }
+ }
+ if (IsIllegalAddress(addr)) {
+ HandleIllegalAccess(addr, instr);
+ } else {
+ if (instr->Bit(8) == 0) {
+ int32_t regs_cnt = imm_val;
+ int32_t start = instr->Bit(22) | (instr->Bits(12, 4) << 1);
+ for (int i = start; i < start + regs_cnt; i++) {
+ SRegister sd = static_cast<SRegister>(i);
+ if (instr->Bit(20) == 1) {
+ // Format(instr, "vldms'cond'pu 'rn'w, 'slist");
+ set_sregister(sd, bit_cast<float, int32_t>(ReadW(addr, instr)));
+ } else {
+ // Format(instr, "vstms'cond'pu 'rn'w, 'slist");
+ WriteW(addr, bit_cast<int32_t, float>(get_sregister(sd)), instr);
+ }
+ addr += 4;
+ }
+ } else {
+ int32_t regs_cnt = imm_val >> 1;
+ int32_t start = (instr->Bit(22) << 4) | instr->Bits(12, 4);
+ for (int i = start; i < start + regs_cnt; i++) {
+ DRegister dd = static_cast<DRegister>(i);
+ if (instr->Bit(20) == 1) {
+ // Format(instr, "vldmd'cond'pu 'rn'w, 'dlist");
+ int64_t dd_val = Utils::LowHighTo64Bits(ReadW(addr, instr),
+ ReadW(addr + 4, instr));
+ set_dregister(dd, bit_cast<double, int64_t>(dd_val));
+ } else {
+ // Format(instr, "vstmd'cond'pu 'rn'w, 'dlist");
+ int64_t dd_val = bit_cast<int64_t, double>(get_dregister(dd));
+ WriteW(addr, Utils::Low32Bits(dd_val), instr);
+ WriteW(addr + 4, Utils::High32Bits(dd_val), instr);
+ }
+ addr += 8;
+ }
+ }
+ }
} else {
UNIMPLEMENTED();
}
@@ -2673,7 +2739,7 @@
int32_t r11_val = get_register(R11);
// Setup the callee-saved registers with a known value. To be able to check
- // that they are preserved properly across JS execution.
+ // that they are preserved properly across dart execution.
int32_t callee_saved_value = icount_;
set_register(R4, callee_saved_value);
set_register(R5, callee_saved_value);
diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h
index 7b4a377..2b4589c 100644
--- a/runtime/vm/simulator_arm.h
+++ b/runtime/vm/simulator_arm.h
@@ -27,7 +27,7 @@
class Simulator {
public:
- static const size_t kSimulatorStackUnderflowSize = 64;
+ static const uword kSimulatorStackUnderflowSize = 64;
Simulator();
~Simulator();
@@ -52,9 +52,8 @@
void set_dregister(DRegister reg, double value);
double get_dregister(DRegister reg) const;
- // Accessor to the internal simulator stack area.
- uintptr_t StackTop() const;
- uintptr_t StackLimit() const;
+ // Accessor to the internal simulator stack top.
+ uword StackTop() const;
// Executes ARM instructions until the PC reaches end_sim_pc.
void Execute();
@@ -79,7 +78,7 @@
uword new_value);
// Runtime call support.
- static uword RedirectExternalReference(void* function,
+ static uword RedirectExternalReference(uword function,
uint32_t argument_count);
void Longjmp(int32_t pc, int32_t sp, int32_t fp, const Instance& object);
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 56d73eb..39f92ce 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -17,7 +17,15 @@
namespace dart {
Simulator::Simulator() {
- UNIMPLEMENTED();
+ // Setup simulator support first. Some of this information is needed to
+ // setup the architecture state.
+ // We allocate the stack here, the size is computed as the sum of
+ // the size specified by the user and the buffer space needed for
+ // handling stack overflow exceptions. To be safe in potential
+ // stack underflows we also add some underflow buffer space.
+ stack_ = new char[(Isolate::GetSpecifiedStackSize() +
+ Isolate::kStackSizeBuffer +
+ kSimulatorStackUnderflowSize)];
}
@@ -40,6 +48,31 @@
}
+// Sets the register in the architecture state. It will also deal with updating
+// Simulator internal state for special registers such as PC.
+void Simulator::set_register(Register reg, int32_t value) {
+ UNIMPLEMENTED();
+}
+
+
+// Get the register from the architecture state. This function does handle
+// the special case of accessing the PC register.
+int32_t Simulator::get_register(Register reg) const {
+ UNIMPLEMENTED();
+ return 0;
+}
+
+
+// Returns the top of the stack area to enable checking for stack pointer
+// validity.
+uword Simulator::StackTop() const {
+ // To be safe in potential stack underflows we leave some buffer above and
+ // set the stack top.
+ return reinterpret_cast<uword>(stack_) +
+ (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
+}
+
+
void Simulator::InitOnce() {
}
diff --git a/runtime/vm/simulator_mips.h b/runtime/vm/simulator_mips.h
index b852ebb..cd8df77 100644
--- a/runtime/vm/simulator_mips.h
+++ b/runtime/vm/simulator_mips.h
@@ -16,10 +16,14 @@
#error Do not include simulator_mips.h directly; use simulator.h.
#endif
+#include "vm/constants_mips.h"
+
namespace dart {
class Simulator {
public:
+ static const uword kSimulatorStackUnderflowSize = 64;
+
Simulator();
~Simulator();
@@ -27,6 +31,13 @@
// current isolate
static Simulator* Current();
+ // Accessors for register state.
+ void set_register(Register reg, int32_t value);
+ int32_t get_register(Register reg) const;
+
+ // Accessor to the internal simulator stack top.
+ uword StackTop() const;
+
// Call on program start.
static void InitOnce();
@@ -39,6 +50,9 @@
int32_t parameter2,
int32_t parameter3,
int32_t parameter4);
+
+ private:
+ char* stack_;
};
} // namespace dart
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 70941d9..b729606 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -578,6 +578,36 @@
}
+RawFloat32x4* SnapshotReader::NewFloat32x4(float v0, float v1, float v2,
+ float v3) {
+ ASSERT(kind_ == Snapshot::kFull);
+ ASSERT(isolate()->no_gc_scope_depth() != 0);
+ cls_ = object_store()->float32x4_class();
+ RawFloat32x4* obj = reinterpret_cast<RawFloat32x4*>(
+ AllocateUninitialized(cls_, Float32x4::InstanceSize()));
+ obj->ptr()->value_[0] = v0;
+ obj->ptr()->value_[1] = v1;
+ obj->ptr()->value_[2] = v2;
+ obj->ptr()->value_[3] = v3;
+ return obj;
+}
+
+
+RawUint32x4* SnapshotReader::NewUint32x4(uint32_t v0, uint32_t v1, uint32_t v2,
+ uint32_t v3) {
+ ASSERT(kind_ == Snapshot::kFull);
+ ASSERT(isolate()->no_gc_scope_depth() != 0);
+ cls_ = object_store()->uint32x4_class();
+ RawUint32x4* obj = reinterpret_cast<RawUint32x4*>(
+ AllocateUninitialized(cls_, Uint32x4::InstanceSize()));
+ obj->ptr()->value_[0] = v0;
+ obj->ptr()->value_[1] = v1;
+ obj->ptr()->value_[2] = v2;
+ obj->ptr()->value_[3] = v3;
+ return obj;
+}
+
+
RawApiError* SnapshotReader::NewApiError() {
ALLOC_NEW_OBJECT(ApiError, Object::api_error_class());
}
@@ -601,6 +631,11 @@
}
+RawStacktrace* SnapshotReader::NewStacktrace() {
+ ALLOC_NEW_OBJECT(Stacktrace, object_store()->stacktrace_class());
+}
+
+
RawClass* SnapshotReader::LookupInternalClass(intptr_t class_header) {
// If the header is an object Id, lookup singleton VM classes or classes
// stored in the object store.
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 616235d..be21112 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -42,6 +42,8 @@
class RawRedirectionData;
class RawFunction;
class RawGrowableObjectArray;
+class RawFloat32x4;
+class RawUint32x4;
class RawImmutableArray;
class RawLanguageError;
class RawLibrary;
@@ -54,6 +56,7 @@
class RawPatchClass;
class RawScript;
class RawSmi;
+class RawStacktrace;
class RawTokenStream;
class RawType;
class RawTypeParameter;
@@ -263,9 +266,12 @@
RawScript* NewScript();
RawLiteralToken* NewLiteralToken();
RawGrowableObjectArray* NewGrowableObjectArray();
+ RawFloat32x4* NewFloat32x4(float v0, float v1, float v2, float v3);
+ RawUint32x4* NewUint32x4(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3);
RawApiError* NewApiError();
RawLanguageError* NewLanguageError();
RawObject* NewInteger(int64_t value);
+ RawStacktrace* NewStacktrace();
private:
class BackRefNode : public ZoneAllocated {
@@ -340,6 +346,7 @@
friend class LiteralToken;
friend class PatchClass;
friend class Script;
+ friend class Stacktrace;
friend class TokenStream;
friend class Type;
friend class TypeArguments;
diff --git a/runtime/vm/snapshot_test.dart b/runtime/vm/snapshot_test.dart
index b42d771..9742c38 100644
--- a/runtime/vm/snapshot_test.dart
+++ b/runtime/vm/snapshot_test.dart
@@ -104,8 +104,8 @@
class Towers {
List<TowersDisk> piles;
int movesDone;
- Towers(int disks)
- : piles = new List<TowersDisk>.fixedLength(3), movesDone = 0 {
+ Towers(int disks)
+ : piles = new List<TowersDisk>(3), movesDone = 0 {
build(0, disks);
}
@@ -178,7 +178,7 @@
static int sieve(int size) {
int primeCount = 0;
- List<bool> flags = new List<bool>.fixedLength(size + 1);
+ List<bool> flags = new List<bool>(size + 1);
for (int i = 1; i < size; i++) flags[i] = true;
for (int i = 2; i < size; i++) {
if (flags[i]) {
@@ -236,7 +236,7 @@
int permute(int size) {
permuteCount = 0;
- List<int> list = new List<int>.fixedLength(size);
+ List<int> list = new List<int>(size);
for (int i = 1; i < size; i++) list[i] = i - 1;
doPermute(size - 1, list);
return permuteCount;
@@ -299,10 +299,10 @@
}
static void queens() {
- List<bool> a = new List<bool>.fixedLength(9);
- List<bool> b = new List<bool>.fixedLength(17);
- List<bool> c = new List<bool>.fixedLength(15);
- List<int> x = new List<int>.fixedLength(9);
+ List<bool> a = new List<bool>(9);
+ List<bool> b = new List<bool>(17);
+ List<bool> c = new List<bool>(15);
+ List<int> x = new List<int>(9);
b[1] = false;
for (int i = -7; i <= 16; i++) {
if ((i >= 1) && (i <= 8)) a[i] = true;
@@ -408,7 +408,7 @@
SortData(int length) {
Random r = new Random();
- list = new List<int>.fixedLength(length);
+ list = new List<int>(length);
for (int i = 0; i < length; i++) list[i] = r.random();
int min, max;
@@ -829,7 +829,7 @@
text += text;
CharAtBenchmark.test(text, ITERATE3);
NumberBenchmark.test(text, ITERATE3);
- CharCodeAtBenchmark.test(text, ITERATE3);
+ CodeUnitAtBenchmark.test(text, ITERATE3);
IndexOfBenchmark.test(text, ITERATE3);
LastIndexOfBenchmark.test(text, ITERATE3);
SliceBenchmark.test(text, ITERATE4);
@@ -918,17 +918,17 @@
}
-class CharCodeAtBenchmark {
- CharCodeAtBenchmark() {}
+class CodeUnitAtBenchmark {
+ CodeUnitAtBenchmark() {}
static String test(String input, var iterations) {
var str;
for (var j = 0; j < iterations; j++) {
- str = input.charCodeAt(0);
- str = input.charCodeAt(input.length - 1);
- str = input.charCodeAt(150); //set it to 15000
- str = input.charCodeAt(100); //set it to 10000
- str = input.charCodeAt(50); //set it to 5000
+ str = input.codeUnitAt(0);
+ str = input.codeUnitAt(input.length - 1);
+ str = input.codeUnitAt(150); //set it to 15000
+ str = input.codeUnitAt(100); //set it to 10000
+ str = input.codeUnitAt(50); //set it to 5000
}
return str;
}
@@ -1319,7 +1319,7 @@
List local_list1 = ["Hello", "World", "Hello", 0xffffffffff];
List local_list2 = [null, local_list1, local_list1 ];
List local_list3 = [local_list2, 2.0, true, false, 0xffffffffff];
- List sendObject = new List.fixedLength(5);
+ List sendObject = new List(5);
sendObject[0] = local_list1;
sendObject[1] = sendObject;
sendObject[2] = local_list2;
@@ -1443,7 +1443,7 @@
MandelbrotState() {
_result = new List<List<int>>(N);
- _lineProcessedBy = new List<LineProcessorClient>.fixedLength(N);
+ _lineProcessedBy = new List<LineProcessorClient>(N);
_sent = 0;
_missing = N;
_validated = new Completer<bool>();
@@ -1523,7 +1523,7 @@
List<int> processLine(int y) {
double inverseN = 2.0 / N;
double Civ = y * inverseN - 1.0;
- List<int> result = new List<int>.fixedLength(N);
+ List<int> result = new List<int>(N);
for (int x = 0; x < N; x++) {
double Crv = x * inverseN - 1.5;
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index ca20583..f0fdd3e 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -20,7 +20,8 @@
bool StackFrame::IsStubFrame() const {
ASSERT(!(IsEntryFrame() || IsExitFrame()));
- uword saved_pc = *(reinterpret_cast<uword*>(fp() - kWordSize));
+ uword saved_pc =
+ *(reinterpret_cast<uword*>(fp() + EntrypointMarkerOffsetFromFp()));
return (saved_pc == 0);
}
@@ -138,7 +139,8 @@
// a GC as we are handling raw object references here. It is possible
// that the code is called while a GC is in progress, that is ok.
NoGCScope no_gc;
- uword saved_pc = *(reinterpret_cast<uword*>(fp() - kWordSize));
+ uword saved_pc =
+ *(reinterpret_cast<uword*>(fp() + EntrypointMarkerOffsetFromFp()));
if (saved_pc != 0) {
uword entry_point =
(saved_pc - AssemblerMacros::kOffsetOfSavedPCfromEntrypoint);
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 483f212..5e5290d 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -34,7 +34,7 @@
void SetEntrypointMarker(uword value) {
ASSERT(!(IsStubFrame() || IsEntryFrame() || IsExitFrame()));
- *reinterpret_cast<uword*>(fp_ - kWordSize) = value;
+ *reinterpret_cast<uword*>(fp_ + EntrypointMarkerOffsetFromFp()) = value;
}
// Visit objects in the frame.
@@ -73,6 +73,7 @@
// Target specific implementations for locating pc and caller fp/sp values.
static intptr_t PcAddressOffsetFromSp();
+ static intptr_t EntrypointMarkerOffsetFromFp();
uword GetCallerSp() const;
uword GetCallerFp() const;
diff --git a/runtime/vm/stack_frame_arm.cc b/runtime/vm/stack_frame_arm.cc
index 8d4ee28..e3ea537 100644
--- a/runtime/vm/stack_frame_arm.cc
+++ b/runtime/vm/stack_frame_arm.cc
@@ -5,47 +5,63 @@
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM)
+#include "vm/instructions.h"
+#include "vm/isolate.h"
#include "vm/stack_frame.h"
namespace dart {
+// The constant kExitLinkOffsetInEntryFrame must be kept in sync with the
+// code in the InvokeDartCode stub.
+static const int kSavedContextOffsetInEntryFrame = -10 * kWordSize;
+static const int kExitLinkOffsetInEntryFrame = -9 * kWordSize;
+static const int kPcAddressOffsetFromSp = -2 * kWordSize;
+static const int kEntrypointMarkerOffsetFromFp = 2 * kWordSize;
+static const int kSpOffsetFromPreviousFp = 3 * kWordSize;
+
+
intptr_t StackFrame::PcAddressOffsetFromSp() {
- UNIMPLEMENTED();
- return 0;
+ return kPcAddressOffsetFromSp;
}
-uword StackFrame::GetCallerFp() const {
- UNIMPLEMENTED();
- return 0;
+intptr_t StackFrame::EntrypointMarkerOffsetFromFp() {
+ return kEntrypointMarkerOffsetFromFp;
}
uword StackFrame::GetCallerSp() const {
- UNIMPLEMENTED();
- return 0;
+ return fp() + kSpOffsetFromPreviousFp;
+}
+
+
+uword StackFrame::GetCallerFp() const {
+ return *(reinterpret_cast<uword*>(fp()));
}
intptr_t EntryFrame::ExitLinkOffset() const {
- UNIMPLEMENTED();
- return 0;
+ return kExitLinkOffsetInEntryFrame;
}
intptr_t EntryFrame::SavedContextOffset() const {
- UNIMPLEMENTED();
- return 0;
+ return kSavedContextOffsetInEntryFrame;
}
void StackFrameIterator::SetupLastExitFrameData() {
- UNIMPLEMENTED();
+ Isolate* current = Isolate::Current();
+ uword exit_marker = current->top_exit_frame_info();
+ frames_.fp_ = exit_marker;
}
void StackFrameIterator::SetupNextExitFrameData() {
- UNIMPLEMENTED();
+ uword exit_address = entry_.fp() + kExitLinkOffsetInEntryFrame;
+ uword exit_marker = *reinterpret_cast<uword*>(exit_address);
+ frames_.fp_ = exit_marker;
+ frames_.sp_ = 0;
}
} // namespace dart
diff --git a/runtime/vm/stack_frame_ia32.cc b/runtime/vm/stack_frame_ia32.cc
index b3f554e..ae4de47 100644
--- a/runtime/vm/stack_frame_ia32.cc
+++ b/runtime/vm/stack_frame_ia32.cc
@@ -16,6 +16,7 @@
static const int kSavedContextOffsetInEntryFrame = -5 * kWordSize;
static const int kExitLinkOffsetInEntryFrame = -4 * kWordSize;
static const int kPcAddressOffsetFromSp = -1 * kWordSize;
+static const int kEntrypointMarkerOffsetFromFp = -1 * kWordSize;
static const int kSpOffsetFromPreviousFp = 2 * kWordSize;
@@ -24,6 +25,11 @@
}
+intptr_t StackFrame::EntrypointMarkerOffsetFromFp() {
+ return kEntrypointMarkerOffsetFromFp;
+}
+
+
uword StackFrame::GetCallerSp() const {
return fp() + kSpOffsetFromPreviousFp;
}
diff --git a/runtime/vm/stack_frame_mips.cc b/runtime/vm/stack_frame_mips.cc
index eb79f18..b15de57 100644
--- a/runtime/vm/stack_frame_mips.cc
+++ b/runtime/vm/stack_frame_mips.cc
@@ -15,6 +15,12 @@
}
+intptr_t StackFrame::EntrypointMarkerOffsetFromFp() {
+ UNIMPLEMENTED();
+ return 0;
+}
+
+
uword StackFrame::GetCallerFp() const {
UNIMPLEMENTED();
return 0;
diff --git a/runtime/vm/stack_frame_x64.cc b/runtime/vm/stack_frame_x64.cc
index d0ae422..64ff644 100644
--- a/runtime/vm/stack_frame_x64.cc
+++ b/runtime/vm/stack_frame_x64.cc
@@ -16,6 +16,7 @@
static const int kSavedContextOffsetInEntryFrame = -9 * kWordSize;
static const int kExitLinkOffsetInEntryFrame = -8 * kWordSize;
static const int kPcAddressOffsetFromSp = -1 * kWordSize;
+static const int kEntrypointMarkerOffsetFromFp = -1 * kWordSize;
static const int kSpOffsetFromPreviousFp = 2 * kWordSize;
@@ -24,6 +25,11 @@
}
+intptr_t StackFrame::EntrypointMarkerOffsetFromFp() {
+ return kEntrypointMarkerOffsetFromFp;
+}
+
+
uword StackFrame::GetCallerSp() const {
return fp() + kSpOffsetFromPreviousFp;
}
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 50c189b..32ea56f 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -5,14 +5,127 @@
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM)
+#include "vm/assembler.h"
+#include "vm/assembler_macros.h"
+#include "vm/code_generator.h"
+#include "vm/dart_entry.h"
+#include "vm/instructions.h"
+#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#define __ assembler->
namespace dart {
+// Input parameters:
+// LR : return address.
+// SP : address of last argument in argument array.
+// SP + 4*R4 - 4 : address of first argument in argument array.
+// SP + 4*R4 : address of return value.
+// R5 : address of the runtime function to call.
+// R4 : number of arguments to the call.
void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
- __ Unimplemented("CallToRuntime stub");
+ const intptr_t isolate_offset = NativeArguments::isolate_offset();
+ const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
+ const intptr_t argv_offset = NativeArguments::argv_offset();
+ const intptr_t retval_offset = NativeArguments::retval_offset();
+ __ EnterFrame((1 << FP) | (1 << LR), 0);
+
+ // Load current Isolate pointer from Context structure into R0.
+ __ ldr(R0, FieldAddress(CTX, Context::isolate_offset()));
+
+ // Save exit frame information to enable stack walking as we are about
+ // to transition to Dart VM C++ code.
+ {
+ // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+ // restriction on the offset.
+ const intptr_t offset = Isolate::top_exit_frame_info_offset();
+ const int32_t offset12_hi = offset & ~kOffset12Mask; // signed
+ const uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
+ __ AddImmediate(IP, R0, offset12_hi);
+ __ str(SP, Address(IP, offset12_lo));
+ }
+
+ // Save current Context pointer into Isolate structure.
+ {
+ // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+ // restriction on the offset.
+ const intptr_t offset = Isolate::top_context_offset();
+ const int32_t offset12_hi = offset & ~kOffset12Mask; // signed
+ const uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
+ __ AddImmediate(IP, R0, offset12_hi);
+ __ str(CTX, Address(IP, offset12_lo));
+ }
+
+ // Cache Isolate pointer into CTX while executing runtime code.
+ __ mov(CTX, ShifterOperand(R0));
+
+ // Reserve space for arguments and align frame before entering C++ world.
+ // NativeArguments are passed in registers.
+ ASSERT(sizeof(NativeArguments) == 4 * kWordSize);
+ __ ReserveAlignedFrameSpace(0);
+
+ // Pass NativeArguments structure by value and call runtime.
+ // Registers R0, R1, R2, and R3 are used.
+
+ ASSERT(isolate_offset == 0 * kWordSize);
+ __ mov(R0, ShifterOperand(CTX)); // Set isolate in NativeArgs.
+
+ // There are no runtime calls to closures, so we do not need to set the tag
+ // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
+ ASSERT(argc_tag_offset == 1 * kWordSize);
+ __ mov(R1, ShifterOperand(R4)); // Set argc in NativeArguments.
+
+ ASSERT(argv_offset == 2 * kWordSize);
+ __ add(R2, FP, ShifterOperand(R4, LSL, 2)); // Compute argv.
+ __ AddImmediate(R2, kWordSize); // Set argv in NativeArguments.
+
+ ASSERT(retval_offset == 3 * kWordSize);
+ __ add(R3, R2, ShifterOperand(kWordSize)); // Retval is next to 1st argument.
+
+ // Call runtime or redirection via simulator.
+ __ blx(R5);
+
+ // Reset exit frame information in Isolate structure.
+ __ LoadImmediate(R2, 0);
+ {
+ // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+ // restriction on the offset.
+ const intptr_t offset = Isolate::top_exit_frame_info_offset();
+ const int32_t offset12_hi = offset & ~kOffset12Mask; // signed
+ const uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
+ __ AddImmediate(IP, CTX, offset12_hi);
+ __ str(R2, Address(IP, offset12_lo));
+ }
+
+ // Load Context pointer from Isolate structure into R2.
+ {
+ // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+ // restriction on the offset.
+ const intptr_t offset = Isolate::top_context_offset();
+ const int32_t offset12_hi = offset & ~kOffset12Mask; // signed
+ const uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
+ __ AddImmediate(IP, CTX, offset12_hi);
+ __ ldr(R2, Address(IP, offset12_lo));
+ }
+
+ // Reset Context pointer in Isolate structure.
+ __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null()));
+ {
+ // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+ // restriction on the offset.
+ const intptr_t offset = Isolate::top_context_offset();
+ const int32_t offset12_hi = offset & ~kOffset12Mask; // signed
+ const uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
+ __ AddImmediate(IP, CTX, offset12_hi);
+ __ str(R3, Address(IP, offset12_lo));
+ }
+
+ // Cache Context pointer into CTX while executing Dart code.
+ __ mov(CTX, ShifterOperand(R2));
+
+ __ LeaveFrame((1 << FP) | (1 << LR));
+ __ Ret();
}
@@ -26,8 +139,22 @@
}
+// Input parameters:
+// R4: arguments descriptor array.
void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
- __ Unimplemented("CallStaticFunction stub");
+ AssemblerMacros::EnterStubFrame(assembler);
+ // Setup space on stack for return value and preserve arguments descriptor.
+ __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ PushList((1 << R0) | (1 << R4));
+ __ CallRuntime(kPatchStaticCallRuntimeEntry);
+ // Get Code object result and restore arguments descriptor array.
+ __ PopList((1 << R0) | (1 << R4));
+ // Remove the stub frame as we are about to jump to the dart function.
+ AssemblerMacros::LeaveStubFrame(assembler);
+
+ __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
+ __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
+ __ bx(R0);
}
@@ -66,8 +193,134 @@
}
+// Called when invoking Dart code from C++ (VM code).
+// Input parameters:
+// LR : points to return address.
+// R0 : entrypoint of the Dart function to call.
+// R1 : arguments descriptor array.
+// R2 : arguments array.
+// R3 : new context containing the current isolate pointer.
void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
- __ Unimplemented("InvokeDartCode stub");
+ // Save frame pointer coming in.
+ AssemblerMacros::EnterStubFrame(assembler);
+
+ // Save new context and C++ ABI callee-saved registers.
+ const intptr_t kNewContextOffset =
+ -(1 + kAbiPreservedCpuRegCount) * kWordSize;
+ __ PushList((1 << R3) | kAbiPreservedCpuRegs);
+
+ // The new Context structure contains a pointer to the current Isolate
+ // structure. Cache the Context pointer in the CTX register so that it is
+ // available in generated code and calls to Isolate::Current() need not be
+ // done. The assumption is that this register will never be clobbered by
+ // compiled or runtime stub code.
+
+ // Cache the new Context pointer into CTX while executing Dart code.
+ __ ldr(CTX, Address(R3, VMHandles::kOffsetOfRawPtrInHandle));
+
+ // Load Isolate pointer from Context structure into temporary register R8.
+ __ ldr(R8, FieldAddress(CTX, Context::isolate_offset()));
+
+ // Save the top exit frame info. Use R5 as a temporary register.
+ // StackFrameIterator reads the top exit frame info saved in this frame.
+ {
+ // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+ // restriction on the offset.
+ const intptr_t offset = Isolate::top_exit_frame_info_offset();
+ const int32_t offset12_hi = offset & ~kOffset12Mask; // signed
+ const uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
+ __ AddImmediate(R7, R8, offset12_hi);
+ __ ldr(R5, Address(R7, offset12_lo));
+ __ LoadImmediate(R6, 0);
+ __ str(R6, Address(R7, offset12_lo));
+ }
+
+ // Save the old Context pointer. Use R4 as a temporary register.
+ // Note that VisitObjectPointers will find this saved Context pointer during
+ // GC marking, since it traverses any information between SP and
+ // FP - kExitLinkOffsetInEntryFrame.
+ // EntryFrame::SavedContext reads the context saved in this frame.
+ {
+ const intptr_t offset = Isolate::top_context_offset();
+ const int32_t offset12_hi = offset & ~kOffset12Mask; // signed
+ const uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
+ __ AddImmediate(R7, R8, offset12_hi);
+ __ ldr(R4, Address(R7, offset12_lo));
+ }
+
+ // The constants kSavedContextOffsetInEntryFrame and
+ // kExitLinkOffsetInEntryFrame must be kept in sync with the code below.
+ __ PushList((1 << R4) | (1 << R5));
+
+ // The stack pointer is restore after the call to this location.
+ const intptr_t kSavedContextOffsetInEntryFrame = -10 * kWordSize;
+
+ // Load arguments descriptor array into R4, which is passed to Dart code.
+ __ ldr(R4, Address(R1, VMHandles::kOffsetOfRawPtrInHandle));
+
+ // Load number of arguments into R5.
+ __ ldr(R5, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+ __ SmiUntag(R5);
+
+ // Compute address of 'arguments array' data area into R2.
+ __ ldr(R2, Address(R2, VMHandles::kOffsetOfRawPtrInHandle));
+ __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag);
+
+ // Set up arguments for the Dart call.
+ Label push_arguments;
+ Label done_push_arguments;
+ __ CompareImmediate(R5, 0); // check if there are arguments.
+ __ b(&done_push_arguments, EQ);
+ __ LoadImmediate(R1, 0);
+ __ Bind(&push_arguments);
+ __ ldr(R3, Address(R2));
+ __ Push(R3);
+ __ AddImmediate(R2, kWordSize);
+ __ AddImmediate(R1, 1);
+ __ cmp(R1, ShifterOperand(R5));
+ __ b(&push_arguments, LT);
+ __ Bind(&done_push_arguments);
+
+ // Call the Dart code entrypoint.
+ __ blx(R0); // R4 is the arguments descriptor array.
+
+ // Read the saved new Context pointer.
+ __ ldr(CTX, Address(FP, kNewContextOffset));
+ __ ldr(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle));
+
+ // Get rid of arguments pushed on the stack.
+ __ AddImmediate(SP, FP, kSavedContextOffsetInEntryFrame);
+
+ // Load Isolate pointer from Context structure into CTX. Drop Context.
+ __ ldr(CTX, FieldAddress(CTX, Context::isolate_offset()));
+
+ // Restore the saved Context pointer into the Isolate structure.
+ // Uses R4 as a temporary register for this.
+ // Restore the saved top exit frame info back into the Isolate structure.
+ // Uses R5 as a temporary register for this.
+ __ PopList((1 << R4) | (1 << R5));
+ {
+ const intptr_t offset = Isolate::top_context_offset();
+ const int32_t offset12_hi = offset & ~kOffset12Mask; // signed
+ const uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
+ __ AddImmediate(R7, CTX, offset12_hi);
+ __ str(R4, Address(R7, offset12_lo));
+ }
+ {
+ const intptr_t offset = Isolate::top_exit_frame_info_offset();
+ const int32_t offset12_hi = offset & ~kOffset12Mask; // signed
+ const uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
+ __ AddImmediate(R7, CTX, offset12_hi);
+ __ str(R5, Address(R7, offset12_lo));
+ }
+
+ // Restore C++ ABI callee-saved registers.
+ __ PopList((1 << R3) | kAbiPreservedCpuRegs); // Ignore restored R3.
+
+ // Restore the frame pointer.
+ AssemblerMacros::LeaveStubFrame(assembler);
+
+ __ Ret();
}
diff --git a/runtime/vm/stub_code_arm_test.cc b/runtime/vm/stub_code_arm_test.cc
index a1893b1..67a15c9 100644
--- a/runtime/vm/stub_code_arm_test.cc
+++ b/runtime/vm/stub_code_arm_test.cc
@@ -55,7 +55,7 @@
*CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
- result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+ result ^= DartEntry::InvokeFunction(function, Object::empty_array());
EXPECT_EQ((value1 - value2), result.Value());
}
@@ -80,7 +80,7 @@
*CreateFunction("Test_CallLeafRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
- result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+ result ^= DartEntry::InvokeFunction(function, Object::empty_array());
EXPECT_EQ((value1 + value2), result.Value());
}
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 387a52d..f844588 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -679,28 +679,25 @@
AssemblerMacros::EnterStubFrame(assembler);
__ pushl(raw_null); // Setup space on stack for result from error reporting.
- __ pushl(EDI); // Non-closure object.
__ pushl(EDX); // Arguments descriptor.
// Load smi-tagged arguments array length, including the non-closure.
__ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
- // See stack layout below explaining "wordSize * 6" offset.
- PushArgumentsArray(assembler, (kWordSize * 6));
+ // See stack layout below explaining "wordSize * 5" offset.
+ PushArgumentsArray(assembler, (kWordSize * 5));
// Stack:
// TOS + 0: Argument array.
// TOS + 1: Arguments descriptor array.
- // TOS + 2: Non-closure object.
- // TOS + 3: Place for result from the call.
- // TOS + 4: PC marker => RawInstruction object.
- // TOS + 5: Saved EBP of previous frame. <== EBP
- // TOS + 6: Dart code return address
- // TOS + 7: Last argument of caller.
+ // TOS + 2: Place for result from the call.
+ // TOS + 3: PC marker => RawInstruction object.
+ // TOS + 4: Saved EBP of previous frame. <== EBP
+ // TOS + 5: Dart code return address
+ // TOS + 6: Last argument of caller.
// ....
__ CallRuntime(kInvokeNonClosureRuntimeEntry);
// Remove arguments.
__ popl(EAX);
__ popl(EAX);
- __ popl(EAX);
__ popl(EAX); // Get result into EAX.
// Remove the stub frame as we are about to return.
diff --git a/runtime/vm/stub_code_ia32_test.cc b/runtime/vm/stub_code_ia32_test.cc
index 222fd0f..6e43487 100644
--- a/runtime/vm/stub_code_ia32_test.cc
+++ b/runtime/vm/stub_code_ia32_test.cc
@@ -71,7 +71,7 @@
*CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
- result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+ result ^= DartEntry::InvokeFunction(function, Object::empty_array());
EXPECT_EQ((value1 - value2), result.Value());
}
@@ -106,7 +106,7 @@
*CreateFunction("Test_CallLeafRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
- result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+ result ^= DartEntry::InvokeFunction(function, Object::empty_array());
EXPECT_EQ((value1 + value2), result.Value());
}
diff --git a/runtime/vm/stub_code_mips_test.cc b/runtime/vm/stub_code_mips_test.cc
index 7181fda..df573cb 100644
--- a/runtime/vm/stub_code_mips_test.cc
+++ b/runtime/vm/stub_code_mips_test.cc
@@ -55,7 +55,7 @@
*CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
- result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+ result ^= DartEntry::InvokeFunction(function, Object::empty_array());
EXPECT_EQ((value1 - value2), result.Value());
}
@@ -80,7 +80,7 @@
*CreateFunction("Test_CallLeafRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
- result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+ result ^= DartEntry::InvokeFunction(function, Object::empty_array());
EXPECT_EQ((value1 + value2), result.Value());
}
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index de2b1de..703a058 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -668,28 +668,25 @@
AssemblerMacros::EnterStubFrame(assembler);
__ pushq(raw_null); // Setup space on stack for result from call.
- __ pushq(R13); // Non-closure object.
__ pushq(R10); // Arguments descriptor.
// Load smi-tagged arguments array length, including the non-closure.
__ movq(R10, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
- // See stack layout below explaining "wordSize * 6" offset.
- PushArgumentsArray(assembler, (kWordSize * 6));
+ // See stack layout below explaining "wordSize * 5" offset.
+ PushArgumentsArray(assembler, (kWordSize * 5));
// Stack:
// TOS + 0: Argument array.
// TOS + 1: Arguments descriptor array.
- // TOS + 2: Non-closure object.
- // TOS + 3: Place for result from the call.
- // TOS + 4: PC marker => RawInstruction object.
- // TOS + 5: Saved RBP of previous frame. <== RBP
- // TOS + 6: Dart code return address
- // TOS + 7: Last argument of caller.
+ // TOS + 2: Place for result from the call.
+ // TOS + 3: PC marker => RawInstruction object.
+ // TOS + 4: Saved RBP of previous frame. <== RBP
+ // TOS + 5: Dart code return address
+ // TOS + 6: Last argument of caller.
// ....
__ CallRuntime(kInvokeNonClosureRuntimeEntry);
// Remove arguments.
__ popq(RAX);
__ popq(RAX);
- __ popq(RAX);
__ popq(RAX); // Get result into RAX.
// Remove the stub frame as we are about to return.
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index 20a7d7a..b73a0b4 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -71,7 +71,7 @@
*CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
- result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+ result ^= DartEntry::InvokeFunction(function, Object::empty_array());
EXPECT_EQ((value1 - value2), result.Value());
}
@@ -104,7 +104,7 @@
*CreateFunction("Test_CallLeafRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
- result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+ result ^= DartEntry::InvokeFunction(function, Object::empty_array());
EXPECT_EQ((value1 + value2), result.Value());
}
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index ee82911..afac4a3 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -44,7 +44,6 @@
V(List, "List") \
V(ListLiteralFactory, "List._fromLiteral") \
V(ListFactory, "List.") \
- V(ListFixedLengthFactory, "List.fixedLength") \
V(Map, "Map") \
V(MapLiteralFactory, "Map._fromLiteral") \
V(ImmutableMap, "ImmutableMap") \
@@ -111,17 +110,24 @@
V(_Double, "_Double") \
V(Bool, "bool") \
V(ObjectArray, "_ObjectArray") \
+ V(ObjectArrayDot, "_ObjectArray.") \
V(GrowableObjectArray, "_GrowableObjectArray") \
+ V(GrowableObjectArrayDot, "_GrowableObjectArray.") \
+ V(GrowableObjectArrayWithData, "_GrowableObjectArray.withData") \
V(ImmutableArray, "_ImmutableArray") \
V(OneByteString, "_OneByteString") \
V(TwoByteString, "_TwoByteString") \
V(ExternalOneByteString, "_ExternalOneByteString") \
V(ExternalTwoByteString, "_ExternalTwoByteString") \
- V(Stacktrace, "Stacktrace") \
+ V(StackTrace, "StackTrace") \
V(JSSyntaxRegExp, "_JSSyntaxRegExp") \
V(Object, "Object") \
V(Int, "int") \
V(Double, "double") \
+ V(_Float32x4, "_Float32x4") \
+ V(_Uint32x4, "_Uint32x4") \
+ V(Float32x4, "Float32x4") \
+ V(Uint32x4, "Uint32x4") \
V(Int8List, "Int8List") \
V(Uint8List, "Uint8List") \
V(Uint8ClampedList, "Uint8ClampedList") \
@@ -131,6 +137,7 @@
V(Uint32List, "Uint32List") \
V(Int64List, "Int64List") \
V(Uint64List, "Uint64List") \
+ V(Float32x4List, "Float32x4List") \
V(Float32List, "Float32List") \
V(Float64List, "Float64List") \
V(_Int8Array, "_Int8Array") \
@@ -142,6 +149,7 @@
V(_Uint32Array, "_Uint32Array") \
V(_Int64Array, "_Int64Array") \
V(_Uint64Array, "_Uint64Array") \
+ V(_Float32x4Array, "_Float32x4Array") \
V(_Float32Array, "_Float32Array") \
V(_Float64Array, "_Float64Array") \
V(_ExternalInt8Array, "_ExternalInt8Array") \
@@ -153,6 +161,7 @@
V(_ExternalUint32Array, "_ExternalUint32Array") \
V(_ExternalInt64Array, "_ExternalInt64Array") \
V(_ExternalUint64Array, "_ExternalUint64Array") \
+ V(_ExternalFloat32x4Array, "_ExternalFloat32x4Array") \
V(_ExternalFloat32Array, "_ExternalFloat32Array") \
V(_ExternalFloat64Array, "_ExternalFloat64Array") \
V(_WeakProperty, "_WeakProperty") \
@@ -174,9 +183,9 @@
V(OutOfMemoryError, "OutOfMemoryError") \
V(InternalError, "InternalError") \
V(NullThrownError, "NullThrownError") \
- V(IllegalJSRegExpException, "IllegalJSRegExpException") \
V(IsolateSpawnException, "IsolateSpawnException") \
V(IsolateUnhandledException, "IsolateUnhandledException") \
+ V(_setupFullStackTrace, "_setupFullStackTrace") \
V(BooleanExpression, "boolean expression") \
V(Malformed, "malformed") \
V(InstanceOf, "InstanceOf") \
diff --git a/runtime/vm/unicode.h b/runtime/vm/unicode.h
index 993ee9e..3a9b862 100644
--- a/runtime/vm/unicode.h
+++ b/runtime/vm/unicode.h
@@ -79,12 +79,12 @@
int32_t* dst,
intptr_t len);
- private:
static const int32_t kMaxOneByteChar = 0x7F;
static const int32_t kMaxTwoByteChar = 0x7FF;
static const int32_t kMaxThreeByteChar = 0xFFFF;
static const int32_t kMaxFourByteChar = Utf::kMaxCodePoint;
+ private:
static bool IsTrailByte(uint8_t code_unit) {
return (code_unit & 0xC0) == 0x80;
}
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 26547cc..308b8ba 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -84,7 +84,7 @@
} \
static void CodeGenTestRun##name(const Function& function) { \
Object& result = Object::Handle(); \
- result = DartEntry::InvokeStatic(function, Object::empty_array()); \
+ result = DartEntry::InvokeFunction(function, Object::empty_array()); \
EXPECT(!result.IsError()); \
Instance& actual = Instance::Handle(); \
actual ^= result.raw(); \
@@ -122,7 +122,7 @@
} \
static void CodeGenTestRun##name1(const Function& function) { \
Object& result = Object::Handle(); \
- result = DartEntry::InvokeStatic(function, Object::empty_array()); \
+ result = DartEntry::InvokeFunction(function, Object::empty_array()); \
EXPECT(!result.IsError()); \
Instance& actual = Instance::Handle(); \
actual ^= result.raw(); \
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index ca69ca5..1c1b10f 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -19,6 +19,7 @@
'isolate_cc_file': '<(SHARED_INTERMEDIATE_DIR)/isolate_gen.cc',
'isolate_patch_cc_file': '<(SHARED_INTERMEDIATE_DIR)/isolate_patch_gen.cc',
'json_cc_file': '<(SHARED_INTERMEDIATE_DIR)/json_gen.cc',
+ 'json_patch_cc_file': '<(SHARED_INTERMEDIATE_DIR)/json_patch_gen.cc',
'scalarlist_cc_file': '<(SHARED_INTERMEDIATE_DIR)/scalarlist_gen.cc',
'scalarlist_patch_cc_file': '<(SHARED_INTERMEDIATE_DIR)/scalarlist_patch_gen.cc',
'uri_cc_file': '<(SHARED_INTERMEDIATE_DIR)/uri_gen.cc',
@@ -101,6 +102,7 @@
'generate_isolate_cc_file',
'generate_isolate_patch_cc_file',
'generate_json_cc_file',
+ 'generate_json_patch_cc_file',
'generate_mirrors_cc_file',
'generate_mirrors_patch_cc_file',
'generate_scalarlist_cc_file',
@@ -131,6 +133,7 @@
'<(isolate_cc_file)',
'<(isolate_patch_cc_file)',
'<(json_cc_file)',
+ '<(json_patch_cc_file)',
'<(mirrors_cc_file)',
'<(mirrors_patch_cc_file)',
'<(scalarlist_cc_file)',
@@ -848,6 +851,44 @@
]
},
{
+ 'target_name': 'generate_json_patch_cc_file',
+ 'type': 'none',
+ 'includes': [
+ # Load the shared json library sources.
+ '../lib/json_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_json_patch_cc',
+ 'inputs': [
+ '../tools/create_string_literal.py',
+ '<(builtin_in_cc_file)',
+ '<@(_sources)',
+ ],
+ 'outputs': [
+ '<(json_patch_cc_file)',
+ ],
+ 'action': [
+ 'python',
+ 'tools/create_string_literal.py',
+ '--output', '<(json_patch_cc_file)',
+ '--input_cc', '<(builtin_in_cc_file)',
+ '--include', 'vm/bootstrap.h',
+ '--var_name', 'dart::Bootstrap::json_patch_',
+ '<@(_sources)',
+ ],
+ 'message': 'Generating ''<(json_patch_cc_file)'' file.'
+ },
+ ]
+ },
+ {
'target_name': 'generate_scalarlist_cc_file',
'type': 'none',
'variables': {
diff --git a/sdk/lib/collection/arrays.dart b/sdk/lib/_collection_dev/arrays.dart
similarity index 98%
rename from sdk/lib/collection/arrays.dart
rename to sdk/lib/_collection_dev/arrays.dart
index eab2240..f3a7caf 100644
--- a/sdk/lib/collection/arrays.dart
+++ b/sdk/lib/_collection_dev/arrays.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 dart.collection;
+part of dart._collection.dev;
// TODO(ngeoffray): Rename to Lists.
class Arrays {
diff --git a/sdk/lib/_collection_dev/collection_dev.dart b/sdk/lib/_collection_dev/collection_dev.dart
index 839fd1c..dabbe2b 100644
--- a/sdk/lib/_collection_dev/collection_dev.dart
+++ b/sdk/lib/_collection_dev/collection_dev.dart
@@ -4,6 +4,7 @@
library dart._collection.dev;
+part 'arrays.dart';
part 'iterable.dart';
part 'list.dart';
part 'sort.dart';
diff --git a/sdk/lib/_collection_dev/collection_dev_sources.gypi b/sdk/lib/_collection_dev/collection_dev_sources.gypi
index 819f237..4f941b6 100644
--- a/sdk/lib/_collection_dev/collection_dev_sources.gypi
+++ b/sdk/lib/_collection_dev/collection_dev_sources.gypi
@@ -5,6 +5,9 @@
# This file contains all sources for the dart:collection-dev library.
{
'sources': [
+ 'collection_dev.dart',
+ # The above file needs to be first as it lists the parts below.
+ 'arrays.dart',
'iterable.dart',
'list.dart',
'sort.dart',
diff --git a/sdk/lib/_collection_dev/iterable.dart b/sdk/lib/_collection_dev/iterable.dart
index bf6c85e..daad6af 100644
--- a/sdk/lib/_collection_dev/iterable.dart
+++ b/sdk/lib/_collection_dev/iterable.dart
@@ -14,6 +14,8 @@
int get length;
E elementAt(int i);
+ const ListIterable();
+
Iterator<E> get iterator => new ListIterator<E>(this);
void forEach(void action(E element)) {
@@ -26,7 +28,7 @@
}
}
- bool get isEmpty => length != 0;
+ bool get isEmpty => length == 0;
E get first {
if (length == 0) throw new StateError("No elements");
@@ -217,8 +219,13 @@
Iterable<E> takeWhile(bool test(E element)) => super.takeWhile(test);
- List<E> toList() {
- List<E> result = new List(length);
+ List<E> toList({ bool growable: true }) {
+ List<E> result;
+ if (growable) {
+ result = new List<E>()..length = length;
+ } else {
+ result = new List<E>(length);
+ }
for (int i = 0; i < length; i++) {
result[i] = elementAt(i);
}
@@ -674,7 +681,7 @@
Iterable<E> takeWhile(bool test(E element)) => this;
- List toList() => <E>[];
+ List toList({ bool growable: true }) => growable ? <E>[] : new List<E>(0);
Set toSet() => new Set<E>();
}
@@ -687,6 +694,6 @@
}
/** An [Iterator] that can move in both directions. */
-abstract class BiDirectionalIterator<T> implements Iterator<T> {
+abstract class BidirectionalIterator<T> implements Iterator<T> {
bool movePrevious();
}
diff --git a/sdk/lib/_collection_dev/list.dart b/sdk/lib/_collection_dev/list.dart
index fe698ec..9685fda 100644
--- a/sdk/lib/_collection_dev/list.dart
+++ b/sdk/lib/_collection_dev/list.dart
@@ -10,104 +10,49 @@
* Implements all read-only operations, except [:operator[]:] and [:length:],
* in terms of those two operations.
*/
-abstract class ListBase<E> extends Collection<E> implements List<E> {
- Iterator<E> get iterator => new ListIterator(this);
+abstract class ListBase<E> extends ListIterable<E> implements List<E> {
+ // List interface.
+ int get length;
+ E operator[](int index);
- void forEach(f(E element)) {
- for (int i = 0; i < this.length; i++) f(this[i]);
- }
+ // Collection interface.
+ // Implement in a fully mutable specialized class if necessary.
+ // The fixed-length and unmodifiable lists throw on all members
+ // of the collection interface.
- bool contains(E value) {
- for (int i = 0; i < length; i++) {
- if (this[i] == value) return true;
- }
- return false;
- }
-
- reduce(initialValue, combine(previousValue, E element)) {
- var value = initialValue;
- for (int i = 0; i < this.length; i++) {
- value = combine(value, this[i]);
- }
- return value;
- }
-
- bool every(bool f(E element)) {
- for (int i = 0; i < this.length; i++) {
- if (!f(this[i])) return false;
- }
- return true;
- }
-
- bool any(bool f(E element)) {
- for (int i = 0; i < this.length; i++) {
- if (f(this[i])) return true;
- }
- return false;
- }
-
- bool get isEmpty {
- return this.length == 0;
- }
-
+ // Iterable interface.
E elementAt(int index) {
return this[index];
}
- int indexOf(E value, [int start = 0]) {
- for (int i = start; i < length; i++) {
- if (this[i] == value) return i;
- }
- return -1;
- }
-
- int lastIndexOf(E value, [int start]) {
- if (start == null) start = length - 1;
- for (int i = start; i >= 0; i--) {
- if (this[i] == value) return i;
- }
- return -1;
- }
-
- E get first {
- if (length > 0) return this[0];
- throw new StateError("No elements");
- }
-
- E get last {
- if (length > 0) return this[length - 1];
- throw new StateError("No elements");
- }
-
- E get single {
- if (length == 1) return this[0];
- if (length == 0) throw new StateError("No elements");
- throw new StateError("More than one element");
+ Map<int, E> asMap() {
+ return new ListMapView(this);
}
List<E> getRange(int start, int length) {
- List<E> result = <E>[];
+ if (start < 0 || start > this.length) {
+ throw new RangeError.range(start, 0, this.length);
+ }
+ if (length < 0 || start + length > this.length) {
+ throw new RangeError.range(length, 0, this.length - start);
+ }
+ List<E> result = new List<E>(length);
for (int i = 0; i < length; i++) {
- result.add(this[start + i]);
+ result[i] = this[start + i];
}
return result;
}
- Iterable map(f(E element)) {
- return new MappedIterable(this, f);
+ int indexOf(E element, [int start = 0]) {
+ return Arrays.indexOf(this, element, start, this.length);
}
- Iterable<E> take(int n) {
- return new SubListIterable(this, 0, n);
- }
-
- Iterable<E> skip(int n) {
- return new SubListIterable(this, n, null);
+ int lastIndexOf(E element, [int start = null]) {
+ if (start == null) start = length - 1;
+ return Arrays.lastIndexOf(this, element, start);
}
Iterable<E> get reversed => new ReversedListIterable(this);
-
- String toString() => ToString.collectionToString(this);
}
/**
@@ -170,6 +115,11 @@
"Cannot remove from a fixed-length list");
}
+ void retainMatching(bool test(E element)) {
+ throw new UnsupportedError(
+ "Cannot remove from a fixed-length list");
+ }
+
void clear() {
throw new UnsupportedError(
"Cannot clear a fixed-length list");
@@ -246,6 +196,11 @@
"Cannot remove from an unmodifiable list");
}
+ void retainMatching(bool test(E element)) {
+ throw new UnsupportedError(
+ "Cannot remove from an unmodifiable list");
+ }
+
void sort([Comparator<E> compare]) {
throw new UnsupportedError(
"Cannot modify an unmodifiable list");
@@ -301,3 +256,70 @@
E elementAt(int index) => _source.elementAt(_source.length - 1 - index);
}
+
+/**
+ * An [Iterable] of the UTF-16 code units of a [String] in index order.
+ */
+class CodeUnits extends UnmodifiableListBase<int> {
+ /** The string that this is the code units of. */
+ String _string;
+
+ CodeUnits(this._string);
+
+ int get length => _string.length;
+ int operator[](int i) => _string.codeUnitAt(i);
+}
+
+class _ListIndicesIterable extends ListIterable<int> {
+ List _backedList;
+
+ _ListIndicesIterable(this._backedList);
+
+ int get length => _backedList.length;
+ int elementAt(int index) {
+ if (index < 0 || index >= length) throw new RangeError(index);
+ return index;
+ }
+}
+
+class ListMapView<E> implements Map<int, E> {
+ List<E> _values;
+
+ ListMapView(this._values);
+
+ E operator[] (int key) => containsKey(key) ? _values[key] : null;
+ int get length => _values.length;
+
+ Iterable<E> get values => new SubListIterable<E>(_values, 0, null);
+ Iterable<int> get keys => new _ListIndicesIterable(_values);
+
+ bool get isEmpty => _values.isEmpty;
+ bool containsValue(E value) => _values.contains(value);
+ bool containsKey(int key) => key is int && key >= 0 && key < length;
+
+ void forEach(void f(int key, E value)) {
+ int length = _values.length;
+ for (int i = 0; i < length; i++) {
+ f(i, _values[i]);
+ if (length != _values.length) {
+ throw new ConcurrentModificationError(_values);
+ }
+ }
+ }
+
+ void operator[]= (int key, E value) {
+ throw new UnsupportedError("Cannot modify an unmodifiable map");
+ }
+
+ E putIfAbsent(int key, E ifAbsent()) {
+ throw new UnsupportedError("Cannot modify an unmodifiable map");
+ }
+
+ E remove(int key) {
+ throw new UnsupportedError("Cannot modify an unmodifiable map");
+ }
+
+ void clear() {
+ throw new UnsupportedError("Cannot modify an unmodifiable map");
+ }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 4ed1564..6df2cc6 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -12,8 +12,10 @@
import "util/util.dart";
import "elements/modelx.dart" show ElementX, FunctionElementX, ClassElementX;
-abstract class ClosureNamer {
- SourceString getClosureVariableName(SourceString name, int id);
+class ClosureNamer {
+ SourceString getClosureVariableName(SourceString name, int id) {
+ return new SourceString("${name.slowToString()}_$id");
+ }
}
@@ -190,6 +192,20 @@
this.parametersWithSentinel = new Map<Element, Element>();
bool isClosure() => closureElement != null;
+
+ bool captures(Element element) => freeVariableMapping.containsKey(element);
+
+ bool mutates(Element element) {
+ Element copy = freeVariableMapping[element];
+ return copy != null && !copy.isMember();
+ }
+
+ void forEachCapturedVariable(void f(Element element)) {
+ freeVariableMapping.forEach((variable, _) {
+ if (variable is BoxElement) return;
+ f(variable);
+ });
+ }
}
class ClosureTranslator extends Visitor {
@@ -431,11 +447,10 @@
}
if (outermostElement.isMember() &&
compiler.world.needsRti(outermostElement.getEnclosingClass())) {
- if (outermostElement.isInstanceMember()
- || outermostElement.isGenerativeConstructor()) {
- if (hasTypeVariable(type)) useLocal(closureData.thisElement);
- } else if (outermostElement.isFactoryConstructor()) {
+ if (outermostElement.isConstructor()) {
analyzeTypeVariables(type);
+ } else if (outermostElement.isInstanceMember()) {
+ if (hasTypeVariable(type)) useLocal(closureData.thisElement);
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index ec15da18..bdda72e 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -98,12 +98,19 @@
[ConstantSystem constantSystem = DART_CONSTANT_SYSTEM])
: this.constantSystem = constantSystem;
+ void initializeHelperClasses() {}
+
void enqueueAllTopLevelFunctions(LibraryElement lib, Enqueuer world) {
lib.forEachExport((Element e) {
if (e.isFunction()) world.addToWorkList(e);
});
}
+ // TODO(karlklose): get rid of this and add a factory constructor to [List]
+ // that creates an instance of JSArray to make the dependency visible in from
+ // the source code.
+ void addBackendRtiDependencies(World world);
+
void enqueueHelpers(ResolutionEnqueuer world);
void codegen(CodegenWorkItem work);
@@ -368,6 +375,7 @@
closureNamer = jsBackend.namer;
backend = jsBackend;
} else {
+ closureNamer = new closureMapping.ClosureNamer();
backend = new dart_backend.DartBackend(this, strips);
}
@@ -566,6 +574,7 @@
}
types = new Types(this, dynamicClass);
+ backend.initializeHelperClasses();
}
void scanBuiltinLibraries() {
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index 0f0a029..c76c45f 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -151,12 +151,6 @@
return passThrough('--categories=${categories.join(",")}');
}
- // TODO(8522): Remove this method once option is restored.
- complainAboutDisallowUnsafeEval(String argument) {
- fail('Error: $argument is currently not supported, '
- 'see http://dartbug.com/8522');
- }
-
handleShortOptions(String argument) {
var shortOptions = argument.substring(1).split("");
for (var shortOption in shortOptions) {
@@ -202,8 +196,7 @@
(_) => passThrough('--enable-concrete-type-inference')),
new OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
new OptionHandler('--package-root=.+|-p.+', setPackageRoot),
- new OptionHandler('--disallow-unsafe-eval',
- complainAboutDisallowUnsafeEval),
+ new OptionHandler('--disallow-unsafe-eval', passThrough),
new OptionHandler('--analyze-all', passThrough),
new OptionHandler('--analyze-only', setAnalyzeOnly),
new OptionHandler('--disable-native-live-type-analysis', passThrough),
@@ -413,6 +406,10 @@
--minify
Generate minified output.
+ --disallow-unsafe-eval
+ Disable dynamic generation of code in the generated output. This is
+ necessary to satisfy CSP restrictions (see http://www.w3.org/TR/CSP/).
+
--suppress-warnings
Do not display any warnings.
@@ -442,18 +439,6 @@
Disable the optimization that removes unused native types from dart:html
and related libraries.
-'''
-/* TODO(8522): Restore this comment once option is restored.
-'''
- --disallow-unsafe-eval
- Disable dynamic generation of code in the generated output. This is
- necessary to satisfy CSP restrictions (see http://www.w3.org/TR/CSP/).
- This flag is not continuously tested. Please report breakages and we
- will fix them as soon as possible.
-
-'''
-*/
-'''
--reject-deprecated-language-features
Reject deprecated language features. Without this option, the
compiler will accept language features that are no longer valid
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index d400708..91cff3e 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -217,6 +217,8 @@
stripAsserts = strips.indexOf('asserts') != -1,
super(compiler);
+ void addBackendRtiDependencies(World world) {}
+
void enqueueHelpers(ResolutionEnqueuer world) {
// Right now resolver doesn't always resolve interfaces needed
// for literals, so force them. TODO(antonm): fix in the resolver.
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
index 669aa02..693afa0 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -448,8 +448,7 @@
static bool isDynamicType(TypeAnnotation typeAnnotation) {
if (!isPlainTypeName(typeAnnotation)) return false;
String name = typeAnnotation.typeName.asIdentifier().source.slowToString();
- // TODO(aprelev@gmail.com): Removed deprecated Dynamic keyword support.
- return name == 'Dynamic' || name == 'dynamic';
+ return name == 'dynamic';
}
visitTypeAnnotation(TypeAnnotation node) {
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 00bcbd2..42b33e9 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1479,12 +1479,10 @@
*/
Element lookupSuperMemberInLibrary(SourceString memberName,
LibraryElement library) {
- bool includeInjectedMembers = isPatch;
bool isPrivate = memberName.isPrivate();
for (ClassElement s = superclass; s != null; s = s.superclass) {
// Private members from a different library are not visible.
if (isPrivate && !identical(library, s.getLibrary())) continue;
- s = includeInjectedMembers ? s.implementation : s;
Element e = s.lookupLocalMember(memberName);
if (e == null) continue;
// Static members are not inherited.
@@ -1499,11 +1497,9 @@
Element lookupSuperInterfaceMember(SourceString memberName,
LibraryElement fromLibrary) {
- bool includeInjectedMembers = isPatch;
bool isPrivate = memberName.isPrivate();
for (InterfaceType t in interfaces) {
ClassElement cls = t.element;
- cls = includeInjectedMembers ? cls.implementation : cls;
Element e = cls.lookupLocalMember(memberName);
if (e == null) continue;
// Private members from a different library are not visible.
@@ -1526,14 +1522,36 @@
* origin and the patch class are returned.
*/
Element lookupSelector(Selector selector) {
- SourceString memberName = selector.name;
+ SourceString name = selector.name;
+ bool isPrivate = name.isPrivate();
LibraryElement library = selector.library;
- Element localMember = lookupLocalMember(memberName);
- if (localMember != null &&
- (!memberName.isPrivate() || getLibrary() == library)) {
- return localMember;
+ for (ClassElement current = this;
+ current != null;
+ current = current.superclass) {
+ Element member = current.lookupLocalMember(name);
+ if (member == null) continue;
+ // Private members from a different library are not visible.
+ if (isPrivate && !identical(library, member.getLibrary())) continue;
+ // Static members are not inherited.
+ if (member.modifiers.isStatic() && !identical(this, current)) continue;
+ // If we find an abstract field we have to make sure that it has
+ // the getter or setter part we're actually looking
+ // for. Otherwise, we continue up the superclass chain.
+ if (member.isAbstractField()) {
+ AbstractFieldElement field = member;
+ FunctionElement getter = field.getter;
+ FunctionElement setter = field.setter;
+ if (selector.isSetter()) {
+ if (setter != null) return setter;
+ } else {
+ assert(selector.isGetter() || selector.isCall());
+ if (getter != null) return getter;
+ }
+ } else {
+ return member;
+ }
}
- return lookupSuperMemberInLibrary(memberName, library);
+ return null;
}
/**
@@ -1953,19 +1971,17 @@
*
* For example, consider:
*
- * [:
- * class Data {
- * const Data();
- * }
+ * class Data {
+ * const Data();
+ * }
*
- * const data = const Data();
+ * const data = const Data();
*
- * @data
- * class Foo {}
+ * @data
+ * class Foo {}
*
- * @data @data
- * class Bar {}
- * :]
+ * @data @data
+ * class Bar {}
*
* In this example, there are three instances of [MetadataAnnotation]
* and they correspond each to a location in the source code where
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index e22fb11..615ffe8 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -86,6 +86,11 @@
// the work list'?
bool addElementToWorkList(Element element, [TreeElements elements]);
+ void registerInstantiatedType(InterfaceType type) {
+ universe.instantiatedTypes.add(type);
+ registerInstantiatedClass(type.element);
+ }
+
void registerInstantiatedClass(ClassElement cls) {
if (universe.instantiatedClasses.contains(cls)) return;
if (!cls.isAbstract(compiler)) {
@@ -317,7 +322,7 @@
|| selector.isOperator()
|| selector.isIndex()
|| selector.isIndexSet());
- if (element.isFunction()) {
+ if (element.isFunction() || element.isGetter()) {
addToWorkList(element);
} else if (element.isAbstractField()) {
AbstractFieldElement field = element;
@@ -351,6 +356,11 @@
}
void registerIsCheck(DartType type) {
+ // Even in checked mode, type annotations for return type and argument
+ // types do not imply type checks, so there should never be a check
+ // against the type variable of a typedef.
+ assert(type.kind != TypeKind.TYPE_VARIABLE ||
+ !type.element.enclosingElement.isTypedef());
universe.isChecks.add(type);
compiler.backend.registerIsCheck(type, this);
}
diff --git a/sdk/lib/_internal/compiler/implementation/js/nodes.dart b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
index ccf91b9..fe89432 100644
--- a/sdk/lib/_internal/compiler/implementation/js/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
@@ -1081,8 +1081,7 @@
String message;
String toString() {
- var codes =
- new List.fixedLength(parser.lastPosition, fill: charCodes.$SPACE);
+ var codes = new List.filled(parser.lastPosition, charCodes.$SPACE);
var spaces = new String.fromCharCodes(codes);
return "Error in MiniJsParser:\n${parser.src}\n$spaces^\n$spaces$message\n";
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index a66ab80..50433d4 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -42,8 +42,8 @@
final List<HType> types;
OptionalParameterTypes(int optionalArgumentsCount)
- : names = new List<SourceString>.fixedLength(optionalArgumentsCount),
- types = new List<HType>.fixedLength(optionalArgumentsCount);
+ : names = new List<SourceString>(optionalArgumentsCount),
+ types = new List<HType>(optionalArgumentsCount);
int get length => names.length;
SourceString name(int index) => names[index];
@@ -69,10 +69,10 @@
final List<SourceString> namedArguments;
HTypeList(int length)
- : types = new List<HType>.fixedLength(length),
+ : types = new List<HType>(length),
namedArguments = null;
HTypeList.withNamedArguments(int length, this.namedArguments)
- : types = new List<HType>.fixedLength(length);
+ : types = new List<HType>(length);
const HTypeList.withAllUnknown()
: types = null,
namedArguments = null;
@@ -90,6 +90,7 @@
HTypeList result = new HTypeList(node.inputs.length - 1);
for (int i = 0; i < result.types.length; i++) {
result.types[i] = node.inputs[i + 1].instructionType;
+ assert(!result.types[i].isConflicting());
}
return result;
}
@@ -115,6 +116,7 @@
for (int i = 0; i < result.types.length; i++) {
result.types[i] = node.inputs[i + startInvokeIndex].instructionType;
+ assert(!result.types[i].isConflicting());
}
return result;
}
@@ -276,6 +278,7 @@
Element field,
HType type) {
assert(field.isField());
+ assert(!type.isConflicting());
HType before = optimisticFieldType(field);
HType oldType = typeMap[field];
@@ -639,7 +642,6 @@
ClassElement jsFunctionClass;
ClassElement jsNullClass;
ClassElement jsBoolClass;
- ClassElement objectInterceptorClass;
Element jsArrayLength;
Element jsStringLength;
Element jsArrayRemoveLast;
@@ -648,6 +650,7 @@
Element jsStringConcat;
Element jsStringToString;
Element getInterceptorMethod;
+ Element interceptedNames;
Element fixedLengthListConstructor;
bool seenAnyClass = false;
@@ -702,11 +705,9 @@
final Map<String, Collection<ClassElement>> specializedGetInterceptors;
/**
- * Set of classes whose instances are intercepted. Implemented as a
- * [LinkedHashMap] to preserve the insertion order.
- * TODO(ngeoffray): No need to preserve order anymore.
+ * Set of classes whose methods are intercepted.
*/
- final Map<ClassElement, ClassElement> interceptedClasses;
+ final Set<ClassElement> interceptedClasses;
/**
* Set of selectors that are used from within loops. Used by the
@@ -732,11 +733,10 @@
rti = new RuntimeTypeInformation(compiler),
specializedGetInterceptors =
new Map<String, Collection<ClassElement>>(),
- interceptedClasses = new LinkedHashMap<ClassElement, ClassElement>(),
+ interceptedClasses = new Set<ClassElement>(),
super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) {
emitter = disableEval
- // TODO(8522): Restore --disallow-unsafe-eval.
- ? null // new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap)
+ ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap)
: new CodeEmitterTask(compiler, namer, generateSourceMap);
builder = new SsaBuilderTask(this);
optimizer = new SsaOptimizerTask(this);
@@ -753,7 +753,7 @@
bool isInterceptorClass(Element element) {
if (element == null) return false;
- return interceptedClasses.containsKey(element);
+ return interceptedClasses.contains(element);
}
void addInterceptedSelector(Selector selector) {
@@ -761,7 +761,7 @@
}
String registerOneShotInterceptor(Selector selector) {
- Set<ClassElement> classes = getInterceptedClassesOn(selector);
+ Set<ClassElement> classes = getInterceptedClassesOn(selector.name);
String name = namer.getOneShotInterceptorName(selector, classes);
if (!oneShotInterceptors.containsKey(name)) {
registerSpecializedGetInterceptor(classes);
@@ -770,50 +770,43 @@
return name;
}
- final Map<Selector, Set<ClassElement>> interceptedClassesCache =
- new Map<Selector, Set<ClassElement>>();
- final Map<Selector, Set<ClassElement>> interceptedClassesNonNullCache =
- new Map<Selector, Set<ClassElement>>();
-
- /**
- * Returns a set of interceptor classes that contain a member whose
- * signature matches the given [selector]. Returns [:null:] if there
- * is no class.
- */
- Set<ClassElement> getInterceptedClassesOn(Selector selector,
- {bool canBeNull: true}) {
- Set<Element> intercepted = interceptedElements[selector.name];
- if (intercepted == null) return null;
- // Pick the right cache and query it.
- Map<Selector, Set<ClassElement>> cache = canBeNull
- ? interceptedClassesCache
- : interceptedClassesNonNullCache;
- if (cache.containsKey(selector)) return cache[selector];
- // Populate the cache by running through all the elements and
- // determine if the given selector applies to them.
- Set<ClassElement> result = new Set<ClassElement>();
- for (Element element in intercepted) {
- ClassElement enclosing = element.getEnclosingClass();
- // We have to treat null as a bottom type, so we use the untyped
- // applies method for those elements that are implemented on the
- // null class.
- bool applies = (enclosing == jsNullClass)
- ? canBeNull && selector.appliesUntyped(element, compiler)
- : selector.applies(element, compiler);
- if (applies) result.add(enclosing);
- }
- if (result.isEmpty) result = null;
- cache[selector] = result;
- assert(cache.containsKey(selector));
- return result;
+ bool isInterceptedMethod(Element element) {
+ return element.isInstanceMember()
+ && interceptedElements[element.name] != null;
}
- void initializeInterceptorElements() {
- objectInterceptorClass =
- compiler.findInterceptor(const SourceString('ObjectInterceptor'));
+ bool isInterceptedName(SourceString name) {
+ return interceptedElements[name] != null;
+ }
+
+ final Map<SourceString, Set<ClassElement>> interceptedClassesCache =
+ new Map<SourceString, Set<ClassElement>>();
+
+ /**
+ * Returns a set of interceptor classes that contain a member named
+ * [name]. Returns [:null:] if there is no class.
+ */
+ Set<ClassElement> getInterceptedClassesOn(SourceString name) {
+ Set<Element> intercepted = interceptedElements[name];
+ if (intercepted == null) return null;
+ return interceptedClassesCache.putIfAbsent(name, () {
+ // Populate the cache by running through all the elements and
+ // determine if the given selector applies to them.
+ Set<ClassElement> result = new Set<ClassElement>();
+ for (Element element in intercepted) {
+ result.add(element.getEnclosingClass());
+ }
+ return result;
+ });
+ }
+
+ void initializeHelperClasses() {
getInterceptorMethod =
compiler.findInterceptor(const SourceString('getInterceptor'));
+ interceptedNames =
+ compiler.findInterceptor(const SourceString('interceptedNames'));
List<ClassElement> classes = [
+ compiler.objectClass,
jsStringClass = compiler.findInterceptor(const SourceString('JSString')),
jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')),
// The int class must be before the double class, because the
@@ -845,7 +838,7 @@
jsStringClass, const SourceString('toString'));
for (ClassElement cls in classes) {
- if (cls != null) interceptedClasses[cls] = null;
+ if (cls != null) interceptedClasses.add(cls);
}
}
@@ -863,23 +856,11 @@
}
void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
- compiler.enqueuer.codegen.registerInstantiatedClass(objectInterceptorClass);
String name = namer.getInterceptorName(getInterceptorMethod, classes);
if (classes.contains(compiler.objectClass)) {
// We can't use a specialized [getInterceptorMethod], so we make
// sure we emit the one with all checks.
- specializedGetInterceptors.putIfAbsent(name, () {
- // It is important to take the order provided by the map,
- // because we want the int type check to happen before the
- // double type check: the double type check covers the int
- // type check. Also we don't need to do a number type check
- // because that is covered by the double type check.
- List<ClassElement> keys = <ClassElement>[];
- interceptedClasses.forEach((ClassElement cls, _) {
- if (cls != jsNumberClass) keys.add(cls);
- });
- return keys;
- });
+ specializedGetInterceptors[name] = interceptedClasses;
} else {
specializedGetInterceptors[name] = classes;
}
@@ -890,14 +871,14 @@
// make sure all [noSuchMethod] methods know they might take a
// [JsInvocationMirror] as parameter.
HTypeList types = new HTypeList(1);
- types[0] = new HBoundedType.exact(
- compiler.jsInvocationMirrorClass.computeType(compiler));
+ types[0] = new HType.nonNullExact(
+ compiler.jsInvocationMirrorClass.computeType(compiler),
+ compiler);
argumentTypes.registerDynamicInvocation(types, new Selector.noSuchMethod());
}
void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {
if (!seenAnyClass) {
- initializeInterceptorElements();
initializeNoSuchMethod();
seenAnyClass = true;
}
@@ -967,6 +948,12 @@
return new JavaScriptItemCompilationContext();
}
+ void addBackendRtiDependencies(World world) {
+ if (jsArrayClass != null) {
+ world.registerRtiDependency(jsArrayClass, compiler.listClass);
+ }
+ }
+
void enqueueHelpers(ResolutionEnqueuer world) {
jsIndexingBehaviorInterface =
compiler.findHelper(const SourceString('JavaScriptIndexingBehavior'));
@@ -1008,6 +995,14 @@
enqueueInResolution(getTraceFromException());
}
+ void registerSetRuntimeType() {
+ enqueueInResolution(getSetRuntimeTypeInfo());
+ }
+
+ void registerGetRuntimeTypeArgument() {
+ enqueueInResolution(getGetRuntimeTypeArgument());
+ }
+
void registerRuntimeType() {
enqueueInResolution(getSetRuntimeTypeInfo());
enqueueInResolution(getGetRuntimeTypeInfo());
@@ -1016,11 +1011,13 @@
}
void registerIsCheck(DartType type, Enqueuer world) {
- if (!type.isRaw) {
+ bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE;
+ if (!type.isRaw || isTypeVariable) {
enqueueInResolution(getSetRuntimeTypeInfo());
enqueueInResolution(getGetRuntimeTypeInfo());
enqueueInResolution(getGetRuntimeTypeArgument());
enqueueInResolution(getCheckArguments());
+ if (isTypeVariable) enqueueInResolution(getGetObjectIsSubtype());
world.registerInstantiatedClass(compiler.listClass);
}
// [registerIsCheck] is also called for checked mode checks, so we
@@ -1469,6 +1466,10 @@
return compiler.findHelper(const SourceString('checkArguments'));
}
+ Element getGetObjectIsSubtype() {
+ return compiler.findHelper(const SourceString('objectIsSubtype'));
+ }
+
Element getThrowNoSuchMethod() {
return compiler.findHelper(const SourceString('throwNoSuchMethod'));
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 64a6aa6..227f850 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -59,17 +59,22 @@
final Namer namer;
ConstantEmitter constantEmitter;
NativeEmitter nativeEmitter;
- CodeBuffer boundClosureBuffer;
CodeBuffer mainBuffer;
final CodeBuffer deferredBuffer = new CodeBuffer();
/** Shorter access to [isolatePropertiesName]. Both here in the code, as
well as in the generated code. */
String isolateProperties;
String classesCollector;
- Set<ClassElement> neededClasses;
+ final Set<ClassElement> neededClasses = new Set<ClassElement>();
+ final List<ClassElement> regularClasses = <ClassElement>[];
+ final List<ClassElement> deferredClasses = <ClassElement>[];
+ final List<ClassElement> nativeClasses = <ClassElement>[];
+
// TODO(ngeoffray): remove this field.
Set<ClassElement> instantiatedClasses;
+ final List<jsAst.Expression> boundClosures = <jsAst.Expression>[];
+
JavaScriptBackend get backend => compiler.backend;
String get _ => compiler.enableMinification ? "" : " ";
@@ -107,9 +112,20 @@
final bool generateSourceMap;
+ Iterable<ClassElement> cachedClassesUsingTypeVariableTests;
+
+ Iterable<ClassElement> get classesUsingTypeVariableTests {
+ if (cachedClassesUsingTypeVariableTests == null) {
+ cachedClassesUsingTypeVariableTests = compiler.codegenWorld.isChecks
+ .where((DartType t) => t is TypeVariableType)
+ .map((TypeVariableType v) => v.element.getEnclosingClass())
+ .toList();
+ }
+ return cachedClassesUsingTypeVariableTests;
+ }
+
CodeEmitterTask(Compiler compiler, Namer namer, this.generateSourceMap)
- : boundClosureBuffer = new CodeBuffer(),
- mainBuffer = new CodeBuffer(),
+ : mainBuffer = new CodeBuffer(),
this.namer = namer,
boundClosureCache = new Map<int, String>(),
interceptorClosureCache = new Map<int, String>(),
@@ -123,7 +139,10 @@
}
void computeRequiredTypeChecks() {
- assert(checkedClasses == null);
+ assert(checkedClasses == null && checkedTypedefs == null);
+
+ compiler.codegenWorld.addImplicitChecks(classesUsingTypeVariableTests);
+
checkedClasses = new Set<ClassElement>();
checkedTypedefs = new Set<TypedefElement>();
compiler.codegenWorld.isChecks.forEach((DartType t) {
@@ -231,7 +250,7 @@
fun);
}
- jsAst.Fun get defineClassFunction {
+ List get defineClassFunction {
// First the class name, then the field names in an array and the members
// (inside an Object literal).
// The caller can also pass in the constructor as a function if needed.
@@ -247,11 +266,11 @@
// });
// function(cls, fields, prototype) {
- return js.fun(['cls', 'fields', 'prototype'], [
+ var defineClass = js.fun(['cls', 'fields', 'prototype'], [
js['var constructor'],
- // if (typeof fields == 'function') {
- js.if_(js["typeof fields == 'function'"], [
+ // if (typeof fields == "function") {
+ js.if_(js['typeof fields == "function"'], [
js['constructor = fields']
], /* else */ [
js['var str = "function " + cls + "("'],
@@ -279,6 +298,13 @@
// return constructor;
js.return_('constructor')
]);
+ // Declare a function called "generateAccessor". This is used in
+ // defineClassFunction (it's a local declaration in init()).
+ return [
+ generateAccessorFunction,
+ js['$generateAccessorHolder = generateAccessor'],
+ new jsAst.FunctionDeclaration(
+ new jsAst.VariableDeclaration('defineClass'), defineClass) ];
}
/** Needs defineClass to be defined. */
@@ -295,11 +321,11 @@
return [
js['var $supportsProtoName = false'],
- js["var tmp = (defineClass('c', ['f?'], {})).prototype"],
+ js['var tmp = (defineClass("c", ["f?"], {})).prototype'],
js.if_(js['tmp.__proto__'], [
js['tmp.__proto__ = {}'],
- js.if_(js[r"typeof tmp.get$f != 'undefined'"],
+ js.if_(js[r'typeof tmp.get$f != "undefined"'],
js['$supportsProtoName = true'])
])
@@ -341,13 +367,13 @@
* Super;field1,field2 from the null-string property on the
* descriptor.
*/
- // var fields = desc[''], supr;
- js["var fields = desc[''], supr"],
+ // var fields = desc[""], supr;
+ js['var fields = desc[""], supr'],
- js.if_(js["typeof fields == 'string'"], [
+ js.if_(js['typeof fields == "string"'], [
js['var s = fields.split(";")'],
js['supr = s[0]'],
- js["fields = s[1] == '' ? [] : s[1].split(',')"],
+ js['fields = s[1] == "" ? [] : s[1].split(",")'],
], /* else */ [
js['supr = desc.super']
]),
@@ -462,7 +488,7 @@
List copyFinishClasses = [];
if (needsDefineClass) {
copyFinishClasses.add(
- // newIsolate.$finishClasses = oldIsolate.\$finishClasses;
+ // newIsolate.$finishClasses = oldIsolate.$finishClasses;
js['newIsolate'][finishClassesProperty].assign(
js['oldIsolate'][finishClassesProperty]));
}
@@ -569,17 +595,7 @@
List buildDefineClassAndFinishClassFunctionsIfNecessary() {
if (!needsDefineClass) return [];
- return [
- // Declare a function called "generateAccessor". This is used in
- // defineClassFunction (it's a local declaration in init()).
- generateAccessorFunction,
-
- js['$generateAccessorHolder = generateAccessor'],
-
- // function defineClass ...
- new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration('defineClass'), defineClassFunction)
- ]
+ return defineClassFunction
..addAll(buildProtoSupportCheck())
..addAll([
js[finishClassesName].assign(finishClassesFunction)
@@ -637,12 +653,11 @@
if (alreadyGenerated.contains(invocationName)) return;
alreadyGenerated.add(invocationName);
- bool isInterceptorClass =
- backend.isInterceptorClass(member.getEnclosingClass());
+ bool isInterceptedMethod = backend.isInterceptedMethod(member);
- // If the method is in an interceptor class, we need to also pass
+ // If the method is intercepted, we need to also pass
// the actual receiver.
- int extraArgumentCount = isInterceptorClass ? 1 : 0;
+ int extraArgumentCount = isInterceptedMethod ? 1 : 0;
// Use '$receiver' to avoid clashes with other parameter names. Using
// '$receiver' works because [:namer.safeName:] used for getting parameter
// names never returns a name beginning with a single '$'.
@@ -650,15 +665,14 @@
// The parameters that this stub takes.
List<jsAst.Parameter> parametersBuffer =
- new List<jsAst.Parameter>.fixedLength(
- selector.argumentCount + extraArgumentCount);
+ new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
// The arguments that will be passed to the real method.
List<jsAst.Expression> argumentsBuffer =
- new List<jsAst.Expression>.fixedLength(
+ new List<jsAst.Expression>(
parameters.parameterCount + extraArgumentCount);
int count = 0;
- if (isInterceptorClass) {
+ if (isInterceptedMethod) {
count++;
parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
argumentsBuffer[0] = js[receiverArgumentName];
@@ -898,11 +912,6 @@
void emitInstanceMembers(ClassElement classElement,
ClassBuilder builder) {
assert(invariant(classElement, classElement.isDeclaration));
- if (classElement == backend.objectInterceptorClass) {
- emitInterceptorMethods(builder);
- // The ObjectInterceptor does not have any instance methods.
- return;
- }
void visitMember(ClassElement enclosing, Element member) {
assert(invariant(classElement, member.isDeclaration));
@@ -933,7 +942,10 @@
void generateIsTest(Element other) {
jsAst.Expression code;
- if (compiler.objectClass == other) return;
+ if (other == compiler.objectClass && other != classElement) {
+ // Avoid emitting [:$isObject:] on all classes but [Object].
+ return;
+ }
if (nativeEmitter.requiresNativeIsCheck(other)) {
code = js.fun([], [js.return_(true)]);
} else {
@@ -977,13 +989,10 @@
}
}
- if (backend.isInterceptorClass(classElement)) {
- // The operator== method in [:Object:] does not take the same
- // number of arguments as an intercepted method, therefore we
- // explicitely add one to all interceptor classes. Note that we
- // would not have do do that if all intercepted methods had
- // a calling convention where the receiver is the first
- // parameter.
+ if (backend.isInterceptorClass(classElement)
+ && classElement != compiler.objectClass) {
+ // We optimize the operator== on interceptor classes to
+ // just do a JavaScript double or triple equals.
String name = backend.namer.publicInstanceMethodNameByArity(
const SourceString('=='), 1);
Function kind = (classElement == backend.jsNullClass)
@@ -994,13 +1003,16 @@
}
}
- void emitRuntimeClassesAndTests(CodeBuffer buffer) {
+ void emitRuntimeTypeSupport(CodeBuffer buffer) {
RuntimeTypeInformation rti = backend.rti;
TypeChecks typeChecks = rti.getRequiredChecks();
+ /// Classes that are not instantiated and native classes need a holder
+ /// object for their checks, because there will be no class defined for
+ /// them.
bool needsHolder(ClassElement cls) {
return !neededClasses.contains(cls) || cls.isNative() ||
- rti.isJsNative(cls);
+ rti.isJsNative(cls);
}
/**
@@ -1013,7 +1025,7 @@
if (!needsHolder(cls)) return;
String holder = namer.isolateAccess(cls);
String name = namer.getName(cls);
- buffer.add("$holder$_=$_{builtin\$cls:$_'$name'");
+ buffer.add('$holder$_=$_{builtin\$cls:$_"$name"');
buffer.add('}$N');
}
@@ -1108,10 +1120,15 @@
? member.fixedBackendName()
: (isMixinNativeField ? member.name.slowToString() : accessorName);
bool needsCheckedSetter = false;
- if (needsSetter && compiler.enableTypeAssertions
- && canGenerateCheckedSetter(member)) {
- needsCheckedSetter = true;
- needsSetter = false;
+ if (needsSetter) {
+ if (compiler.enableTypeAssertions
+ && canGenerateCheckedSetter(member)) {
+ needsCheckedSetter = true;
+ needsSetter = false;
+ } else if (backend.isInterceptedMethod(member)) {
+ // The [addField] will take care of generating the setter.
+ needsSetter = false;
+ }
}
// Getters and setters with suffixes will be generated dynamically.
addField(member,
@@ -1149,6 +1166,7 @@
void generateGetter(Element member, String fieldName, String accessorName,
ClassBuilder builder) {
+ assert(!backend.isInterceptorClass(member));
String getterName = namer.getterNameFromAccessorName(accessorName);
builder.addProperty(getterName,
js.fun([], js.return_(js['this'][fieldName])));
@@ -1156,9 +1174,13 @@
void generateSetter(Element member, String fieldName, String accessorName,
ClassBuilder builder) {
+ assert(!backend.isInterceptorClass(member));
String setterName = namer.setterNameFromAccessorName(accessorName);
+ List<String> args = backend.isInterceptedMethod(member)
+ ? ['receiver', 'v']
+ : ['v'];
builder.addProperty(setterName,
- js.fun(['v'], js['this'][fieldName].assign('v')));
+ js.fun(args, js['this'][fieldName].assign('v')));
}
bool canGenerateCheckedSetter(Element member) {
@@ -1189,8 +1211,11 @@
}
String setterName = namer.setterNameFromAccessorName(accessorName);
+ List<String> args = backend.isInterceptedMethod(member)
+ ? ['receiver', 'v']
+ : ['v'];
builder.addProperty(setterName,
- js.fun(['v'], js['this'][fieldName].assign(js[helperName](arguments))));
+ js.fun(args, js['this'][fieldName].assign(js[helperName](arguments))));
}
void emitClassConstructor(ClassElement classElement, ClassBuilder builder) {
@@ -1204,7 +1229,7 @@
void emitClassFields(ClassElement classElement,
ClassBuilder builder,
{ String superClass: "",
- bool classIsNative: false}) {
+ bool classIsNative: false }) {
bool isFirstField = true;
StringBuffer buffer = new StringBuffer();
if (!classIsNative) {
@@ -1275,6 +1300,13 @@
assert(!needsSetter);
generateCheckedSetter(member, name, accessorName, builder);
}
+ if (backend.isInterceptedMethod(member)
+ && instanceFieldNeedsSetter(member)) {
+ // The caller of this method sets [needsSetter] as false
+ // when the setter is intercepted.
+ assert(!needsSetter);
+ generateSetter(member, name, accessorName, builder);
+ }
if (!getterAndSetterCanBeImplementedByFieldSpec) {
if (needsGetter) {
generateGetter(member, name, accessorName, builder);
@@ -1294,10 +1326,7 @@
*/
void generateClass(ClassElement classElement, CodeBuffer buffer) {
assert(invariant(classElement, classElement.isDeclaration));
- if (classElement.isNative()) {
- nativeEmitter.generateNativeClass(classElement);
- return;
- }
+ assert(invariant(classElement, !classElement.isNative()));
needsDefineClass = true;
String className = namer.getName(classElement);
@@ -1344,38 +1373,6 @@
return _selectorRank(selector1) - _selectorRank(selector2);
}
- void emitInterceptorMethods(ClassBuilder builder) {
- // Emit forwarders for the ObjectInterceptor class. We need to
- // emit all possible sends on intercepted methods. Because of
- // typed selectors we have to avoid generating the same forwarder
- // multiple times.
- Set<String> alreadyGenerated = new Set<String>();
- for (Selector selector in
- backend.usedInterceptors.toList()..sort(_compareSelectorNames)) {
- String name = backend.namer.invocationName(selector);
- if (alreadyGenerated.contains(name)) continue;
- alreadyGenerated.add(name);
-
- List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
- parameters.add(new jsAst.Parameter('receiver'));
-
- if (selector.isSetter()) {
- parameters.add(new jsAst.Parameter('value'));
- arguments.add(js['value']);
- } else {
- for (int i = 0; i < selector.argumentCount; i++) {
- String argName = 'a$i';
- parameters.add(new jsAst.Parameter(argName));
- arguments.add(js[argName]);
- }
- }
- jsAst.Fun function =
- js.fun(parameters, js.return_(js['receiver'][name](arguments)));
- builder.addProperty(name, function);
- }
- }
-
Iterable<Element> getTypedefChecksOn(DartType type) {
bool isSubtype(TypedefElement typedef) {
FunctionType typedefType =
@@ -1423,6 +1420,11 @@
emitted.add(superclass);
}
for (DartType supertype in cls.allSupertypes) {
+ ClassElement superclass = supertype.element;
+ if (classesUsingTypeVariableTests.contains(superclass)) {
+ emitSubstitution(superclass, emitNull: true);
+ emitted.add(superclass);
+ }
for (ClassElement check in checkedClasses) {
if (supertype.element == check && !emitted.contains(check)) {
// Generate substitution. If no substitution is necessary, emit
@@ -1537,8 +1539,9 @@
}
// Add unneeded interceptors to the [unneededClasses] set.
- for (ClassElement interceptor in backend.interceptedClasses.keys) {
- if (!needed.contains(interceptor)) {
+ for (ClassElement interceptor in backend.interceptedClasses) {
+ if (!needed.contains(interceptor)
+ && interceptor != compiler.objectClass) {
unneededClasses.add(interceptor);
}
}
@@ -1546,40 +1549,7 @@
return (ClassElement cls) => !unneededClasses.contains(cls);
}
- void emitClasses(CodeBuffer buffer) {
- // Compute the required type checks to know which classes need a
- // 'is$' method.
- computeRequiredTypeChecks();
- List<ClassElement> sortedClasses =
- new List<ClassElement>.from(neededClasses);
- sortedClasses.sort((ClassElement class1, ClassElement class2) {
- // We sort by the ids of the classes. There is no guarantee that these
- // ids are meaningful (or even deterministic), but in the current
- // implementation they are increasing within a source file.
- return class1.id - class2.id;
- });
-
- // If we need noSuchMethod support, we run through all needed
- // classes to figure out if we need the support on any native
- // class. If so, we let the native emitter deal with it.
- if (compiler.enabledNoSuchMethod) {
- SourceString noSuchMethodName = Compiler.NO_SUCH_METHOD;
- Selector noSuchMethodSelector = new Selector.noSuchMethod();
- for (ClassElement element in sortedClasses) {
- if (!element.isNative()) continue;
- Element member = element.lookupLocalMember(noSuchMethodName);
- if (member == null) continue;
- if (noSuchMethodSelector.applies(member, compiler)) {
- nativeEmitter.handleNoSuchMethod = true;
- break;
- }
- }
- }
-
- for (ClassElement element in sortedClasses) {
- generateClass(element, bufferForElement(element, buffer));
- }
-
+ void emitClosureClassIfNeeded(CodeBuffer buffer) {
// The closure class could have become necessary because of the generation
// of stubs.
ClassElement closureClass = compiler.closureClass;
@@ -1595,7 +1565,7 @@
'${_}null)$N');
// Reset the map.
- buffer.add("$classesCollector$_=$_{}$N");
+ buffer.add("$classesCollector$_=${_}null$N$n");
}
}
@@ -1721,9 +1691,9 @@
Map<int, String> cache;
String extraArg = null;
- // Methods on interceptor classes take an extra parameter, which is the
- // actual receiver of the call.
- bool inInterceptor = backend.isInterceptorClass(member.getEnclosingClass());
+ // Intercepted methods take an extra parameter, which is the
+ // receiver of the call.
+ bool inInterceptor = backend.isInterceptedMethod(member);
if (inInterceptor) {
cache = interceptorClosureCache;
extraArg = 'receiver';
@@ -1802,11 +1772,9 @@
boundClosureBuilder.addProperty(operator, new jsAst.LiteralBool(true));
});
- jsAst.Expression init =
+ boundClosures.add(
js[classesCollector][mangledName].assign(
- boundClosureBuilder.toObjectInitializer());
- boundClosureBuffer.add(jsAst.prettyPrint(init, compiler));
- boundClosureBuffer.add("$N");
+ boundClosureBuilder.toObjectInitializer()));
closureClass = namer.isolateAccess(closureClassElement);
@@ -1846,10 +1814,9 @@
DefineStubFunction defineStub) {
assert(invariant(member, member.isDeclaration));
LibraryElement memberLibrary = member.getLibrary();
- // If the class is an interceptor class, the stub gets the
+ // If the method is intercepted, the stub gets the
// receiver explicitely and we need to pass it to the getter call.
- bool isInterceptorClass =
- backend.isInterceptorClass(member.getEnclosingClass());
+ bool isInterceptedMethod = backend.isInterceptedMethod(member);
const String receiverArgumentName = r'$receiver';
@@ -1857,7 +1824,7 @@
if (member.isGetter()) {
String getterName = namer.getterName(member);
return js['this'][getterName](
- isInterceptorClass
+ isInterceptedMethod
? <jsAst.Expression>[js[receiverArgumentName]]
: <jsAst.Expression>[]);
} else {
@@ -1885,7 +1852,7 @@
List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
List<jsAst.Expression> arguments = <jsAst.Expression>[];
- if (isInterceptorClass) {
+ if (isInterceptedMethod) {
parameters.add(new jsAst.Parameter(receiverArgumentName));
}
@@ -1909,6 +1876,8 @@
Iterable<VariableElement> staticNonFinalFields =
handler.getStaticNonFinalFieldsForEmission();
for (Element element in Elements.sortedByPosition(staticNonFinalFields)) {
+ // [:interceptedNames:] is handled in [emitInterceptedNames].
+ if (element == backend.interceptedNames) continue;
compiler.withCurrentElement(element, () {
Constant initialValue = handler.getInitialValueFor(element);
jsAst.Expression init =
@@ -1957,7 +1926,7 @@
return null;
}
- void emitCompileTimeConstants(CodeBuffer buffer) {
+ void emitCompileTimeConstants(CodeBuffer eagerBuffer) {
ConstantHandler handler = compiler.constantHandler;
List<Constant> constants = handler.getConstantsForEmission();
bool addedMakeConstantList = false;
@@ -1974,8 +1943,10 @@
if (name == null) continue;
if (!addedMakeConstantList && constant.isList()) {
addedMakeConstantList = true;
- emitMakeConstantList(buffer);
+ emitMakeConstantList(eagerBuffer);
}
+ CodeBuffer buffer =
+ bufferForElement(constant.computeType(compiler).element, eagerBuffer);
jsAst.Expression init = js[isolateProperties][name].assign(
constantInitializerExpression(constant));
buffer.add(jsAst.prettyPrint(init, compiler));
@@ -2047,14 +2018,19 @@
String createInvocationMirror = namer.getName(
compiler.createInvocationMirrorElement);
+ assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD));
jsAst.Expression expression = js['this.$noSuchMethodName'](
- js[namer.CURRENT_ISOLATE][createInvocationMirror]([
- js.string(methodName),
- js.string(internalName),
- type,
- new jsAst.ArrayInitializer.from(
- parameters.map((param) => js[param.name]).toList()),
- new jsAst.ArrayInitializer.from(argNames)]));
+ [js['this'],
+ js[namer.CURRENT_ISOLATE][createInvocationMirror]([
+ js.string(methodName),
+ js.string(internalName),
+ type,
+ new jsAst.ArrayInitializer.from(
+ parameters.map((param) => js[param.name]).toList()),
+ new jsAst.ArrayInitializer.from(argNames)])]);
+ parameters = backend.isInterceptedName(selector.name)
+ ? ([new jsAst.Parameter('\$receiver')]..addAll(parameters))
+ : parameters;
return js.fun(parameters, js.return_(expression));
}
@@ -2068,36 +2044,22 @@
// class has a member that matches the current name and
// selector (grabbed from the scope).
bool hasMatchingMember(ClassElement holder) {
- Element element = holder.lookupMember(selector.name);
- if (element == null) return false;
-
- // TODO(kasperl): Consider folding this logic into the
- // Selector.applies() method.
- if (element is AbstractFieldElement) {
- AbstractFieldElement field = element;
- if (selector.isGetter()) {
- return field.getter != null;
- } else if (selector.isSetter()) {
- return field.setter != null;
- } else {
- return false;
- }
- } else if (element is VariableElement) {
- if (selector.isSetter() && element.modifiers.isFinalOrConst()) {
- return false;
- }
- }
- return selector.applies(element, compiler);
+ Element element = holder.lookupSelector(selector);
+ return (element != null)
+ ? selector.applies(element, compiler)
+ : false;
}
// If the selector is typed, we check to see if that type may
// have a user-defined noSuchMethod implementation. If not, we
// skip the selector altogether.
+
+ // TODO(kasperl): This shouldn't depend on the internals of
+ // the type mask. Move more of this code to the type mask.
ClassElement receiverClass = objectClass;
- if (selector is TypedSelector) {
- TypedSelector typedSelector = selector;
- DartType receiverType = typedSelector.receiverType;
- receiverClass = receiverType.element;
+ TypeMask mask = selector.mask;
+ if (mask != null) {
+ receiverClass = mask.base.element;
}
// If the receiver class is guaranteed to have a member that
@@ -2187,10 +2149,10 @@
}
addComment('BEGIN invoke [main].', buffer);
buffer.add("""
-if (typeof document !== 'undefined' && document.readyState !== 'complete') {
- document.addEventListener('readystatechange', function () {
- if (document.readyState == 'complete') {
- if (typeof dartMainRunner === 'function') {
+if (typeof document !== "undefined" && document.readyState !== "complete") {
+ document.addEventListener("readystatechange", function () {
+ if (document.readyState == "complete") {
+ if (typeof dartMainRunner === "function") {
dartMainRunner(function() { ${mainCall}; });
} else {
${mainCall};
@@ -2198,7 +2160,7 @@
}
}, false);
} else {
- if (typeof dartMainRunner === 'function') {
+ if (typeof dartMainRunner === "function") {
dartMainRunner(function() { ${mainCall}; });
} else {
${mainCall};
@@ -2209,7 +2171,6 @@
}
void emitGetInterceptorMethod(CodeBuffer buffer,
- String objectName,
String key,
Collection<ClassElement> classes) {
jsAst.Statement buildReturnInterceptor(ClassElement cls) {
@@ -2261,10 +2222,11 @@
else if (cls == backend.jsNullClass) hasNull = true;
else if (cls == backend.jsNumberClass) hasNumber = true;
else if (cls == backend.jsStringClass) hasString = true;
- else throw 'Internal error: $cls';
+ else {
+ assert(cls == compiler.objectClass);
+ }
}
if (hasDouble) {
- assert(!hasNumber);
hasNumber = true;
}
if (hasInt) hasNumber = true;
@@ -2317,7 +2279,7 @@
if (hasArray) {
block.statements.add(buildInterceptorCheck(backend.jsArrayClass));
}
- block.statements.add(js.return_(js[objectName]['prototype']));
+ block.statements.add(js.return_(receiver));
buffer.add(jsAst.prettyPrint(
js[isolateProperties][key].assign(js.fun(['receiver'], block)),
@@ -2329,22 +2291,27 @@
* Emit all versions of the [:getInterceptor:] method.
*/
void emitGetInterceptorMethods(CodeBuffer buffer) {
- // If no class needs to be intercepted, just return.
- if (backend.objectInterceptorClass == null) return;
- String objectName = namer.isolateAccess(backend.objectInterceptorClass);
var specializedGetInterceptors = backend.specializedGetInterceptors;
for (String name in specializedGetInterceptors.keys.toList()..sort()) {
Collection<ClassElement> classes = specializedGetInterceptors[name];
- emitGetInterceptorMethod(buffer, objectName, name, classes);
+ emitGetInterceptorMethod(buffer, name, classes);
}
}
+ /**
+ * Compute all the classes that must be emitted.
+ */
void computeNeededClasses() {
instantiatedClasses =
compiler.codegenWorld.instantiatedClasses.where(computeClassFilter())
.toSet();
- neededClasses = new Set<ClassElement>.from(instantiatedClasses);
- for (ClassElement element in instantiatedClasses) {
+
+ // The set of classes that must be emitted are based on instantiated
+ // classes.
+ neededClasses.addAll(instantiatedClasses);
+
+ // Then add all superclasses of these classes.
+ for (ClassElement element in neededClasses.toList() /* copy */) {
for (ClassElement superclass = element.superclass;
superclass != null;
superclass = superclass.superclass) {
@@ -2352,6 +2319,43 @@
neededClasses.add(superclass);
}
}
+
+ // Finally, sort the classes.
+ List<ClassElement> sortedClasses = neededClasses.toList();
+ sortedClasses.sort((ClassElement class1, ClassElement class2) {
+ // We sort by the ids of the classes. There is no guarantee that these
+ // ids are meaningful (or even deterministic), but in the current
+ // implementation they are increasing within a source file.
+ return class1.id - class2.id;
+ });
+
+ // If we need noSuchMethod support, we run through all needed
+ // classes to figure out if we need the support on any native
+ // class. If so, we let the native emitter deal with it.
+ if (compiler.enabledNoSuchMethod) {
+ SourceString noSuchMethodName = Compiler.NO_SUCH_METHOD;
+ Selector noSuchMethodSelector = new Selector.noSuchMethod();
+ for (ClassElement element in sortedClasses) {
+ if (!element.isNative()) continue;
+ Element member = element.lookupLocalMember(noSuchMethodName);
+ if (member == null) continue;
+ if (noSuchMethodSelector.applies(member, compiler)) {
+ nativeEmitter.handleNoSuchMethod = true;
+ break;
+ }
+ }
+ }
+
+ for (ClassElement element in sortedClasses) {
+ if (element.isNative()) {
+ // For now, native classes cannot be deferred.
+ nativeClasses.add(element);
+ } else if (isDeferred(element)) {
+ deferredClasses.add(element);
+ } else {
+ regularClasses.add(element);
+ }
+ }
}
int _compareSelectors(Selector selector1, Selector selector2) {
@@ -2386,7 +2390,7 @@
return isNumber(variable).binary('&&',
js['Math']['floor'](receiver).equals(receiver));
}
-
+
jsAst.Expression tripleShiftZero(jsAst.Expression receiver) {
return receiver.binary('>>>', js.toExpression(0));
}
@@ -2516,7 +2520,7 @@
for (String name in names) {
Selector selector = backend.oneShotInterceptors[name];
Set<ClassElement> classes =
- backend.getInterceptedClassesOn(selector);
+ backend.getInterceptedClassesOn(selector.name);
String getInterceptorName =
namer.getInterceptorName(backend.getInterceptorMethod, classes);
@@ -2558,6 +2562,32 @@
}
}
+ /**
+ * If [:invokeOn:] has been compiled, emit all the possible selector names
+ * that are intercepted into the [:interceptedNames:] top-level
+ * variable. The implementation of [:invokeOn:] will use it to
+ * determine whether it should call the method with an extra
+ * parameter.
+ */
+ void emitInterceptedNames(CodeBuffer buffer) {
+ if (!compiler.enabledInvokeOn) return;
+ String name = backend.namer.getName(backend.interceptedNames);
+ jsAst.PropertyAccess property = js[isolateProperties][name];
+
+ int index = 0;
+ List<jsAst.ArrayElement> elements = backend.usedInterceptors.map(
+ (Selector selector) {
+ jsAst.Literal str = js.string(namer.invocationName(selector));
+ return new jsAst.ArrayElement(index++, str);
+ }).toList();
+ jsAst.ArrayInitializer array = new jsAst.ArrayInitializer(
+ backend.usedInterceptors.length,
+ elements);
+
+ buffer.add(jsAst.prettyPrint(property.assign(array), compiler));
+ buffer.add(N);
+ }
+
void emitInitFunction(CodeBuffer buffer) {
jsAst.Fun fun = js.fun([], [
js['$isolateProperties = {}'],
@@ -2575,32 +2605,91 @@
measure(() {
computeNeededClasses();
+ // Compute the required type checks to know which classes need a
+ // 'is$' method.
+ computeRequiredTypeChecks();
+
mainBuffer.add(GENERATED_BY);
addComment(HOOKS_API_USAGE, mainBuffer);
mainBuffer.add('function ${namer.isolateName}()$_{}\n');
mainBuffer.add('init()$N$n');
- // Shorten the code by using "$$" as temporary.
- classesCollector = r"$$";
- mainBuffer.add('var $classesCollector$_=$_{}$N');
// Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
isolateProperties = namer.CURRENT_ISOLATE;
mainBuffer.add(
'var $isolateProperties$_=$_$isolatePropertiesName$N');
- emitClasses(mainBuffer);
- mainBuffer.add(boundClosureBuffer);
- // Clear the buffer, so that we can reuse it for the native classes.
- boundClosureBuffer.clear();
+
+ if (!regularClasses.isEmpty ||
+ !deferredClasses.isEmpty ||
+ !nativeClasses.isEmpty) {
+ // Shorten the code by using "$$" as temporary.
+ classesCollector = r"$$";
+ mainBuffer.add('var $classesCollector$_=$_{}$N$n');
+ }
+
+ // Emit native classes on [nativeBuffer]. As a side-effect,
+ // this will produce "bound closures" in [boundClosures]. The
+ // bound closures are JS AST nodes that add properties to $$
+ // [classesCollector]. The bound closures are not emitted until
+ // we have emitted all other classes (native or not).
+ final CodeBuffer nativeBuffer = new CodeBuffer();
+ if (!nativeClasses.isEmpty) {
+ addComment('Native classes', nativeBuffer);
+ for (ClassElement element in nativeClasses) {
+ nativeEmitter.generateNativeClass(element);
+ }
+ nativeEmitter.assembleCode(nativeBuffer);
+ }
+
+ // Might also create boundClosures.
+ if (!regularClasses.isEmpty) {
+ addComment('Classes', mainBuffer);
+ for (ClassElement element in regularClasses) {
+ generateClass(element, mainBuffer);
+ }
+ }
+
+ // Might also create boundClosures.
+ if (!deferredClasses.isEmpty) {
+ emitDeferredPreambleWhenEmpty(deferredBuffer);
+ deferredBuffer.add('\$\$$_=$_{}$N');
+
+ for (ClassElement element in deferredClasses) {
+ generateClass(element, deferredBuffer);
+ }
+
+ deferredBuffer.add('$finishClassesName(\$\$,'
+ '$_${namer.CURRENT_ISOLATE},'
+ '$_$isolatePropertiesName)$N');
+ // Reset the map.
+ deferredBuffer.add("\$\$$_=${_}null$N$n");
+ }
+
+ emitClosureClassIfNeeded(mainBuffer);
+
+ // Now that we have emitted all classes, we know all the bound
+ // closures that will be needed.
+ for (jsAst.Node node in boundClosures) {
+ // TODO(ahe): Some of these can be deferred.
+ mainBuffer.add(jsAst.prettyPrint(node, compiler));
+ mainBuffer.add("$N$n");
+ }
+
+ emitFinishClassesInvocationIfNecessary(mainBuffer);
+
+ // After this assignment we will produce invalid JavaScript code if we use
+ // the classesCollector variable.
+ classesCollector = 'classesCollector should not be used from now on';
+
emitStaticFunctions(mainBuffer);
emitStaticFunctionGetters(mainBuffer);
- // We need to finish the classes before we construct compile time
- // constants.
- emitFinishClassesInvocationIfNecessary(mainBuffer);
- emitRuntimeClassesAndTests(mainBuffer);
+
+ emitRuntimeTypeSupport(mainBuffer);
emitCompileTimeConstants(mainBuffer);
// Static field initializations require the classes and compile-time
// constants to be set up.
emitStaticNonFinalFieldInitializations(mainBuffer);
emitOneShotInterceptors(mainBuffer);
+ emitInterceptedNames(mainBuffer);
emitGetInterceptorMethods(mainBuffer);
emitLazilyInitializedStaticFields(mainBuffer);
@@ -2608,19 +2697,13 @@
// The following code should not use the short-hand for the
// initialStatics.
mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N');
- if (!boundClosureBuffer.isEmpty) {
- mainBuffer.add(boundClosureBuffer);
- emitFinishClassesInvocationIfNecessary(mainBuffer);
- }
- // After this assignment we will produce invalid JavaScript code if we use
- // the classesCollector variable.
- classesCollector = 'classesCollector should not be used from now on';
emitFinishIsolateConstructorInvocation(mainBuffer);
mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_='
'${_}new ${namer.isolateName}()$N');
- nativeEmitter.assembleCode(mainBuffer);
+ mainBuffer.add(nativeBuffer);
+
emitMain(mainBuffer);
emitInitFunction(mainBuffer);
compiler.assembledCode = mainBuffer.getText();
@@ -2641,13 +2724,7 @@
void emitDeferredCode(CodeBuffer buffer) {
if (buffer.isEmpty) return;
- if (needsDefineClass) {
- buffer.add('$finishClassesName(\$\$,'
- '$_${namer.CURRENT_ISOLATE},'
- '$_$isolatePropertiesName)$N');
- // Reset the map.
- buffer.add("\$\$$_=$_{}$N");
- }
+ buffer.add(n);
buffer.add('${namer.CURRENT_ISOLATE}$_=${_}old${namer.CURRENT_ISOLATE}$N');
@@ -2660,9 +2737,9 @@
void emitDeferredPreambleWhenEmpty(CodeBuffer buffer) {
if (!buffer.isEmpty) return;
- final classesCollector = r"$$";
- buffer.add('$classesCollector$_=$_{}$N');
+ buffer.add(GENERATED_BY);
+
buffer.add('var old${namer.CURRENT_ISOLATE}$_='
'$_${namer.CURRENT_ISOLATE}$N');
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
index 06d5d01..52a237c 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
@@ -10,85 +10,12 @@
bool generateSourceMap)
: super(compiler, namer, generateSourceMap);
- String get generateGetterSetterFunction {
- return """
-function() {
- throw 'Internal Error: no dynamic generation of getters and setters allowed';
-}""";
- }
+ bool get getterAndSetterCanBeImplementedByFieldSpec => false;
- String get defineClassFunction {
- return """
-function(cls, constructor, prototype) {
- constructor.prototype = prototype;
- constructor.builtin\$cls = cls;
- return constructor;
-}""";
- }
-
- String get protoSupportCheck {
- // We don't modify the prototypes in CSP mode. Therefore we can have an
- // easier prototype-check.
- return 'var $supportsProtoName = !!{}.__proto__;\n';
- }
-
- String get finishIsolateConstructorFunction {
- // We replace the old Isolate function with a new one that initializes
- // all its field with the initial (and often final) value of all globals.
- //
- // We also copy over old values like the prototype, and the
- // isolateProperties themselves.
- return """
-function(oldIsolate) {
- var isolateProperties = oldIsolate.${namer.isolatePropertiesName};
- function Isolate() {
- for (var staticName in isolateProperties) {
- if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) {
- this[staticName] = isolateProperties[staticName];
- }
+ void emitSuper(String superName, ClassBuilder builder) {
+ if (superName != '') {
+ builder.addProperty('super', js.string(superName));
}
- // Use the newly created object as prototype. In Chrome this creates a
- // hidden class for the object and makes sure it is fast to access.
- function ForceEfficientMap() {}
- ForceEfficientMap.prototype = this;
- new ForceEfficientMap;
- }
- Isolate.prototype = oldIsolate.prototype;
- Isolate.prototype.constructor = Isolate;
- Isolate.${namer.isolatePropertiesName} = isolateProperties;
- return Isolate;
-}""";
- }
-
- String get lazyInitializerFunction {
- return """
-function(prototype, staticName, fieldName, getterName, lazyValue, getter) {
-$lazyInitializerLogic
-}""";
- }
-
- js.Expression buildLazyInitializedGetter(VariableElement element) {
- String isolate = namer.CURRENT_ISOLATE;
- return js.fun([],
- js.block1(
- js.return_(
- js.fieldAccess(js.use(isolate), namer.getName(element)))));
- }
-
- js.Expression buildConstructor(String mangledName, List<String> fieldNames) {
- return new js.NamedFunction(
- new js.VariableDeclaration(mangledName),
- new js.Fun(
- fieldNames
- .map((fieldName) => new js.Parameter(fieldName))
- .toList(),
- new js.Block(
- fieldNames.map((fieldName) =>
- new js.ExpressionStatement(
- new js.Assignment(
- new js.This().dot(fieldName),
- new js.VariableUse(fieldName))))
- .toList())));
}
void emitBoundClosureClassHeader(String mangledName,
@@ -96,7 +23,16 @@
List<String> fieldNames,
ClassBuilder builder) {
builder.addProperty('', buildConstructor(mangledName, fieldNames));
- builder.addProperty('super', js.string(superName));
+ emitSuper(superName, builder);
+ }
+
+
+ void emitClassFields(ClassElement classElement,
+ ClassBuilder builder,
+ { String superClass: "",
+ bool classIsNative: false }) {
+ // Class fields are dynamically generated so they have to be
+ // emitted using getters and setters instead.
}
void emitClassConstructor(ClassElement classElement, ClassBuilder builder) {
@@ -118,21 +54,80 @@
fields.add(name);
});
String constructorName = namer.safeName(classElement.name.slowToString());
-
builder.addProperty('', buildConstructor(constructorName, fields));
}
- void emitSuper(String superName, ClassBuilder builder) {
- if (superName != '') {
- builder.addProperty('super', js.string(superName));
- }
+ List get defineClassFunction {
+ return [new jsAst.FunctionDeclaration(
+ new jsAst.VariableDeclaration('defineClass'),
+ js.fun(['cls', 'constructor', 'prototype'],
+ [js[r'constructor.prototype = prototype'],
+ js[r'constructor.builtin$cls = cls'],
+ js.return_('constructor')]))];
}
- void emitClassFields(ClassElement classElement,
- ClassBuilder builder,
- { String superClass: "",
- bool classIsNative: false}) {
+ List buildProtoSupportCheck() {
+ // We don't modify the prototypes in CSP mode. Therefore we can have an
+ // easier prototype-check.
+ return [js['var $supportsProtoName = !(!({}.__proto__))']];
}
- bool get getterAndSetterCanBeImplementedByFieldSpec => false;
+ jsAst.Expression buildConstructor(String mangledName,
+ List<String> fieldNames) {
+ return new jsAst.NamedFunction(
+ new jsAst.VariableDeclaration(mangledName),
+ js.fun(fieldNames, fieldNames.map(
+ (name) => js['this.$name = $name']).toList()));
+ }
+
+ jsAst.FunctionDeclaration get generateAccessorFunction {
+ String message =
+ 'Internal error: no dynamic generation of accessors allowed.';
+ return new jsAst.FunctionDeclaration(
+ new jsAst.VariableDeclaration('generateAccessor'),
+ js.fun([], new jsAst.Throw(js.string(message))));
+ }
+
+ jsAst.Expression buildLazyInitializedGetter(VariableElement element) {
+ String isolate = namer.CURRENT_ISOLATE;
+ String name = namer.getName(element);
+ return js.fun([], js.return_(js['$isolate.$name']));
+ }
+
+ jsAst.Fun get lazyInitializerFunction {
+ // function(prototype, staticName, fieldName,
+ // getterName, lazyValue, getter) {
+ var parameters = <String>['prototype', 'staticName', 'fieldName',
+ 'getterName', 'lazyValue', 'getter'];
+ return js.fun(parameters, addLazyInitializerLogic());
+ }
+
+ jsAst.Fun get finishIsolateConstructorFunction {
+ // We replace the old Isolate function with a new one that initializes
+ // all its fields with the initial (and often final) value of all globals.
+ //
+ // We also copy over old values like the prototype, and the
+ // isolateProperties themselves.
+ return js.fun('oldIsolate', [
+ js['var isolateProperties = oldIsolate.${namer.isolatePropertiesName}'],
+ new jsAst.FunctionDeclaration(
+ new jsAst.VariableDeclaration('Isolate'),
+ js.fun([], [
+ js['var hasOwnProperty = Object.prototype.hasOwnProperty'],
+ js.forIn('staticName', 'isolateProperties',
+ js.if_(js['hasOwnProperty.call(isolateProperties, staticName)'],
+ js['this[staticName] = isolateProperties[staticName]'])),
+ // Use the newly created object as prototype. In Chrome,
+ // this creates a hidden class for the object and makes
+ // sure it is fast to access.
+ new jsAst.FunctionDeclaration(
+ new jsAst.VariableDeclaration('ForceEfficientMap'),
+ js.fun([], [])),
+ js['ForceEfficientMap.prototype = this'],
+ js['new ForceEfficientMap()']])),
+ js['Isolate.prototype = oldIsolate.prototype'],
+ js['Isolate.prototype.constructor = Isolate'],
+ js['Isolate.${namer.isolatePropertiesName} = isolateProperties'],
+ js.return_('Isolate')]);
+ }
}
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 8a2f2b8..77ed6f4 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -21,6 +21,7 @@
import '../source_map_builder.dart';
import '../ssa/ssa.dart' hide js; // TODO(ahe): VM bug, see above.
import '../tree/tree.dart';
+import '../types/types.dart';
import '../universe/universe.dart' hide js; // TODO(ahe): VM bug, see above.
import '../util/characters.dart';
import '../util/util.dart';
@@ -29,8 +30,7 @@
part 'constant_emitter.dart';
part 'constant_system_javascript.dart';
part 'emitter.dart';
-// TODO(8522): Restore --disallow-unsafe-eval.
-// part 'emitter_no_eval.dart';
+part 'emitter_no_eval.dart';
part 'minify_namer.dart';
part 'namer.dart';
part 'native_emitter.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
index 547a3e4..e19a442 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
@@ -94,7 +94,7 @@
suggestedInstanceNames,
usedInstanceNames,
const <String>[
- r'$add', r'add$1', r'box_0', r'charCodeAt$1', r'constructor',
+ r'$add', r'add$1', r'box_0', r'codeUnitAt$1', r'constructor',
r'current', r'$defineNativeClass', r'$eq', r'$ne',
r'getPrototypeOf', r'hasOwnProperty', r'$index', r'$indexSet',
r'$isJavaScriptIndexingBehavior', r'$isolateProperties',
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 6500fc3..8e389bf 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -290,7 +290,7 @@
getDirectSubclasses(cls).forEach(visit);
classes.add(cls);
}
- classesWithDynamicDispatch.forEach(visit);
+ Elements.sortedByPosition(classesWithDynamicDispatch).forEach(visit);
List<ClassElement> preorderDispatchClasses = classes.where(
(cls) => !getDirectSubclasses(cls).isEmpty &&
@@ -484,7 +484,9 @@
emitIsChecks();
jsAst.Expression makeCallOnThis(String functionName) {
- return js.fun([], js.return_(js['$functionName(this)']));
+ // Because we know the function is intercepted, we need an extra
+ // parameter.
+ return js.fun(['_'], js.return_(js['$functionName(this)']));
}
// In order to have the toString method on every native class,
@@ -501,7 +503,9 @@
// Same as above, but for operator==.
String equalsName = backend.namer.publicInstanceMethodNameByArity(
const SourceString('=='), 1);
- addProperty(equalsName, js.fun(['a'],
+ // Because we know the function is intercepted, we need an extra
+ // parameter.
+ addProperty(equalsName, js.fun(['_', 'a'],
js.return_(js['this === a'])));
// If the native emitter has been asked to take care of the
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
index bfad207..e893075 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -62,6 +62,16 @@
}
}
}
+
+ // TODO(karlklose): remove this temporary fix: we need to add the classes
+ // used in substitutions to addArguments.
+ allArguments.addAll([compiler.intClass,
+ compiler.boolClass,
+ compiler.numClass,
+ compiler.doubleClass,
+ compiler.stringClass,
+ compiler.listClass]);
+
return cachedRequiredChecks = requiredChecks;
}
@@ -294,4 +304,14 @@
}
Iterator<ClassElement> get iterator => map.keys.iterator;
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ for (ClassElement holder in this) {
+ for (ClassElement check in [holder]) {
+ sb.add('${holder.name.slowToString()}.${check.name.slowToString()}, ');
+ }
+ }
+ return '[$sb]';
+ }
}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/async_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/async_patch.dart
index cd63a24..ade4c99 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/async_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/async_patch.dart
@@ -7,34 +7,15 @@
import 'dart:_isolate_helper' show IsolateNatives, TimerImpl;
import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
-typedef void _TimerCallback0();
-typedef void _TimerCallback1(Timer timer);
-
patch class Timer {
- patch factory Timer(var duration, var callback) {
- // TODO(floitsch): remove these checks when we remove the deprecated
- // millisecond argument and the 1-argument callback. Also remove the
- // int-test below.
- if (callback is! _TimerCallback0 && callback is! _TimerCallback1) {
- throw new ArgumentError(callback);
- }
- int milliseconds = duration is int ? duration : duration.inMilliseconds;
+ patch factory Timer(Duration duration, void callback()) {
+ int milliseconds = duration.inMilliseconds;
if (milliseconds < 0) milliseconds = 0;
- Timer timer;
- _TimerCallback0 zeroArgumentCallback =
- callback is _TimerCallback0 ? callback : () => callback(timer);
- timer = new TimerImpl(milliseconds, zeroArgumentCallback);
- return timer;
+ return new TimerImpl(milliseconds, callback);
}
- /**
- * Creates a new repeating timer. The [callback] is invoked every
- * [milliseconds] millisecond until cancelled.
- */
- patch factory Timer.repeating(var duration, void callback(Timer timer)) {
- // TODO(floitsch): remove this check when we remove the deprecated
- // millisecond argument.
- int milliseconds = duration is int ? duration : duration.inMilliseconds;
+ patch factory Timer.repeating(Duration duration, void callback(Timer timer)) {
+ int milliseconds = duration.inMilliseconds;
if (milliseconds < 0) milliseconds = 0;
return new TimerImpl.repeating(milliseconds, callback);
}
@@ -78,7 +59,7 @@
JS('', '#.addEventListener("load", #, false)', script, onLoad);
JS('', 'document.body.appendChild(#)', script);
} else if (JS('String', 'typeof load') == 'function') {
- new Timer(0, (_) {
+ Timer.run(() {
JS('void', 'load(#)', uri);
completer.complete(true);
});
diff --git a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
index fad1d02..1da20f6 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
@@ -11,8 +11,7 @@
JSSyntaxRegExp,
Primitives,
TypeImpl,
- stringJoinUnchecked,
- JsStringBuffer;
+ stringJoinUnchecked;
patch void print(var object) {
Primitives.printString(object.toString());
@@ -166,16 +165,17 @@
// Patch for List implementation.
patch class List<E> {
- patch factory List([int length = 0]) {
- // Explicit type test is necessary to protect Primitives.newGrowableList in
+ patch factory List([int length]) {
+ if (!?length) return Primitives.newGrowableList(0);
+ // Explicit type test is necessary to protect Primitives.newFixedList in
// unchecked mode.
if ((length is !int) || (length < 0)) {
throw new ArgumentError("Length must be a positive integer: $length.");
}
- return Primitives.newGrowableList(length);
+ return Primitives.newFixedList(length);
}
- patch factory List.fixedLength(int length, {E fill: null}) {
+ patch factory List.filled(int length, E fill) {
// Explicit type test is necessary to protect Primitives.newFixedList in
// unchecked mode.
if ((length is !int) || (length < 0)) {
@@ -287,3 +287,13 @@
}
}
+patch class StackTrace {
+ patch String get fullStackTrace {
+ throw new UnsupportedError('fullStackTrace');
+ }
+
+ patch String get stackTrace {
+ throw new UnsupportedError('stackTrace');
+ }
+}
+
diff --git a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
index 6a32f17..5676e1d 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
@@ -16,7 +16,6 @@
checkNum,
checkString,
getRuntimeTypeString,
- listInsertRange,
regExpGetNative,
stringContainsUnchecked,
stringLastIndexOfUnchecked,
@@ -31,14 +30,6 @@
part 'js_string.dart';
/**
- * The interceptor class for all non-primitive objects. All its
- * members are synthethized by the compiler's emitter.
- */
-class ObjectInterceptor {
- const ObjectInterceptor();
-}
-
-/**
* Get the interceptor for [object]. Called by the compiler when it needs
* to emit a call to an intercepted method, that is a method that is
* defined in an interceptor class.
@@ -50,6 +41,13 @@
}
/**
+ * If [InvocationMirror.invokeOn] is being used, this variable
+ * contains a JavaScript array with the names of methods that are
+ * intercepted.
+ */
+var interceptedNames;
+
+/**
* The interceptor class for tear-off static methods. Unlike
* tear-off instance methods, tear-off static methods are just the JS
* function, and methods inherited from Object must therefore be
diff --git a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
index 00ed800..ed10807 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
@@ -54,31 +54,31 @@
}
patch class _File {
- patch static _exists(String name) {
+ patch static _exists(String path) {
throw new UnsupportedError("File._exists");
}
- patch static _create(String name) {
+ patch static _create(String path) {
throw new UnsupportedError("File._create");
}
- patch static _delete(String name) {
+ patch static _delete(String path) {
throw new UnsupportedError("File._delete");
}
- patch static _directory(String name) {
+ patch static _directory(String path) {
throw new UnsupportedError("File._directory");
}
- patch static _lengthFromName(String name) {
- throw new UnsupportedError("File._lengthFromName");
+ patch static _lengthFromPath(String path) {
+ throw new UnsupportedError("File._lengthFromPath");
}
- patch static _lastModified(String name) {
+ patch static _lastModified(String path) {
throw new UnsupportedError("File._lastModified");
}
- patch static _open(String name, int mode) {
+ patch static _open(String path, int mode) {
throw new UnsupportedError("File._open");
}
patch static int _openStdio(int fd) {
throw new UnsupportedError("File._openStdio");
}
- patch static _fullPath(String name) {
+ patch static _fullPath(String path) {
throw new UnsupportedError("File._fullPath");
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_array.dart b/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
index 1c1e492..9b73f40 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
@@ -69,7 +69,7 @@
return IterableMixinWorkaround.expand(this, f);
}
- void addAll(Collection<E> collection) {
+ void addAll(Iterable<E> collection) {
for (E e in collection) {
this.add(e);
}
@@ -155,7 +155,31 @@
}
void insertRange(int start, int length, [E initialValue]) {
- return listInsertRange(this, start, length, initialValue);
+ checkGrowable(this, 'insertRange');
+ if (length == 0) {
+ return;
+ }
+ if (length is !int) throw new ArgumentError(length);
+ if (length < 0) throw new ArgumentError(length);
+ if (start is !int) throw new ArgumentError(start);
+
+ var receiver = this;
+ var receiverLength = receiver.length;
+ if (start < 0 || start > receiverLength) {
+ throw new RangeError.value(start);
+ }
+ receiver.length = receiverLength + length;
+ Arrays.copy(receiver,
+ start,
+ receiver,
+ start + length,
+ receiverLength - start);
+ if (initialValue != null) {
+ for (int i = start; i < start + length; i++) {
+ receiver[i] = initialValue;
+ }
+ }
+ receiver.length = receiverLength + length;
}
E get first {
@@ -205,21 +229,7 @@
void setRange(int start, int length, List<E> from, [int startFrom = 0]) {
checkMutable(this, 'set range');
- if (length == 0) return;
- checkNull(start); // TODO(ahe): This is not specified but co19 tests it.
- checkNull(length); // TODO(ahe): This is not specified but co19 tests it.
- checkNull(from); // TODO(ahe): This is not specified but co19 tests it.
- checkNull(startFrom); // TODO(ahe): This is not specified but co19 tests it.
- if (start is !int) throw new ArgumentError(start);
- if (length is !int) throw new ArgumentError(length);
- if (startFrom is !int) throw new ArgumentError(startFrom);
- if (length < 0) throw new ArgumentError(length);
- if (start < 0) throw new RangeError.value(start);
- if (start + length > this.length) {
- throw new RangeError.value(start + length);
- }
-
- Arrays.copy(from, startFrom, this, start, length);
+ IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
}
bool any(bool f(E element)) => IterableMixinWorkaround.any(this, f);
@@ -234,13 +244,11 @@
}
int indexOf(E element, [int start = 0]) {
- if (start is !int) throw new ArgumentError(start);
- return Arrays.indexOf(this, element, start, length);
+ return IterableMixinWorkaround.indexOfList(this, element, start);
}
int lastIndexOf(E element, [int start]) {
- if (start == null) start = this.length - 1;
- return Arrays.lastIndexOf(this, element, start);
+ return IterableMixinWorkaround.lastIndexOfList(this, element, start);
}
bool contains(E other) {
@@ -254,7 +262,8 @@
String toString() => Collections.collectionToString(this);
- List<E> toList() => new List<E>.from(this);
+ List<E> toList({ bool growable: true }) =>
+ new List<E>.from(this, growable: growable);
Set<E> toSet() => new Set<E>.from(this);
@@ -288,4 +297,8 @@
if (index >= length || index < 0) throw new RangeError.value(index);
JS('void', r'#[#] = #', this, index, value);
}
+
+ Map<int, E> asMap() {
+ return IterableMixinWorkaround.asMapList(this);
+ }
}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
index 19f6ce8..f9a3af7 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
@@ -15,7 +15,8 @@
JS_HAS_EQUALS,
RAW_DART_FUNCTION_REF,
UNINTERCEPTED;
-import 'dart:_interceptors' show getInterceptor;
+import 'dart:_interceptors' show getInterceptor,
+ interceptedNames;
part 'constant_map.dart';
part 'native_helper.dart';
@@ -23,7 +24,7 @@
part 'string_helper.dart';
bool isJsArray(var value) {
- return value != null && JS('bool', r'#.constructor === Array', value);
+ return value != null && JS('bool', r'(#.constructor === Array)', value);
}
checkMutable(list, reason) {
@@ -98,13 +99,16 @@
return map;
}
- static final _objectInterceptor = getInterceptor(new Object());
invokeOn(Object object) {
var interceptor = getInterceptor(object);
var receiver = object;
var name = _internalName;
var arguments = _arguments;
- if (identical(interceptor, _objectInterceptor)) {
+ // TODO(ngeoffray): If this functionality ever become performance
+ // critical, we might want to dynamically change [interceptedNames]
+ // to be a JavaScript object with intercepted names as property
+ // instead of a JavaScript array.
+ if (JS('int', '#.indexOf(#)', interceptedNames, name) == -1) {
if (!isJsArray(arguments)) arguments = new List.from(arguments);
} else {
arguments = [object]..addAll(arguments);
@@ -157,7 +161,7 @@
// This is somewhat nasty, but we don't want to drag in a bunch of
// dependencies to handle a situation that cannot happen. So we
// avoid using Dart [:throw:] and Dart [toString].
- JS('void', "throw 'Unable to print message: ' + String(#)", string);
+ JS('void', 'throw "Unable to print message: " + String(#)', string);
}
static void _throwFormatException(String string) {
@@ -210,19 +214,19 @@
if (radix <= 10) {
// Allow all digits less than the radix. For example 0, 1, 2 for
// radix 3.
- // "0".charCodeAt(0) + radix - 1;
+ // "0".codeUnitAt(0) + radix - 1;
maxCharCode = 0x30 + radix - 1;
} else {
// Characters are located after the digits in ASCII. Therefore we
// only check for the character code. The regexp above made already
// sure that the string does not contain anything but digits or
// characters.
- // "0".charCodeAt(0) + radix - 1;
+ // "0".codeUnitAt(0) + radix - 1;
maxCharCode = 0x61 + radix - 10 - 1;
}
String digitsPart = match[digitsIndex].toLowerCase();
for (int i = 0; i < digitsPart.length; i++) {
- if (digitsPart.charCodeAt(i) > maxCharCode) {
+ if (digitsPart.codeUnitAt(i) > maxCharCode) {
return handleError(source);
}
}
@@ -255,7 +259,7 @@
return result;
}
- /** [: r"$".charCodeAt(0) :] */
+ /** [: r"$".codeUnitAt(0) :] */
static const int DOLLAR_CHAR_VALUE = 36;
static String objectTypeName(Object object) {
@@ -270,7 +274,7 @@
}
// TODO(kasperl): If the namer gave us a fresh global name, we may
// want to remove the numeric suffix that makes it unique too.
- if (identical(name.charCodeAt(0), DOLLAR_CHAR_VALUE)) name = name.substring(1);
+ if (identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) name = name.substring(1);
return name;
}
@@ -557,32 +561,6 @@
throw new RangeError.value(index);
}
-listInsertRange(receiver, start, length, initialValue) {
- if (length == 0) {
- return;
- }
- if (length is !int) throw new ArgumentError(length);
- if (length < 0) throw new ArgumentError(length);
- if (start is !int) throw new ArgumentError(start);
-
- var receiverLength = JS('num', r'#.length', receiver);
- if (start < 0 || start > receiverLength) {
- throw new RangeError.value(start);
- }
- receiver.length = receiverLength + length;
- Arrays.copy(receiver,
- start,
- receiver,
- start + length,
- receiverLength - start);
- if (initialValue != null) {
- for (int i = start; i < start + length; i++) {
- receiver[i] = initialValue;
- }
- }
- receiver.length = receiverLength + length;
-}
-
stringLastIndexOfUnchecked(receiver, element, start)
=> JS('int', r'#.lastIndexOf(#, #)', receiver, element, start);
@@ -807,6 +785,7 @@
if (message is String) {
if (message == 'null has no properties' ||
message == "'null' is not an object" ||
+ message == "'undefined' is not an object" ||
message.endsWith('is null') ||
message.endsWith('is undefined') ||
message.endsWith('is null or undefined') ||
@@ -845,7 +824,7 @@
// Check for the Firefox specific stack overflow signal.
if (JS('bool',
- r"typeof InternalError == 'function' && # instanceof InternalError",
+ r'typeof InternalError == "function" && # instanceof InternalError',
ex)) {
if (message is String && message == 'too much recursion') {
return new StackOverflowError();
@@ -914,23 +893,20 @@
if (closure == null) return null;
var function = JS('var', r'#.$identity', closure);
if (JS('bool', r'!!#', function)) return function;
- // By fetching the current isolate before creating the JavaScript
- // function, we prevent the compiler from inlining its use in
- // the JavaScript function below (the compiler generates code for
- // fetching the isolate before creating the JavaScript function).
- // If it was inlined, the JavaScript function would not get the
- // current isolate, but the one that is active when the callback
- // executes.
- var currentIsolate = JS_CURRENT_ISOLATE();
// We use $0 and $1 to not clash with variable names used by the
// compiler and/or minifier.
- function = JS("var",
- r"""function($0, $1) { return #(#, #, #, $0, $1); }""",
- DART_CLOSURE_TO_JS(invokeClosure),
+ function = JS('var',
+ r'(function ($2, $3) {'
+ r' return function($0, $1) { '
+ r'return $3(#, $2, #, $0, $1) }})(#, #)',
closure,
+ arity,
+ // Capture the current isolate now. Remember that "#"
+ // in JS is simply textual substitution of compiled
+ // expressions.
JS_CURRENT_ISOLATE(),
- arity);
+ DART_CLOSURE_TO_JS(invokeClosure));
JS('void', r'#.$identity = #', closure, function);
return function;
@@ -1494,7 +1470,7 @@
return "$className<${joinArguments(typeInfo, 0)}>";
}
-bool isJsFunction(var o) => JS('bool', r"typeof # == 'function'", o);
+bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
Object invoke(function, arguments) {
return JS('var', r'#.apply(null, #)', function, arguments);
@@ -1538,23 +1514,57 @@
return true;
}
-getArguments(var type) => JS('var', r'#.slice(1)', type);
+getArguments(var type) {
+ return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
+}
getField(var object, var name) => JS('var', r'#[#]', object, name);
/**
+ * Tests whether the Dart object [o] is a subtype of the runtime type
+ * representation [t], which is a type representation as described in the
+ * comment on [isSubtype].
+ */
+bool objectIsSubtype(Object o, var t) {
+ if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true;
+ // Get the runtime type information from the object here, because we may
+ // overwrite o with the interceptor below.
+ var rti = getRuntimeTypeInfo(o);
+ // Check for native objects and use the interceptor instead of the object.
+ o = getInterceptor(o);
+ // We can use the object as its own type representation because we install
+ // the subtype flags and the substitution on the prototype, so they are
+ // properties of the object in JS.
+ var type;
+ if (JS('bool', '# != null', rti)) {
+ // If the type has type variables (that is, [:rti != null:]), make a copy of
+ // the type arguments and insert [o] in the first position to create a
+ // compound type representation.
+ type = JS('List', '#.slice()', rti);
+ JS('', '#.splice(0, 0, #)', type, o);
+ } else {
+ // Use the object as representation of the raw type.
+ type = o;
+ }
+ return isSubtype(type, t);
+}
+
+
+/**
* Check whether the type represented by [s] is a subtype of the type
* represented by [t].
*
* Type representations can be:
* 1) a JavaScript constructor for a class C: the represented type is the raw
* type C.
- * 2) a JavaScript object: this represents a class for which there is no
+ * 2) a Dart object: this is the interceptor instance for a native type.
+ * 3) a JavaScript object: this represents a class for which there is no
* JavaScript constructor, because it is only used in type arguments or it
* is native. The represented type is the raw type of this class.
- * 3) a JavaScript array: the first entry is of type 1 or 2 and identifies the
- * class of the type and the rest of the array are the type arguments.
- * 4) [:null:]: the dynamic type.
+ * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
+ * subtyping flags and the substitution of the type and the rest of the
+ * array are the type arguments.
+ * 5) [:null:]: the dynamic type.
*/
bool isSubtype(var s, var t) {
// If either type is dynamic, [s] is a subtype of [t].
@@ -1568,15 +1578,20 @@
// Check for a subtyping flag.
var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
if (getField(typeOfS, test) == null) return false;
- // The class of [s] is a subclass of the class of [t]. If either of the types
- // is raw, [s] is a subtype of [t].
- if (!isJsArray(s) || !isJsArray(t)) return true;
// Get the necessary substitution of the type arguments, if there is one.
var substitution;
if (JS('bool', '# !== #', typeOfT, typeOfS)) {
var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
substitution = getField(typeOfS, field);
}
+ // The class of [s] is a subclass of the class of [t]. If [s] has no type
+ // arguments and no substitution, it is used as raw type. If [t] has no
+ // type arguments, it used as a raw type. In both cases, [s] is a subtype
+ // of [t].
+ if ((!isJsArray(s) && JS('bool', '# == null', substitution)) ||
+ !isJsArray(t)) {
+ return true;
+ }
// Recursively check the type arguments.
return checkArguments(substitution, getArguments(s), getArguments(t));
}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_string.dart b/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
index 6d81f32..c271e16 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
@@ -13,8 +13,6 @@
class JSString implements String {
const JSString();
- int charCodeAt(index) => codeUnitAt(index);
-
int codeUnitAt(int index) {
if (index is !num) throw new ArgumentError(index);
if (index < 0) throw new RangeError.value(index);
@@ -71,10 +69,6 @@
}
}
- List<String> splitChars() {
- return JS('=List', r'#.split("")', this);
- }
-
bool startsWith(String other) {
checkString(other);
int otherLength = other.length;
@@ -141,15 +135,7 @@
return JS('String', r'#.trim()', this);
}
- List<int> get charCodes {
- List<int> result = new List<int>.fixedLength(length);
- for (int i = 0; i < length; i++) {
- result[i] = JS('int', '#.charCodeAt(#)', this, i);
- }
- return result;
- }
-
- Iterable<int> get codeUnits => new CodeUnits(this);
+ List<int> get codeUnits => new CodeUnits(this);
Runes get runes => new Runes(this);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart
new file mode 100644
index 0000000..01cce1a
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart
@@ -0,0 +1,91 @@
+// 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 file for dart:json library.
+
+import 'dart:_foreign_helper' show JS;
+
+/**
+ * Parses [json] and builds the corresponding parsed JSON value.
+ *
+ * Parsed JSON values are of the types [num], [String], [bool], [Null],
+ * [List]s of parsed JSON values or [Map]s from [String] to parsed
+ * JSON values.
+ *
+ * The optional [reviver] function, if provided, is called once for each object
+ * or list property parsed. The arguments are the property name ([String]) or
+ * list index ([int]), and the value is the parsed value. The return value of
+ * the reviver will be used as the value of that property instead of the parsed
+ * value. The top level value is passed to the reviver with the empty string as
+ * a key.
+ *
+ * Throws [FormatException] if the input is not valid JSON text.
+ */
+patch parse(String json, [reviver(var key, var value)]) {
+ if (json is! String) throw new ArgumentError(json);
+
+ var parsed;
+ try {
+ parsed = JS('=Object|=List|Null|bool|num|String', 'JSON.parse(#)', json);
+ } catch (e) {
+ throw new FormatException(JS('String', 'String(#)', e));
+ }
+
+ return _convertJsonToDart(parsed, reviver);
+}
+
+/**
+ * Walks the raw JavaScript value [json], replacing JavaScript Objects with
+ * Maps. [json] is expected to be freshly allocated so elements can be replaced
+ * in-place.
+ */
+_convertJsonToDart(json, reviver(key, value)) {
+
+ var revive = reviver == null ? (key, value) => value : reviver;
+
+ walk(e) {
+ // JavaScript null, string, number, bool are in the correct representation.
+ if (JS('bool', '# == null', e) || JS('bool', 'typeof # != "object"', e)) {
+ return e;
+ }
+
+ // This test is needed to avoid identifing '{"__proto__":[]}' as an Array.
+ // TODO(sra): Replace this test with cheaper '#.constructor === Array' when
+ // bug 621 below is fixed.
+ if (JS('bool', 'Object.getPrototypeOf(#) === Array.prototype', e)) {
+ var list = JS('=List', '#', e); // Teach compiler the type is known.
+ // In-place update of the elements since JS Array is a Dart List.
+ for (int i = 0; i < list.length; i++) {
+ // Use JS indexing to avoid range checks. We know this is the only
+ // reference to the list, but the compiler will likely never be able to
+ // tell that this instance of the list cannot have its length changed by
+ // the reviver even though it later will be passed to the reviver at the
+ // outer level.
+ var item = JS('', '#[#]', list, i);
+ JS('', '#[#]=#', list, i, revive(i, walk(item)));
+ }
+ return list;
+ }
+
+ // Otherwise it is a plain Object, so copy to a Map.
+ var keys = JS('=List', 'Object.keys(#)', e);
+ Map map = {};
+ for (int i = 0; i < keys.length; i++) {
+ String key = keys[i];
+ map[key] = revive(key, walk(JS('', '#[#]', e, key)));
+ }
+ // V8 has a bug with properties named "__proto__"
+ // https://code.google.com/p/v8/issues/detail?id=621
+ var proto = JS('', '#.__proto__', e);
+ // __proto__ can be undefined on IE9.
+ if (JS('bool',
+ 'typeof # !== "undefined" && # !== Object.prototype',
+ proto, proto)) {
+ map['__proto__'] = revive('__proto__', walk(proto));
+ }
+ return map;
+ }
+
+ return revive('', walk(json));
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
index b62b0b5..bdd5d23 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
@@ -4,71 +4,73 @@
part of _js_helper;
-List regExpExec(JSSyntaxRegExp regExp, String str) {
- var nativeRegExp = regExpGetNative(regExp);
- var result = JS('=List', r'#.exec(#)', nativeRegExp, str);
- if (JS('bool', r'# == null', result)) return null;
- return result;
-}
-
-bool regExpTest(JSSyntaxRegExp regExp, String str) {
- var nativeRegExp = regExpGetNative(regExp);
- return JS('bool', r'#.test(#)', nativeRegExp, str);
-}
-
-regExpGetNative(JSSyntaxRegExp regExp) {
- var r = JS('var', r'#._re', regExp);
- if (r == null) {
- r = JS('var', r'#._re = #', regExp, regExpMakeNative(regExp));
- }
- return r;
-}
-
-regExpAttachGlobalNative(JSSyntaxRegExp regExp) {
- JS('void', r'#._re = #', regExp, regExpMakeNative(regExp, global: true));
-}
-
-regExpMakeNative(JSSyntaxRegExp regExp, {bool global: false}) {
- String pattern = regExp.pattern;
- bool isMultiLine = regExp.isMultiLine;
- bool isCaseSensitive = regExp.isCaseSensitive;
- checkString(pattern);
- StringBuffer sb = new StringBuffer();
- if (isMultiLine) sb.add('m');
- if (!isCaseSensitive) sb.add('i');
- if (global) sb.add('g');
- try {
- return JS('var', r'new RegExp(#, #)', pattern, sb.toString());
- } catch (e) {
- throw new IllegalJSRegExpException(pattern,
- JS('String', r'String(#)', e));
- }
-}
-
-int regExpMatchStart(m) => JS('int', r'#.index', m);
+// Helper method used by internal libraries.
+regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp;
class JSSyntaxRegExp implements RegExp {
final String _pattern;
final bool _isMultiLine;
final bool _isCaseSensitive;
+ var _nativeRegExp;
- const JSSyntaxRegExp(String pattern,
- {bool multiLine: false,
- bool caseSensitive: true})
- : _pattern = pattern,
- _isMultiLine = multiLine,
- _isCaseSensitive = caseSensitive;
+ JSSyntaxRegExp._internal(String pattern,
+ bool multiLine,
+ bool caseSensitive,
+ bool global)
+ : _nativeRegExp = makeNative(pattern, multiLine, caseSensitive, global),
+ this._pattern = pattern,
+ this._isMultiLine = multiLine,
+ this._isCaseSensitive = caseSensitive;
+
+ JSSyntaxRegExp(String pattern,
+ {bool multiLine: false,
+ bool caseSensitive: true})
+ : this._internal(pattern, multiLine, caseSensitive, false);
+
+ JSSyntaxRegExp._globalVersionOf(JSSyntaxRegExp other)
+ : this._internal(other.pattern,
+ other.isMultiLine,
+ other.isCaseSensitive,
+ true);
+
+ static makeNative(
+ String pattern, bool multiLine, bool caseSensitive, bool global) {
+ checkString(pattern);
+ String m = multiLine ? 'm' : '';
+ String i = caseSensitive ? '' : 'i';
+ String g = global ? 'g' : '';
+ // We're using the JavaScript's try catch instead of the Dart one
+ // to avoid dragging in Dart runtime support just because of using
+ // RegExp.
+ var regexp = JS('',
+ '(function() {'
+ 'try {'
+ 'return new RegExp(#, # + # + #);'
+ '} catch (e) {'
+ 'return e;'
+ '}'
+ '})()', pattern, m, i, g);
+ if (JS('bool', '# instanceof RegExp', regexp)) return regexp;
+ // The returned value is the JavaScript exception. Turn it into a
+ // Dart exception.
+ String errorMessage = JS('String', r'String(#)', regexp);
+ throw new FormatException(
+ "Illegal RegExp pattern: $pattern, $errorMessage");
+ }
Match firstMatch(String str) {
- List<String> m = regExpExec(this, checkString(str));
+ List<String> m =
+ JS('=List|Null', r'#.exec(#)', _nativeRegExp, checkString(str));
if (m == null) return null;
- var matchStart = regExpMatchStart(m);
+ var matchStart = JS('int', r'#.index', m);
// m.lastIndex only works with flag 'g'.
var matchEnd = matchStart + m[0].length;
return new _MatchImplementation(pattern, str, matchStart, matchEnd, m);
}
- bool hasMatch(String str) => regExpTest(this, checkString(str));
+ bool hasMatch(String str) {
+ return JS('bool', r'#.test(#)', _nativeRegExp, checkString(str));
+ }
String stringMatch(String str) {
var match = firstMatch(str);
@@ -83,17 +85,6 @@
String get pattern => _pattern;
bool get isMultiLine => _isMultiLine;
bool get isCaseSensitive => _isCaseSensitive;
-
- static JSSyntaxRegExp _globalVersionOf(JSSyntaxRegExp other) {
- JSSyntaxRegExp re =
- new JSSyntaxRegExp(other.pattern,
- multiLine: other.isMultiLine,
- caseSensitive: other.isCaseSensitive);
- regExpAttachGlobalNative(re);
- return re;
- }
-
- _getNative() => regExpGetNative(this);
}
class _MatchImplementation implements Match {
@@ -138,7 +129,7 @@
Match _current;
_AllMatchesIterator(JSSyntaxRegExp re, String this._str)
- : _re = JSSyntaxRegExp._globalVersionOf(re);
+ : _re = new JSSyntaxRegExp._globalVersionOf(re);
Match get current => _current;
diff --git a/sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart
index 326b892..4106c98 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart
@@ -128,3 +128,33 @@
throw new UnsupportedError('Float64List.view');
}
}
+
+patch class Float32x4 {
+ patch factory Float32x4(double x, double y, double z, double w) {
+ throw new UnsupportedError('Float32x4');
+ }
+ patch factory Float32x4.zero() {
+ throw new UnsupportedError('Float32x4.zero');
+ }
+}
+
+patch class Uint32x4 {
+ patch factory Uint32x4(int x, int y, int z, int w) {
+ throw new UnsupportedError('Uint32x4');
+ }
+ patch factory Uint32x4.bool(bool x, bool y, bool z, bool w) {
+ throw new UnsupportedError('Uint32x4.bool');
+ }
+}
+
+
+patch class Float32x4List {
+ patch factory Float32x4List(int length) {
+ throw new UnsupportedError('Float32x4List');
+ }
+
+ patch factory Float32x4List.view(ByteArray array,
+ [int start = 0, int length]) {
+ throw new UnsupportedError('Float32x4List.view');
+ }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
index 9749028..aa13997 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
@@ -73,12 +73,10 @@
// The JavaScript String.replace method recognizes replacement
// patterns in the replacement string. Dart does not have that
// behavior.
- to = JS('String', r"#.replace('$', '$$$$')", to);
+ to = JS('String', r'#.replace("$", "$$$$")', to);
return JS('String', r'#.replace(#, #)', receiver, replacer, to);
}
-final RegExp quoteRegExp = const JSSyntaxRegExp(r'[-[\]{}()*+?.,\\^$|#\s]');
-
stringReplaceAllUnchecked(receiver, from, to) {
checkString(to);
if (from is String) {
@@ -96,15 +94,14 @@
return result.toString();
}
} else {
- var quoter = regExpMakeNative(quoteRegExp, global: true);
+ var quoter = JS('', "new RegExp(#, 'g')", r'[-[\]{}()*+?.,\\^$|#\s]');
var quoted = JS('String', r'#.replace(#, "\\$&")', from, quoter);
- RegExp replaceRegExp = new JSSyntaxRegExp(quoted);
- var replacer = regExpMakeNative(replaceRegExp, global: true);
+ var replacer = JS('', "new RegExp(#, 'g')", quoted);
return stringReplaceJS(receiver, replacer, to);
}
} else if (from is JSSyntaxRegExp) {
- var re = regExpMakeNative(from, global: true);
- return stringReplaceJS(receiver, re, to);
+ var re = new JSSyntaxRegExp._globalVersionOf(from);
+ return stringReplaceJS(receiver, re._nativeRegExp, to);
} else {
checkNull(from);
// TODO(floitsch): implement generic String.replace (with patterns).
@@ -145,10 +142,10 @@
while (i < length) {
buffer.add(onMatch(new StringMatch(i, receiver, "")));
// Special case to avoid splitting a surrogate pair.
- int code = receiver.charCodeAt(i);
+ int code = receiver.codeUnitAt(i);
if ((code & ~0x3FF) == 0xD800 && length > i + 1) {
// Leading surrogate;
- code = receiver.charCodeAt(i + 1);
+ code = receiver.codeUnitAt(i + 1);
if ((code & ~0x3FF) == 0xDC00) {
// Matching trailing surrogate.
buffer.add(onNonMatch(receiver.substring(i, i + 2)));
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index 13a15f8..d18c2e1 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -251,10 +251,10 @@
: cwd = getCurrentDirectory(),
provider = new SourceFileProvider() {
var handler = new FormattingDiagnosticHandler(provider);
- var libraryUri = cwd.resolve(libraryRoot.toString());
+ var libraryUri = cwd.resolve('${libraryRoot}/');
var packageUri;
if (packageRoot != null) {
- packageUri = cwd.resolve(packageRoot.toString());
+ packageUri = cwd.resolve('${packageRoot}/');
} else {
packageUri = libraryUri;
}
@@ -271,10 +271,10 @@
[Path packageRoot, List<String> opts = const <String>[]])
: cwd = getCurrentDirectory(),
provider = new SourceFileProvider() {
- var libraryUri = cwd.resolve(libraryRoot.toString());
+ var libraryUri = cwd.resolve('${libraryRoot}/');
var packageUri;
if (packageRoot != null) {
- packageUri = cwd.resolve(packageRoot.toString());
+ packageUri = cwd.resolve('${packageRoot}/');
} else {
packageUri = libraryUri;
}
@@ -688,8 +688,8 @@
var columnNumber = 0;
while (0 <= index && index < sourceText.length) {
columnNumber++;
- var charCode = sourceText.charCodeAt(index);
- if (charCode == $CR || charCode == $LF) {
+ var codeUnit = sourceText.codeUnitAt(index);
+ if (codeUnit == $CR || codeUnit == $LF) {
break;
}
index--;
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 54055cd..1ff6f48 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -7,6 +7,11 @@
abstract class TreeElements {
Element operator[](Node node);
Selector getSelector(Send send);
+ Selector getGetterSelectorInComplexSendSet(SendSet node);
+ Selector getOperatorSelectorInComplexSendSet(SendSet node);
+ Selector getIteratorSelector(ForIn node);
+ Selector getMoveNextSelector(ForIn node);
+ Selector getCurrentSelector(ForIn node);
DartType getType(Node node);
bool isParameterChecked(Element element);
Set<Node> get superUses;
@@ -14,7 +19,8 @@
class TreeElementMapping implements TreeElements {
final Element currentElement;
- final Map<Node, Selector> selectors = new LinkedHashMap<Node, Selector>();
+ final Map<Spannable, Selector> selectors =
+ new LinkedHashMap<Spannable, Selector>();
final Map<Node, DartType> types = new LinkedHashMap<Node, DartType>();
final Set<Element> checkedParameters = new Set<Element>();
final Set<Node> superUses = new Set<Node>();
@@ -61,7 +67,53 @@
selectors[node] = selector;
}
- Selector getSelector(Node node) => selectors[node];
+ Selector getSelector(Node node) {
+ return selectors[node];
+ }
+
+ void setGetterSelectorInComplexSendSet(SendSet node, Selector selector) {
+ selectors[node.selector] = selector;
+ }
+
+ Selector getGetterSelectorInComplexSendSet(SendSet node) {
+ return selectors[node.selector];
+ }
+
+ void setOperatorSelectorInComplexSendSet(SendSet node, Selector selector) {
+ selectors[node.assignmentOperator] = selector;
+ }
+
+ Selector getOperatorSelectorInComplexSendSet(SendSet node) {
+ return selectors[node.assignmentOperator];
+ }
+
+ // The following methods set selectors on the "for in" node. Since
+ // we're using three selectors, we need to use children of the node,
+ // and we arbitrarily choose which ones.
+
+ Selector setIteratorSelector(ForIn node, Selector selector) {
+ selectors[node] = selector;
+ }
+
+ Selector getIteratorSelector(ForIn node) {
+ return selectors[node];
+ }
+
+ Selector setMoveNextSelector(ForIn node, Selector selector) {
+ selectors[node.forToken] = selector;
+ }
+
+ Selector getMoveNextSelector(ForIn node) {
+ return selectors[node.forToken];
+ }
+
+ Selector setCurrentSelector(ForIn node, Selector selector) {
+ selectors[node.inToken] = selector;
+ }
+
+ Selector getCurrentSelector(ForIn node) {
+ return selectors[node.inToken];
+ }
bool isParameterChecked(Element element) {
return checkedParameters.contains(element);
@@ -1585,7 +1637,12 @@
this.statementScope = new StatementScope(),
typeResolver = new TypeResolver(compiler),
scope = element.buildScope(),
- inCheckContext = compiler.enableTypeAssertions,
+ // The type annotations on a typedef do not imply type checks.
+ // TODO(karlklose): clean this up (dartbug.com/8870).
+ inCheckContext = compiler.enableTypeAssertions &&
+ !element.isTypedef() &&
+ (element.enclosingElement == null ||
+ !element.enclosingElement.isTypedef()),
inCatchBlock = false,
super(compiler);
@@ -1866,9 +1923,6 @@
FunctionElement function = new FunctionElementX.node(
name, node, ElementKind.FUNCTION, Modifiers.EMPTY,
enclosingElement);
- // [function] and its enclosing method share the same
- // [TreeElementMapping].
- compiler.enqueuer.resolution.resolvedElements[function] = mapping;
Scope oldScope = scope; // The scope is modified by [setupFunction].
setupFunction(node, function);
defineElement(node, function, doAddToScope: node.name != null);
@@ -1955,6 +2009,13 @@
// [target] may be null which means invoking noSuchMethod on
// super.
if (target == null) {
+ target = warnAndCreateErroneousElement(
+ node, name, MessageKind.NO_SUCH_SUPER_MEMBER,
+ {'className': currentClass, 'memberName': name});
+ // We still need to register the invocation, because we might
+ // call [:super.noSuchMethod:] that does a
+ // [:InvocationMirror.invokeOn:].
+ world.registerDynamicInvocation(selector.name, selector);
compiler.backend.registerSuperNoSuchMethod();
}
} else if (Elements.isUnresolved(resolvedReceiver)) {
@@ -2216,24 +2277,29 @@
setter = field.setter;
getter = field.getter;
if (setter == null && !inInstanceContext) {
- setter =
- warnAndCreateErroneousElement(node.selector, field.name,
- MessageKind.CANNOT_RESOLVE_SETTER);
+ setter = warnAndCreateErroneousElement(
+ node.selector, field.name, MessageKind.CANNOT_RESOLVE_SETTER);
compiler.backend.registerThrowNoSuchMethod();
}
if (isComplex && getter == null && !inInstanceContext) {
- getter =
- warnAndCreateErroneousElement(node.selector, field.name,
- MessageKind.CANNOT_RESOLVE_GETTER);
+ getter = warnAndCreateErroneousElement(
+ node.selector, field.name, MessageKind.CANNOT_RESOLVE_GETTER);
compiler.backend.registerThrowNoSuchMethod();
}
} else if (target.impliesType()) {
compiler.backend.registerThrowNoSuchMethod();
} else if (target.modifiers.isFinal() || target.modifiers.isConst()) {
- setter =
- warnAndCreateErroneousElement(node.selector, target.name,
- MessageKind.CANNOT_RESOLVE_SETTER);
+ setter = warnAndCreateErroneousElement(
+ node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER);
compiler.backend.registerThrowNoSuchMethod();
+ } else if (isComplex && target.name == const SourceString('[]=')) {
+ getter = target.getEnclosingClass().lookupMember(
+ const SourceString('[]'));
+ if (getter == null) {
+ getter = warnAndCreateErroneousElement(
+ node, setter.name, MessageKind.CANNOT_RESOLVE_INDEX);
+ compiler.backend.registerThrowNoSuchMethod();
+ }
}
}
@@ -2245,34 +2311,29 @@
Selector selector = mapping.getSelector(node);
if (isComplex) {
+ Selector getterSelector;
if (selector.isSetter()) {
- // TODO(kasperl): We're registering the getter selector for
- // compound assignments on the AST selector node. In the code
- // generator, we then fetch it from there when generating the
- // getter for a SendSet node.
- Selector getterSelector = new Selector.getterFrom(selector);
- registerSend(getterSelector, getter);
- mapping.setSelector(node.selector, getterSelector);
- useElement(node.selector, getter);
+ getterSelector = new Selector.getterFrom(selector);
} else {
- // TODO(kasperl): If [getter] is resolved, it will actually
- // refer to the []= operator which isn't the one we want to
- // register here. We should consider using some notion of
- // abstract indexable element that we can resolve to so we can
- // distinguish the two.
assert(selector.isIndexSet());
- registerSend(new Selector.index(), null);
+ getterSelector = new Selector.index();
}
+ registerSend(getterSelector, getter);
+ mapping.setGetterSelectorInComplexSendSet(node, getterSelector);
+ useElement(node.selector, getter);
// Make sure we include the + and - operators if we are using
// the ++ and -- ones. Also, if op= form is used, include op itself.
void registerBinaryOperator(SourceString name) {
Selector binop = new Selector.binaryOperator(name);
world.registerDynamicInvocation(binop.name, binop);
+ mapping.setOperatorSelectorInComplexSendSet(node, binop);
}
- if (identical(source, '++')) registerBinaryOperator(const SourceString('+'));
- if (identical(source, '--')) registerBinaryOperator(const SourceString('-'));
- if (source.endsWith('=')) {
+ if (identical(source, '++')) {
+ registerBinaryOperator(const SourceString('+'));
+ } else if (identical(source, '--')) {
+ registerBinaryOperator(const SourceString('-'));
+ } else if (source.endsWith('=')) {
registerBinaryOperator(Elements.mapToUserOperator(operatorName));
}
}
@@ -2448,7 +2509,7 @@
ClassElement cls = constructor.getEnclosingClass();
// [cls] might be the implementation element and only declaration elements
// may be registered.
- world.registerInstantiatedClass(cls.declaration);
+ world.registerInstantiatedType(mapping.getType(node));
if (cls.isAbstract(compiler)) {
compiler.backend.registerAbstractClassInstantiation();
}
@@ -2518,9 +2579,7 @@
analyzeTypeArgument(type, argument);
});
}
- // TODO(ngeoffray): Also handle cases like:
- // 1) a is T
- // 2) T a (in checked mode).
+ // TODO(ngeoffray): Also handle T a (in checked mode).
}
return type;
}
@@ -2631,18 +2690,23 @@
world.registerDynamicInvocation(name, selector);
}
- registerImplicitFieldGet(SourceString name) {
- Selector selector = new Selector.getter(name, null);
- world.registerDynamicGetter(name, selector);
- }
-
visitForIn(ForIn node) {
- for (final name in const [
- const SourceString('iterator'),
- const SourceString('current')]) {
- registerImplicitFieldGet(name);
- }
- registerImplicitInvocation(const SourceString('moveNext'), 0);
+ LibraryElement library = enclosingElement.getLibrary();
+ Selector iteratorSelector =
+ new Selector.getter(const SourceString('iterator'), library);
+ world.registerDynamicGetter(iteratorSelector.name, iteratorSelector);
+ mapping.setIteratorSelector(node, iteratorSelector);
+
+ Selector currentSelector =
+ new Selector.getter(const SourceString('current'), library);
+ world.registerDynamicGetter(currentSelector.name, currentSelector);
+ mapping.setCurrentSelector(node, currentSelector);
+
+ Selector moveNextSelector =
+ new Selector.call(const SourceString('moveNext'), library, 0);
+ world.registerDynamicInvocation(moveNextSelector.name, moveNextSelector);
+ mapping.setMoveNextSelector(node, moveNextSelector);
+
visit(node.expression);
Scope blockScope = new BlockScope(scope);
Node declaration = node.declaredIdentifier;
@@ -2968,7 +3032,7 @@
DartType supertype = resolveSupertype(element, superMixin.superclass);
Link<Node> link = superMixin.mixins.nodes;
while (!link.isEmpty) {
- supertype = applyMixin(supertype, visit(link.head));
+ supertype = applyMixin(supertype, resolveType(link.head));
link = link.tail;
}
element.supertype = supertype;
@@ -3013,10 +3077,10 @@
DartType supertype = resolveSupertype(element, node.superclass);
Link<Node> link = node.mixins.nodes;
while (!link.tail.isEmpty) {
- supertype = applyMixin(supertype, visit(link.head));
+ supertype = applyMixin(supertype, resolveType(link.head));
link = link.tail;
}
- doApplyMixinTo(element, supertype, visit(link.head));
+ doApplyMixinTo(element, supertype, resolveType(link.head));
return element.computeType(compiler);
}
@@ -3093,6 +3157,10 @@
return visit(node.typeName);
}
+ DartType resolveType(TypeAnnotation node) {
+ return typeResolver.resolveTypeAnnotation(node, scope, element);
+ }
+
// TODO(johnniwinther): Remove when default class is no longer supported.
DartType visitIdentifier(Identifier node) {
Element element = scope.lookup(node.source);
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart b/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart
index 4d79898..c9372bf 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart
@@ -75,7 +75,7 @@
static AsciiString fromString(String string) {
- List<int> bytes = string.charCodes;
+ List<int> bytes = string.codeUnits;
return AsciiString.of(bytes, 0, bytes.length);
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart b/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart
index 6f47f73..aa85287 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart
@@ -68,9 +68,6 @@
const Keyword("show", isPseudo: true),
const Keyword("source", isPseudo: true) ];
- // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support.
- static const DYNAMIC_DEPRECATED = const Keyword("Dynamic", isBuiltIn: true);
-
final String syntax;
final bool isPseudo;
final bool isBuiltIn;
@@ -136,7 +133,7 @@
static KeywordState get KEYWORD_STATE {
if (_KEYWORD_STATE == null) {
List<String> strings =
- new List<String>.fixedLength(Keyword.values.length);
+ new List<String>(Keyword.values.length);
for (int i = 0; i < Keyword.values.length; i++) {
strings[i] = Keyword.values[i].syntax;
}
@@ -148,7 +145,7 @@
static KeywordState computeKeywordStateTable(int start, List<String> strings,
int offset, int length) {
- List<KeywordState> result = new List<KeywordState>.fixedLength(26);
+ List<KeywordState> result = new List<KeywordState>(26);
assert(length != 0);
int chunk = 0;
int chunkStart = -1;
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
index 8955b00..c2469c3 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
@@ -404,10 +404,8 @@
if (identical(kind, KEYWORD_TOKEN)) {
Keyword keyword = token.value;
String value = keyword.stringValue;
- // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support.
return keyword.isPseudo
|| (identical(value, 'dynamic'))
- || (identical(value, 'Dynamic'))
|| (identical(value, 'void'));
}
return false;
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
index 123b650..75b9cb5 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
@@ -660,46 +660,17 @@
int tokenizeIdentifier(int next, int start, bool allowDollar) {
bool isAscii = true;
- // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support.
- bool isDynamicBuiltIn = false;
-
- if (identical(next, $D)) {
- next = advance();
- if (identical(next, $y)) {
- next = advance();
- if (identical(next, $n)) {
- next = advance();
- if (identical(next, $a)) {
- next = advance();
- if (identical(next, $m)) {
- next = advance();
- if (identical(next, $i)) {
- next = advance();
- if (identical(next, $c)) {
- isDynamicBuiltIn = true;
- next = advance();
- }
- }
- }
- }
- }
- }
- }
-
while (true) {
if (($a <= next && next <= $z) ||
($A <= next && next <= $Z) ||
($0 <= next && next <= $9) ||
identical(next, $_) ||
(identical(next, $$) && allowDollar)) {
- isDynamicBuiltIn = false;
next = advance();
} else if ((next < 128) || (identical(next, $NBSP))) {
// Identifier ends here.
if (start == byteOffset) {
return error(const SourceString("expected identifier"));
- } else if (isDynamicBuiltIn) {
- appendKeywordToken(Keyword.DYNAMIC_DEPRECATED);
} else if (isAscii) {
appendByteStringToken(IDENTIFIER_INFO, asciiString(start, 0));
} else {
@@ -707,7 +678,6 @@
}
return next;
} else {
- isDynamicBuiltIn = false;
int nonAsciiStart = byteOffset;
do {
next = nextByte();
diff --git a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
index c100694..fc4e9b2 100644
--- a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
@@ -19,7 +19,7 @@
String readAll(String filename) {
var file = (new File(filename)).openSync(FileMode.READ);
var length = file.lengthSync();
- var buffer = new List<int>.fixedLength(length);
+ var buffer = new List<int>(length);
var bytes = file.readListSync(buffer, 0, length);
file.closeSync();
return new String.fromCharCodes(new Utf8Decoder(buffer).decodeRest());
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 0c387a8..252afbd 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -11,10 +11,8 @@
*/
class InterceptedElement extends ElementX {
final HType ssaType;
- InterceptedElement(this.ssaType, Element enclosing)
- : super(const SourceString('receiver'),
- ElementKind.PARAMETER,
- enclosing);
+ InterceptedElement(this.ssaType, SourceString name, Element enclosing)
+ : super(name, ElementKind.PARAMETER, enclosing);
DartType computeType(Compiler compiler) => ssaType.computeType(compiler);
}
@@ -185,39 +183,38 @@
// See if any variable in the top-scope of the function is captured. If yes
// we need to create a box-object.
ClosureScope scopeData = closureData.capturingScopes[node];
- if (scopeData != null) {
- HInstruction box;
- // The scope has captured variables.
- if (element != null && element.isGenerativeConstructorBody()) {
- // The box is passed as a parameter to a generative
- // constructor body.
- box = builder.addParameter(scopeData.boxElement);
- } else {
- box = createBox();
- }
- // Add the box to the known locals.
- directLocals[scopeData.boxElement] = box;
- // Make sure that accesses to the boxed locals go into the box. We also
- // need to make sure that parameters are copied into the box if necessary.
- scopeData.capturedVariableMapping.forEach((Element from, Element to) {
- // The [from] can only be a parameter for function-scopes and not
- // loop scopes.
- if (from.isParameter() && !element.isGenerativeConstructorBody()) {
- // Now that the redirection is set up, the update to the local will
- // write the parameter value into the box.
- // Store the captured parameter in the box. Get the current value
- // before we put the redirection in place.
- // We don't need to update the local for a generative
- // constructor body, because it receives a box that already
- // contains the updates as the last parameter.
- HInstruction instruction = readLocal(from);
- redirectElement(from, to);
- updateLocal(from, instruction);
- } else {
- redirectElement(from, to);
- }
- });
+ if (scopeData == null) return;
+ HInstruction box;
+ // The scope has captured variables.
+ if (element != null && element.isGenerativeConstructorBody()) {
+ // The box is passed as a parameter to a generative
+ // constructor body.
+ box = builder.addParameter(scopeData.boxElement);
+ } else {
+ box = createBox();
}
+ // Add the box to the known locals.
+ directLocals[scopeData.boxElement] = box;
+ // Make sure that accesses to the boxed locals go into the box. We also
+ // need to make sure that parameters are copied into the box if necessary.
+ scopeData.capturedVariableMapping.forEach((Element from, Element to) {
+ // The [from] can only be a parameter for function-scopes and not
+ // loop scopes.
+ if (from.isParameter() && !element.isGenerativeConstructorBody()) {
+ // Now that the redirection is set up, the update to the local will
+ // write the parameter value into the box.
+ // Store the captured parameter in the box. Get the current value
+ // before we put the redirection in place.
+ // We don't need to update the local for a generative
+ // constructor body, because it receives a box that already
+ // contains the updates as the last parameter.
+ HInstruction instruction = readLocal(from);
+ redirectElement(from, to);
+ updateLocal(from, instruction);
+ } else {
+ redirectElement(from, to);
+ }
+ });
}
/**
@@ -325,10 +322,12 @@
}
// If this method is an intercepted method, add the extra
- // parameter to it, that is the actual receiver.
+ // parameter to it, that is the actual receiver for intercepted
+ // classes, or the same as [:this:] for non-intercepted classes.
ClassElement cls = element.getEnclosingClass();
- if (builder.backend.isInterceptorClass(cls)) {
+ if (builder.backend.isInterceptedMethod(element)) {
HType type = HType.UNKNOWN;
+ SourceString name = const SourceString('receiver');
if (cls == builder.backend.jsArrayClass) {
type = HType.READABLE_ARRAY;
} else if (cls == builder.backend.jsStringClass) {
@@ -343,12 +342,21 @@
type = HType.NULL;
} else if (cls == builder.backend.jsBoolClass) {
type = HType.BOOLEAN;
+ } else if (cls == builder.backend.jsFunctionClass) {
+ type = HType.UNKNOWN;
+ } else if (cls != compiler.objectClass) {
+ JavaScriptBackend backend = compiler.backend;
+ assert(!backend.isInterceptorClass(cls));
+ name = const SourceString('_');
}
- Element parameter = new InterceptedElement(type, element);
+ Element parameter = new InterceptedElement(type, name, element);
HParameterValue value = new HParameterValue(parameter);
builder.graph.entry.addAfter(
directLocals[closureData.thisElement], value);
- directLocals[closureData.thisElement] = value;
+ if (builder.backend.isInterceptorClass(cls.declaration)) {
+ // Only use the extra parameter in intercepted classes.
+ directLocals[closureData.thisElement] = value;
+ }
value.instructionType = type;
}
}
@@ -895,6 +903,18 @@
// check at the beginning of the method. This is to avoid having
// call sites do the null check.
if (name == const SourceString('==')) {
+ if (functionElement.getEnclosingClass() == compiler.objectClass) {
+ // We special case [Object.operator==] because we know the
+ // receiver is not null and therefore can just do an identity
+ // check on [:this:]. The interceptor classes have their own
+ // synthesized [:operator==:] method.
+ HInstruction parameter = parameters.values.first;
+ HIdentity identity = new HIdentity(graph.thisInstruction, parameter);
+ add(identity);
+ HReturn ret = new HReturn(identity);
+ close(ret).addSuccessor(graph.exit);
+ return closeFunction();
+ }
handleIf(
function,
() {
@@ -1124,6 +1144,7 @@
}
inlinedFrom(Element element, f()) {
+ assert(element is FunctionElement || element is VariableElement);
return compiler.withCurrentElement(element, () {
sourceElementStack.add(element);
var result = f();
@@ -1143,7 +1164,8 @@
Link<Node> arguments,
List<FunctionElement> constructors,
Map<Element, HInstruction> fieldValues,
- FunctionElement inlinedFromElement) {
+ FunctionElement inlinedFromElement,
+ Node callNode) {
compiler.withCurrentElement(constructor, () {
assert(invariant(constructor, constructor.isImplementation));
constructors.addLast(constructor);
@@ -1163,10 +1185,34 @@
element: constructor);
}
- sourceElementStack.add(constructor.enclosingElement);
- buildFieldInitializers(constructor.enclosingElement.implementation,
- fieldValues);
- sourceElementStack.removeLast();
+ ClassElement superclass = constructor.getEnclosingClass();
+ if (compiler.world.needsRti(superclass)) {
+ // If [superclass] needs RTI, we have to give a value to its
+ // type parameters. Those values are in the [supertype]
+ // declaration of [subclass].
+ ClassElement subclass = inlinedFromElement.getEnclosingClass();
+ DartType supertype = subclass.supertype;
+ Link<DartType> typeVariables = superclass.typeVariables;
+ supertype.typeArguments.forEach((DartType argument) {
+ localsHandler.updateLocal(typeVariables.head.element,
+ analyzeTypeArgument(argument, callNode));
+ typeVariables = typeVariables.tail;
+ });
+ // If the supertype is a raw type, we need to set to null the
+ // type variables.
+ assert(typeVariables.isEmpty
+ || superclass.typeVariables == typeVariables);
+ while (!typeVariables.isEmpty) {
+ localsHandler.updateLocal(typeVariables.head.element,
+ graph.addConstantNull(constantSystem));
+ typeVariables = typeVariables.tail;
+ }
+ }
+
+ inlinedFrom(constructor, () {
+ buildFieldInitializers(constructor.enclosingElement.implementation,
+ fieldValues);
+ });
int index = 0;
FunctionSignature params = constructor.computeSignature(compiler);
@@ -1245,16 +1291,16 @@
Selector selector = elements.getSelector(call);
Link<Node> arguments = call.arguments;
inlineSuperOrRedirect(target, selector, arguments, constructors,
- fieldValues, constructor);
+ fieldValues, constructor, call);
foundSuperOrRedirect = true;
} else {
// A field initializer.
SendSet init = link.head;
Link<Node> arguments = init.arguments;
assert(!arguments.isEmpty && arguments.tail.isEmpty);
- sourceElementStack.add(constructor);
- visit(arguments.head);
- sourceElementStack.removeLast();
+ inlinedFrom(constructor, () {
+ visit(arguments.head);
+ });
fieldValues[elements[init]] = pop();
}
}
@@ -1280,7 +1326,8 @@
const Link<Node>(),
constructors,
fieldValues,
- constructor);
+ constructor,
+ functionNode);
}
}
}
@@ -1296,21 +1343,27 @@
assert(invariant(classElement, classElement.isImplementation));
classElement.forEachInstanceField(
(ClassElement enclosingClass, Element member) {
- TreeElements definitions = compiler.analyzeElement(member);
- Node node = member.parseNode(compiler);
- SendSet assignment = node.asSendSet();
- HInstruction value;
- if (assignment == null) {
- value = graph.addConstantNull(constantSystem);
- } else {
- Node right = assignment.arguments.head;
- TreeElements savedElements = elements;
- elements = definitions;
- right.accept(this);
- elements = savedElements;
- value = pop();
- }
- fieldValues[member] = value;
+ compiler.withCurrentElement(member, () {
+ TreeElements definitions = compiler.analyzeElement(member);
+ Node node = member.parseNode(compiler);
+ SendSet assignment = node.asSendSet();
+ HInstruction value;
+ if (assignment == null) {
+ value = graph.addConstantNull(constantSystem);
+ } else {
+ Node right = assignment.arguments.head;
+ TreeElements savedElements = elements;
+ elements = definitions;
+ // In case the field initializer uses closures, run the
+ // closure to class mapper.
+ compiler.closureToClassMapper.computeClosureToClassMapping(
+ member, node, elements);
+ right.accept(this);
+ elements = savedElements;
+ value = pop();
+ }
+ fieldValues[member] = value;
+ });
},
includeBackendMembers: true,
includeSuperMembers: false);
@@ -1375,19 +1428,19 @@
includeSuperMembers: true);
InterfaceType type = classElement.computeType(compiler);
- HType ssaType = new HBoundedType.exact(type);
+ HType ssaType = new HType.nonNullExact(type, compiler);
HForeignNew newObject = new HForeignNew(classElement,
ssaType,
constructorArguments);
add(newObject);
// Create the runtime type information, if needed.
- List<HInstruction> inputs = <HInstruction>[];
if (compiler.world.needsRti(classElement)) {
+ List<HInstruction> rtiInputs = <HInstruction>[];
classElement.typeVariables.forEach((TypeVariableType typeVariable) {
- inputs.add(localsHandler.directLocals[typeVariable.element]);
+ rtiInputs.add(localsHandler.readLocal(typeVariable.element));
});
- callSetRuntimeTypeInfo(classElement, inputs, newObject);
+ callSetRuntimeTypeInfo(classElement, rtiInputs, newObject);
}
// Generate calls to the constructor bodies.
@@ -1398,23 +1451,22 @@
if (body == null) continue;
List bodyCallInputs = <HInstruction>[];
bodyCallInputs.add(newObject);
- FunctionSignature functionSignature = body.computeSignature(compiler);
- functionSignature.orderedForEachParameter((parameter) {
- if (!localsHandler.isBoxed(parameter)) {
- // The parameter will be a field in the box passed as the
- // last parameter. So no need to pass it.
- bodyCallInputs.add(localsHandler.readLocal(parameter));
- }
- });
-
- // If parameters are checked, we pass the already computed
- // boolean to the constructor body.
TreeElements elements =
compiler.enqueuer.resolution.getCachedElements(constructor);
Node node = constructor.parseNode(compiler);
ClosureClassMap parameterClosureData =
compiler.closureToClassMapper.getMappingForNestedFunction(node);
+
+
+ FunctionSignature functionSignature = body.computeSignature(compiler);
functionSignature.orderedForEachParameter((parameter) {
+ // if [parameter] is boxed, it will be a field in the box passed as the
+ // last parameter. So no need to direclty pass it.
+ if (!localsHandler.isBoxed(parameter)) {
+ bodyCallInputs.add(localsHandler.readLocal(parameter));
+ }
+ // If [parameter] is checked, we pass the already computed
+ // boolean to the constructor body.
if (elements.isParameterChecked(parameter)) {
Element fieldCheck =
parameterClosureData.parametersWithSentinel[parameter];
@@ -1422,7 +1474,16 @@
}
});
- // If there are locals that escape (ie used in closures), we
+ ClassElement currentClass = constructor.getEnclosingClass();
+ if (compiler.world.needsRti(currentClass)) {
+ // If [currentClass] needs RTI, we add the type variables as
+ // parameters of the generative constructor body.
+ currentClass.typeVariables.forEach((DartType argument) {
+ bodyCallInputs.add(localsHandler.readLocal(argument.element));
+ });
+ }
+
+ // If there are locals that escape (ie mutated in closures), we
// pass the box to the constructor.
ClosureScope scopeData = parameterClosureData.capturingScopes[node];
if (scopeData != null) {
@@ -1553,7 +1614,8 @@
// Add the type parameters of the class as parameters of this
// method.
var enclosing = element.enclosingElement;
- if (element.isConstructor() && compiler.world.needsRti(enclosing)) {
+ if ((element.isConstructor() || element.isGenerativeConstructorBody())
+ && compiler.world.needsRti(enclosing)) {
enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
HParameterValue param = addParameter(typeVariable.element);
localsHandler.directLocals[typeVariable.element] = param;
@@ -2164,8 +2226,9 @@
}
});
- HType type = new HBoundedType.exact(
- compiler.functionClass.computeType(compiler));
+ HType type = new HType.nonNullExact(
+ compiler.functionClass.computeType(compiler),
+ compiler);
push(new HForeignNew(closureClassElement, type, capturedVariables));
}
@@ -2243,74 +2306,12 @@
pushWithPosition(result, node);
}
- void visitBinary(
- HInstruction left, Operator op, HInstruction right, Send send) {
- Selector selector = null;
- // TODO(ngeoffray): The resolver creates these selectors already
- // but does not put them on the [send] instruction.
+ void visitBinary(HInstruction left,
+ Operator op,
+ HInstruction right,
+ Selector selector,
+ Send send) {
switch (op.source.stringValue) {
- case "+":
- case "+=":
- case "++":
- selector = new Selector.binaryOperator(const SourceString('+'));
- break;
- case "-":
- case "-=":
- case "--":
- selector = new Selector.binaryOperator(const SourceString('-'));
- break;
- case "*":
- case "*=":
- selector = new Selector.binaryOperator(const SourceString('*'));
- break;
- case "/":
- case "/=":
- selector = new Selector.binaryOperator(const SourceString('/'));
- break;
- case "~/":
- case "~/=":
- selector = new Selector.binaryOperator(const SourceString('~/'));
- break;
- case "%":
- case "%=":
- selector = new Selector.binaryOperator(const SourceString('%'));
- break;
- case "<<":
- case "<<=":
- selector = new Selector.binaryOperator(const SourceString('<<'));
- break;
- case ">>":
- case ">>=":
- selector = new Selector.binaryOperator(const SourceString('>>'));
- break;
- case "|":
- case "|=":
- selector = new Selector.binaryOperator(const SourceString('|'));
- break;
- case "&":
- case "&=":
- selector = new Selector.binaryOperator(const SourceString('&'));
- break;
- case "^":
- case "^=":
- selector = new Selector.binaryOperator(const SourceString('^'));
- break;
- case "==":
- case "!=":
- selector = new Selector.binaryOperator(const SourceString('=='));
- break;
- case "<":
- selector = new Selector.binaryOperator(const SourceString('<'));
- break;
- case "<=":
- selector = new Selector.binaryOperator(const SourceString('<='));
- break;
- case ">":
- selector = new Selector.binaryOperator(const SourceString('>'));
- break;
- case ">=":
- selector = new Selector.binaryOperator(const SourceString('>='));
- break;
case "===":
pushWithPosition(new HIdentity(left, right), op);
return;
@@ -2319,9 +2320,6 @@
add(eq);
pushWithPosition(new HNot(eq), op);
return;
- default:
- compiler.internalError("Unexpected operator $op", node: op);
- break;
}
pushWithPosition(
@@ -2350,25 +2348,17 @@
}
/**
- * Returns a set of interceptor classes that contain a member whose
- * signature matches the given [selector].
+ * Returns a set of interceptor classes that contain the given
+ * [selector].
*/
- Set<ClassElement> getInterceptedClassesOn(Selector selector) {
- return backend.getInterceptedClassesOn(selector);
- }
-
void generateInstanceGetterWithCompiledReceiver(Send send,
+ Selector selector,
HInstruction receiver) {
assert(Elements.isInstanceSend(send, elements));
- // TODO(kasperl): This is a convoluted way of checking if we're
- // generating code for a compound assignment. If we are, we need
- // to get the selector from the mapping for the AST selector node.
- Selector selector = (send.asSendSet() == null)
- ? elements.getSelector(send)
- : elements.getSelector(send.selector);
assert(selector.isGetter());
SourceString getterName = selector.name;
- Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
+ Set<ClassElement> interceptedClasses =
+ backend.getInterceptedClassesOn(getterName);
bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
HInstruction instruction;
@@ -2418,7 +2408,8 @@
}
} else if (Elements.isInstanceSend(send, elements)) {
HInstruction receiver = generateInstanceSendReceiver(send);
- generateInstanceGetterWithCompiledReceiver(send, receiver);
+ generateInstanceGetterWithCompiledReceiver(
+ send, elements.getSelector(send), receiver);
} else if (Elements.isStaticOrTopLevelFunction(element)) {
// TODO(5346): Try to avoid the need for calling [declaration] before
// creating an [HStatic].
@@ -2443,7 +2434,8 @@
assert(selector.isSetter());
SourceString setterName = selector.name;
bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
- Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
+ Set<ClassElement> interceptedClasses =
+ backend.getInterceptedClassesOn(setterName);
if (interceptedClasses != null) {
// If we're using an interceptor class, emit a call to the
// getInterceptor method and then the actual dynamic call on the
@@ -2587,14 +2579,10 @@
// TODO(karlklose): change construction of the representations to be GVN'able
// (dartbug.com/7182).
List<HInstruction> buildTypeArgumentRepresentations(DartType type) {
- HInstruction createForeignArray(String code, inputs) {
- return createForeign(code, HType.READABLE_ARRAY, inputs);
- }
-
// Compute the representation of the type arguments, including access
// to the runtime type information for type variables as instructions.
HInstruction representations;
- if (type.element.isTypeVariable()) {
+ if (type.kind == TypeKind.TYPE_VARIABLE) {
return <HInstruction>[addTypeVariableReference(type)];
} else {
assert(type.element.isClass());
@@ -2606,7 +2594,8 @@
HInstruction runtimeType = addTypeVariableReference(variable);
inputs.add(runtimeType);
});
- HInstruction representation = createForeignArray(template, inputs);
+ HInstruction representation =
+ createForeign(template, HType.READABLE_ARRAY, inputs);
add(representation);
arguments.add(representation);
}
@@ -2647,16 +2636,23 @@
}
return;
}
- if (type.element.isTypeVariable()) {
- // TODO(karlklose): remove this check when the backend can deal with
- // checks of the form [:o is T:] where [:T:] is a type variable.
- stack.add(graph.addConstantBool(true, constantSystem));
- return;
- }
HInstruction instruction;
- if (type.element.isTypeVariable() ||
- RuntimeTypeInformation.hasTypeArguments(type)) {
+ if (type.kind == TypeKind.TYPE_VARIABLE) {
+ List<HInstruction> representations =
+ buildTypeArgumentRepresentations(type);
+ assert(representations.length == 1);
+ HInstruction runtimeType = addTypeVariableReference(type);
+ Element helper = backend.getGetObjectIsSubtype();
+ HInstruction helperCall = new HStatic(helper);
+ add(helperCall);
+ List<HInstruction> inputs = <HInstruction>[helperCall, expression,
+ runtimeType];
+ instruction = new HInvokeStatic(inputs, HType.BOOLEAN);
+ add(instruction);
+ compiler.enqueuer.codegen.registerIsCheck(type);
+
+ } else if (RuntimeTypeInformation.hasTypeArguments(type)) {
void argumentsCheck() {
HInstruction typeInfo = getRuntimeTypeInfo(expression);
@@ -2685,7 +2681,8 @@
void classCheck() { push(new HIs(type, <HInstruction>[expression])); }
SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node);
- branchBuilder.handleLogicalAndOr(classCheck, argumentsCheck, isAnd: true);
+ branchBuilder.handleLogicalAndOr(classCheck, argumentsCheck,
+ isAnd: true);
instruction = pop();
} else {
instruction = new HIs(type, <HInstruction>[expression]);
@@ -2711,7 +2708,7 @@
visit(node.argumentsNode);
var right = pop();
var left = pop();
- visitBinary(left, op, right, node);
+ visitBinary(left, op, right, elements.getSelector(node), node);
}
}
@@ -3100,10 +3097,11 @@
argumentNamesInstruction,
HType.UNKNOWN);
- var inputs = <HInstruction>[
- target,
- self,
- pop()];
+ var inputs = <HInstruction>[target, self];
+ if (backend.isInterceptedMethod(element)) {
+ inputs.add(self);
+ }
+ inputs.add(pop());
push(new HInvokeSuper(inputs));
}
@@ -3118,13 +3116,18 @@
visitSuperSend(Send node) {
Selector selector = elements.getSelector(node);
Element element = elements[node];
- if (element == null) return generateSuperNoSuchMethodSend(node);
+ if (Elements.isUnresolved(element)) {
+ return generateSuperNoSuchMethodSend(node);
+ }
// TODO(5346): Try to avoid the need for calling [declaration] before
// creating an [HStatic].
HInstruction target = new HStatic(element.declaration);
HInstruction context = localsHandler.readThis();
add(target);
var inputs = <HInstruction>[target, context];
+ if (backend.isInterceptedMethod(element)) {
+ inputs.add(context);
+ }
if (node.isPropertyAccess) {
push(new HInvokeSuper(inputs));
} else if (element.isFunction() || element.isGenerativeConstructor()) {
@@ -3158,11 +3161,10 @@
member = closureClass.methodElement;
member = member.getOutermostEnclosingMemberOrTopLevel();
}
- if (member.isFactoryConstructor()) {
+ if (member.isConstructor() || member.isGenerativeConstructorBody()) {
// The type variable is stored in a parameter of the method.
return localsHandler.readLocal(type.element);
- } else if (member.isInstanceMember() ||
- member.isGenerativeConstructor()) {
+ } else if (member.isInstanceMember()) {
// The type variable is stored on the object. Generate code to extract
// the type arguments from the object, substitute them as an instance
// of the type we are testing against (if necessary), and extract the
@@ -3268,7 +3270,7 @@
}
} else if (element.isGenerativeConstructor()) {
ClassElement cls = element.getEnclosingClass();
- return new HBoundedType.exact(cls.thisType);
+ return new HType.nonNullExact(cls.thisType, compiler);
} else {
return HType.UNKNOWN;
}
@@ -3564,7 +3566,8 @@
Selector selector,
HInstruction receiver,
List<HInstruction> arguments) {
- Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
+ Set<ClassElement> interceptedClasses =
+ backend.getInterceptedClassesOn(selector.name);
List<HInstruction> inputs = <HInstruction>[];
bool isIntercepted = interceptedClasses != null;
if (isIntercepted) {
@@ -3625,12 +3628,16 @@
}
HInvokeDynamicMethod left = buildInvokeDynamic(
- node, new Selector.index(), receiver, [index]);
+ node,
+ elements.getGetterSelectorInComplexSendSet(node),
+ receiver,
+ <HInstruction>[index]);
add(left);
- visitBinary(left, op, value, node);
+ visitBinary(left, op, value,
+ elements.getOperatorSelectorInComplexSendSet(node), node);
value = pop();
HInvokeDynamicMethod assign = buildInvokeDynamic(
- node, new Selector.indexSet(), receiver, [index, value]);
+ node, elements.getSelector(node), receiver, [index, value]);
add(assign);
if (isPrefix) {
stack.add(value);
@@ -3657,7 +3664,8 @@
HInstruction receiver = null;
if (Elements.isInstanceSend(node, elements)) {
receiver = generateInstanceSendReceiver(node);
- generateInstanceGetterWithCompiledReceiver(node, receiver);
+ generateInstanceGetterWithCompiledReceiver(
+ node, elements.getGetterSelectorInComplexSendSet(node), receiver);
} else {
generateGetter(node, elements[node.selector]);
}
@@ -3669,7 +3677,8 @@
} else {
right = graph.addConstantInt(1, constantSystem);
}
- visitBinary(left, op, right, node);
+ visitBinary(left, op, right,
+ elements.getOperatorSelectorInComplexSendSet(node), node);
HInstruction operation = pop();
assert(operation != null);
if (Elements.isInstanceSend(node, elements)) {
@@ -3915,10 +3924,9 @@
// The iterator is shared between initializer, condition and body.
HInstruction iterator;
void buildInitializer() {
- SourceString iteratorName = const SourceString("iterator");
- Selector selector =
- new Selector.getter(iteratorName, currentElement.getLibrary());
- Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
+ Selector selector = elements.getIteratorSelector(node);
+ Set<ClassElement> interceptedClasses =
+ backend.getInterceptedClassesOn(selector.name);
visit(node.expression);
HInstruction receiver = pop();
bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
@@ -3937,15 +3945,12 @@
add(iterator);
}
HInstruction buildCondition() {
- SourceString name = const SourceString('moveNext');
- Selector selector = new Selector.call(
- name, currentElement.getLibrary(), 0);
+ Selector selector = elements.getMoveNextSelector(node);
push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator]));
return popBoolified();
}
void buildBody() {
- SourceString name = const SourceString('current');
- Selector call = new Selector.getter(name, currentElement.getLibrary());
+ Selector call = elements.getCurrentSelector(node);
bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call);
push(new HInvokeDynamicGetter(call, null, iterator, !hasGetter));
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 527ce59..f2fe22c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -1625,7 +1625,7 @@
if (target != null) {
// If we know we're calling a specific method, register that
// method only.
- assert(selector.typeKind != TypedSelectorKind.UNKNOWN);
+ assert(selector.mask != null);
world.registerDynamicInvocationOf(target, selector);
} else {
SourceString name = node.selector.name;
@@ -2365,8 +2365,7 @@
checkType(input, type);
push(new js.Binary('&&', nullTest, pop()));
attachLocationToLast(node);
- } else if (input.instructionType.canBePrimitive()
- || input.instructionType.canBeNull()) {
+ } else if (input.canBePrimitive(compiler) || input.canBeNull()) {
checkObject(input, '===');
js.Expression objectTest = pop();
checkType(input, type);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index b6714b8..d7acb32 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -168,7 +168,11 @@
if (constant.isFunction()) return HType.UNKNOWN;
if (constant.isSentinel()) return HType.UNKNOWN;
ObjectConstant objectConstant = constant;
- return new HBoundedType.exact(objectConstant.type);
+ // TODO(kasperl): This seems a bit fishy, but we do not have the
+ // compiler at hand so we cannot use the usual HType factory
+ // methods. At some point this should go away.
+ TypeMask mask = new TypeMask.nonNullExact(objectConstant.type);
+ return new HBoundedType(mask);
}
HConstant addConstant(Constant constant) {
@@ -881,8 +885,9 @@
bool isTypeUnknown() => instructionType.isUnknown();
bool isIndexablePrimitive() => instructionType.isIndexablePrimitive();
bool isPrimitive() => instructionType.isPrimitive();
- bool canBePrimitive() => instructionType.canBePrimitive();
bool canBeNull() => instructionType.canBeNull();
+ bool canBePrimitive(Compiler compiler) =>
+ instructionType.canBePrimitive(compiler);
/**
* Type of the unstruction.
@@ -1213,6 +1218,12 @@
bool isJsStatement() => isEnabled;
bool canThrow() => isEnabled;
+ // A [HTypeGuard] cannot be moved anywhere in the graph, otherwise
+ // instructions that have side effects could end up before the guard
+ // in the otpimized version, and after the guard in a bailout
+ // version.
+ bool isPure() => false;
+
accept(HVisitor visitor) => visitor.visitTypeGuard(this);
int typeCode() => HInstruction.TYPE_GUARD_TYPECODE;
bool typeEquals(other) => other is HTypeGuard;
@@ -1305,6 +1316,9 @@
toString() => 'invoke dynamic: $selector';
HInstruction get receiver => inputs[0];
+ /**
+ * Returns whether this call is on an intercepted method.
+ */
bool get isInterceptorCall {
// We know it's a selector call if it follows the interceptor
// calling convention, which adds the actual receiver as a
@@ -1312,6 +1326,18 @@
return inputs.length - 2 == selector.argumentCount;
}
+ /**
+ * Returns whether this call is on an interceptor object.
+ */
+ bool get isCallOnInterceptor {
+ // When the optimizers know this call does not need an
+ // interceptor, they udpate the receiver of the call to be the
+ // actual receiver.
+ // TODO(ngeoffray): This is very fragile and we should inspect the
+ // receiver instead.
+ return isInterceptorCall && inputs[0] != inputs[1];
+ }
+
int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
bool typeEquals(other) => other is HInvokeDynamic;
bool dataEquals(HInvokeDynamic other) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index ced53a5..7a41583 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -138,8 +138,16 @@
// If we can replace [instruction] with [replacement], then
// [replacement]'s type can be narrowed.
- replacement.instructionType = replacement.instructionType.intersection(
+ 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;
+ }
// If the replacement instruction does not know its
// source element, use the source element of the
@@ -309,27 +317,6 @@
}
}
- // Check if this call does not need to be intercepted.
- HType type = input.instructionType;
- // TODO(kasperl): Get rid of this refinement once the receiver
- // specialization phase takes care of it.
- Selector refined = type.refine(selector, compiler);
- Set<ClassElement> classes = backend.getInterceptedClassesOn(
- refined, canBeNull: type.canBeNull());
- if (classes == null) {
- if (selector.isGetter()) {
- // Change the call to a regular invoke dynamic call.
- return new HInvokeDynamicGetter(selector, null, input, false);
- } else if (selector.isSetter()) {
- return new HInvokeDynamicSetter(
- selector, null, input, node.inputs[2], false);
- } else {
- // Change the call to a regular invoke dynamic call.
- return new HInvokeDynamicMethod(
- selector, node.inputs.getRange(1, node.inputs.length - 1));
- }
- }
-
// If the intercepted call is through a constant interceptor, we
// know which element to call.
if (node is !HOneShotInterceptor
@@ -337,7 +324,10 @@
&& selector.isCall()) {
DartType type = interceptor.instructionType.computeType(compiler);
ClassElement cls = type.element;
- node.element = cls.lookupSelector(selector);
+ Element target = cls.lookupSelector(selector);
+ if (target != null && selector.applies(target, compiler)) {
+ node.element = target;
+ }
}
return node;
}
@@ -347,7 +337,7 @@
if (backend.fixedLengthListConstructor == null) {
backend.fixedLengthListConstructor =
compiler.listClass.lookupConstructor(
- new Selector.callConstructor(const SourceString("fixedLength"),
+ new Selector.callConstructor(const SourceString(""),
compiler.listClass.getLibrary()));
}
// TODO(ngeoffray): checking if the second input is an integer
@@ -355,6 +345,7 @@
// other optimizations to reason on a fixed length constructor
// that we know takes an int.
return element == backend.fixedLengthListConstructor
+ && node.inputs.length == 2
&& node.inputs[1].isInteger();
}
@@ -366,7 +357,7 @@
}
HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
- if (node.isInterceptorCall) return handleInterceptorCall(node);
+ if (node.isCallOnInterceptor) return handleInterceptorCall(node);
HType receiverType = node.receiver.instructionType;
Selector selector = receiverType.refine(node.selector, compiler);
Element element = compiler.world.locateSingleElement(selector);
@@ -589,7 +580,7 @@
if (node.element == backend.jsArrayLength) {
if (node.receiver is HInvokeStatic) {
// Try to recognize the length getter with input
- // [:new List.fixedLength(int):].
+ // [:new List(int):].
HInvokeStatic call = node.receiver;
if (isFixedSizeListConstructor(call)) {
return call.inputs[1];
@@ -600,7 +591,7 @@
}
HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
- if (node.isInterceptorCall) return handleInterceptorCall(node);
+ if (node.isCallOnInterceptor) return handleInterceptorCall(node);
Element field =
findConcreteFieldForDynamicAccess(node.receiver, node.selector);
@@ -616,6 +607,14 @@
HFieldGet result = new HFieldGet(
field, node.inputs[0], isAssignable: !isFinalOrConst);
+ // Some native fields are views of data that may be changed by operations.
+ // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2).
+ // TODO(sra): Refine the effect classification so that native effects are
+ // distinct from ordinary Dart effects.
+ if (field.isNative()) {
+ result.setDependsOnSomething();
+ }
+
if (field.getEnclosingClass().isNative()) {
result.instructionType =
new HType.subtype(field.computeType(compiler), compiler);
@@ -636,12 +635,15 @@
}
HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
- if (node.isInterceptorCall) return handleInterceptorCall(node);
+ if (node.isCallOnInterceptor) return handleInterceptorCall(node);
Element field =
findConcreteFieldForDynamicAccess(node.receiver, node.selector);
if (field == null || !field.isAssignable()) return node;
- HInstruction value = node.inputs[1];
+ // Use [:node.inputs.last:] in case the call follows the
+ // interceptor calling convention, but is not a call on an
+ // interceptor.
+ HInstruction value = node.inputs.last;
if (compiler.enableTypeAssertions) {
HInstruction other = value.convertType(
compiler,
@@ -670,9 +672,20 @@
HInstruction visitInterceptor(HInterceptor node) {
if (node.isConstant()) return node;
+ // If the intercepted object does not need to be intercepted, just
+ // return the object (the [:getInterceptor:] method would have
+ // returned the object).
+ HType type = node.receiver.instructionType;
+ if (!type.canBePrimitive(compiler)) {
+ if (!(type.canBeNull()
+ && node.interceptedClasses.contains(compiler.objectClass))) {
+ return node.receiver;
+ }
+ }
HInstruction constant = tryComputeConstantInterceptor(
node.inputs[0], node.interceptedClasses);
if (constant == null) return node;
+
return constant;
}
@@ -1080,8 +1093,8 @@
// loop changes flags list to zero so we can use bitwise or when
// propagating loop changes upwards.
final int length = graph.blocks.length;
- blockChangesFlags = new List<int>.fixedLength(length);
- loopChangesFlags = new List<int>.fixedLength(length);
+ blockChangesFlags = new List<int>(length);
+ loopChangesFlags = new List<int>(length);
for (int i = 0; i < length; i++) loopChangesFlags[i] = 0;
// Run through all the basic blocks in the graph and fill in the
@@ -1156,7 +1169,7 @@
List<ValueSet> values;
void visitGraph(HGraph graph) {
- values = new List<ValueSet>.fixedLength(graph.blocks.length);
+ values = new List<ValueSet>(graph.blocks.length);
for (int i = 0; i < graph.blocks.length; i++) {
values[graph.blocks[i].id] = new ValueSet();
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index fb62f89..fd4884c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -176,36 +176,32 @@
String temporaryId(HInstruction instruction) {
String prefix;
HType type = instruction.instructionType;
- if (!type.isPrimitive()) {
- prefix = 'U';
+ if (type == HType.MUTABLE_ARRAY) {
+ prefix = 'm';
+ } else if (type == HType.READABLE_ARRAY) {
+ prefix = 'a';
+ } else if (type == HType.EXTENDABLE_ARRAY) {
+ prefix = 'e';
+ } else if (type == HType.BOOLEAN) {
+ prefix = 'b';
+ } else if (type == HType.INTEGER) {
+ prefix = 'i';
+ } else if (type == HType.DOUBLE) {
+ prefix = 'd';
+ } else if (type == HType.NUMBER) {
+ prefix = 'n';
+ } else if (type == HType.STRING) {
+ prefix = 's';
+ } else if (type == HType.UNKNOWN) {
+ prefix = 'v';
+ } else if (type == HType.CONFLICTING) {
+ prefix = 'c';
+ } else if (type == HType.INDEXABLE_PRIMITIVE) {
+ prefix = 'r';
+ } else if (type == HType.NULL) {
+ prefix = 'u';
} else {
- if (type == HType.MUTABLE_ARRAY) {
- prefix = 'm';
- } else if (type == HType.READABLE_ARRAY) {
- prefix = 'a';
- } else if (type == HType.EXTENDABLE_ARRAY) {
- prefix = 'e';
- } else if (type == HType.BOOLEAN) {
- prefix = 'b';
- } else if (type == HType.INTEGER) {
- prefix = 'i';
- } else if (type == HType.DOUBLE) {
- prefix = 'd';
- } else if (type == HType.NUMBER) {
- prefix = 'n';
- } else if (type == HType.STRING) {
- prefix = 's';
- } else if (type == HType.UNKNOWN) {
- prefix = 'v';
- } else if (type == HType.CONFLICTING) {
- prefix = 'c';
- } else if (type == HType.INDEXABLE_PRIMITIVE) {
- prefix = 'r';
- } else if (type == HType.NULL) {
- prefix = 'u';
- } else {
- prefix = 'x';
- }
+ prefix = 'U';
}
return "$prefix${instruction.id}";
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
index 8372c2b..0c0ad12 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -8,114 +8,74 @@
const HType();
/**
- * Returns an [HType] that represents [type] and all types that have
- * [type] as supertype.
+ * Returns an [HType] with the given type mask. The factory method
+ * takes care to track whether or not the resulting type may be a
+ * primitive type.
*/
- factory HType.fromBoundedType(DartType type,
- Compiler compiler,
- {bool canBeNull: true,
- bool isExact: false,
- bool isInterfaceType: true}) {
- Element element = type.element;
+ factory HType.fromMask(TypeMask mask, Compiler compiler) {
+ Element element = mask.base.element;
if (element.kind == ElementKind.TYPE_VARIABLE) {
- // TODO(ngeoffray): Replace object type with [type].
- return new HBoundedPotentialPrimitiveType(
- compiler.objectClass.computeType(compiler),
- true,
- canBeNull: canBeNull,
- isInterfaceType: isInterfaceType);
+ // TODO(ngeoffray): Can we do better here?
+ DartType base = compiler.objectClass.computeType(compiler);
+ mask = new TypeMask.internal(base, mask.flags);
+ return new HBoundedType(mask);
}
+ bool isNullable = mask.isNullable;
JavaScriptBackend backend = compiler.backend;
if (element == compiler.intClass || element == backend.jsIntClass) {
- return canBeNull ? HType.INTEGER_OR_NULL : HType.INTEGER;
+ return isNullable ? HType.INTEGER_OR_NULL : HType.INTEGER;
} else if (element == compiler.numClass
|| element == backend.jsNumberClass) {
- return canBeNull ? HType.NUMBER_OR_NULL : HType.NUMBER;
+ return isNullable ? HType.NUMBER_OR_NULL : HType.NUMBER;
} else if (element == compiler.doubleClass
|| element == backend.jsDoubleClass) {
- return canBeNull ? HType.DOUBLE_OR_NULL : HType.DOUBLE;
+ return isNullable ? HType.DOUBLE_OR_NULL : HType.DOUBLE;
} else if (element == compiler.stringClass
|| element == backend.jsStringClass) {
- return canBeNull ? HType.STRING_OR_NULL : HType.STRING;
+ return isNullable ? HType.STRING_OR_NULL : HType.STRING;
} else if (element == compiler.boolClass
|| element == backend.jsBoolClass) {
- return canBeNull ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN;
+ return isNullable ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN;
} else if (element == compiler.nullClass
|| element == backend.jsNullClass) {
return HType.NULL;
} else if (element == backend.jsArrayClass) {
- return canBeNull
+ return isNullable
? HType.READABLE_ARRAY.union(HType.NULL, compiler)
: HType.READABLE_ARRAY;
- } else if (isInterfaceType) {
- if (element == compiler.listClass
- || Elements.isListSupertype(element, compiler)) {
- return new HBoundedPotentialPrimitiveArray(
- type,
- canBeNull: canBeNull,
- isInterfaceType: isInterfaceType);
- } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
- return new HBoundedPotentialPrimitiveNumberOrString(
- type,
- canBeNull: canBeNull,
- isInterfaceType: isInterfaceType);
- } else if (Elements.isStringOnlySupertype(element, compiler)) {
- return new HBoundedPotentialPrimitiveString(
- type,
- canBeNull: canBeNull,
- isInterfaceType: isInterfaceType);
- }
}
- if (!isExact && (element == compiler.objectClass ||
- element == compiler.dynamicClass)) {
- return new HBoundedPotentialPrimitiveType(
- compiler.objectClass.computeType(compiler),
- true,
- canBeNull: canBeNull,
- isInterfaceType: isInterfaceType);
- }
- return new HBoundedType(
- type,
- canBeNull: canBeNull,
- isExact: isExact,
- isInterfaceType: isInterfaceType);
+ return new HBoundedType(mask);
}
- factory HType.nonNullExactClass(DartType type, Compiler compiler) {
- return new HType.fromBoundedType(
- type,
- compiler,
- canBeNull: false,
- isExact: true,
- isInterfaceType: false);
+ factory HType.exact(DartType type, Compiler compiler) {
+ TypeMask mask = new TypeMask.exact(type);
+ return new HType.fromMask(mask, compiler);
}
- factory HType.nonNullSubclass(DartType type, Compiler compiler) {
- return new HType.fromBoundedType(
- type,
- compiler,
- canBeNull: false,
- isExact: false,
- isInterfaceType: false);
+ factory HType.subclass(DartType type, Compiler compiler) {
+ TypeMask mask = new TypeMask.subclass(type);
+ return new HType.fromMask(mask, compiler);
}
factory HType.subtype(DartType type, Compiler compiler) {
- return new HType.fromBoundedType(
- type,
- compiler,
- canBeNull: true,
- isExact: false,
- isInterfaceType: true);
+ TypeMask mask = new TypeMask.subtype(type);
+ return new HType.fromMask(mask, compiler);
+ }
+
+ factory HType.nonNullExact(DartType type, Compiler compiler) {
+ TypeMask mask = new TypeMask.nonNullExact(type);
+ return new HType.fromMask(mask, compiler);
+ }
+
+ factory HType.nonNullSubclass(DartType type, Compiler compiler) {
+ TypeMask mask = new TypeMask.nonNullSubclass(type);
+ return new HType.fromMask(mask, compiler);
}
factory HType.nonNullSubtype(DartType type, Compiler compiler) {
- return new HType.fromBoundedType(
- type,
- compiler,
- canBeNull: false,
- isExact: false,
- isInterfaceType: true);
+ TypeMask mask = new TypeMask.nonNullSubtype(type);
+ return new HType.fromMask(mask, compiler);
}
factory HType.fromBaseType(BaseType baseType, Compiler compiler) {
@@ -132,7 +92,7 @@
return new HType.nonNullSubtype(
compiler.mapLiteralClass.computeType(compiler), compiler);
} else {
- return new HType.nonNullExactClass(
+ return new HType.nonNullExact(
cls.computeType(compiler), compiler);
}
}
@@ -165,7 +125,7 @@
// like [native.SpecialType.JsObject], or [native.SpecialType.JsArray].
factory HType.fromNativeType(type, Compiler compiler) {
if (type == native.SpecialType.JsObject) {
- return new HType.nonNullExactClass(
+ return new HType.nonNullExact(
compiler.objectClass.computeType(compiler), compiler);
} else if (type == native.SpecialType.JsArray) {
return HType.READABLE_ARRAY;
@@ -187,6 +147,26 @@
return ssaType;
}
+ factory HType.readableArrayOrNull(Compiler compiler) {
+ return new HBoundedType(
+ READABLE_ARRAY.computeMask(compiler).nullable());
+ }
+
+ factory HType.mutableArrayOrNull(Compiler compiler) {
+ return new HBoundedType(
+ MUTABLE_ARRAY.computeMask(compiler).nullable());
+ }
+
+ factory HType.fixedArrayOrNull(Compiler compiler) {
+ return new HBoundedType(
+ FIXED_ARRAY.computeMask(compiler).nullable());
+ }
+
+ factory HType.extendableArrayOrNull(Compiler compiler) {
+ return new HBoundedType(
+ EXTENDABLE_ARRAY.computeMask(compiler).nullable());
+ }
+
static const HType CONFLICTING = const HConflictingType();
static const HType UNKNOWN = const HUnknownType();
static const HType BOOLEAN = const HBooleanType();
@@ -209,53 +189,52 @@
bool isConflicting() => identical(this, CONFLICTING);
bool isUnknown() => identical(this, UNKNOWN);
+ bool isExact() => false;
bool isNull() => false;
bool isBoolean() => false;
bool isNumber() => false;
bool isInteger() => false;
bool isDouble() => false;
bool isString() => false;
- bool isBooleanOrNull() => false;
- bool isNumberOrNull() => false;
- bool isIntegerOrNull() => false;
- bool isDoubleOrNull() => false;
- bool isStringOrNull() => false;
bool isIndexablePrimitive() => false;
bool isFixedArray() => false;
bool isReadableArray() => false;
bool isMutableArray() => false;
bool isExtendableArray() => false;
bool isPrimitive() => false;
- bool isExact() => false;
- bool isPrimitiveOrNull() => false;
- bool isTop() => false;
- bool isInterfaceType() => false;
- bool canBePrimitive() => false;
+ bool isBooleanOrNull() => false;
+ bool isNumberOrNull() => false;
+ bool isIntegerOrNull() => false;
+ bool isDoubleOrNull() => false;
+ bool isStringOrNull() => false;
+ bool isPrimitiveOrNull() => false;
+
bool canBeNull() => false;
+ bool canBePrimitive(Compiler compiler) => false;
+ bool canBePrimitiveNumber(Compiler compiler) => false;
+ bool canBePrimitiveString(Compiler compiler) => false;
+ bool canBePrimitiveArray(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() => isReadableArray();
- DartType computeType(Compiler compiler);
+ TypeMask computeMask(Compiler compiler);
Selector refine(Selector selector, Compiler compiler) {
- DartType receiverType = computeType(compiler);
- if (receiverType != null && !receiverType.isMalformed) {
- if (isExact()) {
- return new TypedSelector.exact(receiverType, selector);
- } else if (isInterfaceType()) {
- return new TypedSelector.subtype(receiverType, selector);
- } else {
- return new TypedSelector.subclass(receiverType, selector);
- }
- } else {
- return selector;
- }
+ TypeMask mask = computeMask(compiler);
+ // TODO(kasperl): Should we check if the refinement really is more
+ // specialized than the starting point?
+ if (mask == null || mask.base.isMalformed) return selector;
+ return new TypedSelector(mask, selector);
}
+ // TODO(kasperl): Try to get rid of these.
+ DartType computeType(Compiler compiler);
+ bool isTop(Compiler compiler) => false;
+
/**
* The intersection of two types is the intersection of its values. For
* example:
@@ -293,11 +272,12 @@
String toString() => name;
DartType computeType(Compiler compiler) => null;
+ TypeMask computeMask(Compiler compiler) => null;
}
class HUnknownType extends HAnalysisType {
const HUnknownType() : super("unknown");
- bool canBePrimitive() => true;
+ bool canBePrimitive(Compiler compiler) => true;
bool canBeNull() => true;
HType union(HType other, Compiler compiler) => this;
@@ -306,7 +286,7 @@
class HConflictingType extends HAnalysisType {
const HConflictingType() : super("conflicting");
- bool canBePrimitive() => true;
+ bool canBePrimitive(Compiler compiler) => true;
bool canBeNull() => true;
HType union(HType other, Compiler compiler) => other;
@@ -316,7 +296,7 @@
abstract class HPrimitiveType extends HType {
const HPrimitiveType();
bool isPrimitive() => true;
- bool canBePrimitive() => true;
+ bool canBePrimitive(Compiler compiler) => true;
bool isPrimitiveOrNull() => true;
bool isExact() => true;
}
@@ -332,6 +312,10 @@
return backend.jsNullClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.exact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.NULL;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -356,7 +340,7 @@
abstract class HPrimitiveOrNullType extends HType {
const HPrimitiveOrNullType();
- bool canBePrimitive() => true;
+ bool canBePrimitive(Compiler compiler) => true;
bool canBeNull() => true;
bool isPrimitiveOrNull() => true;
}
@@ -371,6 +355,10 @@
return backend.jsBoolClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.exact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.BOOLEAN_OR_NULL;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -385,7 +373,7 @@
if (other.isUnknown()) return HType.BOOLEAN_OR_NULL;
if (other.isBoolean()) return HType.BOOLEAN;
if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL;
- if (other.isTop()) {
+ if (other.isTop(compiler)) {
return other.canBeNull() ? this : HType.BOOLEAN;
}
if (other.canBeNull()) return HType.NULL;
@@ -404,6 +392,10 @@
return backend.jsBoolClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.nonNullExact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.BOOLEAN;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -427,13 +419,16 @@
bool isNumberOrNull() => true;
String toString() => "number or null";
bool isExact() => false;
- bool isInterfaceType() => true;
DartType computeType(Compiler compiler) {
JavaScriptBackend backend = compiler.backend;
return backend.jsNumberClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.subclass(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.NUMBER_OR_NULL;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -452,7 +447,7 @@
if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL;
if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL;
if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
- if (other.isTop()) {
+ if (other.isTop(compiler)) {
return other.canBeNull() ? this : HType.NUMBER;
}
if (other.canBeNull()) return HType.NULL;
@@ -466,13 +461,16 @@
bool isNumberOrNull() => true;
String toString() => "number";
bool isExact() => false;
- bool isInterfaceType() => true;
DartType computeType(Compiler compiler) {
JavaScriptBackend backend = compiler.backend;
return backend.jsNumberClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.nonNullSubclass(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.NUMBER;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -503,6 +501,10 @@
return backend.jsIntClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.exact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.INTEGER_OR_NULL;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -523,7 +525,7 @@
if (other.isDoubleOrNull()) return HType.NULL;
if (other.isNumber()) return HType.INTEGER;
if (other.isNumberOrNull()) return HType.INTEGER_OR_NULL;
- if (other.isTop()) {
+ if (other.isTop(compiler)) {
return other.canBeNull() ? this : HType.INTEGER;
}
if (other.canBeNull()) return HType.NULL;
@@ -542,6 +544,10 @@
return backend.jsIntClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.nonNullExact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.INTEGER;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -576,6 +582,10 @@
return backend.jsDoubleClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.exact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.DOUBLE_OR_NULL;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -596,7 +606,7 @@
if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL;
if (other.isNumber()) return HType.DOUBLE;
if (other.isNumberOrNull()) return HType.DOUBLE_OR_NULL;
- if (other.isTop()) {
+ if (other.isTop(compiler)) {
return other.canBeNull() ? this : HType.DOUBLE;
}
if (other.canBeNull()) return HType.NULL;
@@ -615,6 +625,10 @@
return backend.jsDoubleClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.nonNullExact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.DOUBLE;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -649,15 +663,20 @@
return null;
}
+ TypeMask computeMask(Compiler compiler) {
+ // TODO(ngeoffray): Represent union types.
+ return null;
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.INDEXABLE_PRIMITIVE;
if (other.isUnknown()) return HType.UNKNOWN;
if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
- if (other is HBoundedPotentialPrimitiveString) {
+ if (other.canBePrimitiveString(compiler)) {
// TODO(ngeoffray): Represent union types.
return HType.UNKNOWN;
}
- if (other is HBoundedPotentialPrimitiveArray) {
+ if (other.canBePrimitiveArray(compiler)) {
// TODO(ngeoffray): Represent union types.
return HType.UNKNOWN;
}
@@ -668,8 +687,8 @@
if (other.isConflicting()) return HType.CONFLICTING;
if (other.isUnknown()) return HType.INDEXABLE_PRIMITIVE;
if (other.isIndexablePrimitive()) return other;
- if (other is HBoundedPotentialPrimitiveString) return HType.STRING;
- if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY;
+ if (other.canBePrimitiveString(compiler)) return HType.STRING;
+ if (other.canBePrimitiveArray(compiler)) return HType.READABLE_ARRAY;
return HType.CONFLICTING;
}
}
@@ -684,6 +703,10 @@
return backend.jsStringClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.exact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.STRING_OR_NULL;
if (other.isUnknown()) return HType.UNKNOWN;
@@ -694,15 +717,12 @@
// primitive.
return HType.UNKNOWN;
}
- if (other is HBoundedPotentialPrimitiveString) {
+ if (other.canBePrimitiveString(compiler)) {
if (other.canBeNull()) {
return other;
} else {
- HBoundedType boundedType = other;
- return new HBoundedPotentialPrimitiveString(
- boundedType.type,
- canBeNull: true,
- isInterfaceType: other.isInterfaceType());
+ TypeMask otherMask = other.computeMask(compiler);
+ return new HType.fromMask(otherMask.nullable(), compiler);
}
}
if (other.isNull()) return HType.STRING_OR_NULL;
@@ -716,10 +736,10 @@
if (other.isStringOrNull()) return HType.STRING_OR_NULL;
if (other.isArray()) return HType.CONFLICTING;
if (other.isIndexablePrimitive()) return HType.STRING;
- if (other is HBoundedPotentialPrimitiveString) {
+ if (other.canBePrimitiveString(compiler)) {
return other.canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
}
- if (other.isTop()) {
+ if (other.isTop(compiler)) {
return other.canBeNull() ? this : HType.STRING;
}
if (other.canBeNull()) return HType.NULL;
@@ -738,13 +758,17 @@
return backend.jsStringClass.computeType(compiler);
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.nonNullExact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.STRING;
if (other.isUnknown()) return HType.UNKNOWN;
if (other.isString()) return HType.STRING;
if (other.isStringOrNull()) return HType.STRING_OR_NULL;
if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
- if (other is HBoundedPotentialPrimitiveString) return other;
+ if (other.canBePrimitiveString(compiler)) return other;
if (other.isNull()) return HType.STRING_OR_NULL;
return HType.UNKNOWN;
}
@@ -756,7 +780,7 @@
if (other.isArray()) return HType.CONFLICTING;
if (other.isIndexablePrimitive()) return HType.STRING;
if (other.isStringOrNull()) return HType.STRING;
- if (other is HBoundedPotentialPrimitiveString) return HType.STRING;
+ if (other.canBePrimitiveString(compiler)) return HType.STRING;
return HType.CONFLICTING;
}
}
@@ -771,19 +795,17 @@
return backend.jsArrayClass.rawType;
}
+ TypeMask computeMask(Compiler compiler) {
+ return new TypeMask.nonNullExact(computeType(compiler));
+ }
+
HType union(HType other, Compiler compiler) {
if (other.isConflicting()) return HType.READABLE_ARRAY;
if (other.isUnknown()) return HType.UNKNOWN;
if (other.isReadableArray()) return HType.READABLE_ARRAY;
if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
- if (other is HBoundedPotentialPrimitiveArray) return other;
- if (other.isNull()) {
- // TODO(ngeoffray): This should be readable array or null.
- return new HBoundedPotentialPrimitiveArray(
- compiler.listClass.computeType(compiler),
- canBeNull: true,
- isInterfaceType: true);
- }
+ if (other.canBePrimitiveArray(compiler)) return other;
+ if (other.isNull()) return new HType.readableArrayOrNull(compiler);
return HType.UNKNOWN;
}
@@ -793,7 +815,7 @@
if (other.isString()) return HType.CONFLICTING;
if (other.isReadableArray()) return other;
if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY;
- if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY;
+ if (other.canBePrimitiveArray(compiler)) return HType.READABLE_ARRAY;
return HType.CONFLICTING;
}
}
@@ -809,14 +831,8 @@
if (other.isMutableArray()) return HType.MUTABLE_ARRAY;
if (other.isReadableArray()) return HType.READABLE_ARRAY;
if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
- if (other is HBoundedPotentialPrimitiveArray) return other;
- if (other.isNull()) {
- // TODO(ngeoffray): This should be mutable array or null.
- return new HBoundedPotentialPrimitiveArray(
- compiler.listClass.computeType(compiler),
- canBeNull: true,
- isInterfaceType: true);
- }
+ if (other.canBePrimitiveArray(compiler)) return other;
+ if (other.isNull()) return new HType.mutableArrayOrNull(compiler);
return HType.UNKNOWN;
}
@@ -826,7 +842,7 @@
if (other.isMutableArray()) return other;
if (other.isString()) return HType.CONFLICTING;
if (other.isIndexablePrimitive()) return HType.MUTABLE_ARRAY;
- if (other is HBoundedPotentialPrimitiveArray) return HType.MUTABLE_ARRAY;
+ if (other.canBePrimitiveArray(compiler)) return HType.MUTABLE_ARRAY;
return HType.CONFLICTING;
}
}
@@ -843,14 +859,8 @@
if (other.isMutableArray()) return HType.MUTABLE_ARRAY;
if (other.isReadableArray()) return HType.READABLE_ARRAY;
if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
- if (other is HBoundedPotentialPrimitiveArray) return other;
- if (other.isNull()) {
- // TODO(ngeoffray): This should be fixed array or null.
- return new HBoundedPotentialPrimitiveArray(
- compiler.listClass.computeType(compiler),
- canBeNull: true,
- isInterfaceType: true);
- }
+ if (other.canBePrimitiveArray(compiler)) return other;
+ if (other.isNull()) return new HType.fixedArrayOrNull(compiler);
return HType.UNKNOWN;
}
@@ -861,7 +871,7 @@
if (other.isExtendableArray()) return HType.CONFLICTING;
if (other.isString()) return HType.CONFLICTING;
if (other.isIndexablePrimitive()) return HType.FIXED_ARRAY;
- if (other is HBoundedPotentialPrimitiveArray) return HType.FIXED_ARRAY;
+ if (other.canBePrimitiveArray(compiler)) return HType.FIXED_ARRAY;
return HType.CONFLICTING;
}
}
@@ -878,14 +888,8 @@
if (other.isMutableArray()) return HType.MUTABLE_ARRAY;
if (other.isReadableArray()) return HType.READABLE_ARRAY;
if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
- if (other is HBoundedPotentialPrimitiveArray) return other;
- if (other.isNull()) {
- // TODO(ngeoffray): This should be extendable array or null.
- return new HBoundedPotentialPrimitiveArray(
- compiler.listClass.computeType(compiler),
- canBeNull: true,
- isInterfaceType: true);
- }
+ if (other.canBePrimitiveArray(compiler)) return other;
+ if (other.isNull()) return new HType.extendableArrayOrNull(compiler);
return HType.UNKNOWN;
}
@@ -896,61 +900,82 @@
if (other.isString()) return HType.CONFLICTING;
if (other.isFixedArray()) return HType.CONFLICTING;
if (other.isIndexablePrimitive()) return HType.EXTENDABLE_ARRAY;
- if (other is HBoundedPotentialPrimitiveArray) return HType.EXTENDABLE_ARRAY;
+ if (other.canBePrimitiveArray(compiler)) return HType.EXTENDABLE_ARRAY;
return HType.CONFLICTING;
}
}
class HBoundedType extends HType {
- final DartType type;
- final bool _canBeNull;
- final bool _isExact;
- final bool _isInterfaceType;
+ final TypeMask mask;
+ const HBoundedType(this.mask);
- String toString() {
- return 'BoundedType($type, canBeNull: $_canBeNull, isExact: $_isExact)';
+ bool isExact() => mask.isExact;
+ bool isTop(Compiler compiler) => mask.containsAll(compiler);
+
+ bool canBeNull() => mask.isNullable;
+
+ bool canBePrimitive(Compiler compiler) {
+ return canBePrimitiveNumber(compiler)
+ || canBePrimitiveArray(compiler)
+ || canBePrimitiveString(compiler);
}
- bool canBeNull() => _canBeNull;
- bool isExact() => _isExact;
- bool isInterfaceType() => _isInterfaceType;
+ bool canBePrimitiveNumber(Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
+ DartType jsNumberType = backend.jsNumberClass.computeType(compiler);
+ return mask.contains(jsNumberType, compiler);
+ }
- const HBoundedType(DartType this.type,
- {bool canBeNull: true,
- bool isExact: false,
- bool isInterfaceType: true})
- : _canBeNull = canBeNull,
- _isExact = isExact,
- _isInterfaceType = isInterfaceType;
+ bool canBePrimitiveArray(Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
+ DartType jsArrayType = backend.jsArrayClass.computeType(compiler);
+ return mask.contains(jsArrayType, compiler);
+ }
- const HBoundedType.exact(DartType this.type)
- : _canBeNull = false, _isExact = true, _isInterfaceType = false;
+ bool canBePrimitiveString(Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
+ DartType jsStringType = backend.jsStringClass.computeType(compiler);
+ return mask.contains(jsStringType, compiler);
+ }
- DartType computeType(Compiler compiler) => type;
+ DartType computeType(Compiler compiler) => mask.base;
+ TypeMask computeMask(Compiler compiler) => mask;
+
+ bool operator ==(HType other) {
+ if (other is !HBoundedType) return false;
+ HBoundedType bounded = other;
+ return mask == bounded.mask;
+ }
HType intersection(HType other, Compiler compiler) {
if (this == other) return this;
if (other.isConflicting()) return HType.CONFLICTING;
+ if (isTop(compiler)) return other;
if (other.isNull()) return canBeNull() ? HType.NULL : HType.CONFLICTING;
- if (other is HBoundedType) {
- HBoundedType temp = other;
- DartType otherType = temp.type;
- if (!type.isMalformed && !otherType.isMalformed) {
- DartType intersectionType;
- if (type == otherType || compiler.types.isSubtype(type, otherType)) {
- intersectionType = type;
- } else if (compiler.types.isSubtype(otherType, type)) {
- intersectionType = otherType;
- }
- if (intersectionType != null) {
- return new HType.fromBoundedType(
- intersectionType,
- compiler,
- canBeNull: canBeNull() && temp.canBeNull(),
- isExact: isExact() || other.isExact(),
- isInterfaceType: isInterfaceType() && other.isInterfaceType());
- }
+ if (canBePrimitiveArray(compiler)) {
+ if (other.isArray()) return other;
+ if (other.isStringOrNull()) {
+ return other.isString() ? HType.CONFLICTING : HType.NULL;
+ }
+ if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY;
+ }
+
+ if (canBePrimitiveString(compiler)) {
+ if (other.isArray()) return HType.CONFLICTING;
+ if (other.isString()) return HType.STRING;
+ if (other.isStringOrNull()) {
+ return canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
+ }
+ if (other.isIndexablePrimitive()) return HType.STRING;
+ }
+
+ TypeMask otherMask = other.computeMask(compiler);
+ if (otherMask != null) {
+ TypeMask intersection = mask.intersection(otherMask, compiler.types);
+ if (intersection != null) {
+ if (intersection == mask) return this;
+ return new HType.fromMask(intersection, compiler);
}
}
if (other.isUnknown()) return this;
@@ -958,212 +983,29 @@
return HType.CONFLICTING;
}
- bool operator ==(HType other) {
- if (other is !HBoundedType) return false;
- HBoundedType bounded = other;
- return type == bounded.type
- && canBeNull() == bounded.canBeNull()
- && isExact() == bounded.isExact()
- && isInterfaceType() == bounded.isInterfaceType();
- }
-
HType union(HType other, Compiler compiler) {
if (this == other) return this;
+ if (isTop(compiler)) return this;
if (other.isNull()) {
if (canBeNull()) {
return this;
} else {
- return new HBoundedType(
- type,
- canBeNull: true,
- isExact: this.isExact(),
- isInterfaceType: this.isInterfaceType());
+ return new HType.fromMask(mask.nullable(), compiler);
}
}
- if (other is HBoundedType) {
- HBoundedType temp = other;
- if (type != temp.type) return HType.UNKNOWN;
- return new HType.fromBoundedType(
- type,
- compiler,
- canBeNull: canBeNull() || other.canBeNull(),
- isInterfaceType: isInterfaceType() || other.isInterfaceType(),
- isExact: isExact() && other.isExact());
+ TypeMask otherMask = other.computeMask(compiler);
+ if (otherMask != null) {
+ TypeMask union = mask.union(otherMask, compiler.types);
+ if (union == null) return HType.UNKNOWN;
+ if (union == mask) return this;
+ return new HType.fromMask(union, compiler);
}
if (other.isConflicting()) return this;
return HType.UNKNOWN;
}
-}
-
-class HBoundedPotentialPrimitiveType extends HBoundedType {
- final bool _isObject;
- const HBoundedPotentialPrimitiveType(DartType type,
- this._isObject,
- {bool canBeNull: true,
- bool isInterfaceType: true})
- : super(type,
- canBeNull: canBeNull,
- isExact: false,
- isInterfaceType: isInterfaceType);
String toString() {
- return 'BoundedPotentialPrimitiveType($type, canBeNull: $_canBeNull)';
- }
-
- bool canBePrimitive() => true;
- bool isTop() => _isObject;
-
- HType union(HType other, Compiler compiler) {
- if (isTop()) {
- // The union of the top type and another type is the top type.
- if (!canBeNull() && other.canBeNull()) {
- return new HBoundedPotentialPrimitiveType(
- type, true, canBeNull: canBeNull(), isInterfaceType: true);
- } else {
- return this;
- }
- } else {
- return super.union(other, compiler);
- }
- }
-
- HType intersection(HType other, Compiler compiler) {
- if (isTop()) {
- // The intersection of the top type and any other type is the other type.
- // TODO(ngeoffray): Also update the canBeNull information.
- return other;
- } else {
- return super.intersection(other, compiler);
- }
- }
-}
-
-class HBoundedPotentialPrimitiveNumberOrString
- extends HBoundedPotentialPrimitiveType {
- const HBoundedPotentialPrimitiveNumberOrString(DartType type,
- {bool canBeNull: true,
- bool isInterfaceType: true})
- : super(type,
- false,
- canBeNull: canBeNull,
- isInterfaceType: isInterfaceType);
-
- HType union(HType other, Compiler compiler) {
- if (other.isNumber()) return this;
- if (other.isNumberOrNull()) {
- if (canBeNull()) return this;
- return new HBoundedPotentialPrimitiveNumberOrString(
- type, canBeNull: true, isInterfaceType: this.isInterfaceType());
- }
-
- if (other.isString()) return this;
- if (other.isStringOrNull()) {
- if (canBeNull()) return this;
- return new HBoundedPotentialPrimitiveNumberOrString(
- type, canBeNull: true, isInterfaceType: this.isInterfaceType());
- }
-
- if (other.isNull()) {
- if (canBeNull()) return this;
- return new HBoundedPotentialPrimitiveNumberOrString(
- type, canBeNull: true, isInterfaceType: this.isInterfaceType());
- }
-
- return super.union(other, compiler);
- }
-
- HType intersection(HType other, Compiler compiler) {
- if (other.isNumber()) return other;
- if (other.isNumberOrNull()) {
- if (!canBeNull()) return HType.NUMBER;
- return other;
- }
- if (other.isString()) return other;
- if (other.isStringOrNull()) {
- if (!canBeNull()) return HType.STRING;
- return other;
- }
- return super.intersection(other, compiler);
- }
-}
-
-class HBoundedPotentialPrimitiveArray extends HBoundedPotentialPrimitiveType {
- const HBoundedPotentialPrimitiveArray(DartType type,
- {bool canBeNull: true,
- bool isInterfaceType: true})
- : super(type,
- false,
- canBeNull: canBeNull,
- isInterfaceType: isInterfaceType);
-
- HType union(HType other, Compiler compiler) {
- if (other.isString()) return HType.UNKNOWN;
- if (other.isReadableArray()) return this;
- // TODO(ngeoffray): implement union types.
- if (other.isIndexablePrimitive()) return HType.UNKNOWN;
- if (other.isNull()) {
- if (canBeNull()) {
- return this;
- } else {
- return new HBoundedPotentialPrimitiveArray(
- type, canBeNull: true, isInterfaceType: isInterfaceType());
- }
- }
- return super.union(other, compiler);
- }
-
- HType intersection(HType other, Compiler compiler) {
- if (other.isConflicting()) return HType.CONFLICTING;
- if (other.isString()) return HType.CONFLICTING;
- if (other.isReadableArray()) return other;
- if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY;
- return super.intersection(other, compiler);
- }
-}
-
-class HBoundedPotentialPrimitiveString extends HBoundedPotentialPrimitiveType {
- const HBoundedPotentialPrimitiveString(DartType type,
- {bool canBeNull: true,
- bool isInterfaceType: true})
- : super(type,
- false,
- canBeNull: canBeNull,
- isInterfaceType: isInterfaceType);
-
- bool isPrimitiveOrNull() => true;
-
- HType union(HType other, Compiler compiler) {
- if (other.isString()) return this;
- if (other.isStringOrNull()) {
- if (canBeNull()) {
- return this;
- } else {
- return new HBoundedPotentialPrimitiveString(
- type, canBeNull: true, isInterfaceType: isInterfaceType());
- }
- }
- if (other.isNull()) {
- if (canBeNull()) {
- return this;
- } else {
- return new HBoundedPotentialPrimitiveString(
- type, canBeNull: true, isInterfaceType: isInterfaceType());
- }
- }
- // TODO(ngeoffray): implement union types.
- if (other.isIndexablePrimitive()) return HType.UNKNOWN;
- return super.union(other, compiler);
- }
-
- HType intersection(HType other, Compiler compiler) {
- if (other.isConflicting()) return HType.CONFLICTING;
- if (other.isString()) return HType.STRING;
- if (other.isStringOrNull()) {
- return canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
- }
- if (other.isReadableArray()) return HType.CONFLICTING;
- if (other.isIndexablePrimitive()) return HType.STRING;
- return super.intersection(other, compiler);
+ return 'BoundedType(mask=$mask)';
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 71a20d6..4f1f4c98 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -136,7 +136,7 @@
DartType functionType = compiler.functionClass.computeType(compiler);
for (Element each in compiler.world.allFunctions.filter(refined)) {
HType inferred = (refined.isGetter() && each.isFunction())
- ? new HType.nonNullExactClass(functionType, compiler)
+ ? new HType.nonNullExact(functionType, compiler)
: new HType.inferredForElement(each, compiler);
type = type.union(inferred, compiler);
if (type.isUnknown()) break;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/value_set.dart b/sdk/lib/_internal/compiler/implementation/ssa/value_set.dart
index d565de7..b68e688 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/value_set.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/value_set.dart
@@ -8,7 +8,7 @@
int size = 0;
List<HInstruction> table;
ValueSetNode collisions;
- ValueSet() : table = new List<HInstruction>.fixedLength(8);
+ ValueSet() : table = new List<HInstruction>(8);
bool get isEmpty => size == 0;
int get length => size;
@@ -137,7 +137,7 @@
// Reset the table with a bigger capacity.
assert(capacity > table.length);
size = 0;
- table = new List<HInstruction>.fixedLength(capacity);
+ table = new List<HInstruction>(capacity);
collisions = null;
// Add the old instructions to the new table.
copyTo(this, oldTable, oldCollisions);
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index 114e8e9..6373921 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -4,6 +4,7 @@
library simple_types_inferrer;
+import '../closure.dart' show ClosureClassMap;
import '../native_handler.dart' as native;
import '../elements/elements.dart';
import '../dart2jslib.dart';
@@ -384,6 +385,13 @@
return result;
}
+ bool isNotClosure(Element element) {
+ // If the outermost enclosing element of [element] is [element]
+ // itself, we know it cannot be a closure.
+ Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
+ return outermost.declaration == element.declaration;
+ }
+
/**
* Registers that [caller] calls [callee] with the given
* [arguments].
@@ -391,6 +399,7 @@
void registerCalledElement(Element caller,
Element callee,
ArgumentsTypes arguments) {
+ assert(isNotClosure(caller));
if (analyzeCount.containsKey(caller)) return;
callee = callee.implementation;
Set<Element> callers = callersOf.putIfAbsent(
@@ -404,6 +413,7 @@
*/
void registerGetterOnElement(Element caller,
Element callee) {
+ assert(isNotClosure(caller));
if (analyzeCount.containsKey(caller)) return;
callee = callee.implementation;
Set<Element> callers = callersOf.putIfAbsent(
@@ -418,6 +428,7 @@
void registerCalledSelector(Element caller,
Selector selector,
ArgumentsTypes arguments) {
+ assert(isNotClosure(caller));
if (analyzeCount.containsKey(caller)) return;
iterateOverElements(selector, (Element element) {
assert(element.isImplementation);
@@ -433,6 +444,7 @@
* through a property access.
*/
void registerGetterOnSelector(Element caller, Selector selector) {
+ assert(isNotClosure(caller));
if (analyzeCount.containsKey(caller)) return;
iterateOverElements(selector, (Element element) {
assert(element.isImplementation);
@@ -447,6 +459,7 @@
* Registers that [caller] closurizes [function].
*/
void registerGetFunction(Element caller, Element function) {
+ assert(isNotClosure(caller));
assert(caller.isImplementation);
if (analyzeCount.containsKey(caller)) return;
// We don't register that [caller] calls [function] because we
@@ -514,6 +527,11 @@
* [secondType].
*/
Element computeLUB(Element firstType, Element secondType) {
+ bool isNumber(type) {
+ return type == compiler.numClass
+ || type == compiler.doubleClass
+ || type == compiler.intClass;
+ }
assert(secondType != null);
if (firstType == null) {
return secondType;
@@ -524,6 +542,10 @@
} else if (firstType == compiler.dynamicClass) {
return firstType;
} else if (firstType != secondType) {
+ if (isNumber(firstType) && isNumber(secondType)) {
+ // The JavaScript backend knows how to deal with numbers.
+ return compiler.numClass;
+ }
// TODO(ngeoffray): Actually compute the least upper bound.
return giveUpType;
} else {
@@ -544,19 +566,114 @@
toString() => "{ positional = $positional, named = $named }";
}
+/**
+ * Placeholder for inferred types of local variables.
+ */
+class LocalsHandler {
+ final SimpleTypesInferrer inferrer;
+ final Map<Element, Element> locals;
+ final Set<Element> captured;
+ final bool inTryBlock;
+
+ LocalsHandler(this.inferrer)
+ : locals = new Map<Element, Element>(),
+ captured = new Set<Element>(),
+ inTryBlock = false;
+ LocalsHandler.from(LocalsHandler other, {bool inTryBlock: false})
+ : locals = new Map<Element, Element>.from(other.locals),
+ captured = new Set<Element>.from(other.captured),
+ inTryBlock = other.inTryBlock || inTryBlock,
+ inferrer = other.inferrer;
+
+ Element use(Element local) {
+ return locals[local];
+ }
+
+ void update(Element local, Element type) {
+ assert(type != null);
+ if (captured.contains(local) || inTryBlock) {
+ // If a local is captured or is set in a try block, we compute the
+ // LUB of its assignments. We don't know if an assignment in a try block
+ // will be executed, so all assigments in a try block are
+ // potential types after we have left the try block.
+ type = inferrer.computeLUB(locals[local], type);
+ if (type == inferrer.giveUpType) type = inferrer.compiler.dynamicClass;
+ }
+ locals[local] = type;
+ }
+
+ void setCaptured(Element local) {
+ captured.add(local);
+ }
+
+ /**
+ * Merge handlers [first] and [second] into [:this:] and returns
+ * whether the merge changed one of the variables types in [first].
+ */
+ bool merge(LocalsHandler other) {
+ bool changed = false;
+ List<Element> toRemove = <Element>[];
+ // Iterating over a map and just updating its entries is OK.
+ locals.forEach((local, oldType) {
+ Element otherType = other.locals[local];
+ if (otherType == null) {
+ // If [local] is not in the other map, we know it is not a
+ // local we want to keep. For example, in an if/else, we don't
+ // want to keep variables declared in the if or in the else
+ // branch at the merge point.
+ toRemove.add(local);
+ return;
+ }
+ var type = inferrer.computeLUB(oldType, otherType);
+ if (type == inferrer.giveUpType) type = inferrer.compiler.dynamicClass;
+ if (type != oldType) changed = true;
+ locals[local] = type;
+ });
+
+ // Remove locals that will not be used anymore.
+ toRemove.forEach((Element element) {
+ locals.remove(element);
+ });
+
+ // Update the locals that are captured.
+ other.captured.forEach((Element element) {
+ if (locals.containsKey(element)) {
+ captured.add(element);
+ }
+ });
+ return changed;
+ }
+}
+
class SimpleTypeInferrerVisitor extends ResolvedVisitor {
final Element analyzedElement;
+ final Element outermostElement;
final SimpleTypesInferrer inferrer;
final Compiler compiler;
+ LocalsHandler locals;
Element returnType;
- SimpleTypeInferrerVisitor(Element element,
- Compiler compiler,
- this.inferrer)
- : super(compiler.enqueuer.resolution.resolvedElements[element.declaration]),
- analyzedElement = element,
- compiler = compiler {
+ SimpleTypeInferrerVisitor.internal(TreeElements mapping,
+ this.analyzedElement,
+ this.outermostElement,
+ this.inferrer,
+ this.compiler,
+ this.locals)
+ : super(mapping);
+
+ factory SimpleTypeInferrerVisitor(Element element,
+ Compiler compiler,
+ SimpleTypesInferrer inferrer,
+ [LocalsHandler handler]) {
+ Element outermostElement =
+ element.getOutermostEnclosingMemberOrTopLevel().implementation;
+ TreeElements elements = compiler.enqueuer.resolution.resolvedElements[
+ outermostElement.declaration];
assert(elements != null);
+ assert(outermostElement != null);
+ handler = handler != null ? handler : new LocalsHandler(inferrer);
+ return new SimpleTypeInferrerVisitor.internal(
+ elements, element, outermostElement, inferrer, compiler, handler);
}
Element run() {
@@ -567,12 +684,14 @@
FunctionElement function = analyzedElement;
FunctionSignature signature = function.computeSignature(compiler);
signature.forEachParameter((element) {
+ // We don't track argument types yet, so just set the fields
+ // and parameters as dynamic.
if (element.kind == ElementKind.FIELD_PARAMETER
&& element.modifiers.isFinal()) {
- // We don't track argument types yet, so just set the field
- // as dynamic.
inferrer.recordFinalFieldType(
analyzedElement, element.fieldElement, compiler.dynamicClass);
+ } else {
+ locals.update(element, compiler.dynamicClass);
}
});
visit(node.initializers);
@@ -584,6 +703,13 @@
// they return dynamic.
returnType = compiler.dynamicClass;
} else {
+ FunctionElement function = analyzedElement;
+ FunctionSignature signature = function.computeSignature(compiler);
+ signature.forEachParameter((element) {
+ // We don't track argument types yet, so just set the
+ // parameters as dynamic.
+ locals.update(element, compiler.dynamicClass);
+ });
visit(node.body);
if (returnType == null) {
// No return in the body.
@@ -611,15 +737,37 @@
}
visitFunctionExpression(FunctionExpression node) {
+ // Fetch the closure data of [node] and mark all locals that are
+ // captured by [node] to be captured in the locals handler.
+ compiler.closureToClassMapper.computeClosureToClassMapping(
+ outermostElement, outermostElement.parseNode(compiler), elements);
+ ClosureClassMap nestedClosureData =
+ compiler.closureToClassMapper.getMappingForNestedFunction(node);
+
+ nestedClosureData.forEachCapturedVariable((variable) {
+ locals.setCaptured(variable);
+ });
// We don't put the closure in the work queue of the
// inferrer, because it will share information with its enclosing
// method, like for example the types of local variables.
- SimpleTypeInferrerVisitor visitor =
- new SimpleTypeInferrerVisitor(elements[node], compiler, inferrer);
+ LocalsHandler closureLocals = new LocalsHandler.from(locals);
+ SimpleTypeInferrerVisitor visitor = new SimpleTypeInferrerVisitor(
+ elements[node], compiler, inferrer, closureLocals);
visitor.run();
+ // Do not register the runtime type, because the analysis may be
+ // invalidated due to updates on locals.
+ // TODO(ngeoffray): Track return types of closures.
+ // The closure may have updated the type of locals.
+ locals.merge(closureLocals);
return compiler.functionClass;
}
+ visitFunctionDeclaration(FunctionDeclaration node) {
+ locals.update(elements[node], compiler.functionClass);
+ return visit(node.function);
+ }
+
+
visitLiteralString(LiteralString node) {
return compiler.stringClass;
}
@@ -687,16 +835,20 @@
return compiler.dynamicClass;
}
} else if (const SourceString("=") == op.source) {
- // [: foo = 42 :]
- visit(node.receiver);
+ // [: foo = 42 :] or [: foo.bar = 42 :].
+ if (element == null) {
+ visit(node.receiver);
+ }
Link<Node> link = node.arguments;
assert(!link.isEmpty && link.tail.isEmpty);
Element type = link.head.accept(this);
- if (!Elements.isUnresolved(element)
- && element.isField()
- && element.modifiers.isFinal()) {
- inferrer.recordFinalFieldType(analyzedElement, element, type);
+ if (!Elements.isUnresolved(element)) {
+ if (element.isField() && element.modifiers.isFinal()) {
+ inferrer.recordFinalFieldType(outermostElement, element, type);
+ } else if (element.isVariable()) {
+ locals.update(element, type);
+ }
}
return type;
} else {
@@ -724,11 +876,11 @@
}
Selector selector = elements.getSelector(node);
if (node.isPropertyAccess) {
- inferrer.registerGetterOnElement(analyzedElement, element);
+ inferrer.registerGetterOnElement(outermostElement, element);
return inferrer.returnTypeOfElement(element);
} else if (element.isFunction()) {
ArgumentsTypes arguments = analyzeArguments(node.arguments);
- inferrer.registerCalledElement(analyzedElement, element, arguments);
+ inferrer.registerCalledElement(outermostElement, element, arguments);
return inferrer.returnTypeOfElement(element);
} else {
// Closure call on a getter. We don't have function types yet,
@@ -746,7 +898,7 @@
return handleForeignSend(node);
}
ArgumentsTypes arguments = analyzeArguments(node.arguments);
- inferrer.registerCalledElement(analyzedElement, element, arguments);
+ inferrer.registerCalledElement(outermostElement, element, arguments);
return inferrer.returnTypeOfElement(element);
}
@@ -817,7 +969,11 @@
return visitDynamicSend(node);
} else if (const SourceString("&&") == op.source ||
const SourceString("||") == op.source) {
- node.visitChildren(this);
+ visit(node.receiver);
+ LocalsHandler saved = new LocalsHandler.from(locals);
+ visit(node.arguments.head);
+ saved.merge(locals);
+ locals = saved;
return compiler.boolClass;
} else if (const SourceString("!") == op.source) {
node.visitChildren(this);
@@ -853,23 +1009,28 @@
visitGetterSend(Send node) {
Element element = elements[node];
if (Elements.isStaticOrTopLevelField(element)) {
- inferrer.registerGetterOnElement(analyzedElement, element);
+ inferrer.registerGetterOnElement(outermostElement, element);
return inferrer.returnTypeOfElement(element);
} else if (Elements.isInstanceSend(node, elements)) {
ClassElement receiverType;
if (node.receiver == null) {
- receiverType = analyzedElement.getEnclosingClass();
+ receiverType = outermostElement.getEnclosingClass();
} else {
receiverType = node.receiver.accept(this);
}
Selector selector = elements.getSelector(node);
- inferrer.registerGetterOnSelector(analyzedElement, selector);
+ inferrer.registerGetterOnSelector(outermostElement, selector);
return inferrer.returnTypeOfSelector(selector);
} else if (Elements.isStaticOrTopLevelFunction(element)) {
- inferrer.registerGetFunction(analyzedElement, element);
+ inferrer.registerGetFunction(outermostElement, element);
return compiler.functionClass;
+ } else if (Elements.isErroneousElement(element)) {
+ return compiler.dynamicClass;
+ } else if (Elements.isLocal(element)) {
+ assert(locals.use(element) != null);
+ return locals.use(element);
} else {
- // TODO: Analyze variable.
+ node.visitChildren(this);
return compiler.dynamicClass;
}
}
@@ -882,13 +1043,13 @@
visitDynamicSend(Send node) {
ClassElement receiverType;
if (node.receiver == null) {
- receiverType = analyzedElement.getEnclosingClass();
+ receiverType = outermostElement.getEnclosingClass();
} else {
receiverType = node.receiver.accept(this);
}
ArgumentsTypes arguments = analyzeArguments(node.arguments);
Selector selector = elements.getSelector(node);
- inferrer.registerCalledSelector(analyzedElement, selector, arguments);
+ inferrer.registerCalledSelector(outermostElement, selector, arguments);
return inferrer.returnTypeOfSelector(selector);
}
@@ -901,13 +1062,120 @@
visitConditional(Conditional node) {
node.condition.accept(this);
+ LocalsHandler saved = new LocalsHandler.from(locals);
Element firstType = node.thenExpression.accept(this);
+ LocalsHandler thenLocals = locals;
+ locals = saved;
Element secondType = node.elseExpression.accept(this);
+ locals.merge(thenLocals);
Element type = inferrer.computeLUB(firstType, secondType);
if (type == inferrer.giveUpType) type = compiler.dynamicClass;
return type;
}
+ visitVariableDefinitions(VariableDefinitions node) {
+ for (Link<Node> link = node.definitions.nodes;
+ !link.isEmpty;
+ link = link.tail) {
+ Node definition = link.head;
+ if (definition is Identifier) {
+ locals.update(elements[definition], compiler.nullClass);
+ } else {
+ assert(definition.asSendSet() != null);
+ visit(definition);
+ }
+ }
+ }
+
+ visitIf(If node) {
+ visit(node.condition);
+ LocalsHandler saved = new LocalsHandler.from(locals);
+ visit(node.thenPart);
+ LocalsHandler thenLocals = locals;
+ locals = saved;
+ visit(node.elsePart);
+ locals.merge(thenLocals);
+ return compiler.dynamicClass;
+ }
+
+ visitWhile(While node) {
+ bool changed = false;
+ do {
+ LocalsHandler saved = new LocalsHandler.from(locals);
+ visit(node.condition);
+ visit(node.body);
+ changed = saved.merge(locals);
+ locals = saved;
+ } while (changed);
+
+ return compiler.dynamicClass;
+ }
+
+ visitDoWhile(DoWhile node) {
+ bool changed = false;
+ do {
+ LocalsHandler saved = new LocalsHandler.from(locals);
+ visit(node.body);
+ visit(node.condition);
+ changed = saved.merge(locals);
+ locals = saved;
+ } while (changed);
+
+ return compiler.dynamicClass;
+ }
+
+ visitFor(For node) {
+ bool changed = false;
+ visit(node.initializer);
+ do {
+ LocalsHandler saved = new LocalsHandler.from(locals);
+ visit(node.condition);
+ visit(node.body);
+ visit(node.update);
+ changed = saved.merge(locals);
+ locals = saved;
+ } while (changed);
+
+ return compiler.dynamicClass;
+ }
+
+ visitForIn(ForIn node) {
+ bool changed = false;
+ visit(node.expression);
+ Element variable;
+ if (node.declaredIdentifier.asSend() != null) {
+ variable = elements[node.declaredIdentifier];
+ } else {
+ assert(node.declaredIdentifier.asVariableDefinitions() != null);
+ VariableDefinitions variableDefinitions = node.declaredIdentifier;
+ variable = elements[variableDefinitions.definitions.nodes.head];
+ }
+ locals.update(variable, compiler.dynamicClass);
+ do {
+ LocalsHandler saved = new LocalsHandler.from(locals);
+ visit(node.body);
+ changed = saved.merge(locals);
+ locals = saved;
+ } while (changed);
+
+ return compiler.dynamicClass;
+ }
+
+ visitTryStatement(TryStatement node) {
+ LocalsHandler saved = locals;
+ locals = new LocalsHandler.from(locals, inTryBlock: true);
+ visit(node.tryBlock);
+ saved.merge(locals);
+ locals = saved;
+ for (Node catchBlock in node.catchBlocks) {
+ saved = new LocalsHandler.from(locals);
+ visit(catchBlock);
+ saved.merge(locals);
+ locals = saved;
+ }
+ visit(node.finallyBlock);
+ }
+
internalError(String reason, {Node node}) {
compiler.internalError(reason, node: node);
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
new file mode 100644
index 0000000..5d4720d
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
@@ -0,0 +1,180 @@
+// 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 types;
+
+/**
+ * A type mask represents a set of concrete types, but the operations
+ * on it are not guaranteed to be precise. When computing the union of
+ * two masks you may get a mask that is too wide (like a common
+ * superclass instead of a proper union type) and when computing the
+ * intersection of two masks you may get a mask that is too narrow.
+ */
+class TypeMask {
+
+ static const int EXACT = 0;
+ static const int SUBCLASS = 1;
+ static const int SUBTYPE = 2;
+
+ final DartType base;
+ final int flags;
+
+ TypeMask(DartType base, int kind, bool isNullable)
+ : this.internal(base, (kind << 1) | (isNullable ? 1 : 0));
+
+ const TypeMask.exact(DartType base)
+ : this.internal(base, (EXACT << 1) | 1);
+ const TypeMask.subclass(DartType base)
+ : this.internal(base, (SUBCLASS << 1) | 1);
+ const TypeMask.subtype(DartType base)
+ : this.internal(base, (SUBTYPE << 1) | 1);
+
+ const TypeMask.nonNullExact(DartType base)
+ : this.internal(base, EXACT << 1);
+ const TypeMask.nonNullSubclass(DartType base)
+ : this.internal(base, SUBCLASS << 1);
+ const TypeMask.nonNullSubtype(DartType base)
+ : this.internal(base, SUBTYPE << 1);
+
+ const TypeMask.internal(this.base, this.flags);
+
+ bool get isNullable => (flags & 1) != 0;
+ bool get isExact => (flags >> 1) == EXACT;
+
+ // TODO(kasperl): Get rid of these. They should not be a visible
+ // part of the implementation because they make it hard to add
+ // proper union types if we ever want to.
+ bool get isSubclass => (flags >> 1) == SUBCLASS;
+ bool get isSubtype => (flags >> 1) == SUBTYPE;
+
+ /**
+ * Returns a nullable variant of [this] type mask.
+ */
+ TypeMask nullable() {
+ return isNullable ? this : new TypeMask.internal(base, flags | 1);
+ }
+
+ /**
+ * Returns whether or not this type mask contains the given type.
+ */
+ bool contains(DartType type, Compiler compiler) {
+ // TODO(kasperl): Do this error handling earlier.
+ if (base.kind != TypeKind.INTERFACE) return false;
+ assert(type.kind == TypeKind.INTERFACE);
+ // Compare the interface types.
+ ClassElement baseElement = base.element;
+ ClassElement typeElement = type.element;
+ if (isExact) {
+ return identical(baseElement, typeElement);
+ } else if (isSubclass) {
+ return typeElement.isSubclassOf(baseElement);
+ } else {
+ assert(isSubtype);
+ Set<ClassElement> subtypes = compiler.world.subtypes[baseElement];
+ return subtypes != null ? subtypes.contains(typeElement) : false;
+ }
+ }
+
+ // TODO(kasperl): Try to get rid of this method. It shouldn't really
+ // be necessary.
+ bool containsAll(Compiler compiler) {
+ // TODO(kasperl): Do this error handling earlier.
+ if (base.kind != TypeKind.INTERFACE) return false;
+ // TODO(kasperl): Should we take nullability into account here?
+ if (isExact) return false;
+ ClassElement baseElement = base.element;
+ return identical(baseElement, compiler.objectClass)
+ || identical(baseElement, compiler.dynamicClass);
+ }
+
+ // TODO(kasperl): This implementation is a bit sketchy, but it
+ // behaves the same as the old implementation on HType. The plan is
+ // to extend this and add proper testing of it.
+ TypeMask union(TypeMask other, Types types) {
+ // TODO(kasperl): Add subclass handling.
+ if (base == other.base) {
+ return unionSame(other, types);
+ } else if (types.isSubtype(other.base, base)) {
+ return unionSubtype(other, types);
+ } else if (types.isSubtype(base, other.base)) {
+ return other.unionSubtype(this, types);
+ }
+ return null;
+ }
+
+ TypeMask unionSame(TypeMask other, Types types) {
+ assert(base == other.base);
+ // The two masks share the base type, so we must chose the least
+ // constraining kind (the highest) of the two. If either one of
+ // the masks are nullable the result should be nullable too.
+ int combined = (flags > other.flags)
+ ? flags | (other.flags & 1)
+ : other.flags | (flags & 1);
+ if (flags == combined) {
+ return this;
+ } else if (other.flags == combined) {
+ return other;
+ } else {
+ return new TypeMask.internal(base, combined);
+ }
+ }
+
+ TypeMask unionSubtype(TypeMask other, Types types) {
+ assert(types.isSubtype(other.base, base));
+ // Since the other mask is a subtype of this mask, we need the
+ // resulting union to be a subtype too. If either one of the masks
+ // are nullable the result should be nullable too.
+ int combined = (SUBTYPE << 1) | ((flags | other.flags) & 1);
+ return (flags != combined)
+ ? new TypeMask.internal(base, combined)
+ : this;
+ }
+
+ // TODO(kasperl): This implementation is a bit sketchy, but it
+ // behaves the same as the old implementation on HType. The plan is
+ // to extend this and add proper testing of it.
+ TypeMask intersection(TypeMask other, Types types) {
+ int combined = (flags < other.flags)
+ ? flags & ((other.flags & 1) | ~1)
+ : other.flags & ((flags & 1) | ~1);
+ if (base == other.base) {
+ if (flags == combined) {
+ return this;
+ } else if (other.flags == combined) {
+ return other;
+ } else {
+ return new TypeMask.internal(base, combined);
+ }
+ } else if (types.isSubtype(other.base, base)) {
+ if (other.flags == combined) {
+ return other;
+ } else {
+ return new TypeMask.internal(other.base, combined);
+ }
+ } else if (types.isSubtype(base, other.base)) {
+ if (flags == combined) {
+ return this;
+ } else {
+ return new TypeMask.internal(base, combined);
+ }
+ }
+ return null;
+ }
+
+ bool operator ==(var other) {
+ if (other is !TypeMask) return false;
+ TypeMask otherMask = other;
+ return (base == otherMask.base) && (flags == otherMask.flags);
+ }
+
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ if (isNullable) buffer.write('null|');
+ if (isExact) buffer.write('exact=');
+ if (isSubclass) buffer.write('subclass=');
+ if (isSubtype) buffer.write('subtype=');
+ buffer.write(base.element.name.slowToString());
+ return "[$buffer]";
+ }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/types/types.dart b/sdk/lib/_internal/compiler/implementation/types/types.dart
index 345f0be..8b03838 100644
--- a/sdk/lib/_internal/compiler/implementation/types/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/types.dart
@@ -13,8 +13,10 @@
import '../util/util.dart';
import '../universe/universe.dart';
import 'simple_types_inferrer.dart' show SimpleTypesInferrer;
+import '../dart_types.dart';
part 'concrete_types_inferrer.dart';
+part 'type_mask.dart';
/**
* Common super class for our type inferrers. Currently, its query methods
diff --git a/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart b/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart
index 1f970f2..c8ad568 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart
@@ -9,52 +9,6 @@
FunctionSetNode newNode(SourceString name)
=> new FullFunctionSetNode(name);
-
- // TODO(kasperl): This interface is a little bit weird and mostly
- // put here to illustrate how we can refine types. Returning a
- // selector seems weird because we're only really interested in the
- // receiver type information and the type kind.
- Selector refine(Selector selector) {
- SourceString name = selector.name;
- FunctionSetNode node = nodes[name];
- if (node == null) return null;
- FullFunctionSetQuery query = node.query(selector, compiler);
-
- // If the selector is already exact, then we cannot refine it
- // further. If the query isn't exact, it means that the exact
- // class didn't contain any mathing element.
- if (selector.typeKind == TypedSelectorKind.EXACT) {
- if (!query.isExact) return null;
- assert(selector.receiverType.element == query.classes[0]);
- return selector;
- }
-
- // If the query yields an exact class, we refine the selector.
- if (query.isExact) {
- ClassElement refinement = query.classes[0];
- DartType type = refinement.computeType(compiler);
- return new TypedSelector.exact(type, selector);
- }
-
- // Get the list of classes from the query. If the type information
- // cannot be represented in the selector, we avoid refining it.
- List<ClassElement> classes = query.classes;
- if (classes == null || classes.length != 1) return selector;
- if (classes.isEmpty) return null;
-
- // We found one non-exact class, so we try to refine the selector
- // to be of subclass kind. We take care to reuse the existing
- // selector if matching class.
- assert(classes.length == 1);
- ClassElement refinement = query.classes[0];
- if (selector.typeKind == TypedSelectorKind.SUBCLASS) {
- ClassElement existing = selector.receiverType.element;
- if (refinement == existing) return selector;
- assert(refinement.isSubclassOf(existing));
- }
- DartType type = refinement.computeType(compiler);
- return new TypedSelector.subclass(type, selector);
- }
}
class FullFunctionSetNode extends FunctionSetNode {
@@ -70,8 +24,7 @@
Selector selector,
Compiler compiler) {
List<ClassElement> classes = computeClasses(functions, compiler);
- bool isExact = (selector.typeKind == TypedSelectorKind.EXACT)
- || isExactClass(classes, compiler);
+ bool isExact = selector.hasExactMask || isExactClass(classes, compiler);
return new FullFunctionSetQuery(functions, classes, isExact);
}
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index 4fb6cfb..ecc1c34 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -8,6 +8,7 @@
import '../elements/elements.dart';
import '../dart2jslib.dart';
import '../dart_types.dart';
+import '../types/types.dart';
import '../tree/tree.dart';
import '../util/util.dart';
import '../js/js.dart' as js;
@@ -88,6 +89,41 @@
bool hasFieldSetter(Element member, Compiler compiler) {
return fieldSetters.contains(member);
}
+
+ /**
+ * Compute type arguments of classes that use one of their type variables in
+ * is-checks and add the is-checks that they imply.
+ *
+ * This function must be called after all is-checks have been registered.
+ *
+ * TODO(karlklose): move these computations into a function producing an
+ * immutable datastructure.
+ */
+ void addImplicitChecks(Iterable<ClassElement> classesUsingChecks) {
+ // If there are no classes that use their variables in checks, there is
+ // nothing to do.
+ if (classesUsingChecks.isEmpty) return;
+ // Find all instantiated types that are a subtype of a class that uses
+ // one of its type arguments in an is-check and add the arguments to the
+ // set of is-checks.
+ // TODO(karlklose): replace this with code that uses a subtype lookup
+ // datastructure in the world.
+ for (DartType type in instantiatedTypes) {
+ if (type.kind != TypeKind.INTERFACE) continue;
+ InterfaceType classType = type;
+ for (ClassElement cls in classesUsingChecks) {
+ // We need the type as instance of its superclass anyway, so we just
+ // try to compute the substitution; if the result is [:null:], the
+ // classes are not related.
+ InterfaceType instance = classType.asInstanceOf(cls);
+ if (instance == null) continue;
+ Link<DartType> typeArguments = instance.typeArguments;
+ for (DartType argument in typeArguments) {
+ isChecks.add(argument);
+ }
+ }
+ }
+ }
}
class SelectorKind {
@@ -103,30 +139,6 @@
String toString() => name;
}
-class TypedSelectorKind {
- final String name;
- const TypedSelectorKind(this.name);
-
- /// Unknown type: used for untyped selector.
- static const TypedSelectorKind UNKNOWN = const TypedSelectorKind('unknown');
-
- // Exact type: the selector knows the exact type of the receiver.
- // For example [:new Map():].
- static const TypedSelectorKind EXACT = const TypedSelectorKind('exact');
-
- // Subclass type: the receiver type is in a subclass hierarchy.
- // For example [:this:].
- static const TypedSelectorKind SUBCLASS = const TypedSelectorKind('subclass');
-
- // Interface type: any type that implements the receiver type.
- // For example [(foo as Foo).bar()], or any type annotation in
- // checked mode.
- static const TypedSelectorKind INTERFACE =
- const TypedSelectorKind('interface');
-
- String toString() => name;
-}
-
class Selector {
final SelectorKind kind;
final SourceString name;
@@ -136,7 +148,6 @@
final int argumentCount;
final List<SourceString> namedArguments;
final List<SourceString> orderedNamedArguments;
- TypedSelectorKind get typeKind => TypedSelectorKind.UNKNOWN;
Selector(
this.kind,
@@ -233,8 +244,9 @@
int get hashCode => argumentCount + 1000 * namedArguments.length;
int get namedArgumentCount => namedArguments.length;
int get positionalArgumentCount => argumentCount - namedArgumentCount;
- DartType get receiverType => null;
+ bool get hasExactMask => false;
+ TypeMask get mask => null;
Selector get asUntyped => this;
/**
@@ -268,7 +280,11 @@
if (element.isForeign(compiler)) return true;
if (element.isSetter()) return isSetter();
if (element.isGetter()) return isGetter() || isCall();
- if (element.isField()) return isGetter() || isSetter() || isCall();
+ if (element.isField()) {
+ return isSetter()
+ ? !element.modifiers.isFinalOrConst()
+ : isGetter() || isCall();
+ }
if (isGetter()) return true;
if (isSetter()) return false;
@@ -386,14 +402,12 @@
bool operator ==(other) {
if (other is !Selector) return false;
- return identical(receiverType, other.receiverType)
- && equalsUntyped(other);
+ return mask == other.mask && equalsUntyped(other);
}
bool equalsUntyped(Selector other) {
return name == other.name
&& kind == other.kind
- && typeKind == other.typeKind
&& identical(library, other.library)
&& argumentCount == other.argumentCount
&& namedArguments.length == other.namedArguments.length
@@ -427,22 +441,17 @@
String named = '';
String type = '';
if (namedArgumentCount > 0) named = ', named=${namedArgumentsToString()}';
- if (receiverType != null) type = ', type=$typeKind $receiverType';
+ if (mask != null) type = ', mask=$mask';
return 'Selector($kind, ${name.slowToString()}, '
'arity=$argumentCount$named$type)';
}
}
class TypedSelector extends Selector {
- /**
- * The type of the receiver.
- */
- final DartType receiverType;
- final TypedSelectorKind typeKind;
-
final Selector asUntyped;
+ final TypeMask mask;
- TypedSelector(DartType this.receiverType, this.typeKind, Selector selector)
+ TypedSelector(this.mask, Selector selector)
: asUntyped = selector.asUntyped,
super(selector.kind,
selector.name,
@@ -450,43 +459,27 @@
selector.argumentCount,
selector.namedArguments) {
// Invariant: Typed selector can not be based on a malformed type.
- assert(!identical(receiverType.kind, TypeKind.MALFORMED_TYPE));
- assert(asUntyped.receiverType == null);
- assert(typeKind != TypedSelectorKind.UNKNOWN);
+ assert(!identical(mask.base.kind, TypeKind.MALFORMED_TYPE));
+ assert(asUntyped.mask == null);
}
- TypedSelector.subclass(DartType receiverType, Selector selector)
- : this(receiverType, TypedSelectorKind.SUBCLASS, selector);
+ TypedSelector.exact(DartType base, Selector selector)
+ : this(new TypeMask.exact(base), selector);
- TypedSelector.exact(DartType receiverType, Selector selector)
- : this(receiverType, TypedSelectorKind.EXACT, selector);
+ TypedSelector.subclass(DartType base, Selector selector)
+ : this(new TypeMask.subclass(base), selector);
- TypedSelector.subtype(DartType receiverType, Selector selector)
- : this(receiverType, TypedSelectorKind.INTERFACE, selector);
+ TypedSelector.subtype(DartType base, Selector selector)
+ : this(new TypeMask.subtype(base), selector);
+
+ bool get hasExactMask => mask.isExact;
/**
* Check if [element] will be the one used at runtime when being
* invoked on an instance of [cls].
*/
bool hasElementIn(ClassElement cls, Element element) {
- // Use the selector for the lookup instead of [:element.name:]
- // because the selector has the right privacy information.
- Element resolved = cls.lookupSelector(this);
- if (resolved == element) return true;
- if (resolved == null) return false;
- if (resolved.isAbstractField()) {
- AbstractFieldElement field = resolved;
- if (element == field.getter || element == field.setter) {
- return true;
- } else {
- // We have not found a match, but another class higher in the
- // hierarchy may define the getter or the setter.
- ClassElement otherCls = field.getEnclosingClass().superclass;
- if (otherCls == null) return false;
- return hasElementIn(otherCls, element);
- }
- }
- return false;
+ return cls.lookupSelector(this) == element;
}
bool appliesUnnamed(Element element, Compiler compiler) {
@@ -505,26 +498,28 @@
return appliesUntyped(element, compiler);
}
- Element self = receiverType.element;
+ // TODO(kasperl): Can't we just avoid creating typed selectors
+ // based of function types?
+ Element self = mask.base.element;
if (self.isTypedef()) {
// A typedef is a function type that doesn't have any
// user-defined members.
return false;
}
- if (typeKind == TypedSelectorKind.EXACT) {
+ if (mask.isExact) {
return hasElementIn(self, element) && appliesUntyped(element, compiler);
- } else if (typeKind == TypedSelectorKind.SUBCLASS) {
+ } else if (mask.isSubclass) {
return (hasElementIn(self, element)
|| other.isSubclassOf(self)
|| compiler.world.hasAnySubclassThatMixes(self, other))
&& appliesUntyped(element, compiler);
} else {
- assert(typeKind == TypedSelectorKind.INTERFACE);
+ assert(mask.isSubtype);
if (other.implementsInterface(self)
|| other.isSubclassOf(self)
|| compiler.world.hasAnySubclassThatMixes(self, other)
- || compiler.world.hasAnySubclassThatImplements(other, receiverType)) {
+ || compiler.world.hasAnySubclassThatImplements(other, mask.base)) {
return appliesUntyped(element, compiler);
}
@@ -534,10 +529,9 @@
if (cls.isSubclassOf(other)) {
// Resolve an invocation of [element.name] on [self]. If it
// is found, this selector is a candidate.
- return hasElementIn(self, element) && appliesUntyped(element, compiler);
+ return hasElementIn(cls, element) && appliesUntyped(element, compiler);
}
}
-
return false;
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/util/link.dart b/sdk/lib/_internal/compiler/implementation/util/link.dart
index 9cc81cc..d3f93ca 100644
--- a/sdk/lib/_internal/compiler/implementation/util/link.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/link.dart
@@ -38,7 +38,7 @@
void printOn(StringBuffer buffer, [separatedBy]) {
}
- List toList() => new List<T>.fixedLength(0);
+ List toList({ bool growable: true }) => growable ? <T>[] : new List<T>(0);
bool get isEmpty => true;
diff --git a/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart b/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart
index 2f9ea84..efd0ff9 100644
--- a/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart
@@ -81,12 +81,8 @@
bool get isEmpty => false;
- List<T> toList() {
- List<T> list = new List<T>();
- for (Link<T> link = this; !link.isEmpty; link = link.tail) {
- list.addLast(link.head);
- }
- return list;
+ List<T> toList({ bool growable: true }) {
+ return new List<T>.from(this, growable: growable);
}
void forEach(void f(T element)) {
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 39f53b6..36c1933 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -215,6 +215,9 @@
static const ILLEGAL_SUPER_SEND = const MessageKind(
"#{name} cannot be called on super");
+ static const NO_SUCH_SUPER_MEMBER = const MessageKind(
+ "Cannot resolve #{memberName} in a superclass of #{className}");
+
static const ADDITIONAL_TYPE_ARGUMENT = const MessageKind(
"additional type argument");
@@ -338,6 +341,9 @@
static const CANNOT_RESOLVE_SETTER = const MessageKind(
'cannot resolve setter.');
+ static const CANNOT_RESOLVE_INDEX = const MessageKind(
+ 'cannot resolve [] member.');
+
static const VOID_NOT_ALLOWED = const MessageKind(
'type void is only allowed in a return type.');
diff --git a/sdk/lib/_internal/compiler/implementation/world.dart b/sdk/lib/_internal/compiler/implementation/world.dart
index f3142f6..a09f629 100644
--- a/sdk/lib/_internal/compiler/implementation/world.dart
+++ b/sdk/lib/_internal/compiler/implementation/world.dart
@@ -51,7 +51,11 @@
}
}
- compiler.resolverWorld.instantiatedClasses.forEach(addSubtypes);
+ // Use the [:seenClasses:] set to include non-instantiated
+ // classes: if the superclass of these classes require RTI, then
+ // they also need RTI, so that a constructor passes the type
+ // variables to the super constructor.
+ compiler.enqueuer.resolution.seenClasses.forEach(addSubtypes);
// Find the classes that need runtime type information. Such
// classes are:
@@ -64,6 +68,7 @@
if (classesNeedingRti.contains(cls)) return;
classesNeedingRti.add(cls);
+ // TODO(ngeoffray): This should use subclasses, not subtypes.
Set<ClassElement> classes = subtypes[cls];
if (classes != null) {
classes.forEach((ClassElement sub) {
@@ -79,12 +84,31 @@
}
}
+ Set<ClassElement> classesUsingTypeVariableTests = new Set<ClassElement>();
compiler.resolverWorld.isChecks.forEach((DartType type) {
- if (type is InterfaceType) {
+ if (type.kind == TypeKind.TYPE_VARIABLE) {
+ TypeVariableElement variable = type.element;
+ classesUsingTypeVariableTests.add(variable.enclosingElement);
+ }
+ });
+ // Add is-checks that result from classes using type variables in checks.
+ compiler.resolverWorld.addImplicitChecks(classesUsingTypeVariableTests);
+ // Add the rti dependencies that are implicit in the way the backend
+ // generates code: when we create a new [List], we actually create
+ // a JSArray in the backend and we need to add type arguments to
+ // the calls of the list constructor whenever we determine that
+ // JSArray needs type arguments.
+ compiler.backend.addBackendRtiDependencies(this);
+ // Compute the set of all classes that need runtime type information.
+ compiler.resolverWorld.isChecks.forEach((DartType type) {
+ if (type.kind == TypeKind.INTERFACE) {
InterfaceType itf = type;
if (!itf.isRaw) {
potentiallyAddForRti(itf.element);
}
+ } else if (type.kind == TypeKind.TYPE_VARIABLE) {
+ TypeVariableElement variable = type.element;
+ potentiallyAddForRti(variable.enclosingElement);
}
});
}
@@ -102,7 +126,6 @@
return uses != null && !uses.isEmpty;
}
-
void registerRtiDependency(Element element, Element dependency) {
// We're not dealing with typedef for now.
if (!element.isClass() || !dependency.isClass()) return;
@@ -154,10 +177,11 @@
if (targets.length != 1) return null;
Element result = targets.first;
ClassElement enclosing = result.getEnclosingClass();
- DartType receiverType = selector.receiverType;
- ClassElement receiverTypeElement = (receiverType == null)
+ // TODO(kasperl): Move this code to the type mask.
+ ti.TypeMask mask = selector.mask;
+ ClassElement receiverTypeElement = (mask == null)
? compiler.objectClass
- : receiverType.element;
+ : mask.base.element;
// We only return the found element if it is guaranteed to be
// implemented on the exact receiver type. It could be found in a
// subclass or in an inheritance-wise unrelated class in case of
@@ -167,10 +191,9 @@
Iterable<ClassElement> locateNoSuchMethodHolders(Selector selector) {
Selector noSuchMethodSelector = new Selector.noSuchMethod();
- DartType receiverType = selector.receiverType;
- if (receiverType != null) {
- noSuchMethodSelector = new TypedSelector(
- receiverType, selector.typeKind, noSuchMethodSelector);
+ ti.TypeMask mask = selector.mask;
+ if (mask != null) {
+ noSuchMethodSelector = new TypedSelector(mask, noSuchMethodSelector);
}
ClassElement objectClass = compiler.objectClass;
return allFunctions
diff --git a/sdk/lib/_internal/dartdoc/dartdoc.status b/sdk/lib/_internal/dartdoc/dartdoc.status
new file mode 100644
index 0000000..8b45e64
--- /dev/null
+++ b/sdk/lib/_internal/dartdoc/dartdoc.status
@@ -0,0 +1,15 @@
+# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+test/markdown_test: Pass
+test/dartdoc_test: Pass
+test/dartdoc_search_test: Pass, Skip
+
+# Dartdoc only runs on the VM, so just rule out all compilers.
+[ $compiler == dart2js || $compiler == dart2dart || $compiler == dartc ]
+*: Skip
+
+# Dartdoc only runs on the standalone VM, not in dartium.
+[ $runtime == drt || $runtime == dartium ]
+*: Skip
diff --git a/sdk/lib/_internal/dartdoc/lib/classify.dart b/sdk/lib/_internal/dartdoc/lib/classify.dart
index d41f12a..4b4d972 100644
--- a/sdk/lib/_internal/dartdoc/lib/classify.dart
+++ b/sdk/lib/_internal/dartdoc/lib/classify.dart
@@ -45,7 +45,7 @@
var token = tokenizer.tokenize();
var inString = false;
while (token.kind != EOF_TOKEN) {
- html.add(text.substring(whitespaceOffset, token.charOffset));
+ html.write(text.substring(whitespaceOffset, token.charOffset));
whitespaceOffset = token.charOffset + token.slowCharCount;
// Track whether or not we're in a string.
@@ -62,9 +62,9 @@
// Add a secondary class to tokens appearing within a string so that
// we can highlight tokens in an interpolation specially.
var stringClass = inString ? Classification.STRING_INTERPOLATION : '';
- html.add('<span class="$kind $stringClass">$escapedText</span>');
+ html.write('<span class="$kind $stringClass">$escapedText</span>');
} else {
- html.add(escapedText);
+ html.write(escapedText);
}
// Track whether or not we're in a string.
diff --git a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
index a6f0179d..e02d513 100644
--- a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
@@ -110,7 +110,7 @@
fromDir.list(recursive: false).listen(
(FileSystemEntity entity) {
if (entity is File) {
- final name = new Path(entity.name).filename;
+ final name = new Path(entity.path).filename;
// TODO(rnystrom): Hackish. Ignore 'hidden' files like .DS_Store.
if (name.startsWith('.')) return;
@@ -293,15 +293,18 @@
static const List<String> COMPILER_OPTIONS =
const <String>['--preserve-comments', '--categories=Client,Server'];
- Dartdoc() {
- // Patch in support for [:...:]-style code to the markdown parser.
- // TODO(rnystrom): Markdown already has syntax for this. Phase this out?
- md.InlineParser.syntaxes.insertRange(0, 1,
- new md.CodeSyntax(r'\[\:((?:.|\n)*?)\:\]'));
+ /// Resolves Dart links to the correct Node.
+ md.Resolver dartdocResolver;
- md.setImplicitLinkResolver((name) => resolveNameReference(name,
- currentLibrary: _currentLibrary, currentType: _currentType,
- currentMember: _currentMember));
+ // Add support for [:...:]-style code to the markdown parser.
+ List<md.InlineSyntax> dartdocSyntaxes =
+ [new md.CodeSyntax(r'\[:\s?((?:.|\n)*?)\s?:\]')];
+
+
+ Dartdoc() {
+ dartdocResolver = (String name) => resolveNameReference(name,
+ currentLibrary: _currentLibrary, currentType: _currentType,
+ currentMember: _currentMember);
}
/**
@@ -420,7 +423,8 @@
version, revision);
for (final lib in _sortedLibraries) {
- var libraryElement = new LibraryElement(lib.qualifiedName, lib, lookupMdnComment)
+ var libraryElement = new LibraryElement(
+ lib, lookupMdnComment: lookupMdnComment)
..stripDuplicateUris(null, null);
packageManifest.libraries.add(new Reference.fromElement(libraryElement));
startFile("$revision/${libraryElement.id}.json");
@@ -467,7 +471,7 @@
}
void write(String s) {
- _file.add(s);
+ _file.write(s);
}
void writeln(String s) {
@@ -821,7 +825,7 @@
// Look for a comment for the entire library.
final comment = getLibraryComment(library);
if (comment != null) {
- writeln('<div class="doc">${comment.html}</div>');
+ writeln('<div class="doc">${markdownFromComment(comment)}</div>');
}
// Document the top-level members.
@@ -1517,17 +1521,25 @@
write(')');
}
+ String markdownFromComment(DocComment comment) {
+ return md.markdownToHtml(comment.text,
+ inlineSyntaxes: dartdocSyntaxes,
+ linkResolver: dartdocResolver);
+ }
+
void docComment(ContainerMirror host, DocComment comment) {
if (comment != null) {
+ var html = markdownFromComment(comment);
+
if (comment.inheritedFrom != null) {
writeln('<div class="inherited">');
- writeln(comment.html);
+ writeln(html);
write('<div class="docs-inherited-from">docs inherited from ');
annotateType(host, comment.inheritedFrom);
write('</div>');
writeln('</div>');
} else {
- writeln(comment.html);
+ writeln(html);
}
}
}
@@ -1986,8 +1998,6 @@
assert(text != null && !text.trim().isEmpty);
}
- String get html => md.markdownToHtml(text);
-
String toString() => text;
}
diff --git a/sdk/lib/_internal/dartdoc/lib/markdown.dart b/sdk/lib/_internal/dartdoc/lib/markdown.dart
index a7ea5cc..01de970 100644
--- a/sdk/lib/_internal/dartdoc/lib/markdown.dart
+++ b/sdk/lib/_internal/dartdoc/lib/markdown.dart
@@ -11,9 +11,12 @@
part 'src/markdown/html_renderer.dart';
part 'src/markdown/inline_parser.dart';
+typedef Node Resolver(String name);
+
/// Converts the given string of markdown to HTML.
-String markdownToHtml(String markdown) {
- final document = new Document();
+String markdownToHtml(String markdown, {inlineSyntaxes, linkResolver}) {
+ final document = new Document(inlineSyntaxes: inlineSyntaxes,
+ linkResolver: linkResolver);
// Replace windows line endings with unix line endings, and split.
final lines = markdown.replaceAll('\r\n','\n').split('\n');
@@ -29,17 +32,13 @@
.replaceAll('>', '>');
}
-var _implicitLinkResolver;
-
-Node setImplicitLinkResolver(Node resolver(String text)) {
- _implicitLinkResolver = resolver;
-}
-
/// Maintains the context needed to parse a markdown document.
class Document {
final Map<String, Link> refLinks;
+ List<InlineSyntax> inlineSyntaxes;
+ Resolver linkResolver;
- Document()
+ Document({this.inlineSyntaxes, this.linkResolver})
: refLinks = <String, Link>{};
parseRefLinks(List<String> lines) {
diff --git a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
index 59e14b5..d7595bd 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
@@ -30,8 +30,8 @@
// TODO(rnystrom): Should be in corelib.
final buffer = new StringBuffer();
for (int i = 0; i < count; i++) {
- buffer.add(text);
- if ((i < count - 1) && (separator != null)) buffer.add(separator);
+ buffer.write(text);
+ if ((i < count - 1) && (separator != null)) buffer.write(separator);
}
return buffer.toString();
diff --git a/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart b/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart
index 01e456e..882f6b2 100755
--- a/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart
@@ -74,7 +74,7 @@
}
if (classMirror.superclass != null &&
classMirror.superclass.qualifiedName != classMirror.qualifiedName &&
- classMirror.superclass.qualifiedName != 'dart:core.Object') {
+ classMirror.superclass.qualifiedName != 'dart.core.Object') {
determineAllMembers(classMirror.superclass, members);
}
}
@@ -120,7 +120,7 @@
void startObject(String name) {
_start(name);
- _sb.add('{');
+ _sb.write('{');
_indent += 1;
_inSet = false;
@@ -131,7 +131,7 @@
if (_inSet) {
_newline();
}
- _sb.add('}');
+ _sb.write('}');
_inSet = true;
}
@@ -139,7 +139,7 @@
_start(name);
_inSet = false;
- _sb.add('[');
+ _sb.write('[');
_indent += 1;
}
@@ -148,49 +148,49 @@
if (_inSet) {
_newline();
}
- _sb.add(']');
+ _sb.write(']');
_inSet = true;
}
void addString(String name, String value) {
_start(name);
- _sb.add('"');
+ _sb.write('"');
_escape(_sb, value);
- _sb.add('"');
+ _sb.write('"');
_inSet = true;
}
void addBool(String name, bool value) {
_start(name);
- _sb.add(value.toString());
+ _sb.write(value.toString());
_inSet = true;
}
void addNum(String name, num value) {
_start(name);
- _sb.add(value.toString());
+ _sb.write(value.toString());
_inSet = true;
}
void _start(String name) {
if (_inSet) {
- _sb.add(',');
+ _sb.write(',');
}
// Do not print a newline at the beginning of the file.
if (!_sb.isEmpty) {
_newline();
}
if (name != null) {
- _sb.add('"$name": ');
+ _sb.write('"$name": ');
}
}
void _newline([int indent = 0]) {
- _sb.add('\n');
+ _sb.write('\n');
_indent += indent;
for (var i = 0; i < _indent; ++i) {
- _sb.add(' ');
+ _sb.write(' ');
}
}
@@ -209,45 +209,45 @@
static void _escape(StringBuffer sb, String s) {
final int length = s.length;
bool needsEscape = false;
- final charCodes = new List<int>();
+ final codeUnits = new List<int>();
for (int i = 0; i < length; i++) {
- int charCode = s.charCodeAt(i);
- if (charCode < 32) {
+ int codeUnit = s.codeUnitAt(i);
+ if (codeUnit < 32) {
needsEscape = true;
- charCodes.add(JsonPrinter.BACKSLASH);
- switch (charCode) {
+ codeUnits.add(JsonPrinter.BACKSLASH);
+ switch (codeUnit) {
case JsonPrinter.BACKSPACE:
- charCodes.add(JsonPrinter.CHAR_B);
+ codeUnits.add(JsonPrinter.CHAR_B);
break;
case JsonPrinter.TAB:
- charCodes.add(JsonPrinter.CHAR_T);
+ codeUnits.add(JsonPrinter.CHAR_T);
break;
case JsonPrinter.NEW_LINE:
- charCodes.add(JsonPrinter.CHAR_N);
+ codeUnits.add(JsonPrinter.CHAR_N);
break;
case JsonPrinter.FORM_FEED:
- charCodes.add(JsonPrinter.CHAR_F);
+ codeUnits.add(JsonPrinter.CHAR_F);
break;
case JsonPrinter.CARRIAGE_RETURN:
- charCodes.add(JsonPrinter.CHAR_R);
+ codeUnits.add(JsonPrinter.CHAR_R);
break;
default:
- charCodes.add(JsonPrinter.CHAR_U);
- charCodes.add(_hexDigit((charCode >> 12) & 0xf));
- charCodes.add(_hexDigit((charCode >> 8) & 0xf));
- charCodes.add(_hexDigit((charCode >> 4) & 0xf));
- charCodes.add(_hexDigit(charCode & 0xf));
+ codeUnits.add(JsonPrinter.CHAR_U);
+ codeUnits.add(_hexDigit((codeUnit >> 12) & 0xf));
+ codeUnits.add(_hexDigit((codeUnit >> 8) & 0xf));
+ codeUnits.add(_hexDigit((codeUnit >> 4) & 0xf));
+ codeUnits.add(_hexDigit(codeUnit & 0xf));
break;
}
- } else if (charCode == JsonPrinter.QUOTE ||
- charCode == JsonPrinter.BACKSLASH) {
+ } else if (codeUnit == JsonPrinter.QUOTE ||
+ codeUnit == JsonPrinter.BACKSLASH) {
needsEscape = true;
- charCodes.add(JsonPrinter.BACKSLASH);
- charCodes.add(charCode);
+ codeUnits.add(JsonPrinter.BACKSLASH);
+ codeUnits.add(codeUnit);
} else {
- charCodes.add(charCode);
+ codeUnits.add(codeUnit);
}
}
- sb.add(needsEscape ? new String.fromCharCodes(charCodes) : s);
+ sb.write(needsEscape ? new String.fromCharCodes(codeUnits) : s);
}
}
diff --git a/sdk/lib/_internal/dartdoc/lib/src/markdown/html_renderer.dart b/sdk/lib/_internal/dartdoc/lib/src/markdown/html_renderer.dart
index 1695e96..5494394 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/markdown/html_renderer.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/markdown/html_renderer.dart
@@ -24,17 +24,17 @@
}
void visitText(Text text) {
- buffer.add(text.text);
+ buffer.write(text.text);
}
bool visitElementBefore(Element element) {
// Hackish. Separate block-level elements with newlines.
if (!buffer.isEmpty &&
_BLOCK_TAGS.firstMatch(element.tag) != null) {
- buffer.add('\n');
+ buffer.write('\n');
}
- buffer.add('<${element.tag}');
+ buffer.write('<${element.tag}');
// Sort the keys so that we generate stable output.
// TODO(rnystrom): This assumes keys returns a fresh mutable
@@ -42,20 +42,20 @@
final attributeNames = element.attributes.keys.toList();
attributeNames.sort((a, b) => a.compareTo(b));
for (final name in attributeNames) {
- buffer.add(' $name="${element.attributes[name]}"');
+ buffer.write(' $name="${element.attributes[name]}"');
}
if (element.isEmpty) {
// Empty element like <hr/>.
- buffer.add(' />');
+ buffer.write(' />');
return false;
} else {
- buffer.add('>');
+ buffer.write('>');
return true;
}
}
void visitElementAfter(Element element) {
- buffer.add('</${element.tag}>');
+ buffer.write('</${element.tag}>');
}
}
diff --git a/sdk/lib/_internal/dartdoc/lib/src/markdown/inline_parser.dart b/sdk/lib/_internal/dartdoc/lib/src/markdown/inline_parser.dart
index af42e3e..5faebf2 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/markdown/inline_parser.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/markdown/inline_parser.dart
@@ -7,56 +7,51 @@
/// Maintains the internal state needed to parse inline span elements in
/// markdown.
class InlineParser {
- static List<InlineSyntax> get syntaxes {
- // Lazy initialize.
- if (_syntaxes == null) {
- _syntaxes = <InlineSyntax>[
- // This first regexp matches plain text to accelerate parsing. It must
- // be written so that it does not match any prefix of any following
- // syntax. Most markdown is plain text, so it is faster to match one
- // regexp per 'word' rather than fail to match all the following regexps
- // at each non-syntax character position. It is much more important
- // that the regexp is fast than complete (for example, adding grouping
- // is likely to slow the regexp down enough to negate its benefit).
- // Since it is purely for optimization, it can be removed for debugging.
- new TextSyntax(r'\s*[A-Za-z0-9]+'),
+ static List<InlineSyntax> defaultSyntaxes = <InlineSyntax>[
+ // This first regexp matches plain text to accelerate parsing. It must
+ // be written so that it does not match any prefix of any following
+ // syntax. Most markdown is plain text, so it is faster to match one
+ // regexp per 'word' rather than fail to match all the following regexps
+ // at each non-syntax character position. It is much more important
+ // that the regexp is fast than complete (for example, adding grouping
+ // is likely to slow the regexp down enough to negate its benefit).
+ // Since it is purely for optimization, it can be removed for debugging.
- // The real syntaxes.
+ // TODO(amouravski): this regex will glom up any custom syntaxes unless
+ // they're at the beginning.
+ new TextSyntax(r'\s*[A-Za-z0-9]+'),
- new AutolinkSyntax(),
- new LinkSyntax(),
- // "*" surrounded by spaces is left alone.
- new TextSyntax(r' \* '),
- // "_" surrounded by spaces is left alone.
- new TextSyntax(r' _ '),
- // Leave already-encoded HTML entities alone. Ensures we don't turn
- // "&" into "&amp;"
- new TextSyntax(r'&[#a-zA-Z0-9]*;'),
- // Encode "&".
- new TextSyntax(r'&', sub: '&'),
- // Encode "<". (Why not encode ">" too? Gruber is toying with us.)
- new TextSyntax(r'<', sub: '<'),
- // Parse "**strong**" tags.
- new TagSyntax(r'\*\*', tag: 'strong'),
- // Parse "__strong__" tags.
- new TagSyntax(r'__', tag: 'strong'),
- // Parse "*emphasis*" tags.
- new TagSyntax(r'\*', tag: 'em'),
- // Parse "_emphasis_" tags.
- // TODO(rnystrom): Underscores in the middle of a word should not be
- // parsed as emphasis like_in_this.
- new TagSyntax(r'_', tag: 'em'),
- // Parse inline code within double backticks: "``code``".
- new CodeSyntax(r'``\s?((?:.|\n)*?)\s?``'),
- // Parse inline code within backticks: "`code`".
- new CodeSyntax(r'`([^`]*)`')
- ];
- }
+ // The real syntaxes.
- return _syntaxes;
- }
-
- static List<InlineSyntax> _syntaxes;
+ new AutolinkSyntax(),
+ new LinkSyntax(),
+ // "*" surrounded by spaces is left alone.
+ new TextSyntax(r' \* '),
+ // "_" surrounded by spaces is left alone.
+ new TextSyntax(r' _ '),
+ // Leave already-encoded HTML entities alone. Ensures we don't turn
+ // "&" into "&amp;"
+ new TextSyntax(r'&[#a-zA-Z0-9]*;'),
+ // Encode "&".
+ new TextSyntax(r'&', sub: '&'),
+ // Encode "<". (Why not encode ">" too? Gruber is toying with us.)
+ new TextSyntax(r'<', sub: '<'),
+ // Parse "**strong**" tags.
+ new TagSyntax(r'\*\*', tag: 'strong'),
+ // Parse "__strong__" tags.
+ new TagSyntax(r'__', tag: 'strong'),
+ // Parse "*emphasis*" tags.
+ new TagSyntax(r'\*', tag: 'em'),
+ // Parse "_emphasis_" tags.
+ // TODO(rnystrom): Underscores in the middle of a word should not be
+ // parsed as emphasis like_in_this.
+ new TagSyntax(r'_', tag: 'em'),
+ // Parse inline code within double backticks: "``code``".
+ new CodeSyntax(r'``\s?((?:.|\n)*?)\s?``'),
+ // Parse inline code within backticks: "`code`".
+ new CodeSyntax(r'`([^`]*)`')
+ // We will add the LinkSyntax once we know about the specific link resolver.
+ ];
/// The string of markdown being parsed.
final String source;
@@ -64,6 +59,8 @@
/// The markdown document this parser is parsing.
final Document document;
+ List<InlineSyntax> syntaxes;
+
/// The current read position.
int pos = 0;
@@ -73,7 +70,19 @@
final List<TagState> _stack;
InlineParser(this.source, this.document)
- : _stack = <TagState>[];
+ : _stack = <TagState>[] {
+ /// User specified syntaxes will be the first syntaxes to be evaluated.
+ if (document.inlineSyntaxes != null) {
+ syntaxes = [];
+ syntaxes.addAll(document.inlineSyntaxes);
+ syntaxes.addAll(defaultSyntaxes);
+ } else {
+ syntaxes = defaultSyntaxes;
+ }
+ // Custom link resolver goes after the generic text syntax.
+ syntaxes.insertRange(1, 1,
+ new LinkSyntax(linkResolver: document.linkResolver));
+ }
List<Node> parse() {
// Make a fake top tag to hold the results.
@@ -236,6 +245,8 @@
/// Matches inline links like `[blah] [id]` and `[blah] (url)`.
class LinkSyntax extends TagSyntax {
+ Resolver linkResolver;
+
/// The regex for the end of a link needs to handle both reference style and
/// inline styles as well as optional titles for inline links. To make that
/// a bit more palatable, this breaks it into pieces.
@@ -253,7 +264,7 @@
// 4: Contains the title, if present, for an inline link.
}
- LinkSyntax()
+ LinkSyntax({this.linkResolver})
: super(r'\[', end: linkPattern);
bool onMatchEnd(InlineParser parser, Match match, TagState state) {
@@ -263,10 +274,10 @@
// If we didn't match refLink or inlineLink, then it means there was
// nothing after the first square bracket, so it isn't a normal markdown
// link at all. Instead, we allow users of the library to specify a special
- // resolver function ([setImplicitLinkResolver]) that may choose to handle
+ // resolver function ([linkResolver]) that may choose to handle
// this. Otherwise, it's just treated as plain text.
if ((match[1] == null) || (match[1] == '')) {
- if (_implicitLinkResolver == null) return false;
+ if (linkResolver == null) return false;
// Only allow implicit links if the content is just text.
// TODO(rnystrom): Do we want to relax this?
@@ -276,7 +287,7 @@
Text link = state.children[0];
// See if we have a resolver that will generate a link for us.
- final node = _implicitLinkResolver(link.text);
+ final node = linkResolver(link.text);
if (node == null) return false;
parser.addNode(node);
diff --git a/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart b/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart
index 53da583..ea87229 100755
--- a/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart
+++ b/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart
@@ -62,6 +62,8 @@
*/
String line;
+ // TODO(jacobr): refactor the code so that lookupMdnComment does not need to
+ // be passed to every Element constructor.
Element(Mirror mirror, this.kind, this.name, String id, this.comment,
MdnComment lookupMdnComment(Mirror))
: line = mirror.location.line.toString(),
@@ -116,33 +118,78 @@
}
/**
+ * Helper class to track what members of a library should be included.
+ */
+class LibrarySubset {
+ final LibraryMirror library;
+ Set<String> includedChildren;
+
+ LibrarySubset(this.library) : includedChildren = new Set<String>();
+}
+
+/**
* [Element] describing a Dart library.
*/
class LibraryElement extends Element {
- LibraryElement(String name, LibraryMirror mirror,
- MdnComment lookupMdnComment(Mirror))
- : super(mirror, 'library', _libraryName(mirror), name,
- computeComment(mirror), lookupMdnComment) {
+ /**
+ * Partial versions of LibraryElements containing classes that are extended
+ * or implemented by classes in this library.
+ */
+ List<LibraryElement> dependencies;
+ /**
+ * Construct a LibraryElement from a [mirror].
+ *
+ * If [includedChildren] is specified, only elements matching names in
+ * [includedChildren] are included and no dependencies are included.
+ * [lookupMdnComment] is an optional function that returns the MDN
+ * documentation for elements. [dependencies] is an optional map
+ * tracking all classes dependend on by this [ClassElement].
+ */
+ LibraryElement(LibraryMirror mirror,
+ {MdnComment lookupMdnComment(Mirror), Set<String> includedChildren})
+ : super(mirror, 'library', _libraryName(mirror), mirror.displayName,
+ computeComment(mirror), lookupMdnComment) {
+ var requiredDependencies;
+ // We don't need to track our required dependencies when generating a
+ // filtered version of this library which will be used as a dependency for
+ // another library.
+ if (includedChildren == null)
+ requiredDependencies = new Map<String, LibrarySubset>();
mirror.functions.forEach((childName, childMirror) {
- addChild(new MethodElement(childName, childMirror, lookupMdnComment));
+ if (includedChildren == null || includedChildren.contains(childName))
+ addChild(new MethodElement(childName, childMirror, lookupMdnComment));
});
mirror.getters.forEach((childName, childMirror) {
- addChild(new GetterElement(childName, childMirror, lookupMdnComment));
+ if (includedChildren == null || includedChildren.contains(childName))
+ addChild(new GetterElement(childName, childMirror, lookupMdnComment));
});
mirror.variables.forEach((childName, childMirror) {
+ if (includedChildren == null || includedChildren.contains(childName))
addChild(new VariableElement(childName, childMirror, lookupMdnComment));
});
mirror.classes.forEach((className, classMirror) {
- if (classMirror is TypedefMirror) {
- addChild(new TypedefElement(className, classMirror));
- } else {
- addChild(new ClassElement(className, classMirror, lookupMdnComment));
+ if (includedChildren == null || includedChildren.contains(className)) {
+ if (classMirror is TypedefMirror) {
+ addChild(new TypedefElement(className, classMirror));
+ } else {
+ addChild(new ClassElement(classMirror,
+ dependencies: requiredDependencies,
+ lookupMdnComment: lookupMdnComment));
+ }
}
});
+
+ if (requiredDependencies != null && !requiredDependencies.isEmpty) {
+ dependencies = requiredDependencies.values.map((librarySubset) =>
+ new LibraryElement(
+ librarySubset.library,
+ lookupMdnComment: lookupMdnComment,
+ includedChildren: librarySubset.includedChildren)).toList();
+ }
}
static String _libraryName(LibraryMirror mirror) {
@@ -170,6 +217,16 @@
return mirror.uri.toString();
}
}
+
+ void stripDuplicateUris(String parentUri, parentLine) {
+ super.stripDuplicateUris(parentUri, parentLine);
+
+ if (dependencies != null) {
+ for (var child in dependencies) {
+ child.stripDuplicateUris(null, null);
+ }
+ }
+ }
}
/**
@@ -196,14 +253,46 @@
List<Reference> interfaces;
/** Whether the class implements or extends [Error] or [Exception]. */
bool isThrowable;
-
- ClassElement(String name, ClassMirror mirror,
- MdnComment lookupMdnComment(Mirror))
- : super(mirror, 'class', mirror.simpleName, name, computeComment(mirror),
+
+ /**
+ * Constructs a [ClassElement] from a [ClassMirror].
+ *
+ * [dependencies] is an optional map updated as a side effect of running
+ * this constructor that tracks what classes from other libraries are
+ * dependencies of classes in this library. A class is considered a
+ * dependency if it implements or extends another class.
+ * [lookupMdnComment] is an optional function that returns the MDN
+ * documentation for elements. [dependencies] is an optional map
+ * tracking all classes dependend on by this [ClassElement].
+ */
+ ClassElement(ClassMirror mirror,
+ {Map<String, LibrarySubset> dependencies,
+ MdnComment lookupMdnComment(Mirror)})
+ : super(mirror, 'class', mirror.simpleName, mirror.simpleName, computeComment(mirror),
lookupMdnComment),
superclass = _optionalReference(mirror.superclass),
- isAbstract = _optionalBool(mirror.isAbstract) {
- isThrowable = _optionalBool(_isThrowable(mirror));
+ isAbstract = _optionalBool(mirror.isAbstract),
+ isThrowable = _optionalBool(_isThrowable(mirror)){
+
+ addCrossLibraryDependencies(clazz) {
+ if (clazz == null) return;
+
+ if (mirror.library != clazz.library) {
+ var libraryStub = dependencies.putIfAbsent(clazz.library.simpleName,
+ () => new LibrarySubset(clazz.library));
+ libraryStub.includedChildren.add(clazz.simpleName);
+ }
+
+ for (var interface in clazz.superinterfaces) {
+ addCrossLibraryDependencies(interface);
+ }
+ addCrossLibraryDependencies(clazz.superclass);
+ }
+
+ if (dependencies != null) {
+ addCrossLibraryDependencies(mirror);
+ }
+
for (var interface in mirror.superinterfaces) {
if (this.interfaces == null) {
this.interfaces = <Reference>[];
diff --git a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
index 817889e..18d44cc 100644
--- a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
@@ -7,10 +7,12 @@
import 'dart:async';
import 'dart:io';
+import '../../../../../pkg/pathos/lib/path.dart' as path;
// TODO(rnystrom): Use "package:" URL (#4968).
import '../lib/dartdoc.dart' as dd;
-import '../lib/markdown.dart' as md;
+import '../lib/markdown.dart';
+import 'markdown_test.dart';
// TODO(rnystrom): Better path to unittest.
import '../../../../../pkg/unittest/lib/unittest.dart';
@@ -120,6 +122,80 @@
});
});
+ group('dartdoc markdown', () {
+ group('[::] blocks', () {
+
+ validateDartdocMarkdown('simple case', '''
+ before [:source:] after
+ ''', '''
+ <p>before <code>source</code> after</p>
+ ''');
+
+ validateDartdocMarkdown('unmatched [:', '''
+ before [: after
+ ''', '''
+ <p>before [: after</p>
+ ''');
+ validateDartdocMarkdown('multiple spans in one text', '''
+ a [:one:] b [:two:] c
+ ''', '''
+ <p>a <code>one</code> b <code>two</code> c</p>
+ ''');
+
+ validateDartdocMarkdown('multi-line', '''
+ before [:first
+ second:] after
+ ''', '''
+ <p>before <code>first
+ second</code> after</p>
+ ''');
+
+ validateDartdocMarkdown('contain backticks', '''
+ before [:can `contain` backticks:] after
+ ''', '''
+ <p>before <code>can `contain` backticks</code> after</p>
+ ''');
+
+ validateDartdocMarkdown('contain double backticks', '''
+ before [:can ``contain`` backticks:] after
+ ''', '''
+ <p>before <code>can ``contain`` backticks</code> after</p>
+ ''');
+
+ validateDartdocMarkdown('contain backticks with spaces', '''
+ before [: `tick` :] after
+ ''', '''
+ <p>before <code>`tick`</code> after</p>
+ ''');
+
+ validateDartdocMarkdown('multiline with spaces', '''
+ before [:in `tick`
+ another:] after
+ ''', '''
+ <p>before <code>in `tick`
+ another</code> after</p>
+ ''');
+
+ validateDartdocMarkdown('ignore markup inside code', '''
+ before [:*b* _c_:] after
+ ''', '''
+ <p>before <code>*b* _c_</code> after</p>
+ ''');
+
+ validateDartdocMarkdown('escape HTML characters', '''
+ [:<&>:]
+ ''', '''
+ <p><code><&></code></p>
+ ''');
+
+ validateDartdocMarkdown('escape HTML tags', '''
+ '*' [:<em>:]
+ ''', '''
+ <p>'*' <code><em></code></p>
+ ''');
+ });
+ });
+
group('integration tests', () {
test('no entrypoints', () {
expect(_runDartdoc([], exitCode: 1), completes);
@@ -138,16 +214,31 @@
'package_test_file.dart').toNativePath()]),
completes);
});
-
});
}
Future _runDartdoc(List<String> arguments, {int exitCode: 0}) {
var dartBin = new Options().executable;
- var dartdoc = 'bin/dartdoc.dart';
+
+ var dir = path.absolute(new Options().script);
+ while (path.basename(dir) != 'dartdoc') {
+ if (!path.absolute(dir).contains('dartdoc') || dir == path.dirname(dir)) {
+ fail('Unable to find root dartdoc directory.');
+ }
+ dir = path.dirname(dir);
+ }
+
+ var dartdoc = path.join(path.absolute(dir), 'bin/dartdoc.dart');
arguments.insertRange(0, 1, dartdoc);
return Process.run(dartBin, arguments)
.then((result) {
expect(result.exitCode, exitCode);
});
}
+
+validateDartdocMarkdown(String description, String markdown,
+ String html) {
+ var dartdoc = new dd.Dartdoc();
+ validate(description, markdown, html, linkResolver: dartdoc.dartdocResolver,
+ inlineSyntaxes: dartdoc.dartdocSyntaxes);
+}
diff --git a/sdk/lib/_internal/dartdoc/test/markdown_test.dart b/sdk/lib/_internal/dartdoc/test/markdown_test.dart
index bd23384..44c9431 100644
--- a/sdk/lib/_internal/dartdoc/test/markdown_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/markdown_test.dart
@@ -649,6 +649,12 @@
second</code> after</p>
''');
+ validate('simple double backticks', '''
+ before ``source`` after
+ ''', '''
+ <p>before <code>source</code> after</p>
+ ''');
+
validate('double backticks', '''
before ``can `contain` backticks`` after
''', '''
@@ -798,6 +804,29 @@
<p>links <a href="http://foo.com"><em>are</em></a> awesome</p>
''');
});
+
+ group('Resolver', () {
+ var nyanResolver = (text) => new Text('~=[,,_${text}_,,]:3');
+ validate('simple resolver', '''
+ resolve [this] thing
+ ''', '''
+ <p>resolve ~=[,,_this_,,]:3 thing</p>
+ ''', linkResolver: nyanResolver);
+ });
+
+ group('Custom inline syntax', () {
+ List<InlineSyntax> nyanSyntax =
+ [new TextSyntax('nyan', sub: '~=[,,_,,]:3')];
+ validate('simple inline syntax', '''
+ nyan
+ ''', '''
+ <p>~=[,,_,,]:3</p>
+ ''', inlineSyntaxes: nyanSyntax);
+
+ // TODO(amouravski): need more tests here for custom syntaxes, as some
+ // things are not quite working properly. The regexps are sometime a little
+ // too greedy, I think.
+ });
}
/**
@@ -829,12 +858,13 @@
}
validate(String description, String markdown, String html,
- {bool verbose: false}) {
+ {bool verbose: false, inlineSyntaxes, linkResolver}) {
test(description, () {
markdown = cleanUpLiteral(markdown);
html = cleanUpLiteral(html);
- var result = markdownToHtml(markdown);
+ var result = markdownToHtml(markdown, inlineSyntaxes: inlineSyntaxes,
+ linkResolver: linkResolver);
var passed = compareOutput(html, result);
if (!passed) {
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index 8ab2e7f..b8146bb 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -66,7 +66,8 @@
dart2jsPatchPath: "_internal/compiler/implementation/lib/isolate_patch.dart"),
"json": const LibraryInfo(
- "json/json.dart"),
+ "json/json.dart",
+ dart2jsPatchPath: "_internal/compiler/implementation/lib/json_patch.dart"),
"math": const LibraryInfo(
"math/math.dart",
diff --git a/sdk/lib/async/async_error.dart b/sdk/lib/async/async_error.dart
index 81a1e04..fa90e87 100644
--- a/sdk/lib/async/async_error.dart
+++ b/sdk/lib/async/async_error.dart
@@ -20,30 +20,29 @@
AsyncError(this.error, [this.stackTrace]): cause = null;
AsyncError.withCause(this.error, this.stackTrace, this.cause);
- void _writeOn(StringBuffer buffer) {
- buffer.add("'");
+ void _writeOn(StringSink buffer) {
+ buffer.write("'");
String message;
try {
message = error.toString();
} catch (e) {
message = Error.safeToString(error);
}
- buffer.add(message);
- buffer.add("'\n");
+ buffer.write(message);
+ buffer.write("'\n");
if (stackTrace != null) {
- buffer.add("Stack trace:\n");
- buffer.add(stackTrace.toString());
- buffer.add("\n");
+ buffer.write("Stack trace:\n");
+ buffer.writeln(stackTrace.toString());
}
}
String toString() {
StringBuffer buffer = new StringBuffer();
- buffer.add("AsyncError: ");
+ buffer.write("AsyncError: ");
_writeOn(buffer);
AsyncError cause = this.cause;
while (cause != null) {
- buffer.add("Caused by: ");
+ buffer.write("Caused by: ");
cause._writeOn(buffer);
cause = cause.cause;
}
diff --git a/sdk/lib/async/async_sources.gypi b/sdk/lib/async/async_sources.gypi
index d297cae..7fdd956 100644
--- a/sdk/lib/async/async_sources.gypi
+++ b/sdk/lib/async/async_sources.gypi
@@ -5,6 +5,8 @@
# This file contains all sources for the dart:async library.
{
'sources': [
+ 'async.dart',
+ # The above file needs to be first as it lists the parts below.
'async_error.dart',
'collection_sink.dart',
'deferred_load.dart',
diff --git a/sdk/lib/async/deferred_load.dart b/sdk/lib/async/deferred_load.dart
index bc99a4d..35ff034 100644
--- a/sdk/lib/async/deferred_load.dart
+++ b/sdk/lib/async/deferred_load.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.
+part of dart.async;
+
/**
* Indicates that loading of [libraryName] is deferred.
*
@@ -9,21 +11,19 @@
*
* Example usage:
*
- * [:
- * @lazy
- * import 'foo.dart' as foo;
+ * @lazy
+ * import 'foo.dart' as foo;
*
- * const lazy = const DeferredLibrary('com.example.foo');
+ * const lazy = const DeferredLibrary('com.example.foo');
*
- * void main() {
- * foo.method(); // Throws a NoSuchMethodError, foo is not loaded yet.
- * lazy.load().then(onFooLoaded);
- * }
+ * void main() {
+ * foo.method(); // Throws a NoSuchMethodError, foo is not loaded yet.
+ * lazy.load().then(onFooLoaded);
+ * }
*
- * void onFooLoaded(_) {
- * foo.method();
- * }
- * :]
+ * void onFooLoaded(_) {
+ * foo.method();
+ * }
*/
class DeferredLibrary {
final String libraryName;
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 820ba00..96bf0cc 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -149,11 +149,8 @@
* error.
*
* See [Completer]s, for futures with values that are computed asynchronously.
- *
- * *Deprecation note*: this method initially took an [int] as argument (the
- * milliseconds to wait). It is now a [Duration].
*/
- factory Future.delayed(var duration, [T computation()]) {
+ factory Future.delayed(Duration duration, [T computation()]) {
// TODO(floitsch): no need to allocate a ThenFuture when the computation is
// null.
if (computation == null) computation = (() => null);
@@ -190,7 +187,8 @@
Iterator iterator = input.iterator;
void nextElement(_) {
if (iterator.moveNext()) {
- f(iterator.current).then(nextElement, onError: doneSignal._setError);
+ new Future.of(() => f(iterator.current))
+ .then(nextElement, onError: doneSignal._setError);
} else {
doneSignal._setValue(null);
}
@@ -362,4 +360,9 @@
* [AsyncError] and sent to this future's listeners.
*/
void completeError(Object exception, [Object stackTrace]);
+
+ /**
+ * Whether the future has been completed.
+ */
+ bool get isCompleted;
}
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 85d73af..c793d8f 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -33,6 +33,8 @@
_FutureImpl future = this.future;
future._setError(asyncError);
}
+
+ bool get isCompleted => _isComplete;
}
/**
@@ -139,7 +141,7 @@
if (remaining == 0) {
return new Future.immediate(const []);
}
- values = new List.fixedLength(remaining);
+ values = new List(remaining);
completer = new Completer<List>();
return completer.future;
}
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index a026484..185ce2a 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -20,8 +20,14 @@
* or to temporarily pause events from the stream.
*
* When an event is fired, the listeners at that time are informed.
- * If a listener is added or removed while an event is being fired, the change
- * will only take effect after the event is completely fired.
+ * If a listener is added while an event is being fired, the change
+ * will only take effect after the event is completely fired. If a listener
+ * is canceled, it immediately stops receiving events.
+ *
+ * When the "done" event is fired, subscribers are unsubscribed before
+ * receiving the event. After the event has been sent, the stream has no
+ * subscribers. Adding new subscribers after this point is allowed, but
+ * they will just receive a new "done" event as soon as possible.
*
* Streams always respect "pause" requests. If necessary they need to buffer
* their input, but often, and preferably, they can simply request their input
@@ -77,7 +83,7 @@
}
/**
- * Whether the stream is a broadcast stream.
+ * Reports whether this stream is a broadcast stream.
*/
bool get isBroadcast => false;
@@ -97,9 +103,9 @@
}
/**
- * Add a subscription to this stream.
+ * Adds a subscription to this stream.
*
- * On each data event from this stream, the subscribers [onData] handler
+ * On each data event from this stream, the subscriber's [onData] handler
* is called. If [onData] is null, nothing happens.
*
* On errors from this stream, the [onError] handler is given a
@@ -126,7 +132,7 @@
}
/**
- * Create a new stream that converts each element of this stream
+ * Creates a new stream that converts each element of this stream
* to a new value using the [convert] function.
*/
Stream map(convert(T event)) {
@@ -134,7 +140,7 @@
}
/**
- * Create a wrapper Stream that intercepts some errors from this stream.
+ * Creates a wrapper Stream that intercepts some errors from this stream.
*
* If this stream sends an error that matches [test], then it is intercepted
* by the [handle] function.
@@ -155,7 +161,7 @@
}
/**
- * Create a new stream from this stream that converts each element
+ * Creates a new stream from this stream that converts each element
* into zero or more events.
*
* Each incoming event is converted to an [Iterable] of new events,
@@ -167,14 +173,14 @@
}
/**
- * Bind this stream as the input of the provided [StreamConsumer].
+ * Binds this stream as the input of the provided [StreamConsumer].
*/
Future pipe(StreamConsumer<T, dynamic> streamConsumer) {
return streamConsumer.consume(this);
}
/**
- * Chain this stream as the input of the provided [StreamTransformer].
+ * Chains this stream as the input of the provided [StreamTransformer].
*
* Returns the result of [:streamTransformer.bind:] itself.
*/
@@ -225,7 +231,7 @@
/**
- * Check whether [match] occurs in the elements provided by this stream.
+ * Checks whether [match] occurs in the elements provided by this stream.
*
* Completes the [Future] when the answer is known.
* If this stream reports an error, the [Future] will report that error.
@@ -257,7 +263,7 @@
}
/**
- * Check whether [test] accepts all elements provided by this stream.
+ * Checks whether [test] accepts all elements provided by this stream.
*
* Completes the [Future] when the answer is known.
* If this stream reports an error, the [Future] will report that error.
@@ -289,7 +295,7 @@
}
/**
- * Check whether [test] accepts any element provided by this stream.
+ * Checks whether [test] accepts any element provided by this stream.
*
* Completes the [Future] when the answer is known.
* If this stream reports an error, the [Future] will report that error.
@@ -440,7 +446,7 @@
return future;
}
- /** Collect the data of this stream in a [List]. */
+ /** Collects the data of this stream in a [List]. */
Future<List<T>> toList() {
List<T> result = <T>[];
_FutureImpl<List<T>> future = new _FutureImpl<List<T>>();
@@ -458,7 +464,7 @@
return future;
}
- /** Collect the data of this stream in a [Set]. */
+ /** Collects the data of this stream in a [Set]. */
Future<Set<T>> toSet() {
Set<T> result = new Set<T>();
_FutureImpl<Set<T>> future = new _FutureImpl<Set<T>>();
@@ -477,7 +483,7 @@
}
/**
- * Provide at most the first [n] values of this stream.
+ * Provides at most the first [n] values of this stream.
*
* Forwards the first [n] data events of this stream, and all error
* events, to the returned stream, and ends with a done event.
@@ -521,7 +527,7 @@
}
/**
- * Skip data events if they are equal to the previous data event.
+ * Skips data events if they are equal to the previous data event.
*
* The returned stream provides the same events as this stream, except
* that it never provides two consequtive data events that are equal.
@@ -624,7 +630,7 @@
}
/**
- * Find the first element of this stream matching [test].
+ * Finds the first element of this stream matching [test].
*
* Returns a future that is filled with the first element of this stream
* that [test] returns true for.
@@ -1014,6 +1020,7 @@
{ void onError(AsyncError error),
void onDone(),
bool unsubscribeOnError }) {
+ unsubscribeOnError = identical(true, unsubscribeOnError);
return new _EventTransformStreamSubscription(_source, _transformer,
onData, onError, onDone,
unsubscribeOnError);
@@ -1077,6 +1084,7 @@
}
void _handleDone() {
+ _subscription = null;
try {
_transformer.handleDone(_sink);
} catch (e, s) {
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index e5b8b45..9ea10f5 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -19,6 +19,32 @@
* It's possible to check whether the stream is paused or not, and whether
* it has subscribers or not, as well as getting a callback when either of
* these change.
+ *
+ * If the stream starts or stops having listeners (first listener subscribing,
+ * last listener unsubscribing), the `onSubscriptionStateChange` callback
+ * is notified as soon as possible. If the subscription stat changes during
+ * an event firing or a callback being executed, the change will not be reported
+ * until the current event or callback has finished.
+ * If the pause state has also changed during an event or callback, only the
+ * subscription state callback is notified.
+ *
+ * If the subscriber state has not changed, but the pause state has, the
+ * `onPauseStateChange` callback is notified as soon as possible, after firing
+ * a current event or completing another callback. This happens if the stream
+ * is not paused, and a listener pauses it, or if the stream has been resumed
+ * from pause and has no pending events. If the listeners resume a paused stream
+ * while it still has queued events, the controller will still consider the
+ * stream paused until all queued events have been dispatched.
+ *
+ * Whether to invoke a callback depends only on the state before and after
+ * a stream action, for example firing an event. If the state changes multiple
+ * times during the action, and then ends up in the same state as before, no
+ * callback is performed.
+ *
+ * If listeners are added after the stream has completed (sent a "done" event),
+ * the listeners will be sent a "done" event eventually, but they won't affect
+ * the stream at all, and won't trigger callbacks. From the controller's point
+ * of view, the stream is completely inert when has completed.
*/
class StreamController<T> implements StreamSink<T> {
final _StreamImpl<T> stream;
@@ -63,8 +89,16 @@
*/
StreamSink<T> get sink => new StreamSinkView<T>(this);
+ /**
+ * Whether the stream is closed for adding more events.
+ *
+ * If true, the "done" event might not have fired yet, but it has been
+ * scheduled, and it is too late to add more events.
+ */
+ bool get isClosed => stream._isClosed;
+
/** Whether one or more active subscribers have requested a pause. */
- bool get isPaused => stream._isPaused;
+ bool get isPaused => stream._isInputPaused;
/** Whether there are currently any subscribers on this [Stream]. */
bool get hasSubscribers => stream._hasSubscribers;
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 130f226..ccaa506 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -6,6 +6,7 @@
// States shared by single/multi stream implementations.
+// Completion state of the stream.
/// Initial and default state where the stream can receive and send events.
const int _STREAM_OPEN = 0;
/// The stream has received a request to complete, but hasn't done so yet.
@@ -15,17 +16,26 @@
/// Also counts as closed. The stream must not be paused when it's completed.
/// Always used in conjunction with [_STREAM_CLOSED].
const int _STREAM_COMPLETE = 2;
+
/// Bit that alternates between events, and listeners are updated to the
/// current value when they are notified of the event.
const int _STREAM_EVENT_ID = 4;
const int _STREAM_EVENT_ID_SHIFT = 2;
+
+// The activity state of the stream: What is it currently doing.
/// Bit set while firing and clear while not.
const int _STREAM_FIRING = 8;
/// Bit set while calling a pause-state or subscription-state change callback.
const int _STREAM_CALLBACK = 16;
+
+// The pause state of the stream.
+/// Bit set when resuming with pending events. Cleared after all pending events
+/// have been transmitted. Means that the controller still considers the
+/// stream paused, even if the listener doesn't.
+const int _STREAM_PENDING_RESUME = 32;
/// The count of times a stream has paused is stored in the
/// state, shifted by this amount.
-const int _STREAM_PAUSE_COUNT_SHIFT = 5;
+const int _STREAM_PAUSE_COUNT_SHIFT = 6;
// States for listeners.
@@ -36,9 +46,11 @@
/// The listener is subscribed until it has been notified of the current event.
/// This flag bit is always used in conjuction with [_LISTENER_SUBSCRIBED].
const int _LISTENER_PENDING_UNSUBSCRIBE = 2;
+
/// Bit that contains the last sent event's "id bit".
const int _LISTENER_EVENT_ID = 4;
const int _LISTENER_EVENT_ID_SHIFT = 2;
+
/// The count of times a listener has paused is stored in the
/// state, shifted by this amount.
const int _LISTENER_PAUSE_COUNT_SHIFT = 3;
@@ -92,11 +104,16 @@
*/
void _add(T value) {
if (_isClosed) throw new StateError("Sending on closed stream");
- if (!_canFireEvent) {
+ if (!_mayFireState) {
+ // Not the time to send events.
_addPendingEvent(new _DelayedData<T>(value));
return;
}
- _sendData(value);
+ if (_hasPendingEvent) {
+ _addPendingEvent(new _DelayedData<T>(value));
+ } else {
+ _sendData(value);
+ }
_handlePendingEvents();
}
@@ -108,11 +125,16 @@
*/
void _signalError(AsyncError error) {
if (_isClosed) throw new StateError("Sending on closed stream");
- if (!_canFireEvent) {
+ if (!_mayFireState) {
+ // Not the time to send events.
_addPendingEvent(new _DelayedError(error));
return;
}
- _sendError(error);
+ if (_hasPendingEvent) {
+ _addPendingEvent(new _DelayedError(error));
+ } else {
+ _sendError(error);
+ }
_handlePendingEvents();
}
@@ -125,19 +147,29 @@
void _close() {
if (_isClosed) return;
_state |= _STREAM_CLOSED;
- if (!_canFireEvent) {
- // You can't enqueue an event after the Done, so make it const.
+ if (!_mayFireState) {
+ // Not the time to send events.
_addPendingEvent(const _DelayedDone());
return;
}
- _sendDone();
- assert(!_hasPendingEvent);
+ if (_hasPendingEvent) {
+ _addPendingEvent(new _DelayedDone());
+ _handlePendingEvents();
+ } else {
+ _sendDone();
+ assert(_isComplete);
+ assert(!_hasPendingEvent);
+ }
}
// -------------------------------------------------------------------
// Internal implementation.
- // State prediates.
+ // State predicates.
+
+ // Lifecycle state.
+ /** Whether the stream is in the default, open, state for events. */
+ bool get _isOpen => (_state & (_STREAM_CLOSED | _STREAM_COMPLETE)) == 0;
/** Whether the stream has been closed (a done event requested). */
bool get _isClosed => (_state & _STREAM_CLOSED) != 0;
@@ -145,25 +177,64 @@
/** Whether the stream is completed. */
bool get _isComplete => (_state & _STREAM_COMPLETE) != 0;
+ // Pause state.
+
/** Whether one or more active subscribers have requested a pause. */
bool get _isPaused => _state >= (1 << _STREAM_PAUSE_COUNT_SHIFT);
+ /** How many times the stream has been paused. */
+ int get _pauseCount => _state >> _STREAM_PAUSE_COUNT_SHIFT;
+
+ /**
+ * Whether a controller thinks the stream is paused.
+ *
+ * When this changes, a pause-state change callback is performed.
+ *
+ * It may differ from [_isPaused] if there are pending events
+ * in the queue when the listeners resume. The controller won't
+ * be informed until all queued events have been fired.
+ */
+ bool get _isInputPaused => _state >= (_STREAM_PENDING_RESUME);
+
+ /** Whether we have a pending resume scheduled. */
+ bool get _hasPendingResume => (_state & _STREAM_PENDING_RESUME) != 0;
+
+
+ // Action state. If the stream makes a call-out to external code,
+ // this state tracks it and avoids reentrancy problems.
+
+ /** Whether the stream is not currently firing or calling a callback. */
+ bool get _isInactive => (_state & (_STREAM_CALLBACK | _STREAM_FIRING)) == 0;
+
/** Whether we are currently executing a state-chance callback. */
bool get _isInCallback => (_state & _STREAM_CALLBACK) != 0;
+ /** Whether we are currently firing an event. */
+ bool get _isFiring => (_state & _STREAM_FIRING) != 0;
+
/** Check whether the pending event queue is non-empty */
bool get _hasPendingEvent =>
_pendingEvents != null && !_pendingEvents.isEmpty;
- /** Whether we are currently firing an event. */
- bool get _isFiring => (_state & _STREAM_FIRING) != 0;
+ /**
+ * The bit representing the current or last event fired.
+ *
+ * This bit matches a bit on listeners that have received the corresponding
+ * event. It is toggled for each new event being fired.
+ */
+ int get _currentEventIdBit =>
+ (_state & _STREAM_EVENT_ID ) >> _STREAM_EVENT_ID_SHIFT;
+
+ /** Whether there is currently a subscriber on this [Stream]. */
+ bool get _hasSubscribers;
+
/** Whether the state bits allow firing. */
bool get _mayFireState {
- // The state disallows firing if:
- // - an event is currently firing
- // - a stat-change callback is being called
- // - the pause-count is not zero.
+ // The state allows firing unless:
+ // - it's currently firing
+ // - it's currently in a callback
+ // - it's paused
const int mask =
_STREAM_FIRING |
_STREAM_CALLBACK |
@@ -171,20 +242,12 @@
return (_state & mask) == 0;
}
- int get _currentEventIdBit =>
- (_state & _STREAM_EVENT_ID ) >> _STREAM_EVENT_ID_SHIFT;
-
- /** Whether there is currently a subscriber on this [Stream]. */
- bool get _hasSubscribers;
-
- /** Whether the stream can fire a new event. */
- bool get _canFireEvent => _mayFireState && !_hasPendingEvent;
-
// State modification.
/** Record an increases in the number of times the listener has paused. */
void _incrementPauseCount(_StreamListener<T> listener) {
listener._incrementPauseCount();
+ _state &= ~_STREAM_PENDING_RESUME;
_updatePauseCount(1);
}
@@ -222,6 +285,7 @@
void _startFiring() {
assert(!_isFiring);
+ assert(!_isInCallback);
assert(_hasSubscribers);
assert(!_isPaused);
// This sets the _STREAM_FIRING bit and toggles the _STREAM_EVENT_ID
@@ -231,14 +295,11 @@
_state ^= _STREAM_FIRING | _STREAM_EVENT_ID;
}
- void _endFiring() {
+ void _endFiring(bool wasInputPaused) {
assert(_isFiring);
_state ^= _STREAM_FIRING;
- if (!_hasSubscribers) {
- _callOnSubscriptionStateChange();
- } else if (_isPaused) {
- _callOnPauseStateChange();
- }
+ // Had listeners, or we wouldn't have fired.
+ _checkCallbacks(true, wasInputPaused);
}
/**
@@ -256,13 +317,20 @@
throw new StateError("Subscription has been canceled.");
}
assert(!_isComplete); // There can be no subscribers when complete.
+ bool wasInputPaused = _isInputPaused;
bool wasPaused = _isPaused;
_incrementPauseCount(listener);
if (resumeSignal != null) {
resumeSignal.whenComplete(() { this._resume(listener, true); });
}
- if (!wasPaused && !_isFiring) {
- _callOnPauseStateChange();
+ if (!wasPaused && _hasPendingEvent && _pendingEvents.isScheduled) {
+ _pendingEvents.cancelSchedule();
+ }
+ if (_isInactive && !wasInputPaused) {
+ _checkCallbacks(true, false);
+ if (!_isPaused && _hasPendingEvent) {
+ _schedulePendingEvents();
+ }
}
}
@@ -273,13 +341,25 @@
assert(_isPaused);
_decrementPauseCount(listener);
if (!_isPaused) {
- if (!_isFiring) _callOnPauseStateChange();
if (_hasPendingEvent) {
+ _state |= _STREAM_PENDING_RESUME;
+ // Controller's pause state hasn't changed.
// If we can fire events now, fire any pending events right away.
- if (fromEvent && !_isFiring) {
- _handlePendingEvents();
- } else {
- _schedulePendingEvents();
+ if (_isInactive) {
+ if (fromEvent) {
+ _handlePendingEvents();
+ } else {
+ _schedulePendingEvents();
+ }
+ }
+ } else if (_isInactive) {
+ _checkCallbacks(true, true);
+ if (!_isPaused && _hasPendingEvent) {
+ if (fromEvent) {
+ _handlePendingEvents();
+ } else {
+ _schedulePendingEvents();
+ }
}
}
}
@@ -330,27 +410,34 @@
*/
void _forEachSubscriber(void action(_StreamSubscriptionImpl<T> subscription));
- /** Calls [_onPauseStateChange] while setting callback bit. */
- void _callOnPauseStateChange() {
- // After calling [_close], all pauses are handled internally by the Stream.
- if (_isClosed) return;
- if (!_isInCallback) {
- _state |= _STREAM_CALLBACK;
- _onPauseStateChange();
- _state ^= _STREAM_CALLBACK;
- } else {
- _onPauseStateChange();
+ /**
+ * Checks whether the subscription/pause state has changed.
+ *
+ * Calls the appropriate callback if the state has changed from the
+ * provided one. Repeats calling callbacks as long as the call changes
+ * the state.
+ */
+ void _checkCallbacks(bool hadSubscribers, bool wasPaused) {
+ assert(!_isFiring);
+ // Will be handled after the current callback.
+ if (_isInCallback) return;
+ if (_hasPendingResume && !_hasPendingEvent) {
+ _state ^= _STREAM_PENDING_RESUME;
}
- }
-
- /** Calls [_onSubscriptionStateChange] while setting callback bit. */
- void _callOnSubscriptionStateChange() {
- if (!_isInCallback) {
- _state |= _STREAM_CALLBACK;
- _onSubscriptionStateChange();
- _state ^= _STREAM_CALLBACK;
- } else {
- _onSubscriptionStateChange();
+ _state |= _STREAM_CALLBACK;
+ while (true) {
+ bool hasSubscribers = _hasSubscribers;
+ bool isPaused = _isInputPaused;
+ if (hadSubscribers != hasSubscribers) {
+ _onSubscriptionStateChange();
+ } else if (isPaused != wasPaused) {
+ _onPauseStateChange();
+ } else {
+ _state ^= _STREAM_CALLBACK;
+ return;
+ }
+ wasPaused = isPaused;
+ hadSubscribers = hasSubscribers;
}
}
@@ -368,20 +455,32 @@
*/
void _onSubscriptionStateChange() {}
- /** Add a pending event at the end of the pending event queue. */
+ /**
+ * Add a pending event at the end of the pending event queue.
+ *
+ * Schedules events if currently not paused and inside a callback.
+ */
void _addPendingEvent(_DelayedEvent event) {
if (_pendingEvents == null) _pendingEvents = new _StreamImplEvents();
_StreamImplEvents events = _pendingEvents;
events.add(event);
+ if (_isPaused || _isFiring) return;
+ if (_isInCallback) {
+ _schedulePendingEvents();
+ return;
+ }
}
- /** Fire any pending events until the pending event queue. */
+ /** Fire any pending events until the pending event queue is empty. */
void _handlePendingEvents() {
+ assert(_isInactive);
+ if (!_hasPendingEvent) return;
_PendingEvents events = _pendingEvents;
- if (events == null) return;
- while (!events.isEmpty && !_isPaused) {
+ do {
+ if (_isPaused) return;
+ if (events.isScheduled) events.cancelSchedule();
events.handleNext(this);
- }
+ } while (!events.isEmpty);
}
/**
@@ -390,6 +489,7 @@
_sendData(T value) {
assert(!_isPaused);
assert(!_isComplete);
+ if (!_hasSubscribers) return;
_forEachSubscriber((subscriber) {
try {
subscriber._sendData(value);
@@ -407,6 +507,7 @@
void _sendError(AsyncError error) {
assert(!_isPaused);
assert(!_isComplete);
+ if (!_hasSubscribers) return;
_forEachSubscriber((subscriber) {
try {
subscriber._sendError(error);
@@ -467,7 +568,7 @@
* when losing the last subscriber.
* * [_onPauseStateChange]: Called when entering or leaving paused mode.
* * [_hasSubscribers]: Test whether there are currently any subscribers.
- * * [_isPaused]: Test whether the stream is currently paused.
+ * * [_isInputPaused]: Test whether the stream is currently paused.
* The user should not add new events while the stream is paused, but if it
* happens anyway, the stream will enqueue the events just as when new events
* arrive while still firing an old event.
@@ -475,26 +576,17 @@
class _SingleStreamImpl<T> extends _StreamImpl<T> {
_StreamListener _subscriber = null;
- // A single-stream is considered paused when it has no subscriber.
- // Exception is when it's complete (which only matters for pause-state-change
- // callbacks), where it's not considered paused.
- bool get _isPaused => (!_hasSubscribers && !_isComplete) || super._isPaused;
-
-
- bool get _canFireEvent {
- // A single-stream is considered paused when it has no subscriber and
- // isn't complete, so it can't fire if there is no subscriber.
- // It won't try to fire when completed, so no need to check that.
- return _mayFireState && !_hasPendingEvent && _hasSubscribers;
- }
-
-
/** Whether there is currently a subscriber on this [Stream]. */
bool get _hasSubscribers => _subscriber != null;
// -------------------------------------------------------------------
// Internal implementation.
+ _SingleStreamImpl() {
+ // Start out paused.
+ _updatePauseCount(1);
+ }
+
/**
* Create the new subscription object.
*/
@@ -508,14 +600,19 @@
}
void _addListener(_StreamListener subscription) {
+ assert(!_isComplete);
if (_hasSubscribers) {
throw new StateError("Stream already has subscriber.");
}
+ assert(_pauseCount == 1);
+ _updatePauseCount(-1);
_subscriber = subscription;
subscription._setSubscribed(0);
- _callOnSubscriptionStateChange();
- if (_hasPendingEvent) {
- _schedulePendingEvents();
+ if (_isInactive) {
+ _checkCallbacks(false, true);
+ if (!_isPaused && _hasPendingEvent) {
+ _schedulePendingEvents();
+ }
}
}
@@ -523,9 +620,6 @@
* Handle a cancel requested from a [_StreamSubscriptionImpl].
*
* This method is called from [_StreamSubscriptionImpl.cancel].
- *
- * If an event is currently firing, the cancel is delayed
- * until after the subscriber has received the event.
*/
void _cancel(_StreamListener subscriber) {
assert(identical(subscriber._source, this));
@@ -538,21 +632,27 @@
}
_subscriber = null;
// Unsubscribing a paused subscription also cancels its pauses.
- int subscriptionPauseCount = subscriber._setUnsubscribed();
- _updatePauseCount(-subscriptionPauseCount);
- if (!_isFiring) {
- _callOnSubscriptionStateChange();
+ int resumeCount = subscriber._setUnsubscribed();
+ // Keep being paused while there is no subscriber and the stream is not
+ // complete.
+ _updatePauseCount(_isComplete ? -resumeCount : -resumeCount + 1);
+ if (_isInactive) {
+ _checkCallbacks(true, resumeCount > 0);
+ if (!_isPaused && _hasPendingEvent) {
+ _schedulePendingEvents();
+ }
}
}
void _forEachSubscriber(
void action(_StreamListener<T> subscription)) {
assert(!_isPaused);
+ bool wasInputPaused = _isInputPaused;
_StreamListener subscription = _subscriber;
assert(subscription != null);
_startFiring();
action(subscription);
- _endFiring();
+ _endFiring(wasInputPaused);
}
}
@@ -638,6 +738,7 @@
void action(_StreamListener<T> subscription)) {
assert(!_isFiring);
if (!_hasSubscribers) return;
+ bool wasInputPaused = _isInputPaused;
_startFiring();
_InternalLink cursor = this._nextLink;
while (!identical(cursor, this)) {
@@ -652,15 +753,18 @@
_removeListener(current);
}
}
- _endFiring();
+ _endFiring(wasInputPaused);
}
void _addListener(_StreamListener listener) {
listener._setSubscribed(_currentEventIdBit);
- bool firstSubscriber = !_hasSubscribers;
+ bool hadSubscribers = _hasSubscribers;
_InternalLinkList.add(this, listener);
- if (firstSubscriber) {
- _callOnSubscriptionStateChange();
+ if (!hadSubscribers && _isInactive) {
+ _checkCallbacks(false, false);
+ if (!_isPaused && _hasPendingEvent) {
+ _schedulePendingEvents();
+ }
}
}
@@ -681,7 +785,7 @@
if (_isFiring) {
if (listener._needsEvent(_currentEventIdBit)) {
assert(listener._isSubscribed);
- listener._setPendingUnsubscribe();
+ listener._setPendingUnsubscribe(_currentEventIdBit);
} else {
// The listener has been notified of the event (or don't need to,
// if it's still pending subscription) so it's safe to remove it.
@@ -690,10 +794,14 @@
// Pause and subscription state changes are reported when we end
// firing.
} else {
- bool wasPaused = _isPaused;
+ bool wasInputPaused = _isInputPaused;
_removeListener(listener);
- if (wasPaused != _isPaused) _onPauseStateChange();
- if (!_hasSubscribers) _callOnSubscriptionStateChange();
+ if (_isInactive) {
+ _checkCallbacks(true, wasInputPaused);
+ if (!_isPaused && _hasPendingEvent) {
+ _schedulePendingEvents();
+ }
+ }
}
}
@@ -705,8 +813,13 @@
*/
void _removeListener(_StreamListener listener) {
int pauseCount = listener._setUnsubscribed();
- _updatePauseCount(-pauseCount);
_InternalLinkList.remove(listener);
+ if (pauseCount > 0) {
+ _updatePauseCount(-pauseCount);
+ if (!_isPaused && _hasPendingEvent) {
+ _state |= _STREAM_PENDING_RESUME;
+ }
+ }
}
}
@@ -1031,9 +1144,13 @@
_state = _LISTENER_SUBSCRIBED | (eventIdBit << _LISTENER_EVENT_ID_SHIFT);
}
- void _setPendingUnsubscribe() {
+ void _setPendingUnsubscribe(int currentEventIdBit) {
assert(_isSubscribed);
- _state |= _LISTENER_PENDING_UNSUBSCRIBE;
+ // Sets the pending unsubscribe, and ensures that the listener
+ // won't get the current event.
+ _state |= _LISTENER_PENDING_UNSUBSCRIBE | _LISTENER_EVENT_ID;
+ _state ^= (1 ^ currentEventIdBit) << _LISTENER_EVENT_ID_SHIFT;
+ assert(!_needsEvent(currentEventIdBit));
}
/**
@@ -1079,7 +1196,7 @@
void schedule(_StreamImpl stream) {
if (isScheduled) return;
- scheduleTimer = Timer.run(() {
+ scheduleTimer = new Timer(Duration.ZERO, () {
scheduleTimer = null;
stream._handlePendingEvents();
});
@@ -1115,7 +1232,7 @@
}
void handleNext(_StreamImpl stream) {
- if (isScheduled) cancelSchedule();
+ assert(!isScheduled);
_DelayedEvent event = firstPendingEvent;
firstPendingEvent = event.next;
if (firstPendingEvent == null) {
@@ -1137,7 +1254,7 @@
void _delayDone() {
assert(_timer == null && _pauseCount == 0);
- _timer = Timer.run(() {
+ _timer = new Timer(Duration.ZERO, () {
if (_handler != null) _handler();
});
}
@@ -1156,8 +1273,12 @@
if (_isComplete) {
throw new StateError("Subscription has been canceled.");
}
- if (_timer != null) _timer.cancel();
+ if (_timer != null) {
+ _timer.cancel();
+ _timer = null;
+ }
_pauseCount++;
+ if (signal != null) signal.whenComplete(resume);
}
void resume() {
@@ -1186,7 +1307,7 @@
}
class _SingleStreamMultiplexer<T> extends _MultiStreamImpl<T> {
- final _SingleStreamImpl<T> _source;
+ final Stream<T> _source;
StreamSubscription<T> _subscription;
_SingleStreamMultiplexer(this._source);
diff --git a/sdk/lib/async/timer.dart b/sdk/lib/async/timer.dart
index 39fe4c2..7ed5d5a 100644
--- a/sdk/lib/async/timer.dart
+++ b/sdk/lib/async/timer.dart
@@ -5,12 +5,14 @@
part of dart.async;
abstract class Timer {
+ // Internal list used to group Timer.run callbacks.
+ static List _runCallbacks = [];
+
/**
* Creates a new timer.
*
- * The [callback] callback is invoked after the given [duration]
- * (a [Duration]) has passed. A negative duration is treated similar to
- * a duration of 0.
+ * The [callback] callback is invoked after the given [duration].
+ * A negative duration is treated similar to a duration of 0.
*
* If the [duration] is statically known to be 0, consider using [run].
*
@@ -25,34 +27,45 @@
* var duration = milliseconds == null ? TIMEOUT : ms * milliseconds;
* return new Timer(duration, handleTimeout);
* }
- *
- * *Deprecation warning*: this constructor used to take an [int] (the time
- * in milliseconds) and a callback with one argument (the timer). This has
- * changed to a [Duration] and a callback without arguments.
*/
- // TODO(floitsch): add types.
- external factory Timer(var duration, Function callback);
+ external factory Timer(Duration duration, void callback());
/**
* Creates a new repeating timer.
*
* The [callback] is invoked repeatedly with [duration] intervals until
* canceled. A negative duration is treated similar to a duration of 0.
- *
- * *Deprecation warning*: this constructor used to take an [int] (the time
- * in milliseconds). This has changed to a [Duration].
*/
- external factory Timer.repeating(var duration,
+ external factory Timer.repeating(Duration duration,
void callback(Timer timer));
/**
* Runs the given [callback] asynchronously as soon as possible.
- *
- * Returns a [Timer] that can be cancelled if the callback is not necessary
- * anymore.
*/
- static Timer run(void callback()) {
- return new Timer(const Duration(), callback);
+ static void run(void callback()) {
+ // Optimizing a group of Timer.run callbacks to be executed in the
+ // same Timer callback.
+ _runCallbacks.add(callback);
+ if (_runCallbacks.length == 1) {
+ new Timer(const Duration(milliseconds: 0), () {
+ List runCallbacks = _runCallbacks;
+ // Create new list to make sure we don't call newly added callbacks in
+ // this event.
+ _runCallbacks = [];
+ for (int i = 0; i < runCallbacks.length; i++) {
+ Function callback = runCallbacks[i];
+ try {
+ callback();
+ } catch (e) {
+ List newCallbacks = _runCallbacks;
+ _runCallbacks = [];
+ _runCallbacks.addAll(runCallbacks.skip(i + 1));
+ _runCallbacks.addAll(newCallbacks);
+ throw;
+ }
+ }
+ });
+ }
}
/**
diff --git a/sdk/lib/chrome/dart2js/chrome_dart2js.dart b/sdk/lib/chrome/dart2js/chrome_dart2js.dart
index 92b66c5..7c1ca62 100644
--- a/sdk/lib/chrome/dart2js/chrome_dart2js.dart
+++ b/sdk/lib/chrome/dart2js/chrome_dart2js.dart
@@ -1,3 +1,10 @@
+/// Native wrappers for the Chrome Packaged App APIs.
+///
+/// These functions allow direct access to the Packaged App APIs, allowing
+/// Chrome Packaged Apps to be written using Dart.
+///
+/// For more information on these APIs, see the
+/// [Chrome APIs Documentation](http://developer.chrome.com/extensions/api_index.html)
library chrome;
import 'dart:_foreign_helper' show JS;
@@ -13,13 +20,6 @@
// https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
// Auto-generated dart:chrome library.
-/// Native wrappers for the Chrome Packaged App APIs.
-///
-/// These functions allow direct access to the Packaged App APIs, allowing
-/// Chrome Packaged Apps to be written using Dart.
-///
-/// For more information on these APIs, see the Chrome.* APIs Documentation:
-/// http://developer.chrome.com/extensions/api_index.html
/* TODO(sashab): Add "show convertDartClosureToJS" once 'show' works. */
diff --git a/sdk/lib/chrome/dartium/chrome_dartium.dart b/sdk/lib/chrome/dartium/chrome_dartium.dart
index c228655..b741b3b 100644
--- a/sdk/lib/chrome/dartium/chrome_dartium.dart
+++ b/sdk/lib/chrome/dartium/chrome_dartium.dart
@@ -1,3 +1,10 @@
+/// Native wrappers for the Chrome Packaged App APIs.
+///
+/// These functions allow direct access to the Packaged App APIs, allowing
+/// Chrome Packaged Apps to be written using Dart.
+///
+/// For more information on these APIs, see the
+/// [Chrome APIs Documentation](http://developer.chrome.com/extensions/api_index.html)
library chrome;
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
diff --git a/sdk/lib/collection/collection.dart b/sdk/lib/collection/collection.dart
index 88c1ada..4d37c77 100644
--- a/sdk/lib/collection/collection.dart
+++ b/sdk/lib/collection/collection.dart
@@ -6,7 +6,6 @@
import 'dart:_collection-dev';
-part 'arrays.dart';
part 'collections.dart';
part 'iterator.dart';
part 'maps.dart';
diff --git a/sdk/lib/collection/collection_sources.gypi b/sdk/lib/collection/collection_sources.gypi
index 37d67be..4531699 100644
--- a/sdk/lib/collection/collection_sources.gypi
+++ b/sdk/lib/collection/collection_sources.gypi
@@ -5,7 +5,8 @@
# This file contains all sources for the dart:collection library.
{
'sources': [
- 'arrays.dart',
+ 'collection.dart',
+ # The above file needs to be first as it lists the parts below.
'collections.dart',
'hash_map.dart',
'hash_set.dart',
diff --git a/sdk/lib/collection/collections.dart b/sdk/lib/collection/collections.dart
index b35a52f..09a0778 100644
--- a/sdk/lib/collection/collections.dart
+++ b/sdk/lib/collection/collections.dart
@@ -115,7 +115,7 @@
* Removes elements matching [test] from [list].
*
* This is performed in two steps, to avoid exposing an inconsistent state
- * to the [test] function. First the elements to ratain are found, and then
+ * to the [test] function. First the elements to retain are found, and then
* the original list is updated to contain those elements.
*/
static void removeMatchingList(List list, bool test(var element)) {
@@ -131,10 +131,10 @@
}
}
if (retained.length == length) return;
+ list.length = retained.length;
for (int i = 0; i < retained.length; i++) {
list[i] = retained[i];
}
- list.length = retained.length;
}
/**
@@ -347,13 +347,46 @@
return new SkipWhileIterable(iterable, test);
}
- static Iterable reversedList(List l) {
- return new ReversedListIterable(l);
+ static Iterable reversedList(List list) {
+ return new ReversedListIterable(list);
}
- static void sortList(List l, int compare(a, b)) {
+ static void sortList(List list, int compare(a, b)) {
if (compare == null) compare = Comparable.compare;
- Sort.sort(l, compare);
+ Sort.sort(list, compare);
+ }
+
+ static int indexOfList(List list, var element, int start) {
+ return Arrays.indexOf(list, element, start, list.length);
+ }
+
+ static int lastIndexOfList(List list, var element, int start) {
+ if (start == null) start = list.length - 1;
+ return Arrays.lastIndexOf(list, element, start);
+ }
+
+ static void setRangeList(List list, int start, int length,
+ List from, int startFrom) {
+ if (length == 0) return;
+
+ // TODO(floitsch): decide what to do with these checks. Currently copied
+ // since that was the old behavior of dart2js, and some co19 tests rely on
+ // it.
+ if (start is! int) throw new ArgumentError(start);
+ if (length is! int) throw new ArgumentError(length);
+ if (from is! List) throw new ArgumentError(from);
+ if (startFrom is! int) throw new ArgumentError(startFrom);
+ if (length < 0) throw new ArgumentError(length);
+ if (start < 0) throw new RangeError.value(start);
+ if (start + length > list.length) {
+ throw new RangeError.value(start + length);
+ }
+
+ Arrays.copy(from, startFrom, list, start, length);
+ }
+
+ static Map<int, dynamic> asMapList(List l) {
+ return new ListMapView(l);
}
}
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index 22fb38f..6908029 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -19,6 +19,8 @@
// Iterable.
Iterator<E> get iterator => new _HashTableKeyIterator<E>(_table);
+ int get length => _table._elementCount;
+
bool get isEmpty => _table._elementCount == 0;
bool contains(Object object) => _table._get(object) >= 0;
diff --git a/sdk/lib/collection/hash_table.dart b/sdk/lib/collection/hash_table.dart
index 7ab52cb..ececc47 100644
--- a/sdk/lib/collection/hash_table.dart
+++ b/sdk/lib/collection/hash_table.dart
@@ -74,7 +74,7 @@
* Create an empty table.
*/
List _createTable(int capacity) {
- List table = new List.fixedLength(capacity * _entrySize);
+ List table = new List(capacity * _entrySize);
return table;
}
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index e72493a..7fc0653 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -30,6 +30,8 @@
}
}
+ int get length => _table._elementCount;
+
bool get isEmpty => _table._elementCount == 0;
bool contains(Object object) => _table._get(object) >= 0;
diff --git a/sdk/lib/collection/linked_hash_table.dart b/sdk/lib/collection/linked_hash_table.dart
index fbf6172..4b8b063 100644
--- a/sdk/lib/collection/linked_hash_table.dart
+++ b/sdk/lib/collection/linked_hash_table.dart
@@ -22,7 +22,7 @@
int get _entrySize => 3;
List _createTable(int capacity) {
- List result = new List.fixedLength(capacity * _entrySize);
+ List result = new List(capacity * _entrySize);
result[_HEAD_OFFSET] = _HEAD_MARKER;
result[_HEAD_OFFSET + _NEXT_INDEX] = _HEAD_OFFSET;
result[_HEAD_OFFSET + _PREV_INDEX] = _HEAD_OFFSET;
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 13ec536..975939a 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -350,7 +350,7 @@
initialCapacity = _nextPowerOf2(initialCapacity);
}
assert(_isPowerOf2(initialCapacity));
- _table = new List<E>.fixedLength(initialCapacity);
+ _table = new List<E>(initialCapacity);
}
/**
@@ -409,8 +409,13 @@
return _table[(_head + index) & (_table.length - 1)];
}
- List<E> toList() {
- List<E> list = new List<E>(length);
+ List<E> toList({ bool growable: true }) {
+ List<E> list;
+ if (growable) {
+ list = new List<E>()..length = length;
+ } else {
+ list = new List<E>(length);
+ }
_writeToList(list);
return list;
}
@@ -629,7 +634,7 @@
* Grow the table when full.
*/
void _grow() {
- List<E> newTable = new List<E>.fixedLength(_table.length * 2);
+ List<E> newTable = new List<E>(_table.length * 2);
int split = _table.length - _head;
newTable.setRange(0, split, _table, _head);
newTable.setRange(split, _head, _table, 0);
@@ -656,7 +661,7 @@
void _preGrow(int newElementCount) {
assert(newElementCount >= length);
int newCapacity = _nextPowerOf2(newElementCount);
- List<E> newTable = new List<E>.fixedLength(newCapacity);
+ List<E> newTable = new List<E>(newCapacity);
_tail = _writeToList(newTable);
_table = newTable;
_head = 0;
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 0345f8a..53707f1 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -5,40 +5,48 @@
part of dart.collection;
/**
- * A node in a splay tree. It holds the key, the value and the left
+ * A node in a splay tree. It holds the sorting key and the left
* and right children in the tree.
*/
-class SplayTreeNode<K, V> {
+class _SplayTreeNode<K> {
final K key;
- V value;
- SplayTreeNode<K, V> left;
- SplayTreeNode<K, V> right;
+ _SplayTreeNode<K> left;
+ _SplayTreeNode<K> right;
- SplayTreeNode(K this.key, V this.value);
+ _SplayTreeNode(K this.key);
}
/**
- * A splay tree is a self-balancing binary
- * search tree with the additional property that recently accessed
- * elements are quick to access again. It performs basic operations
- * such as insertion, look-up and removal in O(log(n)) amortized time.
+ * A node in a splay tree based map.
*
- * This implementation is a Dart version of the JavaScript
- * implementation in the V8 project.
+ * A [_SplayTreeNode] that also contains a value
*/
-class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> {
+class _SplayTreeMapNode<K, V> extends _SplayTreeNode<K> {
+ V value;
+ _SplayTreeMapNode(K key, V this.value) : super(key);
+}
+/**
+ * A splay tree is a self-balancing binary search tree.
+ *
+ * It has the additional property that recently accessed elements
+ * are quick to access again.
+ * It performs basic operations such as insertion, look-up and
+ * removal, in O(log(n)) amortized time.
+ */
+abstract class _SplayTree<K> {
// The root node of the splay tree. It will contain either the last
// element inserted, or the last element looked up.
- SplayTreeNode<K, V> _root;
+ _SplayTreeNode<K> _root;
// The dummy node used when performing a splay on the tree. It is a
// local field of the class to avoid allocating a node each time a
// splay is performed.
- SplayTreeNode<K, V> _dummy;
+ // TODO(lrn); Should it be a getter backed by a static instead?
+ _SplayTreeNode<K> _dummy = new _SplayTreeNode<K>(null);
// Number of elements in the splay tree.
- int _count;
+ int _count = 0;
/**
* Counter incremented whenever the keys in the map changes.
@@ -46,6 +54,7 @@
* Used to detect concurrent modifications.
*/
int _modificationCount = 0;
+
/**
* Counter incremented whenever the tree structure changes.
*
@@ -54,9 +63,8 @@
*/
int _splayCount = 0;
- SplayTreeMap() :
- _dummy = new SplayTreeNode<K, V>(null, null),
- _count = 0;
+ /** Comparison used to compare keys. */
+ int _compare(K key1, K key2);
/**
* Perform the splay operation for the given key. Moves the node with
@@ -75,9 +83,9 @@
// the L tree of the algorithm. The left child of the dummy node
// will hold the R tree of the algorithm. Using a dummy node, left
// and right will always be nodes and we avoid special cases.
- SplayTreeNode<K, V> left = _dummy;
- SplayTreeNode<K, V> right = _dummy;
- SplayTreeNode<K, V> current = _root;
+ _SplayTreeNode<K> left = _dummy;
+ _SplayTreeNode<K> right = _dummy;
+ _SplayTreeNode<K> current = _root;
int comp;
while (true) {
comp = current.key.compareTo(key);
@@ -86,7 +94,7 @@
comp = current.left.key.compareTo(key);
if (comp > 0) {
// Rotate right.
- SplayTreeNode<K, V> tmp = current.left;
+ _SplayTreeNode<K> tmp = current.left;
current.left = tmp.right;
tmp.right = current;
current = tmp;
@@ -101,7 +109,7 @@
comp = current.right.key.compareTo(key);
if (comp < 0) {
// Rotate left.
- SplayTreeNode<K, V> tmp = current.right;
+ _SplayTreeNode<K> tmp = current.right;
current.right = tmp.left;
tmp.left = current;
current = tmp;
@@ -128,26 +136,17 @@
return comp;
}
- V operator [](K key) {
- if (_root != null) {
- int comp = _splay(key);
- if (comp == 0) return _root.value;
- }
- return null;
- }
-
- V remove(K key) {
+ _SplayTreeNode _remove(K key) {
if (_root == null) return null;
int comp = _splay(key);
if (comp != 0) return null;
- V value = _root.value;
-
+ _SplayTreeNode result = _root;
_count--;
// assert(_count >= 0);
if (_root.left == null) {
_root = _root.right;
} else {
- SplayTreeNode<K, V> right = _root.right;
+ _SplayTreeNode<K> right = _root.right;
_root = _root.left;
// Splay to make sure that the new root has an empty right child.
_splay(key);
@@ -156,24 +155,7 @@
_root.right = right;
}
_modificationCount++;
- return value;
- }
-
- void operator []=(K key, V value) {
- if (_root == null) {
- _count++;
- _root = new SplayTreeNode(key, value);
- _modificationCount++;
- return;
- }
- // Splay on the key to move the last node on the search path for
- // the key to the root of the tree.
- int comp = _splay(key);
- if (comp == 0) {
- _root.value = value;
- return;
- }
- _addNewRoot(key, value, comp);
+ return result;
}
/**
@@ -182,10 +164,14 @@
* The [comp] value is the result of comparing the existing root's key
* with key.
*/
- void _addNewRoot(K key, V value, int comp) {
- SplayTreeNode<K, V> node = new SplayTreeNode(key, value);
- // assert(_count >= 0);
+ void _addNewRoot(_SplayTreeNode<K> node, int comp) {
_count++;
+ _modificationCount++;
+ if (_root == null) {
+ _root = node;
+ return;
+ }
+ // assert(_count >= 0);
if (comp < 0) {
node.left = _root;
node.right = _root.right;
@@ -196,20 +182,89 @@
_root.left = null;
}
_root = node;
- _modificationCount++;
}
- V putIfAbsent(K key, V ifAbsent()) {
- if (_root == null) {
- V value = ifAbsent();
- if (_root != null) {
- throw new ConcurrentModificationError(this);
- }
- _root = new SplayTreeNode(key, value);
- _count++;
- _modificationCount++;
- return value;
+ _SplayTreeNode get _first {
+ if (_root == null) return null;
+ _SplayTreeNode<K> node = _root;
+ while (node.left != null) {
+ node = node.left;
}
+ // Maybe implement a splay-method that can splay the minimum without
+ // performing comparisons.
+ _splay(node.key);
+ return node;
+ }
+
+ _SplayTreeNode get _last {
+ if (_root == null) return null;
+ _SplayTreeNode<K> node = _root;
+ while (node.right != null) {
+ node = node.right;
+ }
+ // Maybe implement a splay-method that can splay the minimum without
+ // performing comparisons.
+ _splay(node.key);
+ return node;
+ }
+
+ void _clear() {
+ _root = null;
+ _count = 0;
+ _modificationCount++;
+ }
+}
+
+/*
+ * A [Map] of objects that can be ordered relative to each other.
+ *
+ * The map is based on a self-balancing binary tree. It allows most operations
+ * in amortized logarithmic time.
+ *
+ * Keys of the map are compared using the `compare` function passed in
+ * the constructor. If that is omitted, the objects are assumed to be
+ * [Comparable], and are compared using their [Comparable.compareTo]
+ * method.
+ */
+class SplayTreeMap<K, V> extends _SplayTree<K> implements Map<K, V> {
+ // TODO(ngeoffray): Restore type when feature is implemented in dart2js
+ // checked mode. http://dartbug.com/7733
+ Function /* Comparator<K> */_comparator;
+
+ SplayTreeMap([int compare(K key1, K key2)])
+ : _comparator = (compare == null) ? Comparable.compare : compare;
+
+ int _compare(K key1, K key2) => _comparator(key1, key2);
+
+ SplayTreeMap._internal();
+
+ V operator [](K key) {
+ if (_root != null) {
+ int comp = _splay(key);
+ if (comp == 0) return _root.value;
+ }
+ return null;
+ }
+
+ V remove(K key) {
+ _SplayTreeMapNode root = _remove(key);
+ if (root != null) return root.value;
+ return null;
+ }
+
+ void operator []=(K key, V value) {
+ // Splay on the key to move the last node on the search path for
+ // the key to the root of the tree.
+ int comp = _splay(key);
+ if (comp == 0) {
+ _root.value = value;
+ return;
+ }
+ _addNewRoot(new _SplayTreeMapNode(key, value), comp);
+ }
+
+
+ V putIfAbsent(K key, V ifAbsent()) {
int comp = _splay(key);
if (comp == 0) return _root.value;
int modificationCount = _modificationCount;
@@ -223,7 +278,7 @@
// Key is still not there, otherwise _modificationCount would be changed.
assert(comp != 0);
}
- _addNewRoot(key, value, comp);
+ _addNewRoot(new _SplayTreeMapNode(key, value), comp);
return value;
}
@@ -234,10 +289,10 @@
}
void forEach(void f(K key, V value)) {
- Iterator<SplayTreeNode<K, V>> nodes =
- new _SplayTreeNodeIterator<K, V>(this);
+ Iterator<_SplayTreeNode<K>> nodes =
+ new _SplayTreeNodeIterator<K>(this);
while (nodes.moveNext()) {
- SplayTreeNode<K, V> node = nodes.current;
+ _SplayTreeMapNode<K, V> node = nodes.current;
f(node.key, node.value);
}
}
@@ -247,8 +302,7 @@
}
void clear() {
- _root = null;
- _count = 0;
+ _clear();
}
bool containsKey(K key) {
@@ -257,7 +311,7 @@
bool containsValue(V value) {
bool found = false;
- bool visit(SplayTreeNode node) {
+ bool visit(_SplayTreeNode node) {
if (node == null) return false;
if (node.value == value) return true;
// TODO(lrn): Do we want to handle the case where node.value.operator==
@@ -267,9 +321,9 @@
return visit(_root);
}
- Iterable<K> get keys => new _SplayTreeKeyIterable(this);
+ Iterable<K> get keys => new _SplayTreeKeyIterable<K>(this);
- Iterable<V> get values => new _SplayTreeValueIterable(this);
+ Iterable<V> get values => new _SplayTreeValueIterable<K, V>(this);
String toString() {
return Maps.mapToString(this);
@@ -279,30 +333,16 @@
* Get the first key in the map. Returns [null] if the map is empty.
*/
K firstKey() {
- if (_root == null) return null;
- SplayTreeNode<K, V> node = _root;
- while (node.left != null) {
- node = node.left;
- }
- // Maybe implement a splay-method that can splay the minimum without
- // performing comparisons.
- _splay(node.key);
- return node.key;
+ _SplayTreeNode node = _first;
+ return (node == null) ? null : node.key;
}
/**
* Get the last key in the map. Returns [null] if the map is empty.
*/
K lastKey() {
- if (_root == null) return null;
- SplayTreeNode<K, V> node = _root;
- while (node.right != null) {
- node = node.right;
- }
- // Maybe implement a splay-method that can splay the maximum without
- // performing comparisons.
- _splay(node.key);
- return node.key;
+ _SplayTreeNode node = _last;
+ return (node == null) ? null : node.key;
}
/**
@@ -313,7 +353,7 @@
if (_root == null) return null;
int comp = _splay(key);
if (comp < 0) return _root.key;
- SplayTreeNode<K, V> node = _root.left;
+ _SplayTreeNode<K> node = _root.left;
if (node == null) return null;
while (node.right != null) {
node = node.right;
@@ -329,7 +369,7 @@
if (_root == null) return null;
int comp = _splay(key);
if (comp > 0) return _root.key;
- SplayTreeNode<K, V> node = _root.right;
+ _SplayTreeNode<K> node = _root.right;
if (node == null) return null;
while (node.left != null) {
node = node.left;
@@ -339,7 +379,7 @@
}
abstract class _SplayTreeIterator<T> implements Iterator<T> {
- final SplayTreeMap _map;
+ final _SplayTree _tree;
/**
* Worklist of nodes to visit.
*
@@ -348,33 +388,33 @@
* and their right subtrees will visit the remainder of
* the nodes of a full traversal.
*
- * Only valid as long as the original tree map isn't reordered.
+ * Only valid as long as the original tree isn't reordered.
*/
- final List<SplayTreeNode> _workList = <SplayTreeNode>[];
+ final List<_SplayTreeNode> _workList = <_SplayTreeNode>[];
/**
- * Original modification counter of [_map].
+ * Original modification counter of [_tree].
*
- * Incremented on [_map] when a key is added or removed.
+ * Incremented on [_tree] when a key is added or removed.
* If it changes, iteration is aborted.
*/
final int _modificationCount;
/**
- * Count of splay operations on [_map] when [_workList] was built.
+ * Count of splay operations on [_tree] when [_workList] was built.
*
- * If the splay count on [_map] increases, [_workList] becomes invalid.
+ * If the splay count on [_tree] increases, [_workList] becomes invalid.
*/
int _splayCount;
/** Current node. */
- SplayTreeNode _currentNode;
+ _SplayTreeNode _currentNode;
- _SplayTreeIterator(SplayTreeMap map)
- : _map = map,
- _modificationCount = map._modificationCount,
- _splayCount = map._splayCount {
- _findLeftMostDescendent(map._root);
+ _SplayTreeIterator(_SplayTree tree)
+ : _tree = tree,
+ _modificationCount = tree._modificationCount,
+ _splayCount = tree._splayCount {
+ _findLeftMostDescendent(tree._root);
}
T get current {
@@ -382,7 +422,7 @@
return _getValue(_currentNode);
}
- void _findLeftMostDescendent(SplayTreeNode node) {
+ void _findLeftMostDescendent(_SplayTreeNode node) {
while (node != null) {
_workList.add(node);
node = node.left;
@@ -390,28 +430,28 @@
}
/**
- * Called when the tree structure of the map has changed.
+ * Called when the tree structure of the tree has changed.
*
* This can be caused by a splay operation.
* If the key-set changes, iteration is aborted before getting
* here, so we know that the keys are the same as before, it's
* only the tree that has been reordered.
*/
- void _rebuildWorkList(SplayTreeNode currentNode) {
+ void _rebuildWorkList(_SplayTreeNode currentNode) {
assert(!_workList.isEmpty);
_workList.clear();
if (currentNode == null) {
- _findLeftMostDescendent(_map._root);
+ _findLeftMostDescendent(_tree._root);
} else {
- _map._splay(currentNode.key);
- _findLeftMostDescendent(_map._root.right);
+ _tree._splay(currentNode.key);
+ _findLeftMostDescendent(_tree._root.right);
assert(!_workList.isEmpty);
}
}
bool moveNext() {
- if (_modificationCount != _map._modificationCount) {
- throw new ConcurrentModificationError(_map);
+ if (_modificationCount != _tree._modificationCount) {
+ throw new ConcurrentModificationError(_tree);
}
// Picks the next element in the worklist as current.
// Updates the worklist with the left-most path of the current node's
@@ -422,7 +462,7 @@
_currentNode = null;
return false;
}
- if (_map._splayCount != _splayCount) {
+ if (_tree._splayCount != _splayCount) {
_rebuildWorkList(_currentNode);
}
_currentNode = _workList.removeLast();
@@ -430,34 +470,37 @@
return true;
}
- T _getValue(SplayTreeNode node);
+ T _getValue(_SplayTreeNode node);
}
-
-class _SplayTreeKeyIterable<K, V> extends Iterable<K> {
- SplayTreeMap<K, V> _map;
- _SplayTreeKeyIterable(this._map);
- Iterator<K> get iterator => new _SplayTreeKeyIterator<K, V>(_map);
+class _SplayTreeKeyIterable<K> extends Iterable<K> {
+ _SplayTree<K> _tree;
+ _SplayTreeKeyIterable(this._tree);
+ int get length => _tree._count;
+ bool get isEmpty => _tree._count == 0;
+ Iterator<K> get iterator => new _SplayTreeKeyIterator<K>(_tree);
}
class _SplayTreeValueIterable<K, V> extends Iterable<V> {
SplayTreeMap<K, V> _map;
- _SplayTreeValueIterable(this._map) ;
+ _SplayTreeValueIterable(this._map);
+ int get length => _map._count;
+ bool get isEmpty => _map._count == 0;
Iterator<V> get iterator => new _SplayTreeValueIterator<K, V>(_map);
}
-class _SplayTreeKeyIterator<K, V> extends _SplayTreeIterator<K> {
- _SplayTreeKeyIterator(SplayTreeMap<K, V> map): super(map);
- K _getValue(SplayTreeNode node) => node.key;
+class _SplayTreeKeyIterator<K> extends _SplayTreeIterator<K> {
+ _SplayTreeKeyIterator(_SplayTree<K> map): super(map);
+ K _getValue(_SplayTreeNode node) => node.key;
}
class _SplayTreeValueIterator<K, V> extends _SplayTreeIterator<V> {
_SplayTreeValueIterator(SplayTreeMap<K, V> map): super(map);
- V _getValue(SplayTreeNode node) => node.value;
+ V _getValue(_SplayTreeMapNode node) => node.value;
}
-class _SplayTreeNodeIterator<K, V>
- extends _SplayTreeIterator<SplayTreeNode<K, V>> {
- _SplayTreeNodeIterator(SplayTreeMap<K, V> map): super(map);
- SplayTreeNode<K, V> _getValue(SplayTreeNode node) => node;
+class _SplayTreeNodeIterator<K>
+ extends _SplayTreeIterator<_SplayTreeNode<K>> {
+ _SplayTreeNodeIterator(_SplayTree<K> map): super(map);
+ _SplayTreeNode<K> _getValue(_SplayTreeNode node) => node;
}
diff --git a/sdk/lib/core/core.dart b/sdk/lib/core/core.dart
index 016d6c0..7163244 100644
--- a/sdk/lib/core/core.dart
+++ b/sdk/lib/core/core.dart
@@ -32,6 +32,7 @@
part "print.dart";
part "regexp.dart";
part "set.dart";
+part "stacktrace.dart";
part "stopwatch.dart";
part "string.dart";
part "string_buffer.dart";
diff --git a/sdk/lib/core/corelib_sources.gypi b/sdk/lib/core/corelib_sources.gypi
index f85e349..e0e350b 100644
--- a/sdk/lib/core/corelib_sources.gypi
+++ b/sdk/lib/core/corelib_sources.gypi
@@ -4,6 +4,8 @@
{
'sources': [
+ 'core.dart',
+ # The above file needs to be first as it lists the parts below.
'bool.dart',
'collection.dart',
'comparable.dart',
@@ -29,6 +31,7 @@
'print.dart',
'regexp.dart',
'set.dart',
+ 'stacktrace.dart',
'stopwatch.dart',
'string.dart',
'string_buffer.dart',
diff --git a/sdk/lib/core/duration.dart b/sdk/lib/core/duration.dart
index 9e7cdd8..a0cf1b6 100644
--- a/sdk/lib/core/duration.dart
+++ b/sdk/lib/core/duration.dart
@@ -7,12 +7,23 @@
/**
* A [Duration] represents a time span. A duration can be negative.
*/
-class Duration implements Comparable {
+class Duration implements Comparable<Duration> {
+ static const int MICROSECONDS_PER_MILLISECOND = 1000;
static const int MILLISECONDS_PER_SECOND = 1000;
static const int SECONDS_PER_MINUTE = 60;
static const int MINUTES_PER_HOUR = 60;
static const int HOURS_PER_DAY = 24;
+ static const int MICROSECONDS_PER_SECOND =
+ MICROSECONDS_PER_MILLISECOND * MILLISECONDS_PER_SECOND;
+ static const int MICROSECONDS_PER_MINUTE =
+ MICROSECONDS_PER_SECOND * SECONDS_PER_MINUTE;
+ static const int MICROSECONDS_PER_HOUR =
+ MICROSECONDS_PER_MINUTE * MINUTES_PER_HOUR;
+ static const int MICROSECONDS_PER_DAY =
+ MICROSECONDS_PER_HOUR * HOURS_PER_DAY;
+
+
static const int MILLISECONDS_PER_MINUTE =
MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE;
static const int MILLISECONDS_PER_HOUR =
@@ -28,9 +39,9 @@
static const Duration ZERO = const Duration(seconds: 0);
/**
- * This [Duration] in milliseconds.
+ * This [Duration] in microseconds.
*/
- final int inMilliseconds;
+ final int _duration;
/**
* The duration is the sum of all individual parts. This means that individual
@@ -44,18 +55,20 @@
int hours: 0,
int minutes: 0,
int seconds: 0,
- int milliseconds: 0})
- : inMilliseconds = days * Duration.MILLISECONDS_PER_DAY +
- hours * Duration.MILLISECONDS_PER_HOUR +
- minutes * Duration.MILLISECONDS_PER_MINUTE +
- seconds * Duration.MILLISECONDS_PER_SECOND +
- milliseconds;
+ int milliseconds: 0,
+ int microseconds: 0})
+ : _duration = days * MICROSECONDS_PER_DAY +
+ hours * MICROSECONDS_PER_HOUR +
+ minutes * MICROSECONDS_PER_MINUTE +
+ seconds * MICROSECONDS_PER_SECOND +
+ milliseconds * MICROSECONDS_PER_MILLISECOND +
+ microseconds;
/**
* Returns the sum of this [Duration] and [other] as a new [Duration].
*/
Duration operator +(Duration other) {
- return new Duration(milliseconds: inMilliseconds + other.inMilliseconds);
+ return new Duration(microseconds: _duration + other._duration);
}
/**
@@ -63,7 +76,7 @@
* [Duration].
*/
Duration operator -(Duration other) {
- return new Duration(milliseconds: inMilliseconds - other.inMilliseconds);
+ return new Duration(microseconds: _duration - other._duration);
}
/**
@@ -71,7 +84,7 @@
* as a new [Duration].
*/
Duration operator *(int factor) {
- return new Duration(milliseconds: inMilliseconds * factor);
+ return new Duration(microseconds: _duration * factor);
}
/**
@@ -84,85 +97,87 @@
// By doing the check here instead of relying on "~/" below we get the
// exception even with dart2js.
if (quotient == 0) throw new IntegerDivisionByZeroException();
- return new Duration(milliseconds: inMilliseconds ~/ quotient);
+ return new Duration(microseconds: _duration ~/ quotient);
}
- bool operator <(Duration other) => this.inMilliseconds < other.inMilliseconds;
+ bool operator <(Duration other) => this._duration < other._duration;
- bool operator >(Duration other) => this.inMilliseconds > other.inMilliseconds;
+ bool operator >(Duration other) => this._duration > other._duration;
- bool operator <=(Duration other) =>
- this.inMilliseconds <= other.inMilliseconds;
+ bool operator <=(Duration other) => this._duration <= other._duration;
- bool operator >=(Duration other) =>
- this.inMilliseconds >= other.inMilliseconds;
+ bool operator >=(Duration other) => this._duration >= other._duration;
/**
* This [Duration] in days. Incomplete days are discarded
*/
- int get inDays {
- return inMilliseconds ~/ Duration.MILLISECONDS_PER_DAY;
- }
+ int get inDays => _duration ~/ Duration.MICROSECONDS_PER_DAY;
/**
* This [Duration] in hours. Incomplete hours are discarded.
+ *
* The returned value can be greater than 23.
*/
- int get inHours {
- return inMilliseconds ~/ Duration.MILLISECONDS_PER_HOUR;
- }
+ int get inHours => _duration ~/ Duration.MICROSECONDS_PER_HOUR;
/**
* This [Duration] in minutes. Incomplete minutes are discarded.
+ *
* The returned value can be greater than 59.
*/
- int get inMinutes {
- return inMilliseconds ~/ Duration.MILLISECONDS_PER_MINUTE;
- }
+ int get inMinutes => _duration ~/ Duration.MICROSECONDS_PER_MINUTE;
/**
* This [Duration] in seconds. Incomplete seconds are discarded.
+ *
* The returned value can be greater than 59.
*/
- int get inSeconds {
- return inMilliseconds ~/ Duration.MILLISECONDS_PER_SECOND;
- }
+ int get inSeconds => _duration ~/ Duration.MICROSECONDS_PER_SECOND;
+
+ /**
+ * This [Duration] in milliseconds. Incomplete milliseconds are discarded.
+ *
+ * The returned value can be greater than 999.
+ */
+ int get inMilliseconds => _duration ~/ Duration.MICROSECONDS_PER_MILLISECOND;
+
+ /**
+ * This [Duration] in microseconds.
+ */
+ int get inMicroseconds => _duration;
bool operator ==(other) {
if (other is !Duration) return false;
- return inMilliseconds == other.inMilliseconds;
+ return _duration == other._duration;
}
- int get hashCode {
- return inMilliseconds.hashCode;
- }
+ int get hashCode => _duration.hashCode;
- int compareTo(Duration other) {
- return inMilliseconds.compareTo(other.inMilliseconds);
- }
+ int compareTo(Duration other) => _duration.compareTo(other._duration);
String toString() {
- String threeDigits(int n) {
- if (n >= 100) return "$n";
- if (n > 10) return "0$n";
- return "00$n";
+ String sixDigits(int n) {
+ if (n >= 100000) return "$n";
+ if (n >= 10000) return "0$n";
+ if (n >= 1000) return "00$n";
+ if (n >= 100) return "000$n";
+ if (n > 10) return "0000$n";
+ return "00000$n";
}
String twoDigits(int n) {
if (n >= 10) return "$n";
return "0$n";
}
- if (inMilliseconds < 0) {
+ if (inMicroseconds < 0) {
Duration duration =
- new Duration(milliseconds: -inMilliseconds);
+ new Duration(microseconds: -inMicroseconds);
return "-$duration";
}
- String twoDigitMinutes =
- twoDigits(inMinutes.remainder(Duration.MINUTES_PER_HOUR));
- String twoDigitSeconds =
- twoDigits(inSeconds.remainder(Duration.SECONDS_PER_MINUTE));
- String threeDigitMs =
- threeDigits(inMilliseconds.remainder(Duration.MILLISECONDS_PER_SECOND));
- return "$inHours:$twoDigitMinutes:$twoDigitSeconds.$threeDigitMs";
+ String twoDigitMinutes = twoDigits(inMinutes.remainder(MINUTES_PER_HOUR));
+ String twoDigitSeconds = twoDigits(inSeconds.remainder(SECONDS_PER_MINUTE));
+ String sixDigitUs =
+ sixDigits(inMicroseconds.remainder(MICROSECONDS_PER_SECOND));
+ return "$inHours:$twoDigitMinutes:$twoDigitSeconds.$sixDigitUs";
}
}
diff --git a/sdk/lib/core/exceptions.dart b/sdk/lib/core/exceptions.dart
index 8ee78bc..800a652 100644
--- a/sdk/lib/core/exceptions.dart
+++ b/sdk/lib/core/exceptions.dart
@@ -53,16 +53,6 @@
String toString() => "FormatException: $message";
}
-/**
- * Deprecated. Replaced by [FormatException].
- */
-@deprecated
-class IllegalJSRegExpException extends FormatException {
- IllegalJSRegExpException(String pattern, String errmsg)
- : super("Illegal pattern: $pattern, $errmsg");
-}
-
-
class IntegerDivisionByZeroException implements Exception {
const IntegerDivisionByZeroException();
String toString() => "IntegerDivisionByZeroException";
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 618eeb8..c6e09a1 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -156,7 +156,8 @@
return false;
}
- List<E> toList() => new List<E>.from(this);
+ List<E> toList({ bool growable: true }) =>
+ new List<E>.from(this, growable: growable);
Set<E> toSet() => new Set<E>.from(this);
/**
@@ -430,7 +431,7 @@
/**
* An [Iterator] that allows moving backwards as well as forwards.
*/
-abstract class BiDirectionalIterator<T> extends Iterator<T> {
+abstract class BidirectionalIterator<T> extends Iterator<T> {
/**
* Move back to the previous element.
*
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index ecb5535..560f08f 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -5,35 +5,103 @@
part of dart.core;
/**
- * A [List] is an indexable collection with a length. It can be of
- * fixed size or extendable.
+ * A [List] is an indexable collection with a length.
+ *
+ * A `List` implementation can be choose not to support all methods
+ * of the `List` interface.
+ *
+ * The most common list types are:
+ * * Fixed length list. It is an error to use operations that can change
+ * the list's length.
+ * * Growable list. Full implementation of the interface.
+ * * Unmodifiable list. It is an error to use operations that can change
+ * the list's length, or that can change the values of the list.
+ * If an unmodifable list is backed by another modifiable data structure,
+ * the values read from it may still change over time.
+ *
+ * Example:
+ *
+ * var fixedLengthList = new List(5);
+ * fixedLengthList.length = 0; // throws.
+ * fixedLengthList.add(499); // throws
+ * fixedLengthList[0] = 87;
+ * var growableList = [1, 2];
+ * growableList.length = 0;
+ * growableList.add(499);
+ * growableList[0] = 87;
+ * var unmodifiableList = const [1, 2];
+ * unmodifiableList.length = 0; // throws.
+ * unmodifiableList.add(499); // throws
+ * unmodifiableList[0] = 87; // throws.
*/
abstract class List<E> implements Collection<E> {
/**
* Creates a list of the given [length].
*
- * The length of the returned list is not fixed.
+ * The list is a fixed-length list if [length] is provided, and an empty
+ * growable list if [length] is omitted.
*/
- external factory List([int length = 0]);
+ external factory List([int length]);
/**
- * Creates a fixed-sized list of the given [length] where each entry is
- * filled with [fill].
+ * Creates a fixed-length list of the given [length] where each entry
+ * contains [fill].
*/
- external factory List.fixedLength(int length, {E fill: null});
+ external factory List.filled(int length, E fill);
+
+ /**
+ * *Deprecated*: Use `new List(count)` instead.
+ */
+ factory List.fixedLength(int count, { E fill }) {
+ List<E> result = new List(count);
+ if (fill != null) {
+ for (int i = 0; i < count; i++) result[i] = fill;
+ }
+ return result;
+ }
/**
* Creates an list with the elements of [other]. The order in
* the list will be the order provided by the iterator of [other].
*
- * The length of the returned list is not fixed.
+ * The returned list is growable if [growable] is true, otherwise it's
+ * a fixed length list.
*/
- factory List.from(Iterable other) {
- var list = new List<E>();
+ factory List.from(Iterable other, { bool growable: true }) {
+ List<E> list = new List<E>();
for (E e in other) {
list.add(e);
}
- return list;
+ if (growable) return list;
+ int length = list.length;
+ List<E> fixedList = new List<E>(length);
+ for (int i = 0; i < length; i++) {
+ fixedList[i] = list[i];
+ }
+ return fixedList;
+ }
+
+ /**
+ * Generate a `List` of elements.
+ *
+ * Generates a list of values, where the values are created by
+ * calling the [generator] function for each index in the range
+ * 0 .. [length] - 1.
+ *
+ * The created length's length is fixed unless [growable] is true.
+ */
+ factory List.generate(int length, E generator(int index),
+ { bool growable: true }) {
+ List<E> result;
+ if (growable) {
+ result = <E>[]..length = length;
+ } else {
+ result = new List<E>(length);
+ }
+ for (int i = 0; i < length; i++) {
+ result[i] = generator(i);
+ }
+ return result;
}
/**
@@ -66,7 +134,10 @@
* Adds [value] at the end of the list, extending the length by
* one. Throws an [UnsupportedError] if the list is not
* extendable.
+ *
+ * *Deprecated*: Use [add] instead.
*/
+ @deprecated
void addLast(E value);
/**
@@ -186,4 +257,12 @@
* [start] is greater than the length of the list.
*/
void insertRange(int start, int length, [E fill]);
+
+ /**
+ * Returns an unmodifiable [Map] view of `this`.
+ *
+ * It has the indices of this list as keys, and the corresponding elements
+ * as values.
+ */
+ Map<int, E> asMap();
}
diff --git a/sdk/lib/core/regexp.dart b/sdk/lib/core/regexp.dart
index a85b0ff..c6db026 100644
--- a/sdk/lib/core/regexp.dart
+++ b/sdk/lib/core/regexp.dart
@@ -94,6 +94,8 @@
/**
* Constructs a regular expression. The default implementation of a
* [RegExp] sets [multiLine] to false and [caseSensitive] to true.
+ * Throws a [FormatException] if [pattern] is not a valid regular
+ * exression pattern.
*/
external factory RegExp(String pattern, {bool multiLine: false,
bool caseSensitive: true});
diff --git a/sdk/lib/core/stacktrace.dart b/sdk/lib/core/stacktrace.dart
new file mode 100644
index 0000000..a82a840
--- /dev/null
+++ b/sdk/lib/core/stacktrace.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.
+
+part of dart.core;
+
+/**
+ * An interface implemented by all stack trace objects.
+ *
+ * A [StackTrace] is intended to convey information to the user about the call
+ * sequence that triggered an exception.
+ *
+ * These objects are created by the runtime, it is not possible to create
+ * them programmatically.
+ */
+abstract class StackTrace {
+ // Returns a String object that contains the full stack trace starting from
+ // the point where an exception has ocurred to the entry function which is
+ // typically 'main'.
+ // 'toString()' on a stack trace object essentially invokes this getter.
+ external String get fullStackTrace;
+
+ // Returns a String object that contains a stack trace starting from the
+ // point where an exception has ocurred to the point where the exception
+ // is caught.
+ external String get stackTrace;
+}
+
diff --git a/sdk/lib/core/stopwatch.dart b/sdk/lib/core/stopwatch.dart
index 5564801..9afc50b 100644
--- a/sdk/lib/core/stopwatch.dart
+++ b/sdk/lib/core/stopwatch.dart
@@ -20,16 +20,19 @@
* Creates a [Stopwatch] in stopped state with a zero elapsed count.
*
* The following example shows how to start a [Stopwatch]
- * right after allocation.
+ * immediately after allocation.
*
* Stopwatch stopwatch = new Stopwatch()..start();
*/
Stopwatch() : _start = null, _stop = null {}
/**
- * Starts the [Stopwatch]. The [elapsed] count is increasing monotonically.
- * If the [Stopwatch] has been stopped, then calling start again restarts it
- * without resetting the [elapsed] count.
+ * Starts the [Stopwatch].
+ *
+ * The [elapsed] count is increasing monotonically. If the [Stopwatch] has
+ * been stopped, then calling start again restarts it without resetting the
+ * [elapsed] count.
+ *
* If the [Stopwatch] is currently running, then calling start does nothing.
*/
void start() {
@@ -46,9 +49,11 @@
}
/**
- * Stops the [Stopwatch]. The [elapsed] count stops increasing.
- * If the [Stopwatch] is currently not running, then calling stop does
- * nothing.
+ * Stops the [Stopwatch].
+ *
+ * The [elapsedTicks] count stops increasing after this call. If the
+ * [Stopwatch] is currently not running, then calling this method has no
+ * effect.
*/
void stop() {
if (!isRunning) return;
@@ -56,8 +61,9 @@
}
/**
- * Resets the [elapsed] count to zero. This method does not stop or start
- * the [Stopwatch].
+ * Resets the [elapsed] count to zero.
+ *
+ * This method does not stop or start the [Stopwatch].
*/
void reset() {
if (_start == null) return;
@@ -74,9 +80,12 @@
/**
* Returns the elapsed number of clock ticks since calling [start] while the
* [Stopwatch] is running.
+ *
* Returns the elapsed number of clock ticks between calling [start] and
* calling [stop].
+ *
* Returns 0 if the [Stopwatch] has never been started.
+ *
* The elapsed number of clock ticks increases by [frequency] every second.
*/
int get elapsedTicks {
@@ -87,6 +96,13 @@
}
/**
+ * Returns the [elapsedTicks] counter converted to a [Duration].
+ */
+ Duration get elapsed {
+ return new Duration(microseconds: elapsedMicroseconds);
+ }
+
+ /**
* Returns the [elapsedTicks] counter converted to microseconds.
*/
int get elapsedMicroseconds {
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index ba07bae..d780314 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -28,12 +28,6 @@
external factory String.fromCharCodes(Iterable<int> charCodes);
/**
- * *Deprecated*. Use [String.fromCharCode] instead.
- */
- @deprecated
- factory String.character(int charCode) => new String.fromCharCode(charCode);
-
- /**
* Allocates a new String for the specified [charCode].
*
* The new string contains a single code unit if the [charCode] can be
@@ -44,7 +38,7 @@
* one half of a surrogate pair.
*/
factory String.fromCharCode(int charCode) {
- List<int> charCodes = new List<int>.fixedLength(1, fill: charCode);
+ List<int> charCodes = new List<int>.filled(1, charCode);
return new String.fromCharCodes(charCodes);
}
@@ -54,17 +48,19 @@
* The returned string represents exactly one UTF-16 code unit which may be
* half of a surrogate pair. For example the Unicode character for a
* musical G-clef ("𝄞") with rune value 0x1D11E consists of a UTF-16 surrogate
- * pair: `"\uDBFF\uDFFD"`. Using the index-operator on this string yields
+ * pair: `0xD834` and `0xDD1E`. Using the index-operator on this string yields
* a String with half of a surrogate pair:
*
- * var clef = "\uDBFF\uDFFD";
+ * var clef = "\u{1D11E}";
* clef.length; // => 2
* clef.runes.first == 0x1D11E; // => true
* clef.runes.length; // => 1
+ * clef.codeUnitAt(0); // => 0xD834
+ * clef.codeUnitAt(1); // => 0xDD1E
* // The following strings are halves of a UTF-16 surrogate pair and
* // thus invalid UTF-16 strings:
- * clef[0]; // => "\uDBFF"
- * clef[1]; // => "\uDFFD"
+ * clef[0]; // => a string of length 1 with code-unit value 0xD834.
+ * clef[1]; // => a string of length 1 with code-unit value 0xDD1E.
*
* This method is equivalent to
* `new String.fromCharCode(this.codeUnitAt(index))`.
@@ -72,14 +68,6 @@
String operator [](int index);
/**
- * Gets the scalar character code at the given [index].
- *
- * *This method is deprecated. Please use [codeUnitAt] instead.*
- */
- @deprecated
- int charCodeAt(int index);
-
- /**
* Returns the 16-bit UTF-16 code unit at the given [index].
*/
int codeUnitAt(int index);
@@ -219,30 +207,17 @@
* are hence equivalent:
*
* string.split("")
- * string.codeUnits.map((unit) => new String.character(unit))
+ * string.codeUnits.map((unit) => new String.fromCharCode(unit))
*
* Unless it guaranteed that the string is in the basic multilingual plane
* (meaning that each code unit represents a rune) it is often better to
* map the runes instead:
*
- * string.runes.map((rune) => new String.character(rune))
+ * string.runes.map((rune) => new String.fromCharCode(rune))
*/
List<String> split(Pattern pattern);
/**
- * Returns a list of the individual code-units converted to strings.
- *
- * *Deprecated*
- * If you want to split on code-unit boundaries, use [split]. If you
- * want to split on rune boundaries, use [runes] and map the result.
- *
- * Iterable<String> characters =
- * string.runes.map((c) => new String.fromCharCode(c));
- */
- @deprecated
- List<String> splitChars();
-
- /**
* Splits the string on the [pattern], then converts each part and each match.
*
* The pattern is used to split the string into parts and separating matches.
@@ -260,18 +235,9 @@
String onNonMatch(String nonMatch)});
/**
- * Returns a list of UTF-16 code units of this string.
- *
- * *This getter is deprecated. Use [codeUnits] instead.*
+ * Returns an unmodifiable list of the UTF-16 code units of this string.
*/
- List<int> get charCodes;
-
- /**
- * Returns an iterable of the UTF-16 code units of this string.
- */
- // TODO(floitsch): should it return a list?
- // TODO(floitsch): make it a bidirectional iterator.
- Iterable<int> get codeUnits;
+ List<int> get codeUnits;
/**
* Returns an iterable of Unicode code-points of this string.
@@ -311,9 +277,9 @@
throw new StateError("No elements.");
}
int length = string.length;
- int code = string.charCodeAt(length - 1);
+ int code = string.codeUnitAt(length - 1);
if (_isTrailSurrogate(code) && string.length > 1) {
- int previousCode = string.charCodeAt(length - 2);
+ int previousCode = string.codeUnitAt(length - 2);
if (_isLeadSurrogate(previousCode)) {
return _combineSurrogatePair(previousCode, code);
}
@@ -335,7 +301,7 @@
}
/** [Iterator] for reading Unicode code points out of a Dart string. */
-class RuneIterator implements BiDirectionalIterator<int> {
+class RuneIterator implements BidirectionalIterator<int> {
/** String being iterated. */
final String string;
/** Position before the current code point. */
@@ -376,8 +342,8 @@
/** Throw an error if the index is in the middle of a surrogate pair. */
void _checkSplitSurrogate(int index) {
if (index > 0 && index < string.length &&
- _isLeadSurrogate(string.charCodeAt(index - 1)) &&
- _isTrailSurrogate(string.charCodeAt(index))) {
+ _isLeadSurrogate(string.codeUnitAt(index - 1)) &&
+ _isTrailSurrogate(string.codeUnitAt(index))) {
throw new ArgumentError("Index inside surrogate pair: $index");
}
}
@@ -455,10 +421,10 @@
_currentCodePoint = null;
return false;
}
- int codeUnit = string.charCodeAt(_position);
+ int codeUnit = string.codeUnitAt(_position);
int nextPosition = _position + 1;
if (_isLeadSurrogate(codeUnit) && nextPosition < string.length) {
- int nextCodeUnit = string.charCodeAt(nextPosition);
+ int nextCodeUnit = string.codeUnitAt(nextPosition);
if (_isTrailSurrogate(nextCodeUnit)) {
_nextPosition = nextPosition + 1;
_currentCodePoint = _combineSurrogatePair(codeUnit, nextCodeUnit);
@@ -477,9 +443,9 @@
return false;
}
int position = _position - 1;
- int codeUnit = string.charCodeAt(position);
+ int codeUnit = string.codeUnitAt(position);
if (_isTrailSurrogate(codeUnit) && position > 0) {
- int prevCodeUnit = string.charCodeAt(position - 1);
+ int prevCodeUnit = string.codeUnitAt(position - 1);
if (_isLeadSurrogate(prevCodeUnit)) {
_position = position - 1;
_currentCodePoint = _combineSurrogatePair(prevCodeUnit, codeUnit);
@@ -491,16 +457,3 @@
return true;
}
}
-
-/**
- * An [Iterable] of the UTF-16 code units of a [String] in index order.
- */
-class CodeUnits extends ListIterable<int> {
- /** The string that this is the code units of. */
- String string;
-
- CodeUnits(this.string);
-
- int get length => string.length;
- int elementAt(int i) => string.codeUnitAt(i);
-}
diff --git a/sdk/lib/crypto/crypto_sources.gypi b/sdk/lib/crypto/crypto_sources.gypi
index b5a934a..de6faf9 100644
--- a/sdk/lib/crypto/crypto_sources.gypi
+++ b/sdk/lib/crypto/crypto_sources.gypi
@@ -3,12 +3,10 @@
# BSD-style license that can be found in the LICENSE file.
# This file contains all sources for the dart:crypto library.
-#
-# TODO(ager): crypto_base.dart should be removed when the
-# VM can use the 'library' and 'part' directives for libraries.
-# At that point crypto.dart should be the only crypto library file.
{
'sources': [
+ 'crypto.dart',
+ # The above file needs to be first as it lists the parts below.
'crypto_base.dart',
'crypto_utils.dart',
'hash_utils.dart',
diff --git a/sdk/lib/crypto/hash_utils.dart b/sdk/lib/crypto/hash_utils.dart
index ed42140..d0b13cf 100644
--- a/sdk/lib/crypto/hash_utils.dart
+++ b/sdk/lib/crypto/hash_utils.dart
@@ -26,8 +26,8 @@
int this._digestSizeInWords,
bool this._bigEndianWords)
: _pendingData = [] {
- _currentChunk = new List.fixedLength(_chunkSizeInWords);
- _h = new List.fixedLength(_digestSizeInWords);
+ _currentChunk = new List(_chunkSizeInWords);
+ _h = new List(_digestSizeInWords);
}
// Update the hasher with more data.
@@ -97,7 +97,7 @@
// Convert a 32-bit word to four bytes.
_wordToBytes(int word) {
- List<int> bytes = new List.fixedLength(_BYTES_PER_WORD);
+ List<int> bytes = new List(_BYTES_PER_WORD);
bytes[0] = (word >> (_bigEndianWords ? 24 : 0)) & _MASK_8;
bytes[1] = (word >> (_bigEndianWords ? 16 : 8)) & _MASK_8;
bytes[2] = (word >> (_bigEndianWords ? 8 : 16)) & _MASK_8;
diff --git a/sdk/lib/crypto/hmac.dart b/sdk/lib/crypto/hmac.dart
index 2dd3902..794746d 100644
--- a/sdk/lib/crypto/hmac.dart
+++ b/sdk/lib/crypto/hmac.dart
@@ -26,7 +26,7 @@
// Zero-pad the key until its size is equal to the block size of the hash.
if (_key.length < blockSize) {
- var newKey = new List.fixedLength(blockSize);
+ var newKey = new List(blockSize);
newKey.setRange(0, _key.length, _key);
for (var i = _key.length; i < blockSize; i++) {
newKey[i] = 0;
@@ -35,7 +35,7 @@
}
// Compute inner padding.
- var padding = new List.fixedLength(blockSize);
+ var padding = new List(blockSize);
for (var i = 0; i < blockSize; i++) {
padding[i] = 0x36 ^ _key[i];
}
diff --git a/sdk/lib/crypto/sha1.dart b/sdk/lib/crypto/sha1.dart
index af3d354..83e9217 100644
--- a/sdk/lib/crypto/sha1.dart
+++ b/sdk/lib/crypto/sha1.dart
@@ -7,7 +7,7 @@
// The SHA1 hasher is used to compute an SHA1 message digest.
class _SHA1 extends _HashBase implements SHA1 {
// Construct a SHA1 hasher object.
- _SHA1() : _w = new List.fixedLength(80), super(16, 5, true) {
+ _SHA1() : _w = new List(80), super(16, 5, true) {
_h[0] = 0x67452301;
_h[1] = 0xEFCDAB89;
_h[2] = 0x98BADCFE;
diff --git a/sdk/lib/crypto/sha256.dart b/sdk/lib/crypto/sha256.dart
index 84dabf9..3df0ffd 100644
--- a/sdk/lib/crypto/sha256.dart
+++ b/sdk/lib/crypto/sha256.dart
@@ -7,7 +7,7 @@
// The SHA256 hasher is used to compute an SHA256 message digest.
class _SHA256 extends _HashBase implements SHA256 {
// Construct a SHA256 hasher object.
- _SHA256() : _w = new List.fixedLength(64), super(16, 8, true) {
+ _SHA256() : _w = new List(64), super(16, 8, true) {
// Initial value of the hash parts. First 32 bits of the fractional parts
// of the square roots of the first 8 prime numbers.
_h[0] = 0x6a09e667;
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 7cf2fcc..32c8ac9 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -1,3 +1,4 @@
+/// The Dart HTML library.
library dart.dom.html;
import 'dart:async';
@@ -21,7 +22,6 @@
// https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
// Auto-generated dart:html library.
-/// The Dart HTML library.
// Not actually used, but imported since dart:html can generate these objects.
@@ -1478,7 +1478,7 @@
'#.lineDashOffset || #.webkitLineDashOffset', this, this);
@DomName('CanvasRenderingContext2D.lineDashOffset')
- void set lineDashOffset(num value) => JS('void',
+ void set lineDashOffset(num value) => JS('void',
'typeof #.lineDashOffset != "undefined" ? #.lineDashOffset = # : '
'#.webkitLineDashOffset = #', this, this, value, this, value);
}
@@ -1622,7 +1622,7 @@
static Console safeConsole = new Console();
- bool get _isConsoleDefined => JS('bool', "typeof console != 'undefined'");
+ bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
@DomName('Console.memory')
MemoryInfo get memory => _isConsoleDefined ?
@@ -1712,6 +1712,10 @@
@DocsEditable
void clear(Object arg) native;
+ @DomName('Console.table')
+ @DocsEditable
+ void table(Object arg) native;
+
}
// 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
@@ -1810,8 +1814,14 @@
@DocsEditable
@DomName('Crypto')
+@SupportedBrowser(SupportedBrowser.CHROME)
+@SupportedBrowser(SupportedBrowser.SAFARI)
+@Experimental
class Crypto native "*Crypto" {
+ /// Checks if this type is supported on the current platform.
+ static bool get supported => JS('bool', '!!(window.crypto && window.crypto.getRandomValues)');
+
@DomName('Crypto.getRandomValues')
@DocsEditable
ArrayBufferView getRandomValues(ArrayBufferView array) native;
@@ -2377,11 +2387,14 @@
}
void setProperty(String propertyName, String value, [String priority]) {
- JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
- // Bug #2772, IE9 requires a poke to actually apply the value.
- if (JS('bool', '!!#.setAttribute', this)) {
- JS('void', '#.setAttribute(#, #)', this, propertyName, value);
- }
+ // try/catch for IE9 which throws on unsupported values.
+ try {
+ JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
+ // Bug #2772, IE9 requires a poke to actually apply the value.
+ if (JS('bool', '!!#.setAttribute', this)) {
+ JS('void', '#.setAttribute(#, #)', this, propertyName, value);
+ }
+ } catch (e) {}
}
/**
@@ -6322,13 +6335,13 @@
@DocsEditable
String cookie;
- WindowBase get window => _convertNativeToDart_Window(this._window);
+ WindowBase get window => _convertNativeToDart_Window(this._get_window);
@JSName('defaultView')
@DomName('Document.window')
@DocsEditable
@Creates('Window|=Object')
@Returns('Window|=Object')
- final dynamic _window;
+ final dynamic _get_window;
@DomName('Document.documentElement')
@DocsEditable
@@ -6842,7 +6855,7 @@
final mutableMatches = $dom_getElementsByName(
selectors.substring(7,selectors.length - 2));
int len = mutableMatches.length;
- final copyOfMatches = new List<Element>.fixedLength(len);
+ final copyOfMatches = new List<Element>(len);
for (int i = 0; i < len; ++i) {
copyOfMatches[i] = mutableMatches[i];
}
@@ -6850,7 +6863,7 @@
} else if (new RegExp("^[*a-zA-Z0-9]+\$").hasMatch(selectors)) {
final mutableMatches = $dom_getElementsByTagName(selectors);
int len = mutableMatches.length;
- final copyOfMatches = new List<Element>.fixedLength(len);
+ final copyOfMatches = new List<Element>(len);
for (int i = 0; i < len; ++i) {
copyOfMatches[i] = mutableMatches[i];
}
@@ -7140,7 +7153,9 @@
bool any(bool f(DomMimeType element)) => IterableMixinWorkaround.any(this, f);
- List<DomMimeType> toList() => new List<DomMimeType>.from(this);
+ List<DomMimeType> toList({ bool growable: true }) =>
+ new List<DomMimeType>.from(this, growable: growable);
+
Set<DomMimeType> toSet() => new Set<DomMimeType>.from(this);
bool get isEmpty => this.length == 0;
@@ -7394,7 +7409,9 @@
bool any(bool f(DomPlugin element)) => IterableMixinWorkaround.any(this, f);
- List<DomPlugin> toList() => new List<DomPlugin>.from(this);
+ List<DomPlugin> toList({ bool growable: true }) =>
+ new List<DomPlugin>.from(this, growable: growable);
+
Set<DomPlugin> toSet() => new Set<DomPlugin>.from(this);
bool get isEmpty => this.length == 0;
@@ -7755,7 +7772,9 @@
bool any(bool f(String element)) => IterableMixinWorkaround.any(this, f);
- List<String> toList() => new List<String>.from(this);
+ List<String> toList({ bool growable: true }) =>
+ new List<String>.from(this, growable: growable);
+
Set<String> toSet() => new Set<String>.from(this);
bool get isEmpty => this.length == 0;
@@ -7955,8 +7974,14 @@
: _childElements = element.$dom_children,
_element = element;
- List<Element> toList() {
- final output = new List<Element>.fixedLength(_childElements.length);
+ List<Element> toList({ bool growable: true }) {
+ List<Element> output;
+ if (growable) {
+ output = <Element>[];
+ output.length = _childElements.length;
+ } else {
+ output = new List<Element>(_childElements.length);
+ }
for (int i = 0, len = _childElements.length; i < len; i++) {
output[i] = _childElements[i];
}
@@ -8252,7 +8277,8 @@
return false;
}
- List<Element> toList() => new List<Element>.from(this);
+ List<Element> toList({ bool growable: true }) =>
+ new List<Element>.from(this, growable: growable);
Set<Element> toSet() => new Set<Element>.from(this);
Iterable<Element> take(int n) {
@@ -9155,6 +9181,11 @@
static const int ALLOW_KEYBOARD_INPUT = 1;
+ @JSName('attributes')
+ @DomName('Element.attributes')
+ @DocsEditable
+ final _NamedNodeMap $dom_attributes;
+
@JSName('childElementCount')
@DomName('Element.childElementCount')
@DocsEditable
@@ -10055,13 +10086,13 @@
@DocsEditable
final DataTransfer clipboardData;
- EventTarget get currentTarget => _convertNativeToDart_EventTarget(this._currentTarget);
+ EventTarget get currentTarget => _convertNativeToDart_EventTarget(this._get_currentTarget);
@JSName('currentTarget')
@DomName('Event.currentTarget')
@DocsEditable
@Creates('Null')
@Returns('EventTarget|=Object')
- final dynamic _currentTarget;
+ final dynamic _get_currentTarget;
@DomName('Event.defaultPrevented')
@DocsEditable
@@ -10075,13 +10106,13 @@
@DocsEditable
bool returnValue;
- EventTarget get target => _convertNativeToDart_EventTarget(this._target);
+ EventTarget get target => _convertNativeToDart_EventTarget(this._get_target);
@JSName('target')
@DomName('Event.target')
@DocsEditable
@Creates('Node')
@Returns('EventTarget|=Object')
- final dynamic _target;
+ final dynamic _get_target;
@DomName('Event.timeStamp')
@DocsEditable
@@ -10388,9 +10419,11 @@
@DomName('File')
class File extends Blob native "*File" {
+ DateTime get lastModifiedDate => _convertNativeToDart_DateTime(this._get_lastModifiedDate);
+ @JSName('lastModifiedDate')
@DomName('File.lastModifiedDate')
@DocsEditable
- final Date lastModifiedDate;
+ final dynamic _get_lastModifiedDate;
@DomName('File.name')
@DocsEditable
@@ -10586,7 +10619,9 @@
bool any(bool f(File element)) => IterableMixinWorkaround.any(this, f);
- List<File> toList() => new List<File>.from(this);
+ List<File> toList({ bool growable: true }) =>
+ new List<File>.from(this, growable: growable);
+
Set<File> toSet() => new Set<File>.from(this);
bool get isEmpty => this.length == 0;
@@ -11096,7 +11131,7 @@
@DomName('Float32Array.fromBuffer')
@DocsEditable
- factory Float32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+ factory Float32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createFloat32Array_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 4;
@@ -11143,7 +11178,9 @@
bool any(bool f(num element)) => IterableMixinWorkaround.any(this, f);
- List<num> toList() => new List<num>.from(this);
+ List<num> toList({ bool growable: true }) =>
+ new List<num>.from(this, growable: growable);
+
Set<num> toSet() => new Set<num>.from(this);
bool get isEmpty => this.length == 0;
@@ -11312,7 +11349,7 @@
@DomName('Float64Array.fromBuffer')
@DocsEditable
- factory Float64Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+ factory Float64Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createFloat64Array_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 8;
@@ -11359,7 +11396,9 @@
bool any(bool f(num element)) => IterableMixinWorkaround.any(this, f);
- List<num> toList() => new List<num>.from(this);
+ List<num> toList({ bool growable: true }) =>
+ new List<num>.from(this, growable: growable);
+
Set<num> toSet() => new Set<num>.from(this);
bool get isEmpty => this.length == 0;
@@ -11516,11 +11555,11 @@
@DomName('FocusEvent')
class FocusEvent extends UIEvent native "*FocusEvent" {
- EventTarget get relatedTarget => _convertNativeToDart_EventTarget(this._relatedTarget);
+ EventTarget get relatedTarget => _convertNativeToDart_EventTarget(this._get_relatedTarget);
@JSName('relatedTarget')
@DomName('FocusEvent.relatedTarget')
@DocsEditable
- final dynamic _relatedTarget;
+ final dynamic _get_relatedTarget;
}
// 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
@@ -11736,7 +11775,7 @@
@JSName('clearWatch')
@DomName('Geolocation.clearWatch')
@DocsEditable
- void $dom_clearWatch(int watchId) native;
+ void $dom_clearWatch(int watchID) native;
@JSName('getCurrentPosition')
@DomName('Geolocation.getCurrentPosition')
@@ -11904,13 +11943,13 @@
@DocsEditable
final int length;
- dynamic get state => _convertNativeToDart_SerializedScriptValue(this._state);
+ dynamic get state => _convertNativeToDart_SerializedScriptValue(this._get_state);
@JSName('state')
@DomName('History.state')
@DocsEditable
@annotation_Creates_SerializedScriptValue
@annotation_Returns_SerializedScriptValue
- final dynamic _state;
+ final dynamic _get_state;
@DomName('History.back')
@DocsEditable
@@ -11994,7 +12033,9 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
+
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -12201,7 +12242,9 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
+
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -12370,17 +12413,6 @@
document.$dom_body = value;
}
- /**
- * Registers a custom Element subclass as an available HTML tag.
- *
- * Not yet implemented.
- */
- @Experimental
- void register(String tagName, Type elementClass) {
- // TODO: tagName validation
- throw new Exception('Not yet implemented');
- }
-
@DomName('Document.caretRangeFromPoint')
Range caretRangeFromPoint(int x, int y) {
return document.$dom_caretRangeFromPoint(x, y);
@@ -13141,13 +13173,13 @@
@DocsEditable
factory IFrameElement() => document.$dom_createElement("iframe");
- WindowBase get contentWindow => _convertNativeToDart_Window(this._contentWindow);
+ WindowBase get contentWindow => _convertNativeToDart_Window(this._get_contentWindow);
@JSName('contentWindow')
@DomName('HTMLIFrameElement.contentWindow')
@DocsEditable
@Creates('Window|=Object')
@Returns('Window|=Object')
- final dynamic _contentWindow;
+ final dynamic _get_contentWindow;
@DomName('HTMLIFrameElement.height')
@DocsEditable
@@ -13284,7 +13316,6 @@
TelephoneInputElement,
EmailInputElement,
PasswordInputElement,
- DateTimeInputElement,
DateInputElement,
MonthInputElement,
WeekInputElement,
@@ -13487,9 +13518,18 @@
@DocsEditable
String value;
+ DateTime get valueAsDate => _convertNativeToDart_DateTime(this._get_valueAsDate);
+ @JSName('valueAsDate')
@DomName('HTMLInputElement.valueAsDate')
@DocsEditable
- Date valueAsDate;
+ final dynamic _get_valueAsDate;
+
+ void set valueAsDate(DateTime value) {
+ this._set_valueAsDate = _convertDartToNative_DateTime(value);
+ }
+ void set _set_valueAsDate(/*dynamic*/ value) {
+ JS("void", "#.valueAsDate = #", this, value);
+ }
@DomName('HTMLInputElement.valueAsNumber')
@DocsEditable
@@ -13832,32 +13872,6 @@
}
/**
- * A date and time (year, month, day, hour, minute, second, fraction of a
- * second) with the time zone set to UTC.
- *
- * Use [supported] to check if this is supported on the current platform.
- */
-@SupportedBrowser(SupportedBrowser.CHROME, '25')
-@Experimental
-abstract class DateTimeInputElement implements RangeInputElementBase {
- factory DateTimeInputElement() => new InputElement(type: 'datetime');
-
- @DomName('HTMLInputElement.valueAsDate')
- DateTime valueAsDate;
-
- @DomName('HTMLInputElement.readOnly')
- bool readOnly;
-
- @DomName('HTMLInputElement.required')
- bool required;
-
- /// Returns true if this input type is supported on the current platform.
- static bool get supported {
- return (new InputElement(type: 'datetime')).type == 'datetime';
- }
-}
-
-/**
* A date (year, month, day) with no time zone.
*
* Use [supported] to check if this is supported on the current platform.
@@ -14173,7 +14187,7 @@
@DomName('Int16Array.fromBuffer')
@DocsEditable
- factory Int16Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+ factory Int16Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createInt16Array_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 2;
@@ -14220,7 +14234,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -14389,7 +14405,7 @@
@DomName('Int32Array.fromBuffer')
@DocsEditable
- factory Int32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+ factory Int32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createInt32Array_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 4;
@@ -14436,7 +14452,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -14605,7 +14623,7 @@
@DomName('Int8Array.fromBuffer')
@DocsEditable
- factory Int8Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+ factory Int8Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createInt8Array_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 1;
@@ -14652,7 +14670,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -16263,13 +16283,13 @@
return event;
}
- dynamic get data => convertNativeToDart_SerializedScriptValue(this._data);
+ dynamic get data => convertNativeToDart_SerializedScriptValue(this._get_data);
@JSName('data')
@DomName('MessageEvent.data')
@DocsEditable
@annotation_Creates_SerializedScriptValue
@annotation_Returns_SerializedScriptValue
- final dynamic _data;
+ final dynamic _get_data;
@DomName('MessageEvent.lastEventId')
@DocsEditable
@@ -16284,13 +16304,13 @@
@Creates('=List')
final List ports;
- WindowBase get source => _convertNativeToDart_Window(this._source);
+ WindowBase get source => _convertNativeToDart_Window(this._get_source);
@JSName('source')
@DomName('MessageEvent.source')
@DocsEditable
@Creates('Window|=Object')
@Returns('Window|=Object')
- final dynamic _source;
+ final dynamic _get_source;
@JSName('initMessageEvent')
@DomName('MessageEvent.initMessageEvent')
@@ -16388,9 +16408,11 @@
@DomName('Metadata')
class Metadata native "*Metadata" {
+ DateTime get modificationTime => _convertNativeToDart_DateTime(this._get_modificationTime);
+ @JSName('modificationTime')
@DomName('Metadata.modificationTime')
@DocsEditable
- final Date modificationTime;
+ final dynamic _get_modificationTime;
@DomName('Metadata.size')
@DocsEditable
@@ -16525,13 +16547,13 @@
@DocsEditable
final bool metaKey;
- EventTarget get relatedTarget => _convertNativeToDart_EventTarget(this._relatedTarget);
+ EventTarget get relatedTarget => _convertNativeToDart_EventTarget(this._get_relatedTarget);
@JSName('relatedTarget')
@DomName('MouseEvent.relatedTarget')
@DocsEditable
@Creates('Node')
@Returns('EventTarget|=Object')
- final dynamic _relatedTarget;
+ final dynamic _get_relatedTarget;
@DomName('MouseEvent.screenX')
@DocsEditable
@@ -17074,7 +17096,13 @@
void addAll(Iterable<Node> iterable) {
if (iterable is _ChildNodeListLazy) {
- iterable = new List.from(iterable);
+ if (iterable._this != _this) {
+ // Optimized route for copying between nodes.
+ for (var i = 0, len = iterable.length; i < len; ++i) {
+ _this.$dom_appendChild(iterable[0]);
+ }
+ }
+ return;
}
for (Node node in iterable) {
_this.$dom_appendChild(node);
@@ -17161,7 +17189,8 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -17290,11 +17319,6 @@
}
- @JSName('attributes')
- @DomName('Node.attributes')
- @DocsEditable
- final _NamedNodeMap $dom_attributes;
-
@JSName('childNodes')
@DomName('Node.childNodes')
@DocsEditable
@@ -17550,7 +17574,9 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
+
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -18196,10 +18222,18 @@
@DomName('PagePopupController')
class PagePopupController native "*PagePopupController" {
+ @DomName('PagePopupController.closePopup')
+ @DocsEditable
+ void closePopup() native;
+
@DomName('PagePopupController.formatMonth')
@DocsEditable
String formatMonth(int year, int zeroBaseMonth) native;
+ @DomName('PagePopupController.formatShortMonth')
+ @DocsEditable
+ String formatShortMonth(int year, int zeroBaseMonth) native;
+
@DomName('PagePopupController.histogramEnumeration')
@DocsEditable
void histogramEnumeration(String name, int sample, int boundaryValue) native;
@@ -18208,6 +18242,10 @@
@DocsEditable
String localizeNumberString(String numberString) native;
+ @DomName('PagePopupController.setValue')
+ @DocsEditable
+ void setValue(String value) native;
+
@DomName('PagePopupController.setValueAndClosePopup')
@DocsEditable
void setValueAndClosePopup(int numberValue, String stringValue) native;
@@ -18421,13 +18459,13 @@
@SupportedBrowser(SupportedBrowser.SAFARI)
class PopStateEvent extends Event native "*PopStateEvent" {
- dynamic get state => convertNativeToDart_SerializedScriptValue(this._state);
+ dynamic get state => convertNativeToDart_SerializedScriptValue(this._get_state);
@JSName('state')
@DomName('PopStateEvent.state')
@DocsEditable
@annotation_Creates_SerializedScriptValue
@annotation_Returns_SerializedScriptValue
- final dynamic _state;
+ final dynamic _get_state;
}
// 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
@@ -19012,17 +19050,17 @@
}
/**
- * Checks if Real Time Communication (RTC) APIs are supported and enabled on
+ * Checks if Real Time Communication (RTC) APIs are supported and enabled on
* the current platform.
*/
static bool get supported {
// Currently in Firefox some of the RTC elements are defined but throw an
- // error unless the user has specifically enabled them in their
+ // error unless the user has specifically enabled them in their
// about:config. So we have to construct an element to actually test if RTC
// is supported at at the given time.
try {
var c = new RtcPeerConnection({"iceServers": [ {"url":"stun:foo.com"}]});
- return c is RtcPeerConnection;
+ return c is RtcPeerConnection;
} catch (_) {}
return false;
}
@@ -19309,9 +19347,11 @@
@DomName('RTCStatsElement')
class RtcStatsElement native "*RTCStatsElement" {
+ DateTime get timestamp => _convertNativeToDart_DateTime(this._get_timestamp);
+ @JSName('timestamp')
@DomName('RTCStatsElement.timestamp')
@DocsEditable
- final Date timestamp;
+ final dynamic _get_timestamp;
@DomName('RTCStatsElement.names')
@DocsEditable
@@ -19888,7 +19928,9 @@
bool any(bool f(SourceBuffer element)) => IterableMixinWorkaround.any(this, f);
- List<SourceBuffer> toList() => new List<SourceBuffer>.from(this);
+ List<SourceBuffer> toList({ bool growable: true }) =>
+ new List<SourceBuffer>.from(this, growable: growable);
+
Set<SourceBuffer> toSet() => new Set<SourceBuffer>.from(this);
bool get isEmpty => this.length == 0;
@@ -20168,7 +20210,9 @@
bool any(bool f(SpeechGrammar element)) => IterableMixinWorkaround.any(this, f);
- List<SpeechGrammar> toList() => new List<SpeechGrammar>.from(this);
+ List<SpeechGrammar> toList({ bool growable: true }) =>
+ new List<SpeechGrammar>.from(this, growable: growable);
+
Set<SpeechGrammar> toSet() => new Set<SpeechGrammar>.from(this);
bool get isEmpty => this.length == 0;
@@ -20951,14 +20995,46 @@
@DocsEditable
int span;
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+@DocsEditable
@DomName('HTMLTableElement')
class TableElement extends Element native "*HTMLTableElement" {
+ @DomName('HTMLTableElement.tBodies')
+ List<TableSectionElement> get tBodies =>
+ new _WrappedList<TableSectionElement>($dom_tBodies);
+
+ @DomName('HTMLTableElement.rows')
+ List<TableRowElement> get rows =>
+ new _WrappedList<TableRowElement>($dom_rows);
+
+ TableRowElement addRow() {
+ return insertRow(-1);
+ }
+
+ TableCaptionElement createCaption() => $dom_createCaption();
+ TableSectionElement createTBody() => $dom_createTBody();
+ TableSectionElement createTFoot() => $dom_createTFoot();
+ TableSectionElement createTHead() => $dom_createTHead();
+ TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+ TableSectionElement $dom_createTBody() {
+ if (JS('bool', '!!#.createTBody', this)) {
+ return this._createTBody();
+ }
+ var tbody = new Element.tag('tbody');
+ this.children.add(tbody);
+ return tbody;
+ }
+
+ @JSName('createTBody')
+ TableSectionElement _createTBody() native;
+
+
@DomName('HTMLTableElement.HTMLTableElement')
@DocsEditable
factory TableElement() => document.$dom_createElement("table");
@@ -20971,13 +21047,15 @@
@DocsEditable
TableCaptionElement caption;
+ @JSName('rows')
@DomName('HTMLTableElement.rows')
@DocsEditable
- final HtmlCollection rows;
+ final HtmlCollection $dom_rows;
+ @JSName('tBodies')
@DomName('HTMLTableElement.tBodies')
@DocsEditable
- final HtmlCollection tBodies;
+ final HtmlCollection $dom_tBodies;
@DomName('HTMLTableElement.tFoot')
@DocsEditable
@@ -20987,17 +21065,20 @@
@DocsEditable
TableSectionElement tHead;
+ @JSName('createCaption')
@DomName('HTMLTableElement.createCaption')
@DocsEditable
- Element createCaption() native;
+ Element $dom_createCaption() native;
+ @JSName('createTFoot')
@DomName('HTMLTableElement.createTFoot')
@DocsEditable
- Element createTFoot() native;
+ Element $dom_createTFoot() native;
+ @JSName('createTHead')
@DomName('HTMLTableElement.createTHead')
@DocsEditable
- Element createTHead() native;
+ Element $dom_createTHead() native;
@DomName('HTMLTableElement.deleteCaption')
@DocsEditable
@@ -21015,24 +21096,12 @@
@DocsEditable
void deleteTHead() native;
+ @JSName('insertRow')
@DomName('HTMLTableElement.insertRow')
@DocsEditable
- Element insertRow(int index) native;
-
-
- Element createTBody() {
- if (JS('bool', '!!#.createTBody', this)) {
- return this._createTBody();
- }
- var tbody = new Element.tag('tbody');
- this.children.add(tbody);
- return tbody;
- }
-
- @JSName('createTBody')
- Element _createTBody() native;
+ Element $dom_insertRow(int index) native;
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -21041,13 +21110,25 @@
@DomName('HTMLTableRowElement')
class TableRowElement extends Element native "*HTMLTableRowElement" {
+ @DomName('HTMLTableRowElement.cells')
+ List<TableCellElement> get cells =>
+ new _WrappedList<TableCellElement>($dom_cells);
+
+ TableCellElement addCell() {
+ return insertCell(-1);
+ }
+
+ TableCellElement insertCell(int index) => $dom_insertCell(index);
+
+
@DomName('HTMLTableRowElement.HTMLTableRowElement')
@DocsEditable
factory TableRowElement() => document.$dom_createElement("tr");
+ @JSName('cells')
@DomName('HTMLTableRowElement.cells')
@DocsEditable
- final HtmlCollection cells;
+ final HtmlCollection $dom_cells;
@DomName('HTMLTableRowElement.rowIndex')
@DocsEditable
@@ -21061,11 +21142,12 @@
@DocsEditable
void deleteCell(int index) native;
+ @JSName('insertCell')
@DomName('HTMLTableRowElement.insertCell')
@DocsEditable
- Element insertCell(int index) native;
+ Element $dom_insertCell(int index) native;
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -21075,16 +21157,29 @@
class TableSectionElement extends Element native "*HTMLTableSectionElement" {
@DomName('HTMLTableSectionElement.rows')
+ List<TableRowElement> get rows =>
+ new _WrappedList<TableRowElement>($dom_rows);
+
+ TableRowElement addRow() {
+ return insertRow(-1);
+ }
+
+ TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+
+ @JSName('rows')
+ @DomName('HTMLTableSectionElement.rows')
@DocsEditable
- final HtmlCollection rows;
+ final HtmlCollection $dom_rows;
@DomName('HTMLTableSectionElement.deleteRow')
@DocsEditable
void deleteRow(int index) native;
+ @JSName('insertRow')
@DomName('HTMLTableSectionElement.insertRow')
@DocsEditable
- Element insertRow(int index) native;
+ Element $dom_insertRow(int index) native;
}
// 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
@@ -21495,7 +21590,9 @@
bool any(bool f(TextTrackCue element)) => IterableMixinWorkaround.any(this, f);
- List<TextTrackCue> toList() => new List<TextTrackCue>.from(this);
+ List<TextTrackCue> toList({ bool growable: true }) =>
+ new List<TextTrackCue>.from(this, growable: growable);
+
Set<TextTrackCue> toSet() => new Set<TextTrackCue>.from(this);
bool get isEmpty => this.length == 0;
@@ -21700,7 +21797,9 @@
bool any(bool f(TextTrack element)) => IterableMixinWorkaround.any(this, f);
- List<TextTrack> toList() => new List<TextTrack>.from(this);
+ List<TextTrack> toList({ bool growable: true }) =>
+ new List<TextTrack>.from(this, growable: growable);
+
Set<TextTrack> toSet() => new Set<TextTrack>.from(this);
bool get isEmpty => this.length == 0;
@@ -21940,13 +22039,13 @@
@DocsEditable
final int screenY;
- EventTarget get target => _convertNativeToDart_EventTarget(this._target);
+ EventTarget get target => _convertNativeToDart_EventTarget(this._get_target);
@JSName('target')
@DomName('Touch.target')
@DocsEditable
@Creates('Element|Document')
@Returns('Element|Document')
- final dynamic _target;
+ final dynamic _get_target;
@JSName('webkitForce')
@DomName('Touch.webkitForce')
@@ -22112,7 +22211,9 @@
bool any(bool f(Touch element)) => IterableMixinWorkaround.any(this, f);
- List<Touch> toList() => new List<Touch>.from(this);
+ List<Touch> toList({ bool growable: true }) =>
+ new List<Touch>.from(this, growable: growable);
+
Set<Touch> toSet() => new Set<Touch>.from(this);
bool get isEmpty => this.length == 0;
@@ -22459,13 +22560,13 @@
@DocsEditable
final int pageY;
- WindowBase get view => _convertNativeToDart_Window(this._view);
+ WindowBase get view => _convertNativeToDart_Window(this._get_view);
@JSName('view')
@DomName('UIEvent.view')
@DocsEditable
@Creates('Window|=Object')
@Returns('Window|=Object')
- final dynamic _view;
+ final dynamic _get_view;
@DomName('UIEvent.which')
@DocsEditable
@@ -22511,7 +22612,7 @@
@DomName('Uint16Array.fromBuffer')
@DocsEditable
- factory Uint16Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+ factory Uint16Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createUint16Array_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 2;
@@ -22558,7 +22659,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -22727,7 +22830,7 @@
@DomName('Uint32Array.fromBuffer')
@DocsEditable
- factory Uint32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+ factory Uint32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createUint32Array_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 4;
@@ -22774,7 +22877,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -22943,7 +23048,7 @@
@DomName('Uint8Array.fromBuffer')
@DocsEditable
- factory Uint8Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+ factory Uint8Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createUint8Array_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 1;
@@ -22990,7 +23095,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -23159,7 +23266,7 @@
@DomName('Uint8ClampedArray.fromBuffer')
@DocsEditable
- factory Uint8ClampedArray.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+ factory Uint8ClampedArray.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createUint8ClampedArray_fromBuffer(buffer, byteOffset, length);
// Use implementation from Uint8Array.
@@ -23203,7 +23310,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -24573,6 +24682,8 @@
@DomName('WebGLRenderingContext.getParameter')
@DocsEditable
+ @Creates('Null|num|String|bool|=List|Float32Array|Int32Array|Uint32Array|WebGLFramebuffer|WebGLRenderbuffer|WebGLTexture')
+ @Returns('Null|num|String|bool|=List|Float32Array|Int32Array|Uint32Array|WebGLFramebuffer|WebGLRenderbuffer|WebGLTexture')
Object getParameter(int pname) native;
@DomName('WebGLRenderingContext.getProgramInfoLog')
@@ -25516,8 +25627,11 @@
* registered under [name].
*/
SendPortSync lookupPort(String name) {
- var port =
- json.parse(document.documentElement.attributes['dart-port:$name']);
+ var portStr = document.documentElement.attributes['dart-port:$name'];
+ if (portStr == null) {
+ return null;
+ }
+ var port = json.parse(portStr);
return _deserialize(port);
}
@@ -25844,13 +25958,13 @@
@DocsEditable
final bool offscreenBuffering;
- WindowBase get opener => _convertNativeToDart_Window(this._opener);
+ WindowBase get opener => _convertNativeToDart_Window(this._get_opener);
@JSName('opener')
@DomName('DOMWindow.opener')
@DocsEditable
@Creates('Window|=Object')
@Returns('Window|=Object')
- final dynamic _opener;
+ final dynamic _get_opener;
@DomName('DOMWindow.outerHeight')
@DocsEditable
@@ -25872,13 +25986,13 @@
@DocsEditable
final int pageYOffset;
- WindowBase get parent => _convertNativeToDart_Window(this._parent);
+ WindowBase get parent => _convertNativeToDart_Window(this._get_parent);
@JSName('parent')
@DomName('DOMWindow.parent')
@DocsEditable
@Creates('Window|=Object')
@Returns('Window|=Object')
- final dynamic _parent;
+ final dynamic _get_parent;
@DomName('DOMWindow.performance')
@DocsEditable
@@ -25923,13 +26037,13 @@
@DocsEditable
final BarInfo scrollbars;
- WindowBase get self => _convertNativeToDart_Window(this._self);
+ WindowBase get self => _convertNativeToDart_Window(this._get_self);
@JSName('self')
@DomName('DOMWindow.self')
@DocsEditable
@Creates('Window|=Object')
@Returns('Window|=Object')
- final dynamic _self;
+ final dynamic _get_self;
@DomName('DOMWindow.sessionStorage')
@DocsEditable
@@ -25951,13 +26065,13 @@
@DocsEditable
final BarInfo toolbar;
- WindowBase get top => _convertNativeToDart_Window(this._top);
+ WindowBase get top => _convertNativeToDart_Window(this._get_top);
@JSName('top')
@DomName('DOMWindow.top')
@DocsEditable
@Creates('Window|=Object')
@Returns('Window|=Object')
- final dynamic _top;
+ final dynamic _get_top;
@JSName('webkitNotifications')
@DomName('DOMWindow.webkitNotifications')
@@ -25975,13 +26089,13 @@
@Experimental
final StorageInfo storageInfo;
- WindowBase get window => _convertNativeToDart_Window(this._window);
+ WindowBase get window => _convertNativeToDart_Window(this._get_window);
@JSName('window')
@DomName('DOMWindow.window')
@DocsEditable
@Creates('Window|=Object')
@Returns('Window|=Object')
- final dynamic _window;
+ final dynamic _get_window;
@JSName('addEventListener')
@DomName('DOMWindow.addEventListener')
@@ -26070,26 +26184,23 @@
@DomName('DOMWindow.postMessage')
@DocsEditable
void postMessage(/*SerializedScriptValue*/ message, String targetOrigin, [List messagePorts]) {
- if (?message && !?messagePorts) {
+ if (?messagePorts) {
var message_1 = convertDartToNative_SerializedScriptValue(message);
- _postMessage_1(message_1, targetOrigin);
+ _postMessage_1(message_1, targetOrigin, messagePorts);
return;
}
- if (?message) {
- var message_2 = convertDartToNative_SerializedScriptValue(message);
- _postMessage_2(message_2, targetOrigin, messagePorts);
- return;
- }
- throw new ArgumentError("Incorrect number or type of arguments");
+ var message_2 = convertDartToNative_SerializedScriptValue(message);
+ _postMessage_2(message_2, targetOrigin);
+ return;
}
@JSName('postMessage')
@DomName('DOMWindow.postMessage')
@DocsEditable
- void _postMessage_1(message, targetOrigin) native;
+ void _postMessage_1(message, targetOrigin, List messagePorts) native;
@JSName('postMessage')
@DomName('DOMWindow.postMessage')
@DocsEditable
- void _postMessage_2(message, targetOrigin, List messagePorts) native;
+ void _postMessage_2(message, targetOrigin) native;
@DomName('DOMWindow.print')
@DocsEditable
@@ -26925,7 +27036,9 @@
bool any(bool f(ClientRect element)) => IterableMixinWorkaround.any(this, f);
- List<ClientRect> toList() => new List<ClientRect>.from(this);
+ List<ClientRect> toList({ bool growable: true }) =>
+ new List<ClientRect>.from(this, growable: growable);
+
Set<ClientRect> toSet() => new Set<ClientRect>.from(this);
bool get isEmpty => this.length == 0;
@@ -27122,7 +27235,9 @@
bool any(bool f(CssRule element)) => IterableMixinWorkaround.any(this, f);
- List<CssRule> toList() => new List<CssRule>.from(this);
+ List<CssRule> toList({ bool growable: true }) =>
+ new List<CssRule>.from(this, growable: growable);
+
Set<CssRule> toSet() => new Set<CssRule>.from(this);
bool get isEmpty => this.length == 0;
@@ -27319,7 +27434,9 @@
bool any(bool f(CssValue element)) => IterableMixinWorkaround.any(this, f);
- List<CssValue> toList() => new List<CssValue>.from(this);
+ List<CssValue> toList({ bool growable: true }) =>
+ new List<CssValue>.from(this, growable: growable);
+
Set<CssValue> toSet() => new Set<CssValue>.from(this);
bool get isEmpty => this.length == 0;
@@ -27516,7 +27633,9 @@
bool any(bool f(Entry element)) => IterableMixinWorkaround.any(this, f);
- List<Entry> toList() => new List<Entry>.from(this);
+ List<Entry> toList({ bool growable: true }) =>
+ new List<Entry>.from(this, growable: growable);
+
Set<Entry> toSet() => new Set<Entry>.from(this);
bool get isEmpty => this.length == 0;
@@ -27713,7 +27832,9 @@
bool any(bool f(EntrySync element)) => IterableMixinWorkaround.any(this, f);
- List<EntrySync> toList() => new List<EntrySync>.from(this);
+ List<EntrySync> toList({ bool growable: true }) =>
+ new List<EntrySync>.from(this, growable: growable);
+
Set<EntrySync> toSet() => new Set<EntrySync>.from(this);
bool get isEmpty => this.length == 0;
@@ -27910,7 +28031,9 @@
bool any(bool f(Gamepad element)) => IterableMixinWorkaround.any(this, f);
- List<Gamepad> toList() => new List<Gamepad>.from(this);
+ List<Gamepad> toList({ bool growable: true }) =>
+ new List<Gamepad>.from(this, growable: growable);
+
Set<Gamepad> toSet() => new Set<Gamepad>.from(this);
bool get isEmpty => this.length == 0;
@@ -28170,7 +28293,9 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
+
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -28391,7 +28516,9 @@
bool any(bool f(SpeechInputResult element)) => IterableMixinWorkaround.any(this, f);
- List<SpeechInputResult> toList() => new List<SpeechInputResult>.from(this);
+ List<SpeechInputResult> toList({ bool growable: true }) =>
+ new List<SpeechInputResult>.from(this, growable: growable);
+
Set<SpeechInputResult> toSet() => new Set<SpeechInputResult>.from(this);
bool get isEmpty => this.length == 0;
@@ -28588,7 +28715,9 @@
bool any(bool f(SpeechRecognitionResult element)) => IterableMixinWorkaround.any(this, f);
- List<SpeechRecognitionResult> toList() => new List<SpeechRecognitionResult>.from(this);
+ List<SpeechRecognitionResult> toList({ bool growable: true }) =>
+ new List<SpeechRecognitionResult>.from(this, growable: growable);
+
Set<SpeechRecognitionResult> toSet() => new Set<SpeechRecognitionResult>.from(this);
bool get isEmpty => this.length == 0;
@@ -28785,7 +28914,9 @@
bool any(bool f(StyleSheet element)) => IterableMixinWorkaround.any(this, f);
- List<StyleSheet> toList() => new List<StyleSheet>.from(this);
+ List<StyleSheet> toList({ bool growable: true }) =>
+ new List<StyleSheet>.from(this, growable: growable);
+
Set<StyleSheet> toSet() => new Set<StyleSheet>.from(this);
bool get isEmpty => this.length == 0;
@@ -29415,7 +29546,8 @@
String get first => readClasses().first;
String get last => readClasses().last;
String get single => readClasses().single;
- List<String> toList() => readClasses().toList();
+ List<String> toList({ bool growable: true }) =>
+ readClasses().toList(growable: growable);
Set<String> toSet() => readClasses().toSet();
String min([int compare(String a, String b)]) =>
readClasses().min(compare);
@@ -29714,7 +29846,7 @@
EventTarget _target;
// The distance to shift from upper case alphabet Roman letters to lower case.
- final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0];
+ final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
StreamSubscription _keyUpSubscription, _keyDownSubscription,
_keyPressSubscription;
@@ -29849,8 +29981,8 @@
if (prevEvent._shadowCharCode == event.charCode) {
return prevEvent.keyCode;
}
- if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".charCodes[0]
- && event.charCode <= "Z".charCodes[0] && event.charCode +
+ if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".codeUnits[0]
+ && event.charCode <= "Z".codeUnits[0] && event.charCode +
_ROMAN_ALPHABET_OFFSET == prevEvent._shadowCharCode) {
return prevEvent.keyCode;
}
@@ -30093,9 +30225,9 @@
/**
- * Defines the keycode values for keys that are returned by
+ * Defines the keycode values for keys that are returned by
* KeyboardEvent.keyCode.
- *
+ *
* Important note: There is substantial divergence in how different browsers
* handle keycodes and their variants in different locales/keyboard layouts. We
* provide these constants to help make code processing keys more readable.
@@ -30103,7 +30235,7 @@
abstract class KeyCode {
// These constant names were borrowed from Closure's Keycode enumeration
// class.
- // http://closure-library.googlecode.com/svn/docs/closure_goog_events_keycodes.js.source.html
+ // http://closure-library.googlecode.com/svn/docs/closure_goog_events_keycodes.js.source.html
static const int WIN_KEY_FF_LINUX = 0;
static const int MAC_ENTER = 3;
static const int BACKSPACE = 8;
@@ -30298,12 +30430,12 @@
(keyCode >= A && keyCode <= Z)) {
return true;
}
-
+
// Safari sends zero key code for non-latin characters.
if (_Device.isWebKit && keyCode == 0) {
return true;
}
-
+
return (keyCode == SPACE || keyCode == QUESTION_MARK || keyCode == NUM_PLUS
|| keyCode == NUM_MINUS || keyCode == NUM_PERIOD ||
keyCode == NUM_DIVISION || keyCode == SEMICOLON ||
@@ -31410,7 +31542,7 @@
_serializeList(List list) {
int len = list.length;
- var result = new List.fixedLength(len);
+ var result = new List(len);
for (int i = 0; i < len; i++) {
result[i] = _dispatch(list[i]);
}
@@ -31490,6 +31622,147 @@
}
}
+// 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 list which just wraps another list, for either intercepting list calls or
+ * retyping the list (for example, from List<A> to List<B> where B extends A).
+ */
+class _WrappedList<E> implements List<E> {
+ final List _list;
+
+ _WrappedList(this._list);
+
+ // Iterable APIs
+
+ Iterator<E> get iterator => new _WrappedIterator(_list.iterator);
+
+ Iterable map(f(E element)) => _list.map(f);
+
+ Iterable<E> where(bool f(E element)) => _list.where(f);
+
+ Iterable expand(Iterable f(E element)) => _list.expand(f);
+
+ bool contains(E element) => _list.contains(element);
+
+ void forEach(void f(E element)) { _list.forEach(f); }
+
+ dynamic reduce(initialValue, combine(previousValue, E element)) =>
+ _list.reduce(initialValue, combine);
+
+ bool every(bool f(E element)) => _list.every(f);
+
+ String join([String separator]) => _list.join(separator);
+
+ bool any(bool f(E element)) => _list.any(f);
+
+ List<E> toList({ bool growable: true }) =>
+ new List.from(_list, growable: growable);
+
+ Set<E> toSet() => _list.toSet();
+
+ int get length => _list.length;
+
+ E min([int compare(E a, E b)]) => _list.min(compare);
+
+ E max([int compare(E a, E b)]) => _list.max(compare);
+
+ bool get isEmpty => _list.isEmpty;
+
+ Iterable<E> take(int n) => _list.take(n);
+
+ Iterable<E> takeWhile(bool test(E value)) => _list.takeWhile(test);
+
+ Iterable<E> skip(int n) => _list.skip(n);
+
+ Iterable<E> skipWhile(bool test(E value)) => _list.skipWhile(test);
+
+ E get first => _list.first;
+
+ E get last => _list.last;
+
+ E get single => _list.single;
+
+ E firstMatching(bool test(E value), { E orElse() }) =>
+ _list.firstMatching(test, orElse: orElse);
+
+ E lastMatching(bool test(E value), {E orElse()}) =>
+ _list.lastMatching(test, orElse: orElse);
+
+ E singleMatching(bool test(E value)) => _list.singleMatching(test);
+
+ E elementAt(int index) => _list.elementAt(index);
+
+ // Collection APIs
+
+ void add(E element) { _list.add(element); }
+
+ void addAll(Iterable<E> elements) { _list.addAll(elements); }
+
+ void remove(Object element) { _list.remove(element); }
+
+ void removeAll(Iterable elements) { _list.removeAll(elements); }
+
+ void retainAll(Iterable elements) { _list.retainAll(elements); }
+
+ void removeMatching(bool test(E element)) { _list.removeMatching(test); }
+
+ void retainMatching(bool test(E element)) { _list.retainMatching(test); }
+
+ void clear() { _list.clear(); }
+
+ // List APIs
+
+ E operator [](int index) => _list[index];
+
+ void operator []=(int index, E value) { _list[index] = value; }
+
+ void set length(int newLength) { _list.length = newLength; }
+
+ void addLast(E value) { _list.addLast(value); }
+
+ Iterable<E> get reversed => _list.reversed;
+
+ void sort([int compare(E a, E b)]) { _list.sort(compare); }
+
+ int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
+
+ int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
+
+ E removeAt(int index) => _list.removeAt(index);
+
+ E removeLast() => _list.removeLast();
+
+ List<E> getRange(int start, int length) => _list.getRange(start, length);
+
+ void setRange(int start, int length, List<E> from, [int startFrom]) {
+ _list.setRange(start, length, from, startFrom);
+ }
+
+ void removeRange(int start, int length) { _list.removeRange(start, length); }
+
+ void insertRange(int start, int length, [E fill]) {
+ _list.insertRange(start, length, fill);
+ }
+}
+
+/**
+ * Iterator wrapper for _WrappedList.
+ */
+class _WrappedIterator<E> implements Iterator<E> {
+ Iterator _iterator;
+
+ _WrappedIterator(this._iterator);
+
+ bool moveNext() {
+ return _iterator.moveNext();
+ }
+
+ E get current => _iterator.current;
+}
// 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.
@@ -31553,6 +31826,15 @@
// window as a parameter.
+DateTime _convertNativeToDart_DateTime(date) {
+ var millisSinceEpoch = JS('int', '#.getTime()', date);
+ return new DateTime.fromMillisecondsSinceEpoch(millisSinceEpoch, isUtc: true);
+}
+
+_convertDartToNative_DateTime(DateTime date) {
+ return JS('', 'new Date(#)', date.millisecondsSinceEpoch);
+}
+
WindowBase _convertNativeToDart_Window(win) {
return _DOMWindowCrossFrame._createSafe(win);
}
@@ -32091,7 +32373,7 @@
final int _length; // Cache array length for faster access.
int _position;
T _current;
-
+
FixedSizeListIterator(List<T> array)
: _array = array,
_position = -1,
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 0dc02f2..870eaf7 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -1,3 +1,4 @@
+/// The Dart HTML library.
library dart.dom.html;
import 'dart:async';
@@ -2103,6 +2104,10 @@
@DocsEditable
void profileEnd(String title) native "Console_profileEnd_Callback";
+ @DomName('Console.table')
+ @DocsEditable
+ void table(Object arg) native "Console_table_Callback";
+
@DomName('Console.time')
@DocsEditable
void time(String title) native "Console_time_Callback";
@@ -2241,9 +2246,15 @@
@DocsEditable
@DomName('Crypto')
+@SupportedBrowser(SupportedBrowser.CHROME)
+@SupportedBrowser(SupportedBrowser.SAFARI)
+@Experimental
class Crypto extends NativeFieldWrapperClass1 {
Crypto.internal();
+ /// Checks if this type is supported on the current platform.
+ static bool get supported => true;
+
@DomName('Crypto.getRandomValues')
@DocsEditable
ArrayBufferView getRandomValues(ArrayBufferView array) native "Crypto_getRandomValues_Callback";
@@ -7528,7 +7539,7 @@
final mutableMatches = $dom_getElementsByName(
selectors.substring(7,selectors.length - 2));
int len = mutableMatches.length;
- final copyOfMatches = new List<Element>.fixedLength(len);
+ final copyOfMatches = new List<Element>(len);
for (int i = 0; i < len; ++i) {
copyOfMatches[i] = mutableMatches[i];
}
@@ -7536,7 +7547,7 @@
} else if (new RegExp("^[*a-zA-Z0-9]+\$").hasMatch(selectors)) {
final mutableMatches = $dom_getElementsByTagName(selectors);
int len = mutableMatches.length;
- final copyOfMatches = new List<Element>.fixedLength(len);
+ final copyOfMatches = new List<Element>(len);
for (int i = 0; i < len; ++i) {
copyOfMatches[i] = mutableMatches[i];
}
@@ -7832,7 +7843,9 @@
bool any(bool f(DomMimeType element)) => IterableMixinWorkaround.any(this, f);
- List<DomMimeType> toList() => new List<DomMimeType>.from(this);
+ List<DomMimeType> toList({ bool growable: true }) =>
+ new List<DomMimeType>.from(this, growable: growable);
+
Set<DomMimeType> toSet() => new Set<DomMimeType>.from(this);
bool get isEmpty => this.length == 0;
@@ -8100,7 +8113,9 @@
bool any(bool f(DomPlugin element)) => IterableMixinWorkaround.any(this, f);
- List<DomPlugin> toList() => new List<DomPlugin>.from(this);
+ List<DomPlugin> toList({ bool growable: true }) =>
+ new List<DomPlugin>.from(this, growable: growable);
+
Set<DomPlugin> toSet() => new Set<DomPlugin>.from(this);
bool get isEmpty => this.length == 0;
@@ -8486,7 +8501,9 @@
bool any(bool f(String element)) => IterableMixinWorkaround.any(this, f);
- List<String> toList() => new List<String>.from(this);
+ List<String> toList({ bool growable: true }) =>
+ new List<String>.from(this, growable: growable);
+
Set<String> toSet() => new Set<String>.from(this);
bool get isEmpty => this.length == 0;
@@ -8707,8 +8724,14 @@
: _childElements = element.$dom_children,
_element = element;
- List<Element> toList() {
- final output = new List<Element>.fixedLength(_childElements.length);
+ List<Element> toList({ bool growable: true }) {
+ List<Element> output;
+ if (growable) {
+ output = <Element>[];
+ output.length = _childElements.length;
+ } else {
+ output = new List<Element>(_childElements.length);
+ }
for (int i = 0, len = _childElements.length; i < len; i++) {
output[i] = _childElements[i];
}
@@ -9004,7 +9027,8 @@
return false;
}
- List<Element> toList() => new List<Element>.from(this);
+ List<Element> toList({ bool growable: true }) =>
+ new List<Element>.from(this, growable: growable);
Set<Element> toSet() => new Set<Element>.from(this);
Iterable<Element> take(int n) {
@@ -9739,6 +9763,10 @@
static const int ALLOW_KEYBOARD_INPUT = 1;
+ @DomName('Element.attributes')
+ @DocsEditable
+ _NamedNodeMap get $dom_attributes native "Element_attributes_Getter";
+
@DomName('Element.childElementCount')
@DocsEditable
int get $dom_childElementCount native "Element_childElementCount_Getter";
@@ -11098,7 +11126,7 @@
@DomName('File.lastModifiedDate')
@DocsEditable
- Date get lastModifiedDate native "File_lastModifiedDate_Getter";
+ DateTime get lastModifiedDate native "File_lastModifiedDate_Getter";
@DomName('File.name')
@DocsEditable
@@ -11313,7 +11341,9 @@
bool any(bool f(File element)) => IterableMixinWorkaround.any(this, f);
- List<File> toList() => new List<File>.from(this);
+ List<File> toList({ bool growable: true }) =>
+ new List<File>.from(this, growable: growable);
+
Set<File> toSet() => new Set<File>.from(this);
bool get isEmpty => this.length == 0;
@@ -11924,7 +11954,9 @@
bool any(bool f(num element)) => IterableMixinWorkaround.any(this, f);
- List<num> toList() => new List<num>.from(this);
+ List<num> toList({ bool growable: true }) =>
+ new List<num>.from(this, growable: growable);
+
Set<num> toSet() => new Set<num>.from(this);
bool get isEmpty => this.length == 0;
@@ -12159,7 +12191,9 @@
bool any(bool f(num element)) => IterableMixinWorkaround.any(this, f);
- List<num> toList() => new List<num>.from(this);
+ List<num> toList({ bool growable: true }) =>
+ new List<num>.from(this, growable: growable);
+
Set<num> toSet() => new Set<num>.from(this);
bool get isEmpty => this.length == 0;
@@ -12590,7 +12624,7 @@
@DomName('Geolocation.clearWatch')
@DocsEditable
- void $dom_clearWatch(int watchId) native "Geolocation_clearWatch_Callback";
+ void $dom_clearWatch(int watchID) native "Geolocation_clearWatch_Callback";
@DomName('Geolocation.getCurrentPosition')
@DocsEditable
@@ -12848,7 +12882,9 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
+
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -13057,7 +13093,9 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
+
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -13228,17 +13266,6 @@
document.$dom_body = value;
}
- /**
- * Registers a custom Element subclass as an available HTML tag.
- *
- * Not yet implemented.
- */
- @Experimental
- void register(String tagName, Type elementClass) {
- // TODO: tagName validation
- throw new Exception('Not yet implemented');
- }
-
@DomName('Document.caretRangeFromPoint')
Range caretRangeFromPoint(int x, int y) {
return document.$dom_caretRangeFromPoint(x, y);
@@ -14261,7 +14288,6 @@
TelephoneInputElement,
EmailInputElement,
PasswordInputElement,
- DateTimeInputElement,
DateInputElement,
MonthInputElement,
WeekInputElement,
@@ -14607,11 +14633,11 @@
@DomName('HTMLInputElement.valueAsDate')
@DocsEditable
- Date get valueAsDate native "HTMLInputElement_valueAsDate_Getter";
+ DateTime get valueAsDate native "HTMLInputElement_valueAsDate_Getter";
@DomName('HTMLInputElement.valueAsDate')
@DocsEditable
- void set valueAsDate(Date value) native "HTMLInputElement_valueAsDate_Setter";
+ void set valueAsDate(DateTime value) native "HTMLInputElement_valueAsDate_Setter";
@DomName('HTMLInputElement.valueAsNumber')
@DocsEditable
@@ -15019,32 +15045,6 @@
}
/**
- * A date and time (year, month, day, hour, minute, second, fraction of a
- * second) with the time zone set to UTC.
- *
- * Use [supported] to check if this is supported on the current platform.
- */
-@SupportedBrowser(SupportedBrowser.CHROME, '25')
-@Experimental
-abstract class DateTimeInputElement implements RangeInputElementBase {
- factory DateTimeInputElement() => new InputElement(type: 'datetime');
-
- @DomName('HTMLInputElement.valueAsDate')
- DateTime valueAsDate;
-
- @DomName('HTMLInputElement.readOnly')
- bool readOnly;
-
- @DomName('HTMLInputElement.required')
- bool required;
-
- /// Returns true if this input type is supported on the current platform.
- static bool get supported {
- return (new InputElement(type: 'datetime')).type == 'datetime';
- }
-}
-
-/**
* A date (year, month, day) with no time zone.
*
* Use [supported] to check if this is supported on the current platform.
@@ -15415,7 +15415,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -15650,7 +15652,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -15885,7 +15889,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -17930,7 +17936,7 @@
@DomName('Metadata.modificationTime')
@DocsEditable
- Date get modificationTime native "Metadata_modificationTime_Getter";
+ DateTime get modificationTime native "Metadata_modificationTime_Getter";
@DomName('Metadata.size')
@DocsEditable
@@ -18586,7 +18592,13 @@
void addAll(Iterable<Node> iterable) {
if (iterable is _ChildNodeListLazy) {
- iterable = new List.from(iterable);
+ if (iterable._this != _this) {
+ // Optimized route for copying between nodes.
+ for (var i = 0, len = iterable.length; i < len; ++i) {
+ _this.$dom_appendChild(iterable[0]);
+ }
+ }
+ return;
}
for (Node node in iterable) {
_this.$dom_appendChild(node);
@@ -18673,7 +18685,8 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -18803,10 +18816,6 @@
Node.internal() : super.internal();
- @DomName('Node.attributes')
- @DocsEditable
- _NamedNodeMap get $dom_attributes native "Node_attributes_Getter";
-
@DomName('Node.childNodes')
@DocsEditable
List<Node> get $dom_childNodes native "Node_childNodes_Getter";
@@ -19059,7 +19068,9 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
+
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -19830,10 +19841,18 @@
class PagePopupController extends NativeFieldWrapperClass1 {
PagePopupController.internal();
+ @DomName('PagePopupController.closePopup')
+ @DocsEditable
+ void closePopup() native "PagePopupController_closePopup_Callback";
+
@DomName('PagePopupController.formatMonth')
@DocsEditable
String formatMonth(int year, int zeroBaseMonth) native "PagePopupController_formatMonth_Callback";
+ @DomName('PagePopupController.formatShortMonth')
+ @DocsEditable
+ String formatShortMonth(int year, int zeroBaseMonth) native "PagePopupController_formatShortMonth_Callback";
+
@DomName('PagePopupController.histogramEnumeration')
@DocsEditable
void histogramEnumeration(String name, int sample, int boundaryValue) native "PagePopupController_histogramEnumeration_Callback";
@@ -19842,6 +19861,10 @@
@DocsEditable
String localizeNumberString(String numberString) native "PagePopupController_localizeNumberString_Callback";
+ @DomName('PagePopupController.setValue')
+ @DocsEditable
+ void setValue(String value) native "PagePopupController_setValue_Callback";
+
@DomName('PagePopupController.setValueAndClosePopup')
@DocsEditable
void setValueAndClosePopup(int numberValue, String stringValue) native "PagePopupController_setValueAndClosePopup_Callback";
@@ -21011,7 +21034,7 @@
@DomName('RTCStatsElement.timestamp')
@DocsEditable
- Date get timestamp native "RTCStatsElement_timestamp_Getter";
+ DateTime get timestamp native "RTCStatsElement_timestamp_Getter";
@DomName('RTCStatsElement.names')
@DocsEditable
@@ -21732,7 +21755,9 @@
bool any(bool f(SourceBuffer element)) => IterableMixinWorkaround.any(this, f);
- List<SourceBuffer> toList() => new List<SourceBuffer>.from(this);
+ List<SourceBuffer> toList({ bool growable: true }) =>
+ new List<SourceBuffer>.from(this, growable: growable);
+
Set<SourceBuffer> toSet() => new Set<SourceBuffer>.from(this);
bool get isEmpty => this.length == 0;
@@ -22050,7 +22075,9 @@
bool any(bool f(SpeechGrammar element)) => IterableMixinWorkaround.any(this, f);
- List<SpeechGrammar> toList() => new List<SpeechGrammar>.from(this);
+ List<SpeechGrammar> toList({ bool growable: true }) =>
+ new List<SpeechGrammar>.from(this, growable: growable);
+
Set<SpeechGrammar> toSet() => new Set<SpeechGrammar>.from(this);
bool get isEmpty => this.length == 0;
@@ -22964,16 +22991,34 @@
void set span(int value) native "HTMLTableColElement_span_Setter";
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// WARNING: Do not edit - generated code.
-
@DocsEditable
@DomName('HTMLTableElement')
class TableElement extends _Element_Merged {
+
+ @DomName('HTMLTableElement.tBodies')
+ List<TableSectionElement> get tBodies =>
+ new _WrappedList<TableSectionElement>($dom_tBodies);
+
+ @DomName('HTMLTableElement.rows')
+ List<TableRowElement> get rows =>
+ new _WrappedList<TableRowElement>($dom_rows);
+
+ TableRowElement addRow() {
+ return insertRow(-1);
+ }
+
+ TableCaptionElement createCaption() => $dom_createCaption();
+ TableSectionElement createTBody() => $dom_createTBody();
+ TableSectionElement createTFoot() => $dom_createTFoot();
+ TableSectionElement createTHead() => $dom_createTHead();
+ TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+
TableElement.internal() : super.internal();
@DomName('HTMLTableElement.HTMLTableElement')
@@ -22998,11 +23043,11 @@
@DomName('HTMLTableElement.rows')
@DocsEditable
- HtmlCollection get rows native "HTMLTableElement_rows_Getter";
+ HtmlCollection get $dom_rows native "HTMLTableElement_rows_Getter";
@DomName('HTMLTableElement.tBodies')
@DocsEditable
- HtmlCollection get tBodies native "HTMLTableElement_tBodies_Getter";
+ HtmlCollection get $dom_tBodies native "HTMLTableElement_tBodies_Getter";
@DomName('HTMLTableElement.tFoot')
@DocsEditable
@@ -23022,19 +23067,19 @@
@DomName('HTMLTableElement.createCaption')
@DocsEditable
- Element createCaption() native "HTMLTableElement_createCaption_Callback";
+ Element $dom_createCaption() native "HTMLTableElement_createCaption_Callback";
@DomName('HTMLTableElement.createTBody')
@DocsEditable
- Element createTBody() native "HTMLTableElement_createTBody_Callback";
+ Element $dom_createTBody() native "HTMLTableElement_createTBody_Callback";
@DomName('HTMLTableElement.createTFoot')
@DocsEditable
- Element createTFoot() native "HTMLTableElement_createTFoot_Callback";
+ Element $dom_createTFoot() native "HTMLTableElement_createTFoot_Callback";
@DomName('HTMLTableElement.createTHead')
@DocsEditable
- Element createTHead() native "HTMLTableElement_createTHead_Callback";
+ Element $dom_createTHead() native "HTMLTableElement_createTHead_Callback";
@DomName('HTMLTableElement.deleteCaption')
@DocsEditable
@@ -23054,19 +23099,27 @@
@DomName('HTMLTableElement.insertRow')
@DocsEditable
- Element insertRow(int index) native "HTMLTableElement_insertRow_Callback";
-
+ Element $dom_insertRow(int index) native "HTMLTableElement_insertRow_Callback";
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// WARNING: Do not edit - generated code.
-
@DocsEditable
@DomName('HTMLTableRowElement')
class TableRowElement extends _Element_Merged {
+
+ @DomName('HTMLTableRowElement.cells')
+ List<TableCellElement> get cells =>
+ new _WrappedList<TableCellElement>($dom_cells);
+
+ TableCellElement addCell() {
+ return insertCell(-1);
+ }
+
+ TableCellElement insertCell(int index) => $dom_insertCell(index);
+
TableRowElement.internal() : super.internal();
@DomName('HTMLTableRowElement.HTMLTableRowElement')
@@ -23075,7 +23128,7 @@
@DomName('HTMLTableRowElement.cells')
@DocsEditable
- HtmlCollection get cells native "HTMLTableRowElement_cells_Getter";
+ HtmlCollection get $dom_cells native "HTMLTableRowElement_cells_Getter";
@DomName('HTMLTableRowElement.rowIndex')
@DocsEditable
@@ -23091,24 +23144,32 @@
@DomName('HTMLTableRowElement.insertCell')
@DocsEditable
- Element insertCell(int index) native "HTMLTableRowElement_insertCell_Callback";
-
+ Element $dom_insertCell(int index) native "HTMLTableRowElement_insertCell_Callback";
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// WARNING: Do not edit - generated code.
-
@DocsEditable
@DomName('HTMLTableSectionElement')
class TableSectionElement extends _Element_Merged {
+
+ @DomName('HTMLTableSectionElement.rows')
+ List<TableRowElement> get rows =>
+ new _WrappedList<TableRowElement>($dom_rows);
+
+ TableRowElement addRow() {
+ return insertRow(-1);
+ }
+
+ TableRowElement insertRow(int index) => $dom_insertRow(index);
+
TableSectionElement.internal() : super.internal();
@DomName('HTMLTableSectionElement.rows')
@DocsEditable
- HtmlCollection get rows native "HTMLTableSectionElement_rows_Getter";
+ HtmlCollection get $dom_rows native "HTMLTableSectionElement_rows_Getter";
@DomName('HTMLTableSectionElement.deleteRow')
@DocsEditable
@@ -23116,8 +23177,7 @@
@DomName('HTMLTableSectionElement.insertRow')
@DocsEditable
- Element insertRow(int index) native "HTMLTableSectionElement_insertRow_Callback";
-
+ Element $dom_insertRow(int index) native "HTMLTableSectionElement_insertRow_Callback";
}
// 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
@@ -23684,7 +23744,9 @@
bool any(bool f(TextTrackCue element)) => IterableMixinWorkaround.any(this, f);
- List<TextTrackCue> toList() => new List<TextTrackCue>.from(this);
+ List<TextTrackCue> toList({ bool growable: true }) =>
+ new List<TextTrackCue>.from(this, growable: growable);
+
Set<TextTrackCue> toSet() => new Set<TextTrackCue>.from(this);
bool get isEmpty => this.length == 0;
@@ -23893,7 +23955,9 @@
bool any(bool f(TextTrack element)) => IterableMixinWorkaround.any(this, f);
- List<TextTrack> toList() => new List<TextTrack>.from(this);
+ List<TextTrack> toList({ bool growable: true }) =>
+ new List<TextTrack>.from(this, growable: growable);
+
Set<TextTrack> toSet() => new Set<TextTrack>.from(this);
bool get isEmpty => this.length == 0;
@@ -24309,7 +24373,9 @@
bool any(bool f(Touch element)) => IterableMixinWorkaround.any(this, f);
- List<Touch> toList() => new List<Touch>.from(this);
+ List<Touch> toList({ bool growable: true }) =>
+ new List<Touch>.from(this, growable: growable);
+
Set<Touch> toSet() => new Set<Touch>.from(this);
bool get isEmpty => this.length == 0;
@@ -24800,7 +24866,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -25035,7 +25103,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -25270,7 +25340,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -25503,7 +25575,9 @@
bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
- List<int> toList() => new List<int>.from(this);
+ List<int> toList({ bool growable: true }) =>
+ new List<int>.from(this, growable: growable);
+
Set<int> toSet() => new Set<int>.from(this);
bool get isEmpty => this.length == 0;
@@ -27892,7 +27966,7 @@
* frame unwinds, causing the future to complete after all processing has
* completed for the current event, but before any subsequent events.
*/
- void setImmediate(TimeoutHandler callback) {
+ void setImmediate(TimeoutHandler callback) {
_addMicrotaskCallback(callback);
}
/**
@@ -27900,8 +27974,11 @@
* registered under [name].
*/
SendPortSync lookupPort(String name) {
- var port =
- json.parse(document.documentElement.attributes['dart-port:$name']);
+ var portStr = document.documentElement.attributes['dart-port:$name'];
+ if (portStr == null) {
+ return null;
+ }
+ var port = json.parse(portStr);
return _deserialize(port);
}
@@ -27923,7 +28000,7 @@
* If you need to later cancel this animation, use [requestAnimationFrame]
* instead.
*
- * Note: The code that runs when the future completes should call
+ * Note: The code that runs when the future completes should call
* [animationFrame] again for the animation to continue.
*/
Future<num> get animationFrame {
@@ -29185,7 +29262,9 @@
bool any(bool f(ClientRect element)) => IterableMixinWorkaround.any(this, f);
- List<ClientRect> toList() => new List<ClientRect>.from(this);
+ List<ClientRect> toList({ bool growable: true }) =>
+ new List<ClientRect>.from(this, growable: growable);
+
Set<ClientRect> toSet() => new Set<ClientRect>.from(this);
bool get isEmpty => this.length == 0;
@@ -29386,7 +29465,9 @@
bool any(bool f(CssRule element)) => IterableMixinWorkaround.any(this, f);
- List<CssRule> toList() => new List<CssRule>.from(this);
+ List<CssRule> toList({ bool growable: true }) =>
+ new List<CssRule>.from(this, growable: growable);
+
Set<CssRule> toSet() => new Set<CssRule>.from(this);
bool get isEmpty => this.length == 0;
@@ -29587,7 +29668,9 @@
bool any(bool f(CssValue element)) => IterableMixinWorkaround.any(this, f);
- List<CssValue> toList() => new List<CssValue>.from(this);
+ List<CssValue> toList({ bool growable: true }) =>
+ new List<CssValue>.from(this, growable: growable);
+
Set<CssValue> toSet() => new Set<CssValue>.from(this);
bool get isEmpty => this.length == 0;
@@ -29931,7 +30014,9 @@
bool any(bool f(Entry element)) => IterableMixinWorkaround.any(this, f);
- List<Entry> toList() => new List<Entry>.from(this);
+ List<Entry> toList({ bool growable: true }) =>
+ new List<Entry>.from(this, growable: growable);
+
Set<Entry> toSet() => new Set<Entry>.from(this);
bool get isEmpty => this.length == 0;
@@ -30132,7 +30217,9 @@
bool any(bool f(EntrySync element)) => IterableMixinWorkaround.any(this, f);
- List<EntrySync> toList() => new List<EntrySync>.from(this);
+ List<EntrySync> toList({ bool growable: true }) =>
+ new List<EntrySync>.from(this, growable: growable);
+
Set<EntrySync> toSet() => new Set<EntrySync>.from(this);
bool get isEmpty => this.length == 0;
@@ -30333,7 +30420,9 @@
bool any(bool f(Gamepad element)) => IterableMixinWorkaround.any(this, f);
- List<Gamepad> toList() => new List<Gamepad>.from(this);
+ List<Gamepad> toList({ bool growable: true }) =>
+ new List<Gamepad>.from(this, growable: growable);
+
Set<Gamepad> toSet() => new Set<Gamepad>.from(this);
bool get isEmpty => this.length == 0;
@@ -30625,7 +30714,9 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
+
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -30850,7 +30941,9 @@
bool any(bool f(SpeechInputResult element)) => IterableMixinWorkaround.any(this, f);
- List<SpeechInputResult> toList() => new List<SpeechInputResult>.from(this);
+ List<SpeechInputResult> toList({ bool growable: true }) =>
+ new List<SpeechInputResult>.from(this, growable: growable);
+
Set<SpeechInputResult> toSet() => new Set<SpeechInputResult>.from(this);
bool get isEmpty => this.length == 0;
@@ -31051,7 +31144,9 @@
bool any(bool f(SpeechRecognitionResult element)) => IterableMixinWorkaround.any(this, f);
- List<SpeechRecognitionResult> toList() => new List<SpeechRecognitionResult>.from(this);
+ List<SpeechRecognitionResult> toList({ bool growable: true }) =>
+ new List<SpeechRecognitionResult>.from(this, growable: growable);
+
Set<SpeechRecognitionResult> toSet() => new Set<SpeechRecognitionResult>.from(this);
bool get isEmpty => this.length == 0;
@@ -31252,7 +31347,9 @@
bool any(bool f(StyleSheet element)) => IterableMixinWorkaround.any(this, f);
- List<StyleSheet> toList() => new List<StyleSheet>.from(this);
+ List<StyleSheet> toList({ bool growable: true }) =>
+ new List<StyleSheet>.from(this, growable: growable);
+
Set<StyleSheet> toSet() => new Set<StyleSheet>.from(this);
bool get isEmpty => this.length == 0;
@@ -31884,7 +31981,8 @@
String get first => readClasses().first;
String get last => readClasses().last;
String get single => readClasses().single;
- List<String> toList() => readClasses().toList();
+ List<String> toList({ bool growable: true }) =>
+ readClasses().toList(growable: growable);
Set<String> toSet() => readClasses().toSet();
String min([int compare(String a, String b)]) =>
readClasses().min(compare);
@@ -32147,7 +32245,7 @@
EventTarget _target;
// The distance to shift from upper case alphabet Roman letters to lower case.
- final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0];
+ final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
StreamSubscription _keyUpSubscription, _keyDownSubscription,
_keyPressSubscription;
@@ -32282,8 +32380,8 @@
if (prevEvent._shadowCharCode == event.charCode) {
return prevEvent.keyCode;
}
- if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".charCodes[0]
- && event.charCode <= "Z".charCodes[0] && event.charCode +
+ if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".codeUnits[0]
+ && event.charCode <= "Z".codeUnits[0] && event.charCode +
_ROMAN_ALPHABET_OFFSET == prevEvent._shadowCharCode) {
return prevEvent.keyCode;
}
@@ -33341,6 +33439,147 @@
timer = new _Timer(() { canceller(id); });
return timer;
};
+// 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 list which just wraps another list, for either intercepting list calls or
+ * retyping the list (for example, from List<A> to List<B> where B extends A).
+ */
+class _WrappedList<E> implements List<E> {
+ final List _list;
+
+ _WrappedList(this._list);
+
+ // Iterable APIs
+
+ Iterator<E> get iterator => new _WrappedIterator(_list.iterator);
+
+ Iterable map(f(E element)) => _list.map(f);
+
+ Iterable<E> where(bool f(E element)) => _list.where(f);
+
+ Iterable expand(Iterable f(E element)) => _list.expand(f);
+
+ bool contains(E element) => _list.contains(element);
+
+ void forEach(void f(E element)) { _list.forEach(f); }
+
+ dynamic reduce(initialValue, combine(previousValue, E element)) =>
+ _list.reduce(initialValue, combine);
+
+ bool every(bool f(E element)) => _list.every(f);
+
+ String join([String separator]) => _list.join(separator);
+
+ bool any(bool f(E element)) => _list.any(f);
+
+ List<E> toList({ bool growable: true }) =>
+ new List.from(_list, growable: growable);
+
+ Set<E> toSet() => _list.toSet();
+
+ int get length => _list.length;
+
+ E min([int compare(E a, E b)]) => _list.min(compare);
+
+ E max([int compare(E a, E b)]) => _list.max(compare);
+
+ bool get isEmpty => _list.isEmpty;
+
+ Iterable<E> take(int n) => _list.take(n);
+
+ Iterable<E> takeWhile(bool test(E value)) => _list.takeWhile(test);
+
+ Iterable<E> skip(int n) => _list.skip(n);
+
+ Iterable<E> skipWhile(bool test(E value)) => _list.skipWhile(test);
+
+ E get first => _list.first;
+
+ E get last => _list.last;
+
+ E get single => _list.single;
+
+ E firstMatching(bool test(E value), { E orElse() }) =>
+ _list.firstMatching(test, orElse: orElse);
+
+ E lastMatching(bool test(E value), {E orElse()}) =>
+ _list.lastMatching(test, orElse: orElse);
+
+ E singleMatching(bool test(E value)) => _list.singleMatching(test);
+
+ E elementAt(int index) => _list.elementAt(index);
+
+ // Collection APIs
+
+ void add(E element) { _list.add(element); }
+
+ void addAll(Iterable<E> elements) { _list.addAll(elements); }
+
+ void remove(Object element) { _list.remove(element); }
+
+ void removeAll(Iterable elements) { _list.removeAll(elements); }
+
+ void retainAll(Iterable elements) { _list.retainAll(elements); }
+
+ void removeMatching(bool test(E element)) { _list.removeMatching(test); }
+
+ void retainMatching(bool test(E element)) { _list.retainMatching(test); }
+
+ void clear() { _list.clear(); }
+
+ // List APIs
+
+ E operator [](int index) => _list[index];
+
+ void operator []=(int index, E value) { _list[index] = value; }
+
+ void set length(int newLength) { _list.length = newLength; }
+
+ void addLast(E value) { _list.addLast(value); }
+
+ Iterable<E> get reversed => _list.reversed;
+
+ void sort([int compare(E a, E b)]) { _list.sort(compare); }
+
+ int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
+
+ int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
+
+ E removeAt(int index) => _list.removeAt(index);
+
+ E removeLast() => _list.removeLast();
+
+ List<E> getRange(int start, int length) => _list.getRange(start, length);
+
+ void setRange(int start, int length, List<E> from, [int startFrom]) {
+ _list.setRange(start, length, from, startFrom);
+ }
+
+ void removeRange(int start, int length) { _list.removeRange(start, length); }
+
+ void insertRange(int start, int length, [E fill]) {
+ _list.insertRange(start, length, fill);
+ }
+}
+
+/**
+ * Iterator wrapper for _WrappedList.
+ */
+class _WrappedIterator<E> implements Iterator<E> {
+ Iterator _iterator;
+
+ _WrappedIterator(this._iterator);
+
+ bool moveNext() {
+ return _iterator.moveNext();
+ }
+
+ E get current => _iterator.current;
+}
// 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.
@@ -34127,7 +34366,7 @@
_serializeList(List list) {
int len = list.length;
- var result = new List.fixedLength(len);
+ var result = new List(len);
for (int i = 0; i < len; i++) {
result[i] = _dispatch(list[i]);
}
@@ -34299,10 +34538,15 @@
class _Utils {
+ static double dateTimeToDouble(DateTime dateTime) =>
+ dateTime.millisecondsSinceEpoch.toDouble();
+ static DateTime doubleToDateTime(double dateTime) =>
+ new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt());
+
static List convertToList(List list) {
// FIXME: [possible optimization]: do not copy the array if Dart_IsArray is fine w/ it.
final length = list.length;
- List result = new List.fixedLength(length);
+ List result = new List(length);
result.setRange(0, length, list);
return result;
}
diff --git a/sdk/lib/html/html_common/filtered_element_list.dart b/sdk/lib/html/html_common/filtered_element_list.dart
index 9337e6b..2644720 100644
--- a/sdk/lib/html/html_common/filtered_element_list.dart
+++ b/sdk/lib/html/html_common/filtered_element_list.dart
@@ -147,7 +147,8 @@
}
bool every(bool f(Element element)) => _filtered.every(f);
bool any(bool f(Element element)) => _filtered.any(f);
- List<Element> toList() => new List<Element>.from(this);
+ List<Element> toList({ bool growable: true }) =>
+ new List<Element>.from(this, growable: growable);
Set<Element> toSet() => new Set<Element>.from(this);
Element firstMatching(bool test(Element value), {Element orElse()}) {
return _filtered.firstMatching(test, orElse: orElse);
@@ -204,4 +205,8 @@
Element min([int compare(Element a, Element b)]) => _filtered.min(compare);
Element max([int compare(Element a, Element b)]) => _filtered.max(compare);
+
+ Map<int, Element> asMap() {
+ return IterableMixinWorkaround.asMapList(this);
+ }
}
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 9180c8a..9c3b377 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -131,15 +131,32 @@
const String _idbKey = '=List|=Object|num|String'; // TODO(sra): Add DateTime.
const _annotation_Creates_IDBKey = const Creates(_idbKey);
const _annotation_Returns_IDBKey = const Returns(_idbKey);
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-@DocsEditable
@DomName('IDBCursor')
class Cursor native "*IDBCursor" {
+ @DomName('IDBCursor.delete')
+ Future delete() {
+ try {
+ return _completeRequest($dom_delete());
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+ @DomName('IDBCursor.value')
+ Future update(value) {
+ try {
+ return _completeRequest($dom_update(value));
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+
@DomName('IDBCursor.direction')
@DocsEditable
final String direction;
@@ -167,20 +184,22 @@
@DocsEditable
void next([Object key]) native;
+ @JSName('delete')
@DomName('IDBCursor.delete')
@DocsEditable
- Request delete() native;
+ Request $dom_delete() native;
@DomName('IDBCursor.update')
@DocsEditable
- Request update(/*any*/ value) {
+ Request $dom_update(/*any*/ value) {
var value_1 = convertDartToNative_SerializedScriptValue(value);
- return _update_1(value_1);
+ return _$dom_update_1(value_1);
}
@JSName('update')
@DomName('IDBCursor.update')
@DocsEditable
- Request _update_1(value) native;
+ Request _$dom_update_1(value) native;
+
}
// 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
@@ -191,25 +210,40 @@
@DomName('IDBCursorWithValue')
class CursorWithValue extends Cursor native "*IDBCursorWithValue" {
- dynamic get value => _convertNativeToDart_IDBAny(this._value);
+ dynamic get value => _convertNativeToDart_IDBAny(this._get_value);
@JSName('value')
@DomName('IDBCursorWithValue.value')
@DocsEditable
@annotation_Creates_SerializedScriptValue
@annotation_Returns_SerializedScriptValue
- final dynamic _value;
+ final dynamic _get_value;
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+@DocsEditable
@DomName('IDBDatabase')
@SupportedBrowser(SupportedBrowser.CHROME)
@SupportedBrowser(SupportedBrowser.FIREFOX, '15')
@SupportedBrowser(SupportedBrowser.IE, '10')
@Experimental
class Database extends EventTarget native "*IDBDatabase" {
+ @DomName('IDBDatabase.createObjectStore')
+ @DocsEditable
+ ObjectStore createObjectStore(String name,
+ {String keyPath, bool autoIncrement}) {
+ var options = {};
+ if (keyPath != null) {
+ options['keyPath'] = keyPath;
+ }
+ if (autoIncrement != null) {
+ options['autoIncrement'] = autoIncrement;
+ }
+
+ return $dom_createObjectStore(name, options);
+ }
Transaction transaction(storeName_OR_storeNames, String mode) {
if (mode != 'readonly' && mode != 'readwrite') {
@@ -266,21 +300,21 @@
@DomName('IDBDatabase.createObjectStore')
@DocsEditable
- ObjectStore createObjectStore(String name, [Map options]) {
+ ObjectStore $dom_createObjectStore(String name, [Map options]) {
if (?options) {
var options_1 = convertDartToNative_Dictionary(options);
- return _createObjectStore_1(name, options_1);
+ return _$dom_createObjectStore_1(name, options_1);
}
- return _createObjectStore_2(name);
+ return _$dom_createObjectStore_2(name);
}
@JSName('createObjectStore')
@DomName('IDBDatabase.createObjectStore')
@DocsEditable
- ObjectStore _createObjectStore_1(name, options) native;
+ ObjectStore _$dom_createObjectStore_1(name, options) native;
@JSName('createObjectStore')
@DomName('IDBDatabase.createObjectStore')
@DocsEditable
- ObjectStore _createObjectStore_2(name) native;
+ ObjectStore _$dom_createObjectStore_2(name) native;
@DomName('IDBDatabase.deleteObjectStore')
@DocsEditable
@@ -371,6 +405,27 @@
}
}
+ @DomName('IDBFactory.getDatabaseNames')
+ @SupportedBrowser(SupportedBrowser.CHROME)
+ @Experimental
+ Future<List<String>> getDatabaseNames() {
+ try {
+ var request = $dom_webkitGetDatabaseNames();
+
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ /**
+ * Checks to see if getDatabaseNames is supported by the current platform.
+ */
+ bool get supportsDatabaseNames {
+ return supported && JS('bool',
+ '!!(#.getDatabaseNames || #.webkitGetDatabaseNames)', this, this);
+ }
+
@DomName('IDBFactory.cmp')
@DocsEditable
@@ -395,7 +450,10 @@
@SupportedBrowser(SupportedBrowser.CHROME)
@SupportedBrowser(SupportedBrowser.SAFARI)
@Experimental
- Request getDatabaseNames() native;
+ @Returns('Request')
+ @Creates('Request')
+ @Creates('DomStringList')
+ Request $dom_webkitGetDatabaseNames() native;
}
@@ -416,15 +474,105 @@
});
return completer.future;
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-@DocsEditable
@DomName('IDBIndex')
class Index native "*IDBIndex" {
+ @DomName('IDBIndex.count')
+ Future<int> count([key_OR_range]) {
+ try {
+ var request;
+ if (key_OR_range != null) {
+ request = $dom_count(key_OR_range);
+ } else {
+ request = $dom_count();
+ }
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+ @DomName('IDBIndex.get')
+ Future get(key) {
+ try {
+ var request = $dom_get(key);
+
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBIndex.getKey')
+ Future getKey(key) {
+ try {
+ var request = $dom_getKey(key);
+
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ /**
+ * Creates a stream of cursors over the records in this object store.
+ *
+ * See also:
+ *
+ * * [ObjectStore.openCursor]
+ */
+ Stream<CursorWithValue> openCursor({key, KeyRange range, String direction,
+ bool autoAdvance}) {
+ var key_OR_range = null;
+ if (key != null) {
+ if (range != null) {
+ throw new ArgumentError('Cannot specify both key and range.');
+ }
+ key_OR_range = key;
+ } else {
+ key_OR_range = range;
+ }
+ var request;
+ if (direction == null) {
+ request = $dom_openCursor(key_OR_range);
+ } else {
+ request = $dom_openCursor(key_OR_range, direction);
+ }
+ return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+ }
+
+ /**
+ * Creates a stream of cursors over the records in this object store.
+ *
+ * See also:
+ *
+ * * [ObjectStore.openCursor]
+ */
+ Stream<Cursor> openKeyCursor({key, KeyRange range, String direction,
+ bool autoAdvance}) {
+ var key_OR_range = null;
+ if (key != null) {
+ if (range != null) {
+ throw new ArgumentError('Cannot specify both key and range.');
+ }
+ key_OR_range = key;
+ } else {
+ key_OR_range = range;
+ }
+ var request;
+ if (direction == null) {
+ request = $dom_openKeyCursor(key_OR_range);
+ } else {
+ request = $dom_openKeyCursor(key_OR_range, direction);
+ }
+ return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+ }
+
+
@DomName('IDBIndex.keyPath')
@DocsEditable
final dynamic keyPath;
@@ -445,38 +593,44 @@
@DocsEditable
final bool unique;
+ @JSName('count')
@DomName('IDBIndex.count')
@DocsEditable
- Request count([key_OR_range]) native;
+ Request $dom_count([key_OR_range]) native;
+ @JSName('get')
@DomName('IDBIndex.get')
@DocsEditable
@Returns('Request')
@Creates('Request')
@annotation_Creates_SerializedScriptValue
- Request get(key) native;
+ Request $dom_get(key) native;
+ @JSName('getKey')
@DomName('IDBIndex.getKey')
@DocsEditable
@Returns('Request')
@Creates('Request')
@annotation_Creates_SerializedScriptValue
@Creates('ObjectStore')
- Request getKey(key) native;
+ Request $dom_getKey(key) native;
+ @JSName('openCursor')
@DomName('IDBIndex.openCursor')
@DocsEditable
@Returns('Request')
@Creates('Request')
@Creates('Cursor')
- Request openCursor([key_OR_range, String direction]) native;
+ Request $dom_openCursor([key_OR_range, String direction]) native;
+ @JSName('openKeyCursor')
@DomName('IDBIndex.openKeyCursor')
@DocsEditable
@Returns('Request')
@Creates('Request')
@Creates('Cursor')
- Request openKeyCursor([key_OR_range, String direction]) native;
+ Request $dom_openKeyCursor([key_OR_range, String direction]) native;
+
}
// 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
@@ -549,6 +703,54 @@
@DomName('IDBObjectStore')
class ObjectStore native "*IDBObjectStore" {
+ @DomName('IDBObjectStore.add')
+ Future add(value, [key]) {
+ try {
+ var request;
+ if (key != null) {
+ request = $dom_add(value, key);
+ } else {
+ request = $dom_add(value);
+ }
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBObjectStore.clear')
+ Future clear() {
+ try {
+ return _completeRequest($dom_clear());
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBObjectStore.delete')
+ Future delete(key_OR_keyRange){
+ try {
+ return _completeRequest($dom_delete(key_OR_keyRange));
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBObjectStore.count')
+ Future<int> count([key_OR_range]) {
+ try {
+ var request;
+ if (key_OR_range != null) {
+ request = $dom_count(key_OR_range);
+ } else {
+ request = $dom_count();
+ }
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
@DomName('IDBObjectStore.put')
Future put(value, [key]) {
try {
@@ -619,6 +821,19 @@
return _cursorStreamFromResult(request, autoAdvance);
}
+ @DomName('IDBObjectStore.createIndex')
+ Index createIndex(String name, keyPath, {bool unique, bool multiEntry}) {
+ var options = {};
+ if (unique != null) {
+ options['unique'] = unique;
+ }
+ if (multiEntry != null) {
+ options['multiEntry'] = multiEntry;
+ }
+
+ return $dom_createIndex(name, keyPath, options);
+ }
+
@DomName('IDBObjectStore.autoIncrement')
@DocsEditable
@@ -647,14 +862,14 @@
@Returns('Request')
@Creates('Request')
@_annotation_Creates_IDBKey
- Request add(/*any*/ value, [/*any*/ key]) {
+ Request $dom_add(/*any*/ value, [/*any*/ key]) {
if (?key) {
var value_1 = convertDartToNative_SerializedScriptValue(value);
var key_2 = convertDartToNative_SerializedScriptValue(key);
- return _add_1(value_1, key_2);
+ return _$dom_add_1(value_1, key_2);
}
var value_3 = convertDartToNative_SerializedScriptValue(value);
- return _add_2(value_3);
+ return _$dom_add_2(value_3);
}
@JSName('add')
@DomName('IDBObjectStore.add')
@@ -662,64 +877,67 @@
@Returns('Request')
@Creates('Request')
@_annotation_Creates_IDBKey
- Request _add_1(value, key) native;
+ Request _$dom_add_1(value, key) native;
@JSName('add')
@DomName('IDBObjectStore.add')
@DocsEditable
@Returns('Request')
@Creates('Request')
@_annotation_Creates_IDBKey
- Request _add_2(value) native;
+ Request _$dom_add_2(value) native;
+ @JSName('clear')
@DomName('IDBObjectStore.clear')
@DocsEditable
- Request clear() native;
+ Request $dom_clear() native;
+ @JSName('count')
@DomName('IDBObjectStore.count')
@DocsEditable
- Request count([key_OR_range]) native;
+ Request $dom_count([key_OR_range]) native;
@DomName('IDBObjectStore.createIndex')
@DocsEditable
- Index createIndex(String name, keyPath, [Map options]) {
+ Index $dom_createIndex(String name, keyPath, [Map options]) {
if ((keyPath is List<String> || keyPath == null) && !?options) {
List keyPath_1 = convertDartToNative_StringArray(keyPath);
- return _createIndex_1(name, keyPath_1);
+ return _$dom_createIndex_1(name, keyPath_1);
}
if ((keyPath is List<String> || keyPath == null)) {
List keyPath_2 = convertDartToNative_StringArray(keyPath);
var options_3 = convertDartToNative_Dictionary(options);
- return _createIndex_2(name, keyPath_2, options_3);
+ return _$dom_createIndex_2(name, keyPath_2, options_3);
}
if ((keyPath is String || keyPath == null) && !?options) {
- return _createIndex_3(name, keyPath);
+ return _$dom_createIndex_3(name, keyPath);
}
if ((keyPath is String || keyPath == null)) {
var options_4 = convertDartToNative_Dictionary(options);
- return _createIndex_4(name, keyPath, options_4);
+ return _$dom_createIndex_4(name, keyPath, options_4);
}
throw new ArgumentError("Incorrect number or type of arguments");
}
@JSName('createIndex')
@DomName('IDBObjectStore.createIndex')
@DocsEditable
- Index _createIndex_1(name, List keyPath) native;
+ Index _$dom_createIndex_1(name, List keyPath) native;
@JSName('createIndex')
@DomName('IDBObjectStore.createIndex')
@DocsEditable
- Index _createIndex_2(name, List keyPath, options) native;
+ Index _$dom_createIndex_2(name, List keyPath, options) native;
@JSName('createIndex')
@DomName('IDBObjectStore.createIndex')
@DocsEditable
- Index _createIndex_3(name, String keyPath) native;
+ Index _$dom_createIndex_3(name, String keyPath) native;
@JSName('createIndex')
@DomName('IDBObjectStore.createIndex')
@DocsEditable
- Index _createIndex_4(name, String keyPath, options) native;
+ Index _$dom_createIndex_4(name, String keyPath, options) native;
+ @JSName('delete')
@DomName('IDBObjectStore.delete')
@DocsEditable
- Request delete(key_OR_keyRange) native;
+ Request $dom_delete(key_OR_keyRange) native;
@DomName('IDBObjectStore.deleteIndex')
@DocsEditable
@@ -854,12 +1072,12 @@
@DocsEditable
final String readyState;
- dynamic get result => _convertNativeToDart_IDBAny(this._result);
+ dynamic get result => _convertNativeToDart_IDBAny(this._get_result);
@JSName('result')
@DomName('IDBRequest.result')
@DocsEditable
@Creates('Null')
- final dynamic _result;
+ final dynamic _get_result;
@DomName('IDBRequest.source')
@DocsEditable
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 5aa80a1a..c0d888c 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -33,17 +33,32 @@
[bool lowerOpen = false, bool upperOpen = false]) =>
KeyRange.bound_(lower, upper, lowerOpen, upperOpen);
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// WARNING: Do not edit - generated code.
-
-@DocsEditable
@DomName('IDBCursor')
class Cursor extends NativeFieldWrapperClass1 {
- Cursor.internal();
+ @DomName('IDBCursor.delete')
+ Future delete() {
+ try {
+ return _completeRequest($dom_delete());
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBCursor.value')
+ Future update(value) {
+ try {
+ return _completeRequest($dom_update(value));
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ Cursor.internal();
@DomName('IDBCursor.direction')
@DocsEditable
@@ -84,11 +99,11 @@
@DomName('IDBCursor.delete')
@DocsEditable
- Request delete() native "IDBCursor_delete_Callback";
+ Request $dom_delete() native "IDBCursor_delete_Callback";
@DomName('IDBCursor.update')
@DocsEditable
- Request update(Object value) native "IDBCursor_update_Callback";
+ Request $dom_update(Object value) native "IDBCursor_update_Callback";
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
@@ -108,12 +123,10 @@
Object get value native "IDBCursorWithValue_value_Getter";
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// WARNING: Do not edit - generated code.
-
@DocsEditable
@DomName('IDBDatabase')
@@ -122,6 +135,22 @@
@SupportedBrowser(SupportedBrowser.IE, '10')
@Experimental
class Database extends EventTarget {
+ @DomName('IDBDatabase.createObjectStore')
+ @DocsEditable
+ ObjectStore createObjectStore(String name,
+ {String keyPath, bool autoIncrement}) {
+ var options = {};
+ if (keyPath != null) {
+ options['keyPath'] = keyPath;
+ }
+ if (autoIncrement != null) {
+ options['autoIncrement'] = autoIncrement;
+ }
+
+ return $dom_createObjectStore(name, options);
+ }
+
+
Database.internal() : super.internal();
@DomName('IDBDatabase.abortEvent')
@@ -158,7 +187,7 @@
@DomName('IDBDatabase.createObjectStore')
@DocsEditable
- ObjectStore createObjectStore(String name, [Map options]) native "IDBDatabase_createObjectStore_Callback";
+ ObjectStore $dom_createObjectStore(String name, [Map options]) native "IDBDatabase_createObjectStore_Callback";
@DomName('IDBDatabase.deleteObjectStore')
@DocsEditable
@@ -208,7 +237,6 @@
@DomName('IDBDatabase.onversionchange')
@DocsEditable
Stream<VersionChangeEvent> get onVersionChange => versionChangeEvent.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
@@ -271,6 +299,26 @@
}
}
+ @DomName('IDBFactory.getDatabaseNames')
+ @SupportedBrowser(SupportedBrowser.CHROME)
+ @Experimental
+ Future<List<String>> getDatabaseNames() {
+ try {
+ var request = $dom_webkitGetDatabaseNames();
+
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ /**
+ * Checks to see if getDatabaseNames is supported by the current platform.
+ */
+ bool get supportsDatabaseNames {
+ return true;
+ }
+
IdbFactory.internal();
@DomName('IDBFactory.cmp')
@@ -301,7 +349,7 @@
@SupportedBrowser(SupportedBrowser.CHROME)
@SupportedBrowser(SupportedBrowser.SAFARI)
@Experimental
- Request getDatabaseNames() native "IDBFactory_webkitGetDatabaseNames_Callback";
+ Request $dom_webkitGetDatabaseNames() native "IDBFactory_webkitGetDatabaseNames_Callback";
}
@@ -322,17 +370,105 @@
});
return completer.future;
}
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// WARNING: Do not edit - generated code.
-
-@DocsEditable
@DomName('IDBIndex')
class Index extends NativeFieldWrapperClass1 {
- Index.internal();
+ @DomName('IDBIndex.count')
+ Future<int> count([key_OR_range]) {
+ try {
+ var request;
+ if (key_OR_range != null) {
+ request = $dom_count(key_OR_range);
+ } else {
+ request = $dom_count();
+ }
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBIndex.get')
+ Future get(key) {
+ try {
+ var request = $dom_get(key);
+
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBIndex.getKey')
+ Future getKey(key) {
+ try {
+ var request = $dom_getKey(key);
+
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ /**
+ * Creates a stream of cursors over the records in this object store.
+ *
+ * See also:
+ *
+ * * [ObjectStore.openCursor]
+ */
+ Stream<CursorWithValue> openCursor({key, KeyRange range, String direction,
+ bool autoAdvance}) {
+ var key_OR_range = null;
+ if (key != null) {
+ if (range != null) {
+ throw new ArgumentError('Cannot specify both key and range.');
+ }
+ key_OR_range = key;
+ } else {
+ key_OR_range = range;
+ }
+ var request;
+ if (direction == null) {
+ request = $dom_openCursor(key_OR_range);
+ } else {
+ request = $dom_openCursor(key_OR_range, direction);
+ }
+ return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+ }
+
+ /**
+ * Creates a stream of cursors over the records in this object store.
+ *
+ * See also:
+ *
+ * * [ObjectStore.openCursor]
+ */
+ Stream<Cursor> openKeyCursor({key, KeyRange range, String direction,
+ bool autoAdvance}) {
+ var key_OR_range = null;
+ if (key != null) {
+ if (range != null) {
+ throw new ArgumentError('Cannot specify both key and range.');
+ }
+ key_OR_range = key;
+ } else {
+ key_OR_range = range;
+ }
+ var request;
+ if (direction == null) {
+ request = $dom_openKeyCursor(key_OR_range);
+ } else {
+ request = $dom_openKeyCursor(key_OR_range, direction);
+ }
+ return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+ }
+
+ Index.internal();
@DomName('IDBIndex.keyPath')
@DocsEditable
@@ -354,7 +490,7 @@
@DocsEditable
bool get unique native "IDBIndex_unique_Getter";
- Request count([key_OR_range]) {
+ Request $dom_count([key_OR_range]) {
if (!?key_OR_range) {
return _count_1();
}
@@ -379,7 +515,7 @@
@DocsEditable
Request _count_3(key_OR_range) native "IDBIndex__count_3_Callback";
- Request get(key) {
+ Request $dom_get(key) {
if ((key is KeyRange || key == null)) {
return _get_1(key);
}
@@ -397,7 +533,7 @@
@DocsEditable
Request _get_2(key) native "IDBIndex__get_2_Callback";
- Request getKey(key) {
+ Request $dom_getKey(key) {
if ((key is KeyRange || key == null)) {
return _getKey_1(key);
}
@@ -415,7 +551,7 @@
@DocsEditable
Request _getKey_2(key) native "IDBIndex__getKey_2_Callback";
- Request openCursor([key_OR_range, String direction]) {
+ Request $dom_openCursor([key_OR_range, String direction]) {
if (!?key_OR_range && !?direction) {
return _openCursor_1();
}
@@ -454,7 +590,7 @@
@DocsEditable
Request _openCursor_5(key_OR_range, direction) native "IDBIndex__openCursor_5_Callback";
- Request openKeyCursor([key_OR_range, String direction]) {
+ Request $dom_openKeyCursor([key_OR_range, String direction]) {
if (!?key_OR_range && !?direction) {
return _openKeyCursor_1();
}
@@ -602,6 +738,54 @@
@DomName('IDBObjectStore')
class ObjectStore extends NativeFieldWrapperClass1 {
+ @DomName('IDBObjectStore.add')
+ Future add(value, [key]) {
+ try {
+ var request;
+ if (key != null) {
+ request = $dom_add(value, key);
+ } else {
+ request = $dom_add(value);
+ }
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBObjectStore.clear')
+ Future clear() {
+ try {
+ return _completeRequest($dom_clear());
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBObjectStore.delete')
+ Future delete(key_OR_keyRange){
+ try {
+ return _completeRequest($dom_delete(key_OR_keyRange));
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBObjectStore.count')
+ Future<int> count([key_OR_range]) {
+ try {
+ var request;
+ if (key_OR_range != null) {
+ request = $dom_count(key_OR_range);
+ } else {
+ request = $dom_count();
+ }
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
@DomName('IDBObjectStore.put')
Future put(value, [key]) {
try {
@@ -672,6 +856,19 @@
return _cursorStreamFromResult(request, autoAdvance);
}
+ @DomName('IDBObjectStore.createIndex')
+ Index createIndex(String name, keyPath, {bool unique, bool multiEntry}) {
+ var options = {};
+ if (unique != null) {
+ options['unique'] = unique;
+ }
+ if (multiEntry != null) {
+ options['multiEntry'] = multiEntry;
+ }
+
+ return $dom_createIndex(name, keyPath, options);
+ }
+
ObjectStore.internal();
@DomName('IDBObjectStore.autoIncrement')
@@ -694,7 +891,7 @@
@DocsEditable
Transaction get transaction native "IDBObjectStore_transaction_Getter";
- Request add(Object value, [Object key]) {
+ Request $dom_add(Object value, [Object key]) {
if (?key) {
return _add_1(value, key);
}
@@ -711,9 +908,9 @@
@DomName('IDBObjectStore.clear')
@DocsEditable
- Request clear() native "IDBObjectStore_clear_Callback";
+ Request $dom_clear() native "IDBObjectStore_clear_Callback";
- Request count([key_OR_range]) {
+ Request $dom_count([key_OR_range]) {
if (!?key_OR_range) {
return _count_1();
}
@@ -738,7 +935,7 @@
@DocsEditable
Request _count_3(key_OR_range) native "IDBObjectStore__count_3_Callback";
- Index createIndex(String name, keyPath, [Map options]) {
+ Index $dom_createIndex(String name, keyPath, [Map options]) {
if ((name is String || name == null) && (keyPath is List<String> || keyPath == null) && (options is Map || options == null)) {
return _createIndex_1(name, keyPath, options);
}
@@ -756,7 +953,7 @@
@DocsEditable
Index _createIndex_2(name, keyPath, options) native "IDBObjectStore__createIndex_2_Callback";
- Request delete(key_OR_keyRange) {
+ Request $dom_delete(key_OR_keyRange) {
if ((key_OR_keyRange is KeyRange || key_OR_keyRange == null)) {
return _delete_1(key_OR_keyRange);
}
diff --git a/sdk/lib/io/base64.dart b/sdk/lib/io/base64.dart
index f57eea6..12c1e5f8 100644
--- a/sdk/lib/io/base64.dart
+++ b/sdk/lib/io/base64.dart
@@ -68,7 +68,7 @@
int charCount = 0;
int value = 0;
for (int i = 0; i < data.length; i++) {
- int char = data.charCodeAt(i);
+ int char = data.codeUnitAt(i);
if (65 <= char && char <= 90) { // "A" - "Z".
value = (value << 6) | char - 65;
charCount++;
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 5963d83..2b519e7 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -31,7 +31,7 @@
Future<bool> exists() {
_ensureDirectoryService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = EXISTS_REQUEST;
request[1] = _path;
return _directoryService.call(request).then((response) {
@@ -110,7 +110,7 @@
Future<Directory> create({recursive: false}) {
if (recursive) return createRecursively();
_ensureDirectoryService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = CREATE_REQUEST;
request[1] = _path;
return _directoryService.call(request).then((response) {
@@ -149,7 +149,7 @@
Future<Directory> createTemp() {
_ensureDirectoryService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = CREATE_TEMP_REQUEST;
request[1] = _path;
return _directoryService.call(request).then((response) {
@@ -179,7 +179,7 @@
Future<Directory> delete({recursive: false}) {
_ensureDirectoryService();
- List request = new List.fixedLength(3);
+ List request = new List(3);
request[0] = DELETE_REQUEST;
request[1] = _path;
request[2] = recursive;
@@ -203,7 +203,7 @@
Future<Directory> rename(String newPath) {
_ensureDirectoryService();
- List request = new List.fixedLength(3);
+ List request = new List(3);
request[0] = RENAME_REQUEST;
request[1] = _path;
request[2] = newPath;
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index ff956c8..f42555e 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -30,7 +30,7 @@
/**
* Create a File object.
*/
- factory File(String name) => new _File(name);
+ factory File(String path) => new _File(path);
/**
* Create a File object from a Path object.
@@ -143,13 +143,13 @@
RandomAccessFile openSync([FileMode mode = FileMode.READ]);
/**
- * Get the canonical full path corresponding to the file name.
+ * Get the canonical full path corresponding to the file path.
* Returns a [:Future<String>:] that completes with the path.
*/
Future<String> fullPath();
/**
- * Synchronously get the canonical full path corresponding to the file name.
+ * Synchronously get the canonical full path corresponding to the file path.
*/
String fullPathSync();
@@ -274,9 +274,9 @@
Encoding encoding: Encoding.UTF_8});
/**
- * Get the name of the file.
+ * Get the path of the file.
*/
- String get name;
+ String get path;
}
@@ -444,9 +444,9 @@
String toString();
/**
- * Gets the name of the file underlying this RandomAccessFile.
+ * Gets the path of the file underlying this RandomAccessFile.
*/
- String get name;
+ String get path;
}
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index ce60209..0ba765c 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -13,7 +13,7 @@
final int _blockSize = 64 * 1024;
// Information about the underlying file.
- String _name;
+ String _path;
RandomAccessFile _openedFile;
int _position;
@@ -27,7 +27,7 @@
// Block read but not yet send because stream is paused.
List<int> _currentBlock;
- _FileStream(String this._name) : _position = 0 {
+ _FileStream(String this._path) : _position = 0 {
_setupController();
}
@@ -103,8 +103,8 @@
void _start() {
Future<RandomAccessFile> openFuture;
- if (_name != null) {
- openFuture = new File(_name).open(FileMode.READ);
+ if (_path != null) {
+ openFuture = new File(_path).open(FileMode.READ);
} else {
openFuture = new Future.immediate(_File._openStdioSync(0));
}
@@ -211,7 +211,7 @@
const int _SET_POSITION_REQUEST = 8;
const int _TRUNCATE_REQUEST = 9;
const int _LENGTH_REQUEST = 10;
-const int _LENGTH_FROM_NAME_REQUEST = 11;
+const int _LENGTH_FROM_PATH_REQUEST = 11;
const int _LAST_MODIFIED_REQUEST = 12;
const int _FLUSH_REQUEST = 13;
const int _READ_BYTE_REQUEST = 14;
@@ -253,9 +253,9 @@
// Class for encapsulating the native implementation of files.
class _File extends _FileBase implements File {
// Constructor for file.
- _File(String this._name) {
- if (_name is! String) {
- throw new ArgumentError('${Error.safeToString(_name)} '
+ _File(String this._path) {
+ if (_path is! String) {
+ throw new ArgumentError('${Error.safeToString(_path)} '
'is not a String');
}
}
@@ -265,85 +265,85 @@
Future<bool> exists() {
_ensureFileService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _EXISTS_REQUEST;
- request[1] = _name;
+ request[1] = _path;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
- throw _exceptionFromResponse(response, "Cannot open file '$_name'");
+ throw _exceptionFromResponse(response, "Cannot open file '$_path'");
}
return response;
});
}
- external static _exists(String name);
+ external static _exists(String path);
bool existsSync() {
- var result = _exists(_name);
- throwIfError(result, "Cannot check existence of file '$_name'");
+ var result = _exists(_path);
+ throwIfError(result, "Cannot check existence of file '$_path'");
return result;
}
Future<File> create() {
_ensureFileService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _CREATE_REQUEST;
- request[1] = _name;
+ request[1] = _path;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
- throw _exceptionFromResponse(response, "Cannot create file '$_name'");
+ throw _exceptionFromResponse(response, "Cannot create file '$_path'");
}
return this;
});
}
- external static _create(String name);
+ external static _create(String path);
void createSync() {
- var result = _create(_name);
- throwIfError(result, "Cannot create file '$_name'");
+ var result = _create(_path);
+ throwIfError(result, "Cannot create file '$_path'");
}
Future<File> delete() {
_ensureFileService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _DELETE_REQUEST;
- request[1] = _name;
+ request[1] = _path;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
- throw _exceptionFromResponse(response, "Cannot delete file '$_name'");
+ throw _exceptionFromResponse(response, "Cannot delete file '$_path'");
}
return this;
});
}
- external static _delete(String name);
+ external static _delete(String path);
void deleteSync() {
- var result = _delete(_name);
- throwIfError(result, "Cannot delete file '$_name'");
+ var result = _delete(_path);
+ throwIfError(result, "Cannot delete file '$_path'");
}
Future<Directory> directory() {
_ensureFileService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _DIRECTORY_REQUEST;
- request[1] = _name;
+ request[1] = _path;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
"Cannot retrieve directory for "
- "file '$_name'");
+ "file '$_path'");
}
return new Directory(response);
});
}
- external static _directory(String name);
+ external static _directory(String path);
Directory directorySync() {
- var result = _directory(name);
- throwIfError(result, "Cannot retrieve directory for file '$_name'");
+ var result = _directory(path);
+ throwIfError(result, "Cannot retrieve directory for file '$_path'");
return new Directory(result);
}
@@ -358,66 +358,66 @@
});
return completer.future;
}
- List request = new List.fixedLength(3);
+ List request = new List(3);
request[0] = _OPEN_REQUEST;
- request[1] = _name;
+ request[1] = _path;
request[2] = mode._mode; // Direct int value for serialization.
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
- throw _exceptionFromResponse(response, "Cannot open file '$_name'");
+ throw _exceptionFromResponse(response, "Cannot open file '$_path'");
}
- return new _RandomAccessFile(response, _name);
+ return new _RandomAccessFile(response, _path);
});
}
Future<int> length() {
_ensureFileService();
- List request = new List.fixedLength(2);
- request[0] = _LENGTH_FROM_NAME_REQUEST;
- request[1] = _name;
+ List request = new List(2);
+ request[0] = _LENGTH_FROM_PATH_REQUEST;
+ request[1] = _path;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
"Cannot retrieve length of "
- "file '$_name'");
+ "file '$_path'");
}
return response;
});
}
- external static _lengthFromName(String name);
+ external static _lengthFromPath(String path);
int lengthSync() {
- var result = _lengthFromName(_name);
- throwIfError(result, "Cannot retrieve length of file '$_name'");
+ var result = _lengthFromPath(_path);
+ throwIfError(result, "Cannot retrieve length of file '$_path'");
return result;
}
Future<DateTime> lastModified() {
_ensureFileService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _LAST_MODIFIED_REQUEST;
- request[1] = _name;
+ request[1] = _path;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
"Cannot retrieve modification time "
- "for file '$_name'");
+ "for file '$_path'");
}
return new DateTime.fromMillisecondsSinceEpoch(response);
});
}
- external static _lastModified(String name);
+ external static _lastModified(String path);
DateTime lastModifiedSync() {
- var ms = _lastModified(name);
- throwIfError(ms, "Cannot retrieve modification time for file '$_name'");
+ var ms = _lastModified(path);
+ throwIfError(ms, "Cannot retrieve modification time for file '$_path'");
return new DateTime.fromMillisecondsSinceEpoch(ms);
}
- external static _open(String name, int mode);
+ external static _open(String path, int mode);
RandomAccessFile openSync([FileMode mode = FileMode.READ]) {
if (mode != FileMode.READ &&
@@ -426,9 +426,9 @@
throw new FileIOException("Unknown file mode. Use FileMode.READ, "
"FileMode.WRITE or FileMode.APPEND.");
}
- var id = _open(_name, mode._mode);
- throwIfError(id, "Cannot open file '$_name'");
- return new _RandomAccessFile(id, _name);
+ var id = _open(_path, mode._mode);
+ throwIfError(id, "Cannot open file '$_path'");
+ return new _RandomAccessFile(id, _path);
}
external static int _openStdio(int fd);
@@ -443,29 +443,29 @@
Future<String> fullPath() {
_ensureFileService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _FULL_PATH_REQUEST;
- request[1] = _name;
+ request[1] = _path;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
"Cannot retrieve full path"
- " for '$_name'");
+ " for '$_path'");
}
return response;
});
}
- external static _fullPath(String name);
+ external static _fullPath(String path);
String fullPathSync() {
- var result = _fullPath(_name);
- throwIfError(result, "Cannot retrieve full path for file '$_name'");
+ var result = _fullPath(_path);
+ throwIfError(result, "Cannot retrieve full path for file '$_path'");
return result;
}
Stream<List<int>> openRead() {
- return new _FileStream(_name);
+ return new _FileStream(_path);
}
IOSink<File> openWrite([FileMode mode = FileMode.WRITE]) {
@@ -525,9 +525,9 @@
var list = [];
var controller = new StreamController();
controller.stream
- .transform(new StringDecoder(encoding))
- .transform(new LineTransformer())
- .listen((line) => list.add(line));
+ .transform(new StringDecoder(encoding))
+ .transform(new LineTransformer())
+ .listen((line) => list.add(line));
controller.add(bytes);
controller.close();
return list;
@@ -590,9 +590,9 @@
writeAsBytesSync(_encodeString(contents, encoding), mode);
}
- String get name => _name;
+ String get path => _path;
- String toString() => "File: '$name'";
+ String toString() => "File: '$path'";
void _ensureFileService() {
if (_fileService == null) {
@@ -606,20 +606,20 @@
}
}
- final String _name;
+ final String _path;
SendPort _fileService;
}
class _RandomAccessFile extends _FileBase implements RandomAccessFile {
- _RandomAccessFile(int this._id, String this._name);
+ _RandomAccessFile(int this._id, String this._path);
Future<RandomAccessFile> close() {
Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
if (closed) return _completeWithClosedException(completer);
_ensureFileService();
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _CLOSE_REQUEST;
request[1] = _id;
// Set the id_ to 0 (NULL) to ensure the no more async requests
@@ -630,7 +630,7 @@
_id = result;
return this;
} else {
- throw new FileIOException("Cannot close file '$_name'");
+ throw new FileIOException("Cannot close file '$_path'");
}
});
}
@@ -641,7 +641,7 @@
_checkNotClosed();
var id = _close(_id);
if (id == -1) {
- throw new FileIOException("Cannot close file '$_name'");
+ throw new FileIOException("Cannot close file '$_path'");
}
_id = id;
}
@@ -650,13 +650,13 @@
_ensureFileService();
Completer<int> completer = new Completer<int>();
if (closed) return _completeWithClosedException(completer);
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _READ_BYTE_REQUEST;
request[1] = _id;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "readByte failed for file '$_name'");
+ "readByte failed for file '$_path'");
}
return response;
});
@@ -668,7 +668,7 @@
_checkNotClosed();
var result = _readByte(_id);
if (result is OSError) {
- throw new FileIOException("readByte failed for file '$_name'", result);
+ throw new FileIOException("readByte failed for file '$_path'", result);
}
return result;
}
@@ -682,7 +682,7 @@
// then handler.
Timer.run(() {
completer.completeError(new FileIOException(
- "Invalid arguments to read for file '$_name'"));
+ "Invalid arguments to read for file '$_path'"));
});
return completer.future;
};
@@ -694,7 +694,7 @@
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "read failed for file '$_name'");
+ "read failed for file '$_path'");
}
return response[1];
});
@@ -705,7 +705,7 @@
List<int> readSync(int bytes) {
if (bytes is !int) {
throw new FileIOException(
- "Invalid arguments to readSync for file '$_name'");
+ "Invalid arguments to readSync for file '$_path'");
}
return _read(_id, bytes);
}
@@ -719,19 +719,19 @@
// then handler.
Timer.run(() {
completer.completeError(new FileIOException(
- "Invalid arguments to readList for file '$_name'"));
+ "Invalid arguments to readList for file '$_path'"));
});
return completer.future;
};
if (closed) return _completeWithClosedException(completer);
- List request = new List.fixedLength(3);
+ List request = new List(3);
request[0] = _READ_LIST_REQUEST;
request[1] = _id;
request[2] = bytes;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "readList failed for file '$_name'");
+ "readList failed for file '$_path'");
}
var read = response[1];
var data = response[2];
@@ -754,13 +754,13 @@
_checkNotClosed();
if (buffer is !List || offset is !int || bytes is !int) {
throw new FileIOException(
- "Invalid arguments to readList for file '$_name'");
+ "Invalid arguments to readList for file '$_path'");
}
if (bytes == 0) return 0;
_checkReadWriteListArguments(buffer.length, offset, bytes);
var result = _readList(_id, buffer, offset, bytes);
if (result is OSError) {
- throw new FileIOException("readList failed for file '$_name'",
+ throw new FileIOException("readList failed for file '$_path'",
result);
}
return result;
@@ -775,19 +775,19 @@
// then handler.
Timer.run(() {
completer.completeError(new FileIOException(
- "Invalid argument to writeByte for file '$_name'"));
+ "Invalid argument to writeByte for file '$_path'"));
});
return completer.future;
}
if (closed) return _completeWithClosedException(completer);
- List request = new List.fixedLength(3);
+ List request = new List(3);
request[0] = _WRITE_BYTE_REQUEST;
request[1] = _id;
request[2] = value;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "writeByte failed for file '$_name'");
+ "writeByte failed for file '$_path'");
}
return this;
});
@@ -799,11 +799,11 @@
_checkNotClosed();
if (value is !int) {
throw new FileIOException(
- "Invalid argument to writeByte for file '$_name'");
+ "Invalid argument to writeByte for file '$_path'");
}
var result = _writeByte(_id, value);
if (result is OSError) {
- throw new FileIOException("writeByte failed for file '$_name'",
+ throw new FileIOException("writeByte failed for file '$_path'",
result);
}
return result;
@@ -818,7 +818,7 @@
// then handler.
Timer.run(() {
completer.completeError(new FileIOException(
- "Invalid arguments to writeList for file '$_name'"));
+ "Invalid arguments to writeList for file '$_path'"));
});
return completer.future;
}
@@ -835,7 +835,7 @@
return completer.future;
}
- List request = new List.fixedLength(5);
+ List request = new List(5);
request[0] = _WRITE_LIST_REQUEST;
request[1] = _id;
request[2] = result.buffer;
@@ -844,7 +844,7 @@
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "writeList failed for file '$_name'");
+ "writeList failed for file '$_path'");
}
return this;
});
@@ -856,7 +856,7 @@
_checkNotClosed();
if (buffer is !List || offset is !int || bytes is !int) {
throw new FileIOException(
- "Invalid arguments to writeList for file '$_name'");
+ "Invalid arguments to writeList for file '$_path'");
}
if (bytes == 0) return 0;
_checkReadWriteListArguments(buffer.length, offset, bytes);
@@ -865,7 +865,7 @@
var result =
_writeList(_id, bufferAndOffset.buffer, bufferAndOffset.offset, bytes);
if (result is OSError) {
- throw new FileIOException("writeList failed for file '$_name'", result);
+ throw new FileIOException("writeList failed for file '$_path'", result);
}
return result;
}
@@ -897,13 +897,13 @@
_ensureFileService();
Completer<int> completer = new Completer<int>();
if (closed) return _completeWithClosedException(completer);
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _POSITION_REQUEST;
request[1] = _id;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "position failed for file '$_name'");
+ "position failed for file '$_path'");
}
return response;
});
@@ -915,7 +915,7 @@
_checkNotClosed();
var result = _position(_id);
if (result is OSError) {
- throw new FileIOException("position failed for file '$_name'", result);
+ throw new FileIOException("position failed for file '$_path'", result);
}
return result;
}
@@ -924,14 +924,14 @@
_ensureFileService();
Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
if (closed) return _completeWithClosedException(completer);
- List request = new List.fixedLength(3);
+ List request = new List(3);
request[0] = _SET_POSITION_REQUEST;
request[1] = _id;
request[2] = position;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "setPosition failed for file '$_name'");
+ "setPosition failed for file '$_path'");
}
return this;
});
@@ -943,7 +943,7 @@
_checkNotClosed();
var result = _setPosition(_id, position);
if (result is OSError) {
- throw new FileIOException("setPosition failed for file '$_name'", result);
+ throw new FileIOException("setPosition failed for file '$_path'", result);
}
}
@@ -951,14 +951,14 @@
_ensureFileService();
Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
if (closed) return _completeWithClosedException(completer);
- List request = new List.fixedLength(3);
+ List request = new List(3);
request[0] = _TRUNCATE_REQUEST;
request[1] = _id;
request[2] = length;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "truncate failed for file '$_name'");
+ "truncate failed for file '$_path'");
}
return this;
});
@@ -970,7 +970,7 @@
_checkNotClosed();
var result = _truncate(_id, length);
if (result is OSError) {
- throw new FileIOException("truncate failed for file '$_name'", result);
+ throw new FileIOException("truncate failed for file '$_path'", result);
}
}
@@ -978,13 +978,13 @@
_ensureFileService();
Completer<int> completer = new Completer<int>();
if (closed) return _completeWithClosedException(completer);
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _LENGTH_REQUEST;
request[1] = _id;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "length failed for file '$_name'");
+ "length failed for file '$_path'");
}
return response;
});
@@ -996,7 +996,7 @@
_checkNotClosed();
var result = _length(_id);
if (result is OSError) {
- throw new FileIOException("length failed for file '$_name'", result);
+ throw new FileIOException("length failed for file '$_path'", result);
}
return result;
}
@@ -1005,13 +1005,13 @@
_ensureFileService();
Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
if (closed) return _completeWithClosedException(completer);
- List request = new List.fixedLength(2);
+ List request = new List(2);
request[0] = _FLUSH_REQUEST;
request[1] = _id;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
- "flush failed for file '$_name'");
+ "flush failed for file '$_path'");
}
return this;
});
@@ -1023,11 +1023,11 @@
_checkNotClosed();
var result = _flush(_id);
if (result is OSError) {
- throw new FileIOException("flush failed for file '$_name'", result);
+ throw new FileIOException("flush failed for file '$_path'", result);
}
}
- String get name => _name;
+ String get path => _path;
void _ensureFileService() {
if (_fileService == null) {
@@ -1039,19 +1039,19 @@
void _checkNotClosed() {
if (closed) {
- throw new FileIOException("File closed '$_name'");
+ throw new FileIOException("File closed '$_path'");
}
}
Future _completeWithClosedException(Completer completer) {
Timer.run(() {
completer.completeError(
- new FileIOException("File closed '$_name'"));
+ new FileIOException("File closed '$_path'"));
});
return completer.future;
}
- final String _name;
+ final String _path;
int _id;
SendPort _fileService;
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 103f2be..bbe8cd5 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -15,4 +15,5 @@
* if (entity is File) (entity as File).readAsStringSync();
*/
abstract class FileSystemEntity {
+ String get path;
}
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 9c5a6fb..feaeb0e 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -61,7 +61,7 @@
// TODO(ajohnsen): Document with example, once the stream API is final.
// TODO(ajohnsen): Add HttpServer.secure.
/**
- * Start listening for HTTP requests on the specified [host] and
+ * Starts listening for HTTP requests on the specified [address] and
* [port]. If a [port] of 0 is specified the server will choose an
* ephemeral port. The optional argument [backlog] can be used to
* specify the listen backlog for the underlying OS listen
@@ -73,13 +73,13 @@
=> _HttpServer.bind(address, port, backlog);
/**
- * Start listening for HTTPS requests on the specified [host] and
+ * Starts listening for HTTPS requests on the specified [address] and
* [port]. If a [port] of 0 is specified the server will choose an
* ephemeral port. The optional argument [backlog] can be used to
* specify the listen backlog for the underlying OS listen
* setup.
*
- * The certificate with Distinguished Name [certificate_name] is looked
+ * The certificate with Distinguished Name [certificateName] is looked
* up in the certificate database, and is used as the server certificate.
* if [requestClientCertificate] is true, the server will request clients
* to authenticate with a client certificate.
@@ -97,34 +97,34 @@
requestClientCertificate);
/**
- * Attach the HTTP server to an existing [:ServerSocket:]. When the
+ * Attaches the HTTP server to an existing [ServerSocket]. When the
* [HttpServer] is closed, the [HttpServer] will just detach itself,
- * close current connections but not close [serverSocket].
+ * closing current connections but not closing [serverSocket].
*/
factory HttpServer.listenOn(ServerSocket serverSocket)
=> new _HttpServer.listenOn(serverSocket);
/**
- * Stop server listening. This will make the [Stream] close with a done
- * event.
+ * Permanently stops this [HttpServer] from listening for new connections.
+ * This closes this [Stream] of [HttpRequest]s with a done event.
*/
void close();
/**
* Returns the port that the server is listening on. This can be
- * used to get the actual port used when a value of 0 for [port] is
- * specified in the [listen] call.
+ * used to get the actual port used when a value of 0 for [:port:] is
+ * specified in the [bind] or [bindSecure] call.
*/
int get port;
/**
- * Set the timeout, in seconds, for sessions of this HTTP server. Default
- * is 20 minutes.
+ * Sets the timeout, in seconds, for sessions of this [HttpServer].
+ * The default timeout is 20 minutes.
*/
set sessionTimeout(int timeout);
/**
- * Returns a [:HttpConnectionsInfo:] object with an overview of the
+ * Returns an [HttpConnectionsInfo] object summarizing the number of
* current connections handled by the server.
*/
HttpConnectionsInfo connectionsInfo();
@@ -132,7 +132,7 @@
/**
- * Overview information of the [:HttpServer:] socket connections.
+ * Summary statistics about an [HttpServer]s current socket connections.
*/
class HttpConnectionsInfo {
/**
@@ -162,60 +162,64 @@
/**
* Access to the HTTP headers for requests and responses. In some
- * situations the headers will be imutable and the mutating methods
+ * situations the headers will be immutable and the mutating methods
* will then throw exceptions.
*
- * For all operation on HTTP headers the header name is
+ * For all operations on HTTP headers the header name is
* case-insensitive.
*/
abstract class HttpHeaders {
- static const ACCEPT = "Accept";
- static const ACCEPT_CHARSET = "Accept-Charset";
- static const ACCEPT_ENCODING = "Accept-Encoding";
- static const ACCEPT_LANGUAGE = "Accept-Language";
- static const ACCEPT_RANGES = "Accept-Ranges";
- static const AGE = "Age";
- static const ALLOW = "Allow";
- static const AUTHORIZATION = "Authorization";
- static const CACHE_CONTROL = "Cache-Control";
- static const CONNECTION = "Connection";
- static const CONTENT_ENCODING = "Content-Encoding";
- static const CONTENT_LANGUAGE = "Content-Language";
- static const CONTENT_LENGTH = "Content-Length";
- static const CONTENT_LOCATION = "Content-Location";
- static const CONTENT_MD5 = "Content-MD5";
- static const CONTENT_RANGE = "Content-Range";
- static const CONTENT_TYPE = "Content-Type";
- static const DATE = "Date";
- static const ETAG = "ETag";
- static const EXPECT = "Expect";
- static const EXPIRES = "Expires";
- static const FROM = "From";
- static const HOST = "Host";
- static const IF_MATCH = "If-Match";
- static const IF_MODIFIED_SINCE = "If-Modified-Since";
- static const IF_NONE_MATCH = "If-None-Match";
- static const IF_RANGE = "If-Range";
- static const IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
- static const LAST_MODIFIED = "Last-Modified";
- static const LOCATION = "Location";
- static const MAX_FORWARDS = "Max-Forwards";
- static const PRAGMA = "Pragma";
- static const PROXY_AUTHENTICATE = "Proxy-Authenticate";
- static const PROXY_AUTHORIZATION = "Proxy-Authorization";
- static const RANGE = "Range";
- static const REFERER = "Referer";
- static const RETRY_AFTER = "Retry-After";
- static const SERVER = "Server";
- static const TE = "TE";
- static const TRAILER = "Trailer";
- static const TRANSFER_ENCODING = "Transfer-Encoding";
- static const UPGRADE = "Upgrade";
- static const USER_AGENT = "User-Agent";
- static const VARY = "Vary";
- static const VIA = "Via";
- static const WARNING = "Warning";
- static const WWW_AUTHENTICATE = "WWW-Authenticate";
+ static const ACCEPT = "accept";
+ static const ACCEPT_CHARSET = "accept-charset";
+ static const ACCEPT_ENCODING = "accept-encoding";
+ static const ACCEPT_LANGUAGE = "accept-language";
+ static const ACCEPT_RANGES = "accept-ranges";
+ static const AGE = "age";
+ static const ALLOW = "allow";
+ static const AUTHORIZATION = "authorization";
+ static const CACHE_CONTROL = "cache-control";
+ static const CONNECTION = "connection";
+ static const CONTENT_ENCODING = "content-encoding";
+ static const CONTENT_LANGUAGE = "content-language";
+ static const CONTENT_LENGTH = "content-length";
+ static const CONTENT_LOCATION = "content-location";
+ static const CONTENT_MD5 = "content-md5";
+ static const CONTENT_RANGE = "content-range";
+ static const CONTENT_TYPE = "content-type";
+ static const DATE = "date";
+ static const ETAG = "etag";
+ static const EXPECT = "expect";
+ static const EXPIRES = "expires";
+ static const FROM = "from";
+ static const HOST = "host";
+ static const IF_MATCH = "if-match";
+ static const IF_MODIFIED_SINCE = "if-modified-since";
+ static const IF_NONE_MATCH = "if-none-match";
+ static const IF_RANGE = "if-range";
+ static const IF_UNMODIFIED_SINCE = "if-unmodified-since";
+ static const LAST_MODIFIED = "last-modified";
+ static const LOCATION = "location";
+ static const MAX_FORWARDS = "max-forwards";
+ static const PRAGMA = "pragma";
+ static const PROXY_AUTHENTICATE = "proxy-authenticate";
+ static const PROXY_AUTHORIZATION = "proxy-authorization";
+ static const RANGE = "range";
+ static const REFERER = "referer";
+ static const RETRY_AFTER = "retry-after";
+ static const SERVER = "server";
+ static const TE = "te";
+ static const TRAILER = "trailer";
+ static const TRANSFER_ENCODING = "transfer-encoding";
+ static const UPGRADE = "upgrade";
+ static const USER_AGENT = "user-agent";
+ static const VARY = "vary";
+ static const VIA = "via";
+ static const WARNING = "warning";
+ static const WWW_AUTHENTICATE = "www-authenticate";
+
+ // Cookie headers from RFC 6265.
+ static const COOKIE = "cookie";
+ static const SET_COOKIE = "set-cookie";
static const GENERAL_HEADERS = const [CACHE_CONTROL,
CONNECTION,
@@ -271,13 +275,13 @@
/**
* Returns the list of values for the header named [name]. If there
- * is no headers with the provided name [:null:] will be returned.
+ * is no header with the provided name, [:null:] will be returned.
*/
List<String> operator[](String name);
/**
- * Convenience method for the value for a single values header. If
- * there is no header with the provided name [:null:] will be
+ * Convenience method for the value for a single valued header. If
+ * there is no header with the provided name, [:null:] will be
* returned. If the header has more than one value an exception is
* thrown.
*/
@@ -286,7 +290,7 @@
/**
* Adds a header value. The header named [name] will have the value
* [value] added to its list of values. Some headers are single
- * values and for these adding a value will replace the previous
+ * valued, and for these adding a value will replace the previous
* value. If the value is of type DateTime a HTTP date format will be
* applied. If the value is a [:List:] each element of the list will
* be added separately. For all other types the default [:toString:]
@@ -308,7 +312,7 @@
void remove(String name, Object value);
/**
- * Remove all values for the specified header name. Some headers
+ * Removes all values for the specified header name. Some headers
* have system supplied values and for these the system supplied
* values will still be added to the collection of values for the
* header.
@@ -316,46 +320,46 @@
void removeAll(String name);
/**
- * Enumerate the headers applying the function [f] to each
- * header. The header name passed in [name] will be all lower
+ * Enumerates the headers, applying the function [f] to each
+ * header. The header name passed in [:name:] will be all lower
* case.
*/
void forEach(void f(String name, List<String> values));
/**
- * Disable folding for the header named [name] when sending the HTTP
+ * Disables folding for the header named [name] when sending the HTTP
* header. By default, multiple header values are folded into a
* single header line by separating the values with commas. The
- * Set-Cookie header has folding disabled by default.
+ * 'set-cookie' header has folding disabled by default.
*/
void noFolding(String name);
/**
* Gets and sets the date. The value of this property will
- * reflect the "DateTime" header.
+ * reflect the 'date' header.
*/
DateTime date;
/**
* Gets and sets the expiry date. The value of this property will
- * reflect the "Expires" header.
+ * reflect the 'expires' header.
*/
DateTime expires;
/**
- * Gets and sets the 'if-modified-since' date. The value of this property will
+ * Gets and sets the "if-modified-since" date. The value of this property will
* reflect the "if-modified-since" header.
*/
DateTime ifModifiedSince;
/**
- * Gets and sets the host part of the "Host" header for the
+ * Gets and sets the host part of the 'host' header for the
* connection.
*/
String host;
/**
- * Gets and sets the port part of the "Host" header for the
+ * Gets and sets the port part of the 'host' header for the
* connection.
*/
int port;
@@ -367,6 +371,16 @@
* effect.
*/
ContentType contentType;
+
+ /**
+ * Gets and sets the content length header value.
+ */
+ int contentLength;
+
+ /**
+ * Gets and sets the persistent connection header value.
+ */
+ bool persistentConnection;
}
@@ -378,7 +392,7 @@
* [HeaderValue] can be used to conveniently build and parse header
* values on this form.
*
- * To build an [:Accepts:] header with the value
+ * To build an [:accepts:] header with the value
*
* text/plain; q=0.3, text/html
*
@@ -436,23 +450,23 @@
abstract class HttpSession implements Map {
/**
- * Get the id for the current session.
+ * Gets the id for the current session.
*/
String get id;
/**
- * Destroy the session. This will terminate the session and any further
+ * Destroys the session. This will terminate the session and any further
* connections with this id will be given a new id and session.
*/
void destroy();
/**
- * Set a callback that will be called when the session is timed out.
+ * Sets a callback that will be called when the session is timed out.
*/
void set onTimeout(void callback());
/**
- * Is true if the session have not been sent to the client yet.
+ * Is true if the session has not been sent to the client yet.
*/
bool get isNew;
}
@@ -510,8 +524,8 @@
/**
* Representation of a cookie. For cookies received by the server as
* Cookie header values only [:name:] and [:value:] fields will be
- * set. When building a cookie for the Set-Cookie header in the server
- * and when receiving cookies in the client as Set-Cookie headers all
+ * set. When building a cookie for the 'set-cookie' header in the server
+ * and when receiving cookies in the client as 'set-cookie' headers all
* fields can be used.
*/
abstract class Cookie {
@@ -521,7 +535,7 @@
factory Cookie([String name, String value]) => new _Cookie(name, value);
/**
- * Creates a new cookie by parsing a header value from a Set-Cookie
+ * Creates a new cookie by parsing a header value from a 'set-cookie'
* header.
*/
factory Cookie.fromSetCookieValue(String value) {
@@ -572,7 +586,7 @@
/**
* Returns the formatted string representation of the cookie. The
* string representation can be used for for setting the Cookie or
- * Set-Cookie headers
+ * 'set-cookie' headers
*/
String toString();
}
@@ -629,10 +643,10 @@
X509Certificate get certificate;
/**
- * Get the session for the given request. If the session is
+ * Gets the session for the given request. If the session is
* being initialized by this call, [:isNew:] will be true for the returned
* session.
- * See [:HttpServer.sessionTimeout:] on how to change default timeout.
+ * See [HttpServer.sessionTimeout] on how to change default timeout.
*/
HttpSession get session;
@@ -643,13 +657,13 @@
String get protocolVersion;
/**
- * Get information about the client connection. Returns [null] if the socket
- * isn't available.
+ * Gets information about the client connection. Returns [null] if the socket
+ * is not available.
*/
HttpConnectionInfo get connectionInfo;
/**
- * Get the [HttpResponse] object, used for sending back the response to the
+ * Gets the [HttpResponse] object, used for sending back the response to the
* client.
*/
HttpResponse get response;
@@ -695,12 +709,12 @@
HttpHeaders get headers;
/**
- * Cookies to set in the client (in the Set-Cookie header).
+ * Cookies to set in the client (in the 'set-cookie' header).
*/
List<Cookie> get cookies;
/**
- * Detach the underlying socket from the HTTP server. When the
+ * Detaches the underlying socket from the HTTP server. When the
* socket is detached the HTTP server will no longer perform any
* operations on it.
*
@@ -710,8 +724,8 @@
Future<Socket> detachSocket();
/**
- * Get information about the client connection. Returns [null] if the socket
- * isn't available.
+ * Gets information about the client connection. Returns [null] if the socket
+ * is not available.
*/
HttpConnectionInfo get connectionInfo;
}
@@ -734,10 +748,10 @@
/**
* Opens a HTTP connection. The returned [HttpClientRequest] is used to
- * fill in the content of the request before sending it. The "Host" header for
+ * fill in the content of the request before sending it. The 'host' header for
* the request will be set to the value [host]:[port]. This can be overridden
* through the [HttpClientRequest] interface before the request is sent.
- * NOTE if [host] is an IP address this will still be set in the "Host"
+ * NOTE if [host] is an IP address this will still be set in the 'host'
* header.
*/
Future<HttpClientRequest> open(String method,
@@ -747,10 +761,10 @@
/**
* Opens a HTTP connection. The returned [HttpClientRequest] is used to
- * fill in the content of the request before sending it. The "Host" header for
+ * fill in the content of the request before sending it. The 'hosth header for
* the request will be set to the value [host]:[port]. This can be overridden
* through the [HttpClientRequest] interface before the request is sent.
- * NOTE if [host] is an IP address this will still be set in the "Host"
+ * NOTE if [host] is an IP address this will still be set in the 'host'
* header.
*/
Future<HttpClientRequest> openUrl(String method, Uri url);
@@ -803,23 +817,6 @@
void addCredentials(Uri url, String realm, HttpClientCredentials credentials);
/**
- * If [sendClientCertificate] is set to true, authenticate with a client
- * certificate when connecting with an HTTPS server that requests one.
- * Select the certificate from the certificate database that matches
- * the authorities listed by the HTTPS server as valid.
- * If [clientCertificate] is set, send the certificate with that nickname
- * instead.
- */
- set sendClientCertificate(bool send);
-
- /**
- * If [clientCertificate] is non-null and [sendClientCertificate] is true,
- * use [clientCertificate] to select the certificate to send from the
- * certificate database, looking it up by its nickname.
- */
- set clientCertificate(String nickname);
-
- /**
* Sets the function used to resolve the proxy server to be used for
* opening a HTTP connection to the specified [url]. If this
* function is not set, direct connections will always be used.
@@ -882,7 +879,7 @@
HttpHeaders get headers;
/**
- * Cookies to present to the server (in the Cookie header).
+ * Cookies to present to the server (in the 'cookie' header).
*/
List<Cookie> get cookies;
@@ -894,7 +891,7 @@
/**
* A [HttpClientResponse] future that will complete once the response is
- * available. If an error occours before the response is available, this
+ * available. If an error occurs before the response is available, this
* future will complete with an error.
*/
Future<HttpClientResponse> get response;
@@ -934,7 +931,7 @@
/**
* Get information about the client connection. Returns [null] if the socket
- * isn't available.
+ * is not available.
*/
HttpConnectionInfo get connectionInfo;
}
@@ -944,7 +941,6 @@
* HTTP response for a client connection. The [HttpClientResponse] is a
* [Stream] of the body content of the response. Listen to the body to handle
* the data and be notified once the entire body is received.
-
*/
abstract class HttpClientResponse implements Stream<List<int>> {
/**
@@ -958,8 +954,8 @@
String get reasonPhrase;
/**
- * Returns the content length of the request body. If the size of
- * the request body is not known in advance this -1.
+ * Returns the content length of the request body. Returns -1 if the size of
+ * the request body is not known in advance.
*/
int get contentLength;
@@ -970,34 +966,34 @@
/**
* Returns whether the status code is one of the normal redirect
- * codes [:HttpStatus.MOVED_PERMANENTLY:], [:HttpStatus.FOUND:],
- * [:HttpStatus.MOVED_TEMPORARILY:], [:HttpStatus.SEE_OTHER:] and
- * [:HttpStatus.TEMPORARY_REDIRECT:].
+ * codes [HttpStatus.MOVED_PERMANENTLY], [HttpStatus.FOUND],
+ * [HttpStatus.MOVED_TEMPORARILY], [HttpStatus.SEE_OTHER] and
+ * [HttpStatus.TEMPORARY_REDIRECT].
*/
bool get isRedirect;
/**
* Returns the series of redirects this connection has been through. The
- * list will be empty if no redirects was followed. [redirects] will be
+ * list will be empty if no redirects were followed. [redirects] will be
* updated both in the case of an automatic and a manual redirect.
*/
List<RedirectInfo> get redirects;
/**
- * Redirect this connection to a new URL. The default value for
+ * Redirects this connection to a new URL. The default value for
* [method] is the method for the current request. The default value
- * for [url] is the value of the [:HttpHeaders.LOCATION:] header of
+ * for [url] is the value of the [HttpHeaders.LOCATION] header of
* the current response. All body data must have been read from the
* current response before calling [redirect].
*
* All headers added to the request will be added to the redirection
- * request(s). However, any body send with the request will not be
- * part of the redirection request(s).
+ * request. However, any body sent with the request will not be
+ * part of the redirection request.
*
* If [followLoops] is set to [true], redirect will follow the redirect,
- * even if was already visited. Default value is [false].
+ * even if the URL was already visited. The default value is [false].
*
- * [redirect] will ignore [maxRedirects] and always perform the redirect.
+ * [redirect] will ignore [maxRedirects] and will always perform the redirect.
*/
Future<HttpClientResponse> redirect([String method,
Uri url,
@@ -1020,7 +1016,7 @@
Future<Socket> detachSocket();
/**
- * Cookies set by the server (from the Set-Cookie header).
+ * Cookies set by the server (from the 'set-cookie' header).
*/
List<Cookie> get cookies;
@@ -1031,8 +1027,8 @@
X509Certificate get certificate;
/**
- * Get information about the client connection. Returns [null] if the socket
- * isn't available.
+ * Gets information about the client connection. Returns [null] if the socket
+ * is not available.
*/
HttpConnectionInfo get connectionInfo;
}
@@ -1042,7 +1038,7 @@
/**
- * Represent credentials for basic authentication.
+ * Represents credentials for basic authentication.
*/
abstract class HttpClientBasicCredentials extends HttpClientCredentials {
factory HttpClientBasicCredentials(String username, String password) =>
@@ -1051,7 +1047,7 @@
/**
- * Represent credentials for digest authentication.
+ * Represents credentials for digest authentication.
*/
abstract class HttpClientDigestCredentials extends HttpClientCredentials {
factory HttpClientDigestCredentials(String username, String password) =>
@@ -1060,7 +1056,8 @@
/**
- * Connection information.
+ * Information about an [HttpRequest], [HttpResponse], [HttpClientRequest], or
+ * [HttpClientResponse] connection.
*/
abstract class HttpConnectionInfo {
String get remoteHost;
diff --git a/sdk/lib/io/http_headers.dart b/sdk/lib/io/http_headers.dart
index 949ace3..9d586d4 100644
--- a/sdk/lib/io/http_headers.dart
+++ b/sdk/lib/io/http_headers.dart
@@ -50,6 +50,7 @@
if (index != -1) {
values.removeRange(index, 1);
}
+ if (values.length == 0) _headers.remove(name);
}
}
@@ -69,7 +70,7 @@
}
bool get persistentConnection {
- List<String> connection = this[HttpHeaders.CONNECTION];
+ List<String> connection = _headers[HttpHeaders.CONNECTION];
if (protocolVersion == "1.1") {
if (connection == null) return true;
return !connection.any((value) => value.toLowerCase() == "close");
@@ -97,9 +98,9 @@
_checkMutable();
_contentLength = contentLength;
if (_contentLength >= 0) {
- _set("content-length", contentLength.toString());
+ _set(HttpHeaders.CONTENT_LENGTH, contentLength.toString());
} else {
- removeAll("content-length");
+ removeAll(HttpHeaders.CONTENT_LENGTH);
}
}
@@ -108,13 +109,14 @@
void set chunkedTransferEncoding(bool chunkedTransferEncoding) {
_checkMutable();
_chunkedTransferEncoding = chunkedTransferEncoding;
- List<String> values = _headers["transfer-encoding"];
- if (values == null || values[values.length - 1] != "chunked") {
+ List<String> values = _headers[HttpHeaders.TRANSFER_ENCODING];
+ if ((values == null || values[values.length - 1] != "chunked") &&
+ chunkedTransferEncoding) {
// Headers does not specify chunked encoding - add it if set.
- if (chunkedTransferEncoding) _addValue("transfer-encoding", "chunked");
- } else {
+ _addValue(HttpHeaders.TRANSFER_ENCODING, "chunked");
+ } else if (!chunkedTransferEncoding) {
// Headers does specify chunked encoding - remove it if not set.
- if (!chunkedTransferEncoding) remove("transfer-encoding", "chunked");
+ remove(HttpHeaders.TRANSFER_ENCODING, "chunked");
}
}
@@ -135,7 +137,7 @@
}
DateTime get ifModifiedSince {
- List<String> values = _headers["if-modified-since"];
+ List<String> values = _headers[HttpHeaders.IF_MODIFIED_SINCE];
if (values != null) {
try {
return _HttpUtils.parseDate(values[0]);
@@ -150,11 +152,11 @@
_checkMutable();
// Format "ifModifiedSince" header with date in Greenwich Mean Time (GMT).
String formatted = _HttpUtils.formatDate(ifModifiedSince.toUtc());
- _set("if-modified-since", formatted);
+ _set(HttpHeaders.IF_MODIFIED_SINCE, formatted);
}
DateTime get date {
- List<String> values = _headers["date"];
+ List<String> values = _headers[HttpHeaders.DATE];
if (values != null) {
try {
return _HttpUtils.parseDate(values[0]);
@@ -173,7 +175,7 @@
}
DateTime get expires {
- List<String> values = _headers["expires"];
+ List<String> values = _headers[HttpHeaders.EXPIRES];
if (values != null) {
try {
return _HttpUtils.parseDate(values[0]);
@@ -188,7 +190,7 @@
_checkMutable();
// Format "Expires" header with date in Greenwich Mean Time (GMT).
String formatted = _HttpUtils.formatDate(expires.toUtc());
- _set("expires", formatted);
+ _set(HttpHeaders.EXPIRES, formatted);
}
ContentType get contentType {
@@ -202,13 +204,13 @@
void set contentType(ContentType contentType) {
_checkMutable();
- _set("content-type", contentType.toString());
+ _set(HttpHeaders.CONTENT_TYPE, contentType.toString());
}
void _add(String name, Object value) {
var lowerCaseName = name.toLowerCase();
// TODO(sgjesse): Add immutable state throw HttpException is immutable.
- if (lowerCaseName == "content-length") {
+ if (lowerCaseName == HttpHeaders.CONTENT_LENGTH) {
if (value is int) {
contentLength = value;
} else if (value is String) {
@@ -216,37 +218,37 @@
} else {
throw new HttpException("Unexpected type for header named $name");
}
- } else if (lowerCaseName == "transfer-encoding") {
+ } else if (lowerCaseName == HttpHeaders.TRANSFER_ENCODING) {
if (value == "chunked") {
chunkedTransferEncoding = true;
} else {
_addValue(lowerCaseName, value);
}
- } else if (lowerCaseName == "date") {
+ } else if (lowerCaseName == HttpHeaders.DATE) {
if (value is DateTime) {
date = value;
} else if (value is String) {
- _set("date", value);
+ _set(HttpHeaders.DATE, value);
} else {
throw new HttpException("Unexpected type for header named $name");
}
- } else if (lowerCaseName == "expires") {
+ } else if (lowerCaseName == HttpHeaders.EXPIRES) {
if (value is DateTime) {
expires = value;
} else if (value is String) {
- _set("expires", value);
+ _set(HttpHeaders.EXPIRES, value);
} else {
throw new HttpException("Unexpected type for header named $name");
}
- } else if (lowerCaseName == "if-modified-since") {
+ } else if (lowerCaseName == HttpHeaders.IF_MODIFIED_SINCE) {
if (value is DateTime) {
ifModifiedSince = value;
} else if (value is String) {
- _set("if-modified-since", value);
+ _set(HttpHeaders.IF_MODIFIED_SINCE, value);
} else {
throw new HttpException("Unexpected type for header named $name");
}
- } else if (lowerCaseName == "host") {
+ } else if (lowerCaseName == HttpHeaders.HOST) {
if (value is String) {
int pos = (value as String).indexOf(":");
if (pos == -1) {
@@ -268,12 +270,12 @@
}
}
}
- _set("host", value);
+ _set(HttpHeaders.HOST, value);
} else {
throw new HttpException("Unexpected type for header named $name");
}
- } else if (lowerCaseName == "content-type") {
- _set("content-type", value);
+ } else if (lowerCaseName == HttpHeaders.CONTENT_TYPE) {
+ _set(HttpHeaders.CONTENT_TYPE, value);
} else {
_addValue(lowerCaseName, value);
}
@@ -310,7 +312,7 @@
}
_foldHeader(String name) {
- if (name == "set-cookie" ||
+ if (name == HttpHeaders.SET_COOKIE ||
(_noFoldingHeaders != null &&
_noFoldingHeaders.indexOf(name) != -1)) {
return false;
@@ -321,8 +323,12 @@
void _finalize() {
// If the content length is not known make sure chunked transfer
// encoding is used for HTTP 1.1.
- if (contentLength < 0 && protocolVersion == "1.1") {
- chunkedTransferEncoding = true;
+ if (contentLength < 0) {
+ if (protocolVersion == "1.0") {
+ persistentConnection = false;
+ } else {
+ chunkedTransferEncoding = true;
+ }
}
// If a Transfer-Encoding header field is present the
// Content-Length header MUST NOT be sent (RFC 2616 section 4.4).
@@ -352,7 +358,7 @@
_headers.forEach((String name, List<String> values) {
bool fold = _foldHeader(name);
List<int> nameData;
- nameData = name.charCodes;
+ nameData = name.codeUnits;
int nameDataLen = nameData.length;
if (nameDataLen + 2 > bufferSize - bufferPos) writeBuffer();
buffer.setRange(bufferPos, nameDataLen, nameData);
@@ -360,7 +366,7 @@
buffer[bufferPos++] = _CharCode.COLON;
buffer[bufferPos++] = _CharCode.SP;
for (int i = 0; i < values.length; i++) {
- List<int> data = values[i].charCodes;
+ List<int> data = values[i].codeUnits;
int dataLen = data.length;
// Worst case here is writing the name, value and 6 additional bytes.
if (nameDataLen + dataLen + 6 > bufferSize - bufferPos) writeBuffer();
@@ -466,7 +472,7 @@
expect(";");
}
}
- List<String> values = this["cookie"];
+ List<String> values = _headers[HttpHeaders.COOKIE];
if (values != null) {
values.forEach((headerValue) => parseCookieString(headerValue));
}
@@ -659,11 +665,11 @@
_Cookie([String this.name, String this.value]);
_Cookie.fromSetCookieValue(String value) {
- // Parse the Set-Cookie header value.
+ // Parse the 'set-cookie' header value.
_parseSetCookieValue(value);
}
- // Parse a Set-Cookie header value according to the rules in RFC 6265.
+ // Parse a 'set-cookie' header value according to the rules in RFC 6265.
void _parseSetCookieValue(String s) {
int index = 0;
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 8bc8a98..31099cc 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -4,8 +4,7 @@
part of dart.io;
-class _HttpIncoming
- extends Stream<List<int>> implements StreamSink<List<int>> {
+class _HttpIncoming extends Stream<List<int>> {
final int _transferLength;
final Completer _dataCompleter = new Completer();
Stream<List<int>> _stream;
@@ -54,7 +53,7 @@
}
}
-class _HttpInboundMessage extends Stream<List<int>> {
+abstract class _HttpInboundMessage extends Stream<List<int>> {
final _HttpIncoming _incoming;
List<Cookie> _cookies;
@@ -65,7 +64,7 @@
return _cookies = headers._parseCookies();
}
- HttpHeaders get headers => _incoming.headers;
+ _HttpHeaders get headers => _incoming.headers;
String get protocolVersion => headers.protocolVersion;
int get contentLength => headers.contentLength;
bool get persistentConnection => headers.persistentConnection;
@@ -82,7 +81,7 @@
final _HttpConnection _httpConnection;
- HttpSession _session;
+ _HttpSession _session;
_HttpRequest(_HttpResponse this.response,
_HttpIncoming _incoming,
@@ -167,10 +166,15 @@
int get statusCode => _incoming.statusCode;
String get reasonPhrase => _incoming.reasonPhrase;
+ X509Certificate get certificate {
+ var socket = _httpRequest._httpClientConnection._socket;
+ return socket.peerCertificate;
+ }
+
List<Cookie> get cookies {
if (_cookies != null) return _cookies;
_cookies = new List<Cookie>();
- List<String> values = headers["set-cookie"];
+ List<String> values = headers[HttpHeaders.SET_COOKIE];
if (values != null) {
values.forEach((value) {
_cookies.add(new Cookie.fromSetCookieValue(value));
@@ -314,14 +318,21 @@
}
-class _HttpOutboundMessage<T> extends IOSink {
+abstract class _HttpOutboundMessage<T> implements IOSink {
// Used to mark when the body should be written. This is used for HEAD
// requests and in error handling.
bool _ignoreBody = false;
+ bool _headersWritten = false;
+ bool _chunked = false;
+
+ final IOSink _ioSink;
+ final _HttpOutgoing _outgoing;
+
+ final _HttpHeaders headers;
_HttpOutboundMessage(String protocolVersion, _HttpOutgoing outgoing)
- : super(outgoing),
- _outgoing = outgoing,
+ : _outgoing = outgoing,
+ _ioSink = new IOSink(outgoing),
headers = new _HttpHeaders(protocolVersion);
int get contentLength => headers.contentLength;
@@ -330,7 +341,7 @@
}
bool get persistentConnection => headers.persistentConnection;
- bool set persistentConnection(bool p) {
+ void set persistentConnection(bool p) {
headers.persistentConnection = p;
}
@@ -341,19 +352,33 @@
// Transform when chunked.
stream = stream.transform(new _ChunkedTransformer());
}
- return super.consume(stream).then((_) => this);
+ return _ioSink.consume(stream).then((_) => this);
}
void add(List<int> data) {
_writeHeaders();
- if (_ignoreBody) return;
+ if (_ignoreBody || data.length == 0) return;
if (_chunked) {
- _ChunkedTransformer._addChunk(data, super.add);
+ _ChunkedTransformer._addChunk(data, _ioSink.add);
} else {
- super.add(data);
+ _ioSink.add(data);
}
}
+ void addString(String string, [Encoding encoding = Encoding.UTF_8]) {
+ add(_encodeString(string, encoding));
+ }
+
+ Future<T> addStream(Stream<List<int>> stream) {
+ _writeHeaders();
+ if (_ignoreBody) return new Future.immediate(this);
+ if (_chunked) {
+ // Transform when chunked.
+ stream = stream.transform(new _ChunkedTransformer(writeEnd: false));
+ }
+ return _ioSink.addStream(stream).then((_) => this);
+ }
+
void close() {
if (!_headersWritten && !_ignoreBody && headers.chunkedTransferEncoding) {
// If no body was written, _ignoreBody is false (it's not a HEAD
@@ -363,12 +388,14 @@
_writeHeaders();
if (!_ignoreBody) {
if (_chunked) {
- _ChunkedTransformer._addChunk([], super.add);
+ _ChunkedTransformer._addChunk([], _ioSink.add);
}
}
- super.close();
+ _ioSink.close();
}
+ Future<T> get done => _ioSink.done.then((_) => this);
+
void _writeHeaders() {
if (_headersWritten) return;
bool _tmpIgnoreBody = _ignoreBody;
@@ -377,22 +404,16 @@
_writeHeader();
_ignoreBody = _tmpIgnoreBody;
if (_ignoreBody) {
- super.close();
+ _ioSink.close();
return;
}
_chunked = headers.chunkedTransferEncoding;
- if (!_chunked) {
+ if (headers.contentLength >= 0) {
_outgoing.setTransferLength(headers.contentLength);
}
}
void _writeHeader(); // TODO(ajohnsen): Better name.
-
- final _HttpHeaders headers;
-
- final _HttpOutgoing _outgoing;
- bool _headersWritten = false;
- bool _chunked = false;
}
@@ -466,7 +487,7 @@
// Add all the cookies set to the headers.
if (_cookies != null) {
_cookies.forEach((cookie) {
- headers.add("set-cookie", cookie);
+ headers.add(HttpHeaders.SET_COOKIE, cookie);
});
}
@@ -657,7 +678,7 @@
sb.add("=");
sb.add(cookies[i].value);
}
- headers.add("cookie", sb.toString());
+ headers.add(HttpHeaders.COOKIE, sb.toString());
}
headers._finalize();
@@ -670,21 +691,19 @@
// Transformer that transforms data to HTTP Chunked Encoding.
-class _ChunkedTransformer implements StreamTransformer<List<int>, List<int>> {
- final StreamController<List<int>> _controller
- = new StreamController<List<int>>();
+class _ChunkedTransformer extends StreamEventTransformer<List<int>, List<int>> {
+ final bool writeEnd;
+ _ChunkedTransformer({this.writeEnd: true});
- Stream<List<int>> bind(Stream<List<int>> stream) {
- var subscription = stream.listen(
- (data) {
- if (data.length == 0) return; // Avoid close on 0-bytes payload.
- _addChunk(data, _controller.add);
- },
- onDone: () {
- _addChunk([], _controller.add);
- _controller.close();
- });
- return _controller.stream;
+ void handleData(List<int> data, StreamSink<List<int>> sink) {
+ _addChunk(data, sink.add);
+ }
+
+ void handleDone(StreamSink<List<int>> sink) {
+ if (writeEnd) {
+ _addChunk([], sink.add);
+ }
+ sink.close();
}
static void _addChunk(List<int> data, void add(List<int> data)) {
@@ -738,17 +757,12 @@
// Transformer that validates the data written.
class _DataValidatorTransformer
implements StreamTransformer<List<int>, List<int>> {
- final StreamController<List<int>> _controller
- = new StreamController<List<int>>();
+ final StreamController<List<int>> _controller =
+ new StreamController<List<int>>();
int _bytesWritten = 0;
- Completer _completer = new Completer();
int expectedTransferLength;
- _DataValidatorTransformer();
-
- Future get validatorFuture => _completer.future;
-
Stream<List<int>> bind(Stream<List<int>> stream) {
var subscription;
subscription = stream.listen(
@@ -756,45 +770,31 @@
if (expectedTransferLength != null) {
_bytesWritten += data.length;
if (_bytesWritten > expectedTransferLength) {
- _controller.close();
subscription.cancel();
- if (_completer != null) {
- _completer.completeError(new HttpException(
- "Content size exceeds specified contentLength. "
- "$_bytesWritten bytes written while expected "
- "$expectedTransferLength."));
- _completer = null;
- }
+ _controller.signalError(new HttpException(
+ "Content size exceeds specified contentLength. "
+ "$_bytesWritten bytes written while expected "
+ "$expectedTransferLength."));
+ _controller.close();
return;
}
}
_controller.add(data);
},
onError: (error) {
+ _controller.signalError(error);
_controller.close();
- if (_completer != null) {
- _completer.completeError(error);
- _completer = null;
- }
},
onDone: () {
- _controller.close();
if (expectedTransferLength != null) {
if (_bytesWritten < expectedTransferLength) {
- if (_completer != null) {
- _completer.completeError(new HttpException(
- "Content size below specified contentLength. "
- " $_bytesWritten bytes written while expected "
- "$expectedTransferLength."));
- _completer = null;
- return;
- }
+ _controller.signalError(new HttpException(
+ "Content size below specified contentLength. "
+ " $_bytesWritten bytes written while expected "
+ "$expectedTransferLength."));
}
}
- if (_completer != null) {
- _completer.complete(this);
- _completer = null;
- }
+ _controller.close();
},
unsubscribeOnError: true);
return _controller.stream;
@@ -803,31 +803,25 @@
// Extends StreamConsumer as this is an internal type, only used to pipe to.
class _HttpOutgoing implements StreamConsumer<List<int>, dynamic> {
- final Completer _dataCompleter = new Completer();
- final Completer _streamCompleter = new Completer();
final _DataValidatorTransformer _validator = new _DataValidatorTransformer();
+ Function _onStream;
+ final Completer _consumeCompleter = new Completer();
- // Future that completes when all data is written.
- Future get dataDone => _dataCompleter.future;
-
- // Future that completes with the Stream, once the _HttpClientConnection is
- // bound to one.
- Future<Stream<List<int>>> get stream => _streamCompleter.future;
+ Future onStream(Future callback(Stream<List<int>> stream)) {
+ _onStream = callback;
+ return _consumeCompleter.future;
+ }
void setTransferLength(int transferLength) {
_validator.expectedTransferLength = transferLength;
}
Future consume(Stream<List<int>> stream) {
- stream = stream.transform(_validator);
- _streamCompleter.complete(stream);
- _validator.validatorFuture.catchError((e) {
- _dataCompleter.completeError(e);
- });
- return _validator.validatorFuture.then((v) {
- _dataCompleter.complete();
- return v;
- });
+ _onStream(stream.transform(_validator))
+ .then((_) => _consumeCompleter.complete(),
+ onError: _consumeCompleter.completeError);
+ // Use .then to ensure a Future branch.
+ return _consumeCompleter.future.then((_) => this);
}
}
@@ -840,7 +834,7 @@
final _HttpClient _httpClient;
Completer<_HttpIncoming> _nextResponseCompleter;
- Future _writeDoneFuture;
+ Future _streamFuture;
_HttpClientConnection(String this.key,
Socket this._socket,
@@ -858,11 +852,14 @@
_subscription.pause();
// We assume the response is not here, until we have send the request.
assert(_nextResponseCompleter != null);
- _nextResponseCompleter.complete(incoming);
+ var completer = _nextResponseCompleter;
+ _nextResponseCompleter = null;
+ completer.complete(incoming);
},
onError: (error) {
if (_nextResponseCompleter != null) {
_nextResponseCompleter.completeError(error);
+ _nextResponseCompleter = null;
}
},
onDone: () {
@@ -870,37 +867,66 @@
});
}
- Future<_HttpIncoming> sendRequest(_HttpOutgoing outgoing) {
- return outgoing.stream
- .then((stream) {
- // Close socket if output data is invalid.
- outgoing.dataDone.catchError((e) {
- close();
- });
+ _HttpClientRequest send(Uri uri, int port, String method, bool isDirect) {
+ // Start with pausing the parser.
+ _subscription.pause();
+ var outgoing = new _HttpOutgoing();
+ // Create new request object, wrapping the outgoing connection.
+ var request = new _HttpClientRequest(outgoing,
+ uri,
+ method,
+ !isDirect,
+ _httpClient,
+ this);
+ request.headers.host = uri.domain;
+ request.headers.port = port;
+ if (uri.userInfo != null && !uri.userInfo.isEmpty) {
+ // If the URL contains user information use that for basic
+ // authorization
+ String auth =
+ CryptoUtils.bytesToBase64(_encodeString(uri.userInfo));
+ request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
+ } else {
+ // Look for credentials.
+ _Credentials cr = _httpClient._findCredentials(uri);
+ if (cr != null) {
+ cr.authorize(request);
+ }
+ }
+ // Start sending the request (lazy, delayed until the user provides
+ // data).
+ _httpParser.responseToMethod = method;
+ _streamFuture = outgoing.onStream((stream) {
// Sending request, set up response completer.
_nextResponseCompleter = new Completer();
- _writeDoneFuture = _socket.addStream(stream);
+
+ var requestFuture = _socket.addStream(stream)
+ .catchError((e) {
+ destroy();
+ throw e;
+ });
+
// Listen for response.
- return _nextResponseCompleter.future
- .whenComplete(() {
- _nextResponseCompleter = null;
- })
+ _nextResponseCompleter.future
.then((incoming) {
incoming.dataDone.then((_) {
- if (!incoming.headers.persistentConnection) {
- close();
+ if (incoming.headers.persistentConnection &&
+ request.persistentConnection) {
+ // Be sure we have written the full request.
+ requestFuture
+ .then((_) {
+ // Return connection, now we are done.
+ _httpClient._returnConnection(this);
+ _subscription.resume();
+ },
+ onError: (_) {
+ // Already handled.
+ });
} else {
- // Wait for the socket to be done with writing, before we
- // continue.
- _writeDoneFuture.then((_) {
- _subscription.resume();
- // Return connection, now we are done.
- _httpClient._returnConnection(this);
- });
+ destroy();
}
});
- // TODO(ajohnsen): Can there be an error on dataDone?
- return incoming;
+ request._onIncoming(incoming);
})
// If we see a state error, we failed to get the 'first' element.
// Transform the error to a HttpParserException, for consistency.
@@ -911,32 +937,32 @@
.catchError((error) {
// We are done with the socket.
destroy();
- throw error;
+ request._onError(error);
});
- });
+ // Resume the parser now we have a handler.
+ _subscription.resume();
+ return requestFuture;
+ });
+ return request;
}
Future<Socket> detachSocket() {
- return _writeDoneFuture.then((_) =>
- new _DetachedSocket(_socket, _httpParser.detachIncoming()));
+ return _streamFuture
+ .then((_) => new _DetachedSocket(_socket, _httpParser.detachIncoming()),
+ onError: (_) {});
}
void destroy() {
- _socket.destroy();
_httpClient._connectionClosed(this);
+ _socket.destroy();
}
void close() {
- var future = _writeDoneFuture;
- if (future == null) future = new Future.immediate(null);
_httpClient._connectionClosed(this);
- future.then((_) {
- _socket.close();
- // TODO(ajohnsen): Add timeout.
- // Delay destroy until socket is actually done writing.
- _socket.done.then((_) => _socket.destroy(),
- onError: (_) => _socket.destroy());
- });
+ _streamFuture
+ // TODO(ajohnsen): Add timeout.
+ .then((_) => _socket.destroy(),
+ onError: (_) {});
}
HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket);
@@ -1055,55 +1081,19 @@
return new Future.immediateError(error, stackTrace);
}
}
- return _getConnection(uri.domain, port, proxyConf, isSecure).then((info) {
- // Create new internal outgoing connection.
- var outgoing = new _HttpOutgoing();
- // Create new request object, wrapping the outgoing connection.
- var request = new _HttpClientRequest(outgoing,
- uri,
- method.toUpperCase(),
- !info.proxy.isDirect,
- this,
- info.connection);
- request.headers.host = uri.domain;
- request.headers.port = port;
- if (uri.userInfo != null && !uri.userInfo.isEmpty) {
- // If the URL contains user information use that for basic
- // authorization
- String auth =
- CryptoUtils.bytesToBase64(_encodeString(uri.userInfo));
- request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
- } else {
- // Look for credentials.
- _Credentials cr = _findCredentials(uri);
- if (cr != null) {
- cr.authorize(request);
- }
- }
- // Start sending the request (lazy, delayed until the user provides
- // data).
- info.connection._httpParser.responseToMethod = method;
- info.connection.sendRequest(outgoing)
- .then((incoming) {
- // The full request have been sent and a response is received
- // containing status-code, headers and etc.
- request._onIncoming(incoming);
- })
- .catchError((error) {
- // An error occoured before the http-header was parsed. This
- // could be either a socket-error or parser-error.
- request._onError(error);
- });
- // Return the request to the user. Immediate socket errors are not
- // handled, thus forwarded to the user.
- return request;
+ return _getConnection(uri.domain, port, proxyConf, isSecure)
+ .then((info) {
+ return info.connection.send(uri,
+ port,
+ method.toUpperCase(),
+ info.proxy.isDirect);
});
}
Future<HttpClientRequest> _openUrlFromRequest(String method,
Uri uri,
_HttpClientRequest previous) {
- return openUrl(method, uri).then((request) {
+ return openUrl(method, uri).then((_HttpClientRequest request) {
// Only follow redirects if initial request did.
request.followRedirects = previous.followRedirects;
// Allow same number of redirects.
@@ -1220,7 +1210,7 @@
final _HttpParser _httpParser;
StreamSubscription _subscription;
- Future _writeDoneFuture;
+ Future _streamFuture;
_HttpConnection(Socket this._socket, _HttpServer this._httpServer)
: _httpParser = new _HttpParser.requestParser() {
@@ -1233,37 +1223,37 @@
_subscription.pause();
_state = _ACTIVE;
var outgoing = new _HttpOutgoing();
- _writeDoneFuture = outgoing.stream.then(_socket.addStream);
- var response = new _HttpResponse(
- incoming.headers.protocolVersion,
- outgoing);
+ var response = new _HttpResponse(incoming.headers.protocolVersion,
+ outgoing);
var request = new _HttpRequest(response, incoming, _httpServer, this);
+ outgoing.onStream((stream) {
+ return _streamFuture = _socket.addStream(stream)
+ .then((_) {
+ if (_state == _DETACHED) return;
+ if (response.persistentConnection &&
+ request.persistentConnection &&
+ incoming.fullBodyRead) {
+ _state = _IDLE;
+ // Resume the subscription for incoming requests as the
+ // request is now processed.
+ _subscription.resume();
+ } else {
+ // Close socket, keep-alive not used or body sent before
+ // received data was handled.
+ destroy();
+ }
+ })
+ .catchError((e) {
+ destroy();
+ throw e;
+ });
+ });
response._ignoreBody = request.method == "HEAD";
response._httpRequest = request;
- outgoing.dataDone.then((_) {
- if (_state == _DETACHED) return;
- if (response.headers.persistentConnection &&
- incoming.fullBodyRead) {
- // Wait for the socket to be done with writing, before we
- // continue.
- _writeDoneFuture.then((_) {
- _state = _IDLE;
- // Resume the subscription for incoming requests as the
- // request is now processed.
- _subscription.resume();
- });
- } else {
- // Close socket, keep-alive not used or body sent before received
- // data was handled.
- close();
- }
- }).catchError((e) {
- close();
- });
_httpServer._handleRequest(request);
},
onDone: () {
- close();
+ destroy();
},
onError: (error) {
_httpServer._handleError(error);
@@ -1278,21 +1268,6 @@
_httpServer._connectionClosed(this);
}
- void close() {
- if (_state == _CLOSING || _state == _DETACHED) return;
- _state = _CLOSING;
- var future = _writeDoneFuture;
- if (future == null) future = new Future.immediate(null);
- _httpServer._connectionClosed(this);
- future.then((_) {
- _socket.close();
- // TODO(ajohnsen): Add timeout.
- // Delay destroy until socket is actually done writing.
- _socket.done.then((_) => _socket.destroy(),
- onError: (_) => _socket.destroy());
- });
- }
-
Future<Socket> detachSocket() {
_state = _DETACHED;
// Remove connection from server.
@@ -1300,7 +1275,7 @@
_HttpDetachedIncoming detachedIncoming = _httpParser.detachIncoming();
- return _writeDoneFuture.then((_) {
+ return _streamFuture.then((_) {
return new _DetachedSocket(_socket, detachedIncoming);
});
}
@@ -1517,7 +1492,7 @@
}
-class _DetachedSocket implements Socket {
+class _DetachedSocket extends Stream<List<int>> implements Socket {
final Stream<List<int>> _incoming;
final Socket _socket;
@@ -1547,7 +1522,11 @@
void destroy() => _socket.destroy();
void add(List<int> data) => _socket.add(data);
- Future<Socket> close() => _socket.close();
+ void close() => _socket.close();
+ Future<Socket> get done => _socket.done;
+ int get port => _socket.port;
+ String get remoteHost => _socket.remoteHost;
+ int get remotePort => _socket.remotePort;
}
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index 7dc258e..68fbc32 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -108,12 +108,18 @@
controller = new StreamController<List<int>>(
onSubscriptionStateChange: onSubscriptionStateChange,
onPauseStateChange: onPauseStateChange);
- pause();
- if (oldResumeCompleter != null) oldResumeCompleter.complete();
- subscription.resume();
- subscription.onData(controller.add);
- subscription.onDone(controller.close);
- subscription.onError(controller.signalError);
+ if (subscription == null) {
+ // Socket was already closed.
+ if (carryOverData != null) controller.add(carryOverData);
+ controller.close();
+ } else {
+ pause();
+ if (oldResumeCompleter != null) oldResumeCompleter.complete();
+ subscription.resume();
+ subscription.onData(controller.add);
+ subscription.onDone(controller.close);
+ subscription.onError(controller.signalError);
+ }
}
StreamSubscription<List<int>> listen(void onData(List<int> event),
@@ -209,7 +215,7 @@
}
- StreamSubscription<_HttpIncoming> listen(void onData(List<int> event),
+ StreamSubscription<_HttpIncoming> listen(void onData(_HttpIncoming event),
{void onError(AsyncError error),
void onDone(),
bool unsubscribeOnError}) {
@@ -840,9 +846,9 @@
}
int _toLowerCase(int byte) {
- final int aCode = "A".charCodeAt(0);
- final int zCode = "Z".charCodeAt(0);
- final int delta = "a".charCodeAt(0) - aCode;
+ final int aCode = "A".codeUnitAt(0);
+ final int zCode = "Z".codeUnitAt(0);
+ final int delta = "a".codeUnitAt(0) - aCode;
return (aCode <= byte && byte <= zCode) ? byte + delta : byte;
}
@@ -868,7 +874,7 @@
assert(_incoming == null);
assert(_bodyController == null);
_bodyController = new StreamController<List<int>>(
- onSubscriptionStateChange: _updateParsePauseState,
+ onSubscriptionStateChange: _bodySubscriptionStateChange,
onPauseStateChange: _updateParsePauseState);
_incoming = new _HttpIncoming(
_headers, transferLength, _bodyController.stream);
@@ -896,6 +902,14 @@
_paused = true;
}
+ void _bodySubscriptionStateChange() {
+ if (_incoming != null && !_bodyController.hasSubscribers) {
+ _closeIncoming();
+ } else {
+ _updateParsePauseState();
+ }
+ }
+
void _updateParsePauseState() {
if (_bodyController != null) {
if (_bodyController.hasSubscribers && !_bodyController.isPaused) {
diff --git a/sdk/lib/io/http_utils.dart b/sdk/lib/io/http_utils.dart
index a68f08f..8fe62ed 100644
--- a/sdk/lib/io/http_utils.dart
+++ b/sdk/lib/io/http_utils.dart
@@ -18,7 +18,7 @@
// Start decoding from the first encoded character.
List<int> bytes = new List<int>();
- for (int i = 0; i < index; i++) bytes.add(urlEncoded.charCodeAt(i));
+ for (int i = 0; i < index; i++) bytes.add(urlEncoded.codeUnitAt(i));
for (int i = index; i < urlEncoded.length; i++) {
if (urlEncoded[i] == "+") {
bytes.add(32);
@@ -28,7 +28,7 @@
}
int byte = 0;
for (int j = 0; j < 2; j++) {
- var charCode = urlEncoded.charCodeAt(i + j + 1);
+ var charCode = urlEncoded.codeUnitAt(i + j + 1);
if (0x30 <= charCode && charCode <= 0x39) {
byte = byte * 16 + charCode - 0x30;
} else {
@@ -44,7 +44,7 @@
bytes.add(byte);
i += 2;
} else {
- bytes.add(urlEncoded.charCodeAt(i));
+ bytes.add(urlEncoded.codeUnitAt(i));
}
}
return decodeUtf8(bytes);
@@ -229,7 +229,7 @@
int seconds;
if (format == formatAsctime) {
month = expectMonth(" ");
- if (date.charCodeAt(index) == SP) index++;
+ if (date.codeUnitAt(index) == SP) index++;
day = expectNum(" ");
hours = expectNum(":");
minutes = expectNum(":");
@@ -265,7 +265,7 @@
}
bool isDelimiter(String s) {
- int char = s.charCodeAt(0);
+ int char = s.codeUnitAt(0);
if (char == 0x09) return true;
if (char >= 0x20 && char <= 0x2F) return true;
if (char >= 0x3B && char <= 0x40) return true;
@@ -275,7 +275,7 @@
}
bool isNonDelimiter(String s) {
- int char = s.charCodeAt(0);
+ int char = s.codeUnitAt(0);
if (char >= 0x00 && char <= 0x08) return true;
if (char >= 0x0A && char <= 0x1F) return true;
if (char >= 0x30 && char <= 0x39) return true; // Digit
@@ -287,7 +287,7 @@
}
bool isDigit(String s) {
- int char = s.charCodeAt(0);
+ int char = s.codeUnitAt(0);
if (char > 0x2F && char < 0x3A) return true;
return false;
}
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index b7d2843..0ff9b24 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -38,7 +38,7 @@
part 'http_parser.dart';
part 'http_session.dart';
part 'http_utils.dart';
-part 'io_stream_consumer.dart';
+part 'io_sink.dart';
part 'mime_multipart_parser.dart';
part 'path.dart';
part 'path_impl.dart';
diff --git a/sdk/lib/io/io_stream_consumer.dart b/sdk/lib/io/io_sink.dart
similarity index 76%
rename from sdk/lib/io/io_stream_consumer.dart
rename to sdk/lib/io/io_sink.dart
index 51b59ab..ace6f92 100644
--- a/sdk/lib/io/io_stream_consumer.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -10,11 +10,48 @@
* buffers the input given by [add] and [addString] and will delay a [consume]
* or [addStream] until the buffer is flushed.
*
- * When the [IOSink] is bound to a stream (through either [comsume]
+ * When the [IOSink] is bound to a stream (through either [consume]
* or [addStream]) any call to the [IOSink] will throw a
* [StateError].
*/
-class IOSink<T> implements StreamConsumer<List<int>, T> {
+abstract class IOSink<T> implements StreamConsumer<List<int>, T> {
+ factory IOSink(StreamConsumer<List<int>, T> target)
+ => new _IOSinkImpl(target);
+
+ /**
+ * Provide functionality for piping to the [IOSink].
+ */
+ Future<T> consume(Stream<List<int>> stream);
+
+ /**
+ * Like [consume], but will not close the target when done.
+ */
+ Future<T> addStream(Stream<List<int>> stream);
+
+ /**
+ * Write a list of bytes to the target.
+ */
+ void add(List<int> data);
+
+ /**
+ * Write a String to the target.
+ */
+ void addString(String string, [Encoding encoding = Encoding.UTF_8]);
+
+ /**
+ * Close the target.
+ */
+ void close();
+
+ /**
+ * Get future that will complete when all data has been written to
+ * the IOSink and it has been closed.
+ */
+ Future<T> get done;
+}
+
+
+class _IOSinkImpl<T> implements IOSink<T> {
final StreamConsumer<List<int>, T> _target;
StreamController<List<int>> _controllerInstance;
@@ -22,11 +59,8 @@
StreamSubscription<List<int>> _bindSubscription;
bool _paused = true;
- IOSink(StreamConsumer<List<int>, T> target) : _target = target;
+ _IOSinkImpl(StreamConsumer<List<int>, T> target) : _target = target;
- /**
- * Provide functionality for piping to the [IOSink].
- */
Future<T> consume(Stream<List<int>> stream) {
if (_isBound) {
throw new StateError("IOSink is already bound to a stream");
@@ -34,9 +68,6 @@
return _fillFromStream(stream);
}
- /**
- * Like [consume], but will not close the target when done.
- */
Future<T> addStream(Stream<List<int>> stream) {
if (_isBound) {
throw new StateError("IOSink is already bound to a stream");
@@ -44,9 +75,6 @@
return _fillFromStream(stream, unbind: true);
}
- /**
- * Write a list of bytes to the target.
- */
void add(List<int> data) {
if (_isBound) {
throw new StateError("IOSink is already bound to a stream");
@@ -54,16 +82,10 @@
_controller.add(data);
}
- /**
- * Write a String to the target.
- */
void addString(String string, [Encoding encoding = Encoding.UTF_8]) {
add(_encodeString(string, encoding));
}
- /**
- * Close the target.
- */
void close() {
if (_isBound) {
throw new StateError("IOSink is already bound to a stream");
@@ -71,10 +93,6 @@
_controller.close();
}
- /**
- * Get future that will complete when all data has been written to
- * the IOSink and it has been closed.
- */
Future<T> get done {
_controller;
return _pipeFuture.then((_) => this);
@@ -85,7 +103,7 @@
_controllerInstance = new StreamController<List<int>>(
onPauseStateChange: _onPauseStateChange,
onSubscriptionStateChange: _onSubscriptionStateChange);
- _pipeFuture = _controller.stream.pipe(_target);
+ _pipeFuture = _controller.stream.pipe(_target).then((_) => this);
}
return _controllerInstance;
}
@@ -139,12 +157,22 @@
if (unbind) {
unbindCompleter = new Completer<T>();
}
+ completeUnbind([error]) {
+ if (unbindCompleter == null) return;
+ var tmp = unbindCompleter;
+ unbindCompleter = null;
+ if (error == null) {
+ _bindSubscription = null;
+ tmp.complete();
+ } else {
+ tmp.completeError(error);
+ }
+ }
_bindSubscription = stream.listen(
_controller.add,
onDone: () {
- _bindSubscription = null;
if (unbind) {
- unbindCompleter.complete(null);
+ completeUnbind();
} else {
_controller.close();
}
@@ -152,9 +180,12 @@
onError: _controller.signalError);
if (_paused) _pause();
if (unbind) {
+ _pipeFuture
+ .then((_) => completeUnbind(),
+ onError: (error) => completeUnbind(error));
return unbindCompleter.future;
} else {
- return _pipeFuture;
+ return _pipeFuture.then((_) => this);
}
}
}
diff --git a/sdk/lib/io/iolib_sources.gypi b/sdk/lib/io/iolib_sources.gypi
index b695556..92113b4 100644
--- a/sdk/lib/io/iolib_sources.gypi
+++ b/sdk/lib/io/iolib_sources.gypi
@@ -19,7 +19,7 @@
'http_parser.dart',
'http_session.dart',
'http_utils.dart',
- 'io_stream_consumer.dart',
+ 'io_sink.dart',
'mime_multipart_parser.dart',
'path.dart',
'path_impl.dart',
diff --git a/sdk/lib/io/mime_multipart_parser.dart b/sdk/lib/io/mime_multipart_parser.dart
index 1ae374c..51f6b7f 100644
--- a/sdk/lib/io/mime_multipart_parser.dart
+++ b/sdk/lib/io/mime_multipart_parser.dart
@@ -41,8 +41,8 @@
// [boundary]. The boundary should be as specified in the content
// type parameter, that is without the -- prefix.
_MimeMultipartParser(String boundary) {
- List<int> charCodes = boundary.charCodes;
- _boundary = new List<int>.fixedLength(4 + charCodes.length);
+ List<int> charCodes = boundary.codeUnits;
+ _boundary = new List<int>(4 + charCodes.length);
// Set-up the matching boundary preceding it with CRLF and two
// dashes.
_boundary[0] = _CharCode.CR;
@@ -293,9 +293,9 @@
}
int _toLowerCase(int byte) {
- final int aCode = "A".charCodeAt(0);
- final int zCode = "Z".charCodeAt(0);
- final int delta = "a".charCodeAt(0) - aCode;
+ final int aCode = "A".codeUnitAt(0);
+ final int zCode = "Z".codeUnitAt(0);
+ final int delta = "a".codeUnitAt(0) - aCode;
return (aCode <= byte && byte <= zCode) ? byte + delta : byte;
}
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index deb3c83..e3c62e9 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -79,7 +79,7 @@
[ProcessOptions options]);
/**
- * Returns an input stream of the process stdout.
+ * Returns the standard output stream of the process as a [:Stream:].
*
* Throws an [UnsupportedError] if the process is
* non-interactive.
@@ -87,7 +87,7 @@
Stream<List<int>> get stdout;
/**
- * Returns an input stream of the process stderr.
+ * Returns the standard error stream of the process as a [:Stream:].
*
* Throws an [UnsupportedError] if the process is
* non-interactive.
@@ -95,7 +95,7 @@
Stream<List<int>> get stderr;
/**
- * Returns an output stream to the process stdin.
+ * Returns the standard input stream of the process as an [IOSink].
*
* Throws an [UnsupportedError] if the process is
* non-interactive.
@@ -103,8 +103,8 @@
IOSink<Process> get stdin;
/**
- * Sets an exit handler which gets invoked when the process
- * terminates.
+ * Returns a [:Future:] which completes with the exit code of the process
+ * when the process completes.
*
* Throws an [UnsupportedError] if the process is
* non-interactive.
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 333edd1..62ecb4d 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -283,7 +283,7 @@
})
.catchError((error) {
_handshakeComplete.completeError(error);
- close();
+ _close();
});
}
@@ -341,6 +341,10 @@
}
void close() {
+ shutdown(SocketDirection.BOTH);
+ }
+
+ void _close() {
_closedWrite = true;
_closedRead = true;
if (_socket != null) {
@@ -360,24 +364,25 @@
}
void shutdown(SocketDirection direction) {
- if (direction == SocketDirection.BOTH) {
- close();
- } else if (direction == SocketDirection.SEND) {
+ if (direction == SocketDirection.SEND ||
+ direction == SocketDirection.BOTH) {
_closedWrite = true;
_writeEncryptedData();
if (_filterWriteEmpty) {
_socket.shutdown(SocketDirection.SEND);
_socketClosedWrite = true;
if (_closedRead) {
- close();
+ _close();
}
}
- } else if (direction == SocketDirection.RECEIVE) {
+ }
+ if (direction == SocketDirection.RECEIVE ||
+ direction == SocketDirection.BOTH) {
_closedRead = true;
_socketClosedRead = true;
_socket.shutdown(SocketDirection.RECEIVE);
if (_socketClosedWrite) {
- close();
+ _close();
}
}
}
@@ -386,9 +391,10 @@
void set writeEventsEnabled(bool value) {
if (value &&
+ _controller.hasSubscribers &&
_secureFilter != null &&
_secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
- new Timer(0, (_) => _controller.add(RawSocketEvent.WRITE));
+ Timer.run(() => _controller.add(RawSocketEvent.WRITE));
} else {
_writeEventsEnabled = value;
}
@@ -398,11 +404,12 @@
void set readEventsEnabled(bool value) {
_readEventsEnabled = value;
- if (_socketClosedRead) {
- if (value) {
- // We have no underlying socket to set off read events.
- new Timer(0, (_) => _readHandler());
- }
+ if (value &&
+ ((_secureFilter != null &&
+ _secureFilter.buffers[READ_PLAINTEXT].length > 0) ||
+ _socketClosedRead)) {
+ // We might not have no underlying socket to set off read events.
+ Timer.run(_readHandler);
}
}
@@ -431,7 +438,7 @@
// Set up a read event if the filter still has data.
if (!_filterReadEmpty) {
- new Timer(0, (_) => _readHandler());
+ Timer.run(_readHandler);
}
if (_socketClosedRead) { // An onClose event is pending.
@@ -445,7 +452,7 @@
if (_filterReadEmpty) {
// This can't be an else clause: the value of _filterReadEmpty changes.
// This must be asynchronous, because we are in a read call.
- new Timer(0, (_) => _closeHandler());
+ Timer.run(_closeHandler);
}
}
@@ -489,6 +496,7 @@
_secureHandshake();
} catch (e) { _reportError(e, "RawSecureSocket error"); }
} else if (_status == CONNECTED &&
+ _controller.hasSubscribers &&
_writeEventsEnabled &&
_secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
// Reset the one-shot handler.
@@ -530,7 +538,7 @@
}
if (_socketClosedRead) {
// Keep firing read events until we are paused or buffer is empty.
- new Timer(0, (_) => _readHandler());
+ Timer.run(_readHandler);
}
}
} else if (_socketClosedRead) {
@@ -541,7 +549,7 @@
void _doneHandler() {
if (_filterReadEmpty) {
- close();
+ _close();
}
}
@@ -566,7 +574,7 @@
} else {
_controller.signalError(e);
}
- close();
+ _close();
}
void _closeHandler() {
@@ -577,7 +585,7 @@
_closedRead = true;
_controller.add(RawSocketEvent.READ_CLOSED);
if (_socketClosedWrite) {
- close();
+ _close();
}
}
} else if (_status == HANDSHAKE) {
@@ -600,7 +608,7 @@
// If we complete the future synchronously, user code will run here,
// and modify the state of the RawSecureSocket. For example, it
// could close the socket, and set _filter to null.
- new Timer(0, (_) => _handshakeComplete.complete(this));
+ Timer.run(() => _handshakeComplete.complete(this));
}
}
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index b0c04b4..aa05fdc 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -200,7 +200,7 @@
* send a close event on the stream and will no longer react on data being
* piped to it.
*
- * Call [close](inherited by [IOSink]) to only close the [Socket]
+ * Call [close](inherited from [IOSink]) to only close the [Socket]
* for sending data.
*/
void destroy();
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index 857b8dc..cea080a 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.dart
@@ -45,7 +45,7 @@
break;
case Encoding.ASCII:
if (replacementChar == null) {
- replacementChar = '?'.charCodeAt(0);
+ replacementChar = '?'.codeUnitAt(0);
} else if (replacementChar > 127) {
throw new ArgumentError("Invalid replacement character for ASCII");
}
@@ -53,7 +53,7 @@
break;
case Encoding.ISO_8859_1:
if (replacementChar == null) {
- replacementChar = '?'.charCodeAt(0);
+ replacementChar = '?'.codeUnitAt(0);
} else if (replacementChar > 255) {
throw new ArgumentError(
"Invalid replacement character for ISO_8859_1");
@@ -153,131 +153,83 @@
}
-class LineTransformer implements StreamTransformer<String, String> {
+class LineTransformer extends StreamEventTransformer<String, String> {
const int _LF = 10;
const int _CR = 13;
final StringBuffer _buffer = new StringBuffer();
-
- StreamSubscription<String> _subscription;
- StreamController<String> _controller;
String _carry;
- Stream<String> bind(Stream<String> stream) {
- _controller = new StreamController<String>(
- onPauseStateChange: _pauseChanged,
- onSubscriptionStateChange: _subscriptionChanged);
-
- void handle(String data, bool isClosing) {
- if (_carry != null) {
- data = _carry.concat(data);
- _carry = null;
- }
- int startPos = 0;
- int pos = 0;
- while (pos < data.length) {
- int skip = 0;
- int char = data.charCodeAt(pos);
- if (char == _LF) {
- skip = 1;
- } else if (char == _CR) {
- skip = 1;
- if (pos + 1 < data.length) {
- if (data.charCodeAt(pos + 1) == _LF) {
- skip = 2;
- }
- } else if (!isClosing) {
- _carry = data.substring(startPos);
- return;
+ void _handle(String data, StreamSink<String> sink, bool isClosing) {
+ if (_carry != null) {
+ data = _carry.concat(data);
+ _carry = null;
+ }
+ int startPos = 0;
+ int pos = 0;
+ while (pos < data.length) {
+ int skip = 0;
+ int char = data.codeUnitAt(pos);
+ if (char == _LF) {
+ skip = 1;
+ } else if (char == _CR) {
+ skip = 1;
+ if (pos + 1 < data.length) {
+ if (data.codeUnitAt(pos + 1) == _LF) {
+ skip = 2;
}
- }
- if (skip > 0) {
- _buffer.add(data.substring(startPos, pos));
- _controller.add(_buffer.toString());
- _buffer.clear();
- startPos = pos = pos + skip;
- } else {
- pos++;
+ } else if (!isClosing) {
+ _carry = data.substring(startPos);
+ return;
}
}
- if (pos != startPos) {
- // Add remaining
+ if (skip > 0) {
_buffer.add(data.substring(startPos, pos));
- }
- if (isClosing && !_buffer.isEmpty) {
- _controller.add(_buffer.toString());
+ sink.add(_buffer.toString());
_buffer.clear();
+ startPos = pos = pos + skip;
+ } else {
+ pos++;
}
}
-
- _subscription = stream.listen(
- (data) => handle(data, false),
- onDone: () {
- // Handle remaining data (mainly _carry).
- handle("", true);
- _controller.close();
- },
- onError: _controller.signalError);
- return _controller.stream;
- }
-
- void _pauseChanged() {
- if (_controller.isPaused) {
- _subscription.pause();
- } else {
- _subscription.resume();
+ if (pos != startPos) {
+ // Add remaining
+ _buffer.add(data.substring(startPos, pos));
+ }
+ if (isClosing && !_buffer.isEmpty) {
+ sink.add(_buffer.toString());
+ _buffer.clear();
}
}
- void _subscriptionChanged() {
- if (!_controller.hasSubscribers) {
- _subscription.cancel();
- }
+ void handleData(String data, StreamSink<String> sink) {
+ _handle(data, sink, false);
+ }
+
+ void handleDone(StreamSink<String> sink) {
+ _handle("", sink, true);
+ sink.close();
}
}
-class _SingleByteDecoder implements StreamTransformer<List<int>, String> {
- StreamSubscription<List<int>> _subscription;
- StreamController<String> _controller;
+abstract class _SingleByteDecoder
+ extends StreamEventTransformer<List<int>, String> {
final int _replacementChar;
_SingleByteDecoder(this._replacementChar);
- Stream<String> bind(Stream<List<int>> stream) {
- _controller = new StreamController<String>(
- onPauseStateChange: _pauseChanged,
- onSubscriptionStateChange: _subscriptionChanged);
- _subscription = stream.listen(
- (data) {
- var buffer = new List<int>.fixedLength(data.length);
- for (int i = 0; i < data.length; i++) {
- int char = _decodeByte(data[i]);
- if (char < 0) char = _replacementChar;
- buffer[i] = char;
- }
- _controller.add(new String.fromCharCodes(buffer));
- },
- onDone: _controller.close,
- onError: _controller.signalError);
- return _controller.stream;
+ void handleData(List<int> data, StreamSink<String> sink) {
+ var buffer = new List<int>(data.length);
+ for (int i = 0; i < data.length; i++) {
+ int char = _decodeByte(data[i]);
+ if (char < 0) char = _replacementChar;
+ buffer[i] = char;
+ }
+ sink.add(new String.fromCharCodes(buffer));
}
int _decodeByte(int byte);
-
- void _pauseChanged() {
- if (_controller.isPaused) {
- _subscription.pause();
- } else {
- _subscription.resume();
- }
- }
-
- void _subscriptionChanged() {
- if (!_controller.hasSubscribers) {
- _subscription.cancel();
- }
- }
}
@@ -299,53 +251,28 @@
}
-class _SingleByteEncoder implements StreamTransformer<String, List<int>> {
- StreamSubscription<String> _subscription;
- StreamController<List<int>> _controller;
-
- Stream<List<int>> bind(Stream<String> stream) {
- _controller = new StreamController<List<int>>(
- onPauseStateChange: _pauseChanged,
- onSubscriptionStateChange: _subscriptionChanged);
- _subscription = stream.listen(
- (string) {
- var bytes = _encode(string);
- if (bytes == null) {
- _controller.signalError(new FormatException(
- "Invalid character for encoding"));
- _controller.close();
- _subscription.cancel();
- } else {
- _controller.add(bytes);
- }
- },
- onDone: _controller.close,
- onError: _controller.signalError);
- return _controller.stream;
+abstract class _SingleByteEncoder
+ extends StreamEventTransformer<String, List<int>> {
+ void handleData(String data, StreamSink<List<int>> sink) {
+ var bytes = _encode(data);
+ if (bytes == null) {
+ sink.signalError(
+ new AsyncError(
+ new FormatException("Invalid character for encoding")));
+ sink.close();
+ } else {
+ sink.add(bytes);
+ }
}
List<int> _encode(String string);
-
- void _pauseChanged() {
- if (_controller.isPaused) {
- _subscription.pause();
- } else {
- _subscription.resume();
- }
- }
-
- void _subscriptionChanged() {
- if (!_controller.hasSubscribers) {
- _subscription.cancel();
- }
- }
}
// Utility class for encoding a string into an ASCII byte stream.
class _AsciiEncoder extends _SingleByteEncoder {
List<int> _encode(String string) {
- var bytes = string.charCodes;
+ var bytes = string.codeUnits;
for (var byte in bytes) {
if (byte > 127) return null;
}
@@ -357,7 +284,7 @@
// Utility class for encoding a string into a Latin1 byte stream.
class _Latin1Encoder extends _SingleByteEncoder {
List<int> _encode(String string) {
- var bytes = string.charCodes;
+ var bytes = string.codeUnits;
for (var byte in bytes) {
if (byte > 255) return null;
}
@@ -379,36 +306,10 @@
// Utility class for decoding Windows current code page data delivered
// as a stream of bytes.
-class _WindowsCodePageDecoder implements StreamTransformer<List<int>, String> {
- StreamSubscription<List<int>> _subscription;
- StreamController<String> _controller;
-
- Stream<String> bind(Stream<List<int>> stream) {
- _controller = new StreamController<String>(
- onPauseStateChange: _pauseChanged,
- onSubscriptionStateChange: _subscriptionChanged);
- _subscription = stream.listen(
- (data) {
- _controller.add(_decodeBytes(data));
- },
- onDone: _controller.close,
- onError: _controller.signalError);
- return _controller.stream;
+class _WindowsCodePageDecoder extends StreamEventTransformer<List<int>, String> {
+ void handleData(List<int> data, StreamSink<String> sink) {
+ sink.add(_decodeBytes(data));
}
external static String _decodeBytes(List<int> bytes);
-
- void _pauseChanged() {
- if (_controller.isPaused) {
- _subscription.pause();
- } else {
- _subscription.resume();
- }
- }
-
- void _subscriptionChanged() {
- if (!_controller.hasSubscribers) {
- _subscription.cancel();
- }
- }
}
diff --git a/sdk/lib/io/websocket.dart b/sdk/lib/io/websocket.dart
index 48cf54a..65249f1 100644
--- a/sdk/lib/io/websocket.dart
+++ b/sdk/lib/io/websocket.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -24,78 +24,63 @@
}
/**
- * The [WebSocketTransformer] is implemented as a stream transformer that
- * transforms a stream of HttpRequest into a stream of WebSockets by upgrading
- * each HttpRequest from the HTTP or HTTPS server, to the WebSocket protocol.
+ * The [WebSocketTransformer] provides the ability to upgrade a
+ * [HttpRequest] to a [WebSocket] connection. It supports both
+ * upgrading a single [HttpRequest] and upgrading a stream of
+ * [HttpRequest]s.
*
- * Example of usage:
+ * To upgrade a single [HttpRequest] use the static [upgrade] method.
+ *
+ * HttpServer server;
+ * server.listen((request) {
+ * if (...) {
+ * WebSocketTransformer.upgrade(request).then(websocket) {
+ * ...
+ * }
+ * } else {
+ * // Do normal HTTP request processing.
+ * }
+ * });
+ *
+ * To transform a stream of [HttpRequest] events as it implements a
+ * stream transformer that transforms a stream of HttpRequest into a
+ * stream of WebSockets by upgrading each HttpRequest from the HTTP or
+ * HTTPS server, to the WebSocket protocol.
*
* server.transform(new WebSocketTransformer()).listen((webSocket) => ...);
*
- * or
- *
- * server
- * .where((request) => request.uri.scheme == "ws")
- * .transform(new WebSocketTransformer()).listen((webSocket) => ...);
- *
* This transformer strives to implement web sockets as specified by RFC6455.
*/
abstract class WebSocketTransformer
implements StreamTransformer<HttpRequest, WebSocket> {
factory WebSocketTransformer() => new _WebSocketTransformerImpl();
+
+ /**
+ * Upgrades a [HttpRequest] to a [WebSocket] connection. If the
+ * request is not a valid web socket upgrade request a HTTP response
+ * with status code 500 will be returned. Otherwise the returned
+ * future will complete with the [WebSocket] when the upgrade pocess
+ * is complete.
+ */
+ static Future<WebSocket> upgrade(HttpRequest request) {
+ return _WebSocketTransformerImpl._upgrade(request);
+ }
+
+ /**
+ * Checks whether the request is a valid WebSocket upgrade request.
+ */
+ static bool isUpgradeRequest(HttpRequest request) {
+ return _WebSocketTransformerImpl._isUpgradeRequest(request);
+ }
}
/**
- * Base class for the events generated by the W3C complient browser
- * API for web sockets.
+ * A client or server web socket connection. The stream exposes the
+ * messages received. A text message will be of type [:String:] and a
+ * binary message will be of type [:List<int>:].
*/
-abstract class Event { }
-
-/**
- * Event delivered when there is data on a web socket connection.
- */
-abstract class MessageEvent extends Event {
- /**
- * The type of [message] is either [:String:] or [:List<int>:]
- * depending on whether it is a text or binary message. If the
- * message is empty [message] will be [:null:]
- * If the message is a [:List<int>:] then it will contain byte values
- * from 0 to 255.
- */
- get data;
-}
-
-
-/**
- * Event delivered when a web socket connection is closed.
- */
-abstract class CloseEvent extends Event {
- /**
- * Returns whether the connection was closed cleanly or not.
- */
- bool get wasClean;
-
- /**
- * Returns the web socket connection close code provided by the
- * server.
- */
- int get code;
-
- /**
- * Returns the web socket connection close reason provided by the
- * server.
- */
- String get reason;
-}
-
-
-/**
- * Alternative web socket client interface. This interface is compliant
- * with the W3C browser API for web sockets specified in
- * http://dev.w3.org/html5/websockets/.
- */
-abstract class WebSocket implements Stream<Event> {
+abstract class WebSocket implements Stream {
/**
* Possible states of the connection.
*/
@@ -119,11 +104,6 @@
int get readyState;
/**
- * Returns the number of bytes currently buffered for transmission.
- */
- int get bufferedAmount;
-
- /**
* The extensions property is initially the empty string. After the
* web socket connection is established this string reflects the
* extensions used by the server.
@@ -139,6 +119,18 @@
String get protocol;
/**
+ * The close code set when the web socket connection is closed. If
+ * there is no close code available this property will be [:null:]
+ */
+ int get closeCode;
+
+ /**
+ * The close reason set when the web socket connection is closed. If
+ * there is no close reason available this property will be [:null:]
+ */
+ String get closeReason;
+
+ /**
* Closes the web socket connection.
*/
void close([int code, String reason]);
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index a8d01c2..a849ae1 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -363,40 +363,42 @@
Stream<WebSocket> bind(Stream<HttpRequest> stream) {
stream.listen((request) {
- var response = request.response;
- if (!_isWebSocketUpgrade(request)) {
- _controller.signalError(
- new AsyncError(
- new WebSocketException("Invalid WebSocket upgrade request")));
- request.listen((_) {}, onDone: () {
- response.statusCode = HttpStatus.BAD_REQUEST;
- response.contentLength = 0;
- response.close();
- });
- return;
- }
- // Send the upgrade response.
- response.statusCode = HttpStatus.SWITCHING_PROTOCOLS;
- response.headers.add(HttpHeaders.CONNECTION, "Upgrade");
- response.headers.add(HttpHeaders.UPGRADE, "websocket");
- String key = request.headers.value("Sec-WebSocket-Key");
- SHA1 sha1 = new SHA1();
- sha1.add("$key$_webSocketGUID".charCodes);
- String accept = _Base64._encode(sha1.close());
- response.headers.add("Sec-WebSocket-Accept", accept);
- response.headers.contentLength = 0;
- response.detachSocket()
- .then((socket) {
- _controller.add(new _WebSocketImpl._fromSocket(socket));
- }, onError: (error) {
- _controller.signalError(error);
- });
+ _upgrade(request)
+ .then((WebSocket webSocket) => _controller.add(webSocket))
+ .catchError((error) => _controller.signalError(error));
});
return _controller.stream;
}
- bool _isWebSocketUpgrade(HttpRequest request) {
+ static Future<WebSocket> _upgrade(HttpRequest request) {
+ var response = request.response;
+ if (!_isUpgradeRequest(request)) {
+ // Send error response and drain the request.
+ request.listen((_) {}, onDone: () {
+ response.statusCode = HttpStatus.BAD_REQUEST;
+ response.contentLength = 0;
+ response.close();
+ });
+ return new Future.immediateError(
+ new WebSocketException("Invalid WebSocket upgrade request"));
+ }
+
+ // Send the upgrade response.
+ response.statusCode = HttpStatus.SWITCHING_PROTOCOLS;
+ response.headers.add(HttpHeaders.CONNECTION, "Upgrade");
+ response.headers.add(HttpHeaders.UPGRADE, "websocket");
+ String key = request.headers.value("Sec-WebSocket-Key");
+ SHA1 sha1 = new SHA1();
+ sha1.add("$key$_webSocketGUID".codeUnits);
+ String accept = _Base64._encode(sha1.close());
+ response.headers.add("Sec-WebSocket-Accept", accept);
+ response.headers.contentLength = 0;
+ return response.detachSocket()
+ .then((socket) => new _WebSocketImpl._fromSocket(socket));
+ }
+
+ static bool _isUpgradeRequest(HttpRequest request) {
if (request.method != "GET") {
return false;
}
@@ -425,14 +427,17 @@
}
-class _WebSocketImpl extends Stream<Event> implements WebSocket {
- final StreamController<Event> _controller = new StreamController<Event>();
+class _WebSocketImpl extends Stream implements WebSocket {
+ final StreamController _controller = new StreamController();
final _WebSocketProtocolProcessor _processor =
new _WebSocketProtocolProcessor();
final Socket _socket;
int _readyState = WebSocket.CONNECTING;
+ bool _writeClosed = false;
+ int _closeCode;
+ String _closeReason;
static final HttpClient _httpClient = new HttpClient();
@@ -447,7 +452,7 @@
Random random = new Random();
// Generate 16 random bytes.
- List<int> nonceData = new List<int>.fixedLength(16);
+ List<int> nonceData = new List<int>(16);
for (int i = 0; i < 16; i++) {
nonceData[i] = random.nextInt(256);
}
@@ -490,7 +495,7 @@
error("Response did not contain a 'Sec-WebSocket-Accept' header");
}
SHA1 sha1 = new SHA1();
- sha1.add("$nonce$_webSocketGUID".charCodes);
+ sha1.add("$nonce$_webSocketGUID".codeUnits);
List<int> expectedAccept = sha1.close();
List<int> receivedAccept = _Base64._decode(accept);
if (expectedAccept.length != receivedAccept.length) {
@@ -528,9 +533,9 @@
};
_processor.onMessageEnd = () {
if (type == _WebSocketMessageType.TEXT) {
- _controller.add(new _WebSocketMessageEvent(data.toString()));
+ _controller.add(data.toString());
} else {
- _controller.add(new _WebSocketMessageEvent(data));
+ _controller.add(data);
}
};
_processor.onClosed = (code, reason) {
@@ -545,7 +550,9 @@
}
_readyState = WebSocket.CLOSED;
}
- _controller.add(new _WebSocketCloseEvent(clean, code, reason));
+ if (_readyState == WebSocket.CLOSED) return;
+ _closeCode = code;
+ _closeReason = reason;
_controller.close();
};
@@ -553,12 +560,25 @@
(data) => _processor.update(data, 0, data.length),
onDone: () => _processor.closed(),
onError: (error) => _controller.signalError(error));
+
+ _socket.done
+ .catchError((error) {
+ if (_readyState == WebSocket.CLOSED) return;
+ _readyState = WebSocket.CLOSED;
+ _closeCode = ABNORMAL_CLOSURE;
+ _controller.signalError(error);
+ _controller.close();
+ _socket.destroy();
+ })
+ .whenComplete(() {
+ _writeClosed = true;
+ });
}
- StreamSubscription<Event> listen(void onData(Event event),
- {void onError(AsyncError error),
- void onDone(),
- bool unsubscribeOnError}) {
+ StreamSubscription listen(void onData(message),
+ {void onError(AsyncError error),
+ void onDone(),
+ bool unsubscribeOnError}) {
return _controller.stream.listen(onData,
onError: onError,
onDone: onDone,
@@ -566,10 +586,11 @@
}
int get readyState => _readyState;
- int get bufferedAmount => 0;
String get extensions => null;
String get protocol => null;
+ int get closeCode => _closeCode;
+ String get closeReason => _closeReason;
void close([int code, String reason]) {
if (_readyState < WebSocket.CLOSING) _readyState = WebSocket.CLOSING;
@@ -627,10 +648,16 @@
} else {
opcode = _WebSocketOpcode.TEXT;
}
- _sendFrame(opcode, data);
+ try {
+ _sendFrame(opcode, data);
+ } catch (_) {
+ // The socket can be closed before _socket.done have a chance
+ // to complete.
+ }
}
void _sendFrame(int opcode, [List<int> data]) {
+ if (_writeClosed) return;
bool mask = false; // Masking not implemented for server.
int dataLength = data == null ? 0 : data.length;
// Determine the header size.
@@ -640,7 +667,7 @@
} else if (dataLength > 125) {
headerSize += 2;
}
- List<int> header = new List<int>.fixedLength(headerSize);
+ List<int> header = new List<int>(headerSize);
int index = 0;
// Set FIN and opcode.
header[index++] = 0x80 | opcode;
@@ -665,21 +692,3 @@
}
}
}
-
-
-class _WebSocketMessageEvent implements MessageEvent {
- _WebSocketMessageEvent(this._data);
- get data => _data;
- var _data;
-}
-
-
-class _WebSocketCloseEvent implements CloseEvent {
- _WebSocketCloseEvent(this._wasClean, this._code, this._reason);
- bool get wasClean => _wasClean;
- int get code => _code;
- String get reason => _reason;
- bool _wasClean;
- int _code;
- String _reason;
-}
diff --git a/sdk/lib/isolate/isolate_sources.gypi b/sdk/lib/isolate/isolate_sources.gypi
index 4481e93..8077ccf 100644
--- a/sdk/lib/isolate/isolate_sources.gypi
+++ b/sdk/lib/isolate/isolate_sources.gypi
@@ -4,6 +4,8 @@
{
'sources': [
+ 'isolate.dart',
+ # The above file needs to be first as it lists the parts below.
'base.dart',
'isolate_stream.dart',
'mangler.dart',
diff --git a/sdk/lib/isolate/mangler.dart b/sdk/lib/isolate/mangler.dart
index a0e1672..8b31d5a6 100644
--- a/sdk/lib/isolate/mangler.dart
+++ b/sdk/lib/isolate/mangler.dart
@@ -44,7 +44,7 @@
for (int i = 0; i < data.length; i++) {
var mangled = encode(data[i]);
if (mangled != data[i] && !hasBeenDuplicated) {
- result = new List.fixedLength(data.length);
+ result = new List(data.length);
for (int j = 0; j < i; j++) {
result[j] = data[j];
}
diff --git a/sdk/lib/json/json_base.dart b/sdk/lib/json/json_base.dart
index 9f74d65..5432e5aa 100644
--- a/sdk/lib/json/json_base.dart
+++ b/sdk/lib/json/json_base.dart
@@ -47,7 +47,9 @@
*
* Throws [FormatException] if the input is not valid JSON text.
*/
-parse(String json, [reviver(var key, var value)]) {
+external parse(String json, [reviver(var key, var value)]);
+
+_parse(String json, reviver(var key, var value)) {
BuildJsonListener listener;
if (reviver == null) {
listener = new BuildJsonListener();
@@ -322,7 +324,7 @@
int position = 0;
int length = source.length;
while (position < length) {
- int char = source.charCodeAt(position);
+ int char = source.codeUnitAt(position);
switch (char) {
case SPACE:
case CARRIAGE_RETURN:
@@ -423,11 +425,11 @@
* [:source[position]:] must be "t".
*/
int parseTrue(int position) {
- assert(source.charCodeAt(position) == CHAR_t);
+ assert(source.codeUnitAt(position) == CHAR_t);
if (source.length < position + 4) fail(position, "Unexpected identifier");
- if (source.charCodeAt(position + 1) != CHAR_r ||
- source.charCodeAt(position + 2) != CHAR_u ||
- source.charCodeAt(position + 3) != CHAR_e) {
+ if (source.codeUnitAt(position + 1) != CHAR_r ||
+ source.codeUnitAt(position + 2) != CHAR_u ||
+ source.codeUnitAt(position + 3) != CHAR_e) {
fail(position);
}
listener.handleBool(true);
@@ -440,12 +442,12 @@
* [:source[position]:] must be "f".
*/
int parseFalse(int position) {
- assert(source.charCodeAt(position) == CHAR_f);
+ assert(source.codeUnitAt(position) == CHAR_f);
if (source.length < position + 5) fail(position, "Unexpected identifier");
- if (source.charCodeAt(position + 1) != CHAR_a ||
- source.charCodeAt(position + 2) != CHAR_l ||
- source.charCodeAt(position + 3) != CHAR_s ||
- source.charCodeAt(position + 4) != CHAR_e) {
+ if (source.codeUnitAt(position + 1) != CHAR_a ||
+ source.codeUnitAt(position + 2) != CHAR_l ||
+ source.codeUnitAt(position + 3) != CHAR_s ||
+ source.codeUnitAt(position + 4) != CHAR_e) {
fail(position);
}
listener.handleBool(false);
@@ -457,11 +459,11 @@
* [:source[position]:] must be "n".
*/
int parseNull(int position) {
- assert(source.charCodeAt(position) == CHAR_n);
+ assert(source.codeUnitAt(position) == CHAR_n);
if (source.length < position + 4) fail(position, "Unexpected identifier");
- if (source.charCodeAt(position + 1) != CHAR_u ||
- source.charCodeAt(position + 2) != CHAR_l ||
- source.charCodeAt(position + 3) != CHAR_l) {
+ if (source.codeUnitAt(position + 1) != CHAR_u ||
+ source.codeUnitAt(position + 2) != CHAR_l ||
+ source.codeUnitAt(position + 3) != CHAR_l) {
fail(position);
}
listener.handleNull();
@@ -477,7 +479,7 @@
if (position == source.length) {
fail(start - 1, "Unterminated string");
}
- char = source.charCodeAt(position);
+ char = source.codeUnitAt(position);
if (char == QUOTE) {
listener.handleString(source.substring(start, position));
return position + 1;
@@ -494,7 +496,7 @@
if (position == source.length) {
fail(start - 1, "Unterminated string");
}
- char = source.charCodeAt(position);
+ char = source.codeUnitAt(position);
switch (char) {
case CHAR_b: char = BACKSPACE; break;
case CHAR_f: char = FORM_FEED; break;
@@ -513,7 +515,7 @@
if (position == source.length) {
fail(start - 1, "Unterminated string");
}
- char = source.charCodeAt(position);
+ char = source.codeUnitAt(position);
char -= 0x30;
if (char < 0) fail(hexStart, "Invalid unicode escape");
if (char < 10) {
@@ -536,7 +538,7 @@
chars.add(char);
position++;
if (position == source.length) fail(start - 1, "Unterminated string");
- char = source.charCodeAt(position);
+ char = source.codeUnitAt(position);
if (char == QUOTE) {
String result = new String.fromCharCodes(chars);
if (start < firstEscape) {
@@ -553,6 +555,14 @@
}
}
+ int _handleLiteral(start, position, isDouble) {
+ String literal = source.substring(start, position);
+ // This correctly creates -0 for doubles.
+ num value = (isDouble ? double.parse(literal) : int.parse(literal));
+ listener.handleNumber(value);
+ return position;
+ }
+
int parseNumber(int char, int position) {
// Format:
// '-'?('0'|[1-9][0-9]*)('.'[0-9]+)?([eE][+-]?[0-9]+)?
@@ -562,64 +572,57 @@
if (char == MINUS) {
position++;
if (position == length) fail(position, "Missing expected digit");
- char = source.charCodeAt(position);
+ char = source.codeUnitAt(position);
}
if (char < CHAR_0 || char > CHAR_9) {
fail(position, "Missing expected digit");
}
- int handleLiteral(position) {
- String literal = source.substring(start, position);
- // This correctly creates -0 for doubles.
- num value = (isDouble ? double.parse(literal) : int.parse(literal));
- listener.handleNumber(value);
- return position;
- }
if (char == CHAR_0) {
position++;
- if (position == length) return handleLiteral(position);
- char = source.charCodeAt(position);
+ if (position == length) return _handleLiteral(start, position, false);
+ char = source.codeUnitAt(position);
if (CHAR_0 <= char && char <= CHAR_9) {
fail(position);
}
} else {
do {
position++;
- if (position == length) return handleLiteral(position);
- char = source.charCodeAt(position);
+ if (position == length) return _handleLiteral(start, position, false);
+ char = source.codeUnitAt(position);
} while (CHAR_0 <= char && char <= CHAR_9);
}
if (char == DECIMALPOINT) {
isDouble = true;
position++;
if (position == length) fail(position, "Missing expected digit");
- char = source.charCodeAt(position);
+ char = source.codeUnitAt(position);
if (char < CHAR_0 || char > CHAR_9) fail(position);
do {
position++;
- if (position == length) return handleLiteral(position);
- char = source.charCodeAt(position);
+ if (position == length) return _handleLiteral(start, position, true);
+ char = source.codeUnitAt(position);
} while (CHAR_0 <= char && char <= CHAR_9);
}
if (char == CHAR_e || char == CHAR_E) {
isDouble = true;
position++;
if (position == length) fail(position, "Missing expected digit");
- char = source.charCodeAt(position);
+ char = source.codeUnitAt(position);
if (char == PLUS || char == MINUS) {
position++;
if (position == length) fail(position, "Missing expected digit");
- char = source.charCodeAt(position);
+ char = source.codeUnitAt(position);
}
if (char < CHAR_0 || char > CHAR_9) {
fail(position, "Missing expected digit");
}
do {
position++;
- if (position == length) return handleLiteral(position);
- char = source.charCodeAt(position);
+ if (position == length) return _handleLiteral(start, position, true);
+ char = source.codeUnitAt(position);
} while (CHAR_0 <= char && char <= CHAR_9);
}
- return handleLiteral(position);
+ return _handleLiteral(start, position, isDouble);
}
void fail(int position, [String message]) {
@@ -668,7 +671,7 @@
bool needsEscape = false;
final charCodes = new List<int>();
for (int i = 0; i < length; i++) {
- int charCode = s.charCodeAt(i);
+ int charCode = s.codeUnitAt(i);
if (charCode < 32) {
needsEscape = true;
charCodes.add(JsonParser.BACKSLASH);
diff --git a/sdk/lib/json/json_sources.gypi b/sdk/lib/json/json_sources.gypi
index f9a7160..9311d82 100644
--- a/sdk/lib/json/json_sources.gypi
+++ b/sdk/lib/json/json_sources.gypi
@@ -5,6 +5,8 @@
# This file contains all sources for the dart:json library.
{
'sources': [
+ 'json.dart',
+ # The above file needs to be first as it lists the parts below.
'json_base.dart',
],
}
diff --git a/sdk/lib/math/math_sources.gypi b/sdk/lib/math/math_sources.gypi
index dc854da..cbfad89 100644
--- a/sdk/lib/math/math_sources.gypi
+++ b/sdk/lib/math/math_sources.gypi
@@ -4,6 +4,8 @@
{
'sources': [
+ 'math.dart',
+ # The above file needs to be first as it lists the parts below.
'base.dart',
'random.dart',
],
diff --git a/sdk/lib/mirrors/mirrors_sources.gypi b/sdk/lib/mirrors/mirrors_sources.gypi
index 5f55725..73d1620 100644
--- a/sdk/lib/mirrors/mirrors_sources.gypi
+++ b/sdk/lib/mirrors/mirrors_sources.gypi
@@ -4,6 +4,8 @@
{
'sources': [
+ 'mirrors.dart',
+ # The above file needs to be first as it lists the parts below.
'mirrors_impl.dart',
],
}
diff --git a/sdk/lib/scalarlist/byte_arrays.dart b/sdk/lib/scalarlist/byte_arrays.dart
index d843259..e37efc2 100644
--- a/sdk/lib/scalarlist/byte_arrays.dart
+++ b/sdk/lib/scalarlist/byte_arrays.dart
@@ -269,6 +269,30 @@
int setUint64(int byteOffset, int value);
/**
+ * Returns the Float32x4 number represented by the 16 bytes at
+ * the specified [byteOffset] in this byte array.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 16` is greater than the length of this byte array.
+ */
+ Float32x4 getFloat32x4(int byteOffset);
+
+ /**
+ * Sets the sixteen bytes starting at the specified [byteOffset] in this
+ * byte array to the Float32x4 representation of the specified [value].
+ *
+ *
+ * Returns `byteOffset + 16`, which is the offset of the first byte in the
+ * array after the last byte that was set by this call. This return value can
+ * be passed as the [byteOffset] parameter to a subsequent `setXxx` call.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 16` is greater than the length of this byte array.
+ */
+ int setFloat32x4(int byteOffset, Float32x4 value);
+
+
+ /**
* Returns the floating point number represented by the four bytes at
* the specified [byteOffset] in this byte array, in IEEE 754
* single-precision binary floating-point format (binary32).
diff --git a/sdk/lib/scalarlist/scalarlist.dart b/sdk/lib/scalarlist/scalarlist.dart
index 508b20e..9d79daa 100644
--- a/sdk/lib/scalarlist/scalarlist.dart
+++ b/sdk/lib/scalarlist/scalarlist.dart
@@ -12,7 +12,7 @@
*/
library dart.scalarlist;
-// TODO(ager): Inline the contents of byte_arrays.dart here and get
-// rid of scalarlist_sources.gypi when the VM understands normal
-// library structure for builtin libraries.
+import 'dart:collection';
+
part 'byte_arrays.dart';
+part 'simd128.dart';
\ No newline at end of file
diff --git a/sdk/lib/scalarlist/scalarlist_sources.gypi b/sdk/lib/scalarlist/scalarlist_sources.gypi
index 70a6ab8..b04d10d 100644
--- a/sdk/lib/scalarlist/scalarlist_sources.gypi
+++ b/sdk/lib/scalarlist/scalarlist_sources.gypi
@@ -4,10 +4,9 @@
{
'sources': [
- # TODO(ager): remove byte_arrays.dart and inline the code in
- # scalarlist.dart. The reason for not doing that at this point is
- # that the VM does not allow normal library structure for builtin
- # libraries.
+ 'scalarlist.dart',
+ # The above file needs to be first as it lists the parts below.
'byte_arrays.dart',
+ 'simd128.dart',
],
}
diff --git a/sdk/lib/scalarlist/simd128.dart b/sdk/lib/scalarlist/simd128.dart
new file mode 100644
index 0000000..96349fd
--- /dev/null
+++ b/sdk/lib/scalarlist/simd128.dart
@@ -0,0 +1,188 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.scalarlist;
+
+/**
+ * Interface of Dart Float32x4 and operations.
+ * Float32x4 stores 4 32-bit floating point values in "lanes".
+ * The lanes are "x", "y", "z", and "w" respectively.
+ */
+abstract class Float32x4 {
+ external factory Float32x4(double x, double y, double z, double w);
+ external factory Float32x4.zero();
+
+ /// Addition operator.
+ Float32x4 operator+(Float32x4 other);
+ /// Negate operator.
+ Float32x4 operator-();
+ /// Subtraction operator.
+ Float32x4 operator-(Float32x4 other);
+ /// Multiplication operator.
+ Float32x4 operator*(Float32x4 other);
+ /// Division operator.
+ Float32x4 operator/(Float32x4 other);
+
+ /// Relational less than.
+ Uint32x4 lessThan(Float32x4 other);
+ /// Relational less than or equal.
+ Uint32x4 lessThanOrEqual(Float32x4 other);
+ /// Relational greater than.
+ Uint32x4 greaterThan(Float32x4 other);
+ /// Relational greater than or equal.
+ Uint32x4 greaterThanOrEqual(Float32x4 other);
+ /// Relational equal.
+ Uint32x4 equal(Float32x4 other);
+ /// Relational not-equal.
+ Uint32x4 notEqual(Float32x4 other);
+
+ /// Returns a copy of [this] each lane being scaled by [s].
+ Float32x4 scale(double s);
+ /// Returns the absolute value of this [Simd128Float32].
+ Float32x4 abs();
+ /// Clamps [this] to be in the range [lowerLimit]-[upperLimit].
+ Float32x4 clamp(Float32x4 lowerLimit,
+ Float32x4 upperLimit);
+
+ /// Extracted x value.
+ double get x;
+ /// Extracted y value.
+ double get y;
+ /// Extracted z value.
+ double get z;
+ /// Extracted w value.
+ double get w;
+
+ /// Returns a new [Float32x4] with [this]' x value in all four lanes.
+ Float32x4 get xxxx;
+ /// Returns a new [Float32x4] with [this]' y value in all four lanes.
+ Float32x4 get yyyy;
+ /// Returns a new [Float32x4] with [this]' z value in all four lanes.
+ Float32x4 get zzzz;
+ /// Returns a new [Float32x4] with [this]' w value in all four lanes.
+ Float32x4 get wwww;
+ // TODO(johnmccutchan): Add all 256 possible combinations.
+
+ /// Returns a new [Float32x4] copied from [this] with a new x value.
+ Float32x4 withX(double x);
+ /// Returns a new [Float32x4] copied from [this] with a new y value.
+ Float32x4 withY(double y);
+ /// Returns a new [Float32x4] copied from [this] with a new z value.
+ Float32x4 withZ(double z);
+ /// Returns a new [Float32x4] copied from [this] with a new w value.
+ Float32x4 withW(double w);
+
+ /// Returns the lane-wise minimum value in [this] or [other].
+ Float32x4 min(Float32x4 other);
+
+ /// Returns the lane-wise maximum value in [this] or [other].
+ Float32x4 max(Float32x4 other);
+
+ /// Returns the square root of [this].
+ Float32x4 sqrt();
+
+ /// Returns the reciprocal of [this].
+ Float32x4 reciprocal();
+
+ /// Returns the square root of the reciprocal of [this].
+ Float32x4 reciprocalSqrt();
+
+ /// Returns a bit-wise copy of [this] as a [Uint32x4].
+ Uint32x4 toUint32x4();
+}
+
+/**
+ * Interface of Dart Uint32x4 and operations.
+ * Uint32x4 stores 4 32-bit bit-masks in "lanes".
+ * The lanes are "x", "y", "z", and "w" respectively.
+ */
+abstract class Uint32x4 {
+ external factory Uint32x4(int x, int y, int z, int w);
+ external factory Uint32x4.bool(bool x, bool y, bool z, bool w);
+
+ /// The bit-wise or operator.
+ Uint32x4 operator|(Uint32x4 other);
+ /// The bit-wise and operator.
+ Uint32x4 operator&(Uint32x4 other);
+ /// The bit-wise xor operator.
+ Uint32x4 operator^(Uint32x4 other);
+
+ /// Extract 32-bit mask from x lane.
+ int get x;
+ /// Extract 32-bit mask from y lane.
+ int get y;
+ /// Extract 32-bit mask from z lane.
+ int get z;
+ /// Extract 32-bit mask from w lane.
+ int get w;
+
+ /// Returns a new [Uint32x4] copied from [this] with a new x value.
+ Uint32x4 withX(int x);
+ /// Returns a new [Uint32x4] copied from [this] with a new y value.
+ Uint32x4 withY(int y);
+ /// Returns a new [Uint32x4] copied from [this] with a new z value.
+ Uint32x4 withZ(int z);
+ /// Returns a new [Uint32x4] copied from [this] with a new w value.
+ Uint32x4 withW(int w);
+
+ /// Extracted x value. Returns false for 0, true for any other value.
+ bool get flagX;
+ /// Extracted y value. Returns false for 0, true for any other value.
+ bool get flagY;
+ /// Extracted z value. Returns false for 0, true for any other value.
+ bool get flagZ;
+ /// Extracted w value. Returns false for 0, true for any other value.
+ bool get flagW;
+
+ /// Returns a new [Uint32x4] copied from [this] with a new x value.
+ Uint32x4 withFlagX(bool x);
+ /// Returns a new [Uint32x4] copied from [this] with a new y value.
+ Uint32x4 withFlagY(bool y);
+ /// Returns a new [Uint32x4] copied from [this] with a new z value.
+ Uint32x4 withFlagZ(bool z);
+ /// Returns a new [Uint32x4] copied from [this] with a new w value.
+ Uint32x4 withFlagW(bool w);
+
+ /// Merge [trueValue] and [falseValue] based on [this]' bit mask:
+ /// Select bit from [trueValue] when bit in [this] is on.
+ /// Select bit from [falseValue] when bit in [this] is off.
+ Float32x4 select(Float32x4 trueValue, Float32x4 falseValue);
+
+ /// Returns a bit-wise copy of [this] as a [Float32x4].
+ Float32x4 toFloat32x4();
+}
+
+/**
+ * A fixed-length list of Float32x4 numbers that is viewable as a
+ * [ByteArray]. For long lists, this implementation will be considerably more
+ * space- and time-efficient than the default [List] implementation.
+ */
+abstract class Float32x4List implements List<Float32x4>,
+ ByteArrayViewable {
+ /**
+ * Creates a [Simd128Float32List] of the specified length (in elements),
+ * all of whose elements are initially zero.
+ */
+ external factory Float32x4List(int length);
+
+ /**
+ * Creates a [Float32x4List] _view_ of the specified region in the
+ * specified byte [array]. Changes in the [Float32x4List] will be
+ * visible in the byte array and vice versa. If the [start] index of the
+ * region is not specified, it defaults to zero (the first byte in the byte
+ * array). If the length is not specified, it defaults to null, which
+ * indicates that the view extends to the end of the byte array.
+ *
+ * Throws [ArgumentError] if the length of the specified region is not
+ * divisible by 16 (the size of a "Float32x4" in bytes), or if the
+ * [start] of the region is not divisible by 16. If, however, [array] is a
+ * view of another byte array, this constructor will throw [ArgumentError]
+ * if the implicit starting position in the "ultimately backing" byte array
+ * is not divisible by 16. In plain terms, this constructor throws
+ * [ArgumentError] if the specified region does not contain an integral
+ * number of "Float32x4s," or if it is not "Float32x4-aligned."
+ */
+ external factory Float32x4List.view(ByteArray array,
+ [int start = 0, int length]);
+}
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index c34dc27..0784b5a 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -3050,7 +3050,7 @@
@DocsEditable
final int numberOfItems;
- Length operator[](int index) => JS("Length", "#[#]", this, index);
+ Length operator[](int index) => this.getItem(index);
void operator[]=(int index, Length value) {
throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -3093,7 +3093,9 @@
bool any(bool f(Length element)) => IterableMixinWorkaround.any(this, f);
- List<Length> toList() => new List<Length>.from(this);
+ List<Length> toList({ bool growable: true }) =>
+ new List<Length>.from(this, growable: growable);
+
Set<Length> toSet() => new Set<Length>.from(this);
bool get isEmpty => this.length == 0;
@@ -3674,7 +3676,7 @@
@DocsEditable
final int numberOfItems;
- Number operator[](int index) => JS("Number", "#[#]", this, index);
+ Number operator[](int index) => this.getItem(index);
void operator[]=(int index, Number value) {
throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -3717,7 +3719,9 @@
bool any(bool f(Number element)) => IterableMixinWorkaround.any(this, f);
- List<Number> toList() => new List<Number>.from(this);
+ List<Number> toList({ bool growable: true }) =>
+ new List<Number>.from(this, growable: growable);
+
Set<Number> toSet() => new Set<Number>.from(this);
bool get isEmpty => this.length == 0;
@@ -4574,7 +4578,7 @@
@DocsEditable
final int numberOfItems;
- PathSeg operator[](int index) => JS("PathSeg", "#[#]", this, index);
+ PathSeg operator[](int index) => this.getItem(index);
void operator[]=(int index, PathSeg value) {
throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -4617,7 +4621,9 @@
bool any(bool f(PathSeg element)) => IterableMixinWorkaround.any(this, f);
- List<PathSeg> toList() => new List<PathSeg>.from(this);
+ List<PathSeg> toList({ bool growable: true }) =>
+ new List<PathSeg>.from(this, growable: growable);
+
Set<PathSeg> toSet() => new Set<PathSeg>.from(this);
bool get isEmpty => this.length == 0;
@@ -5458,7 +5464,7 @@
@DocsEditable
final int numberOfItems;
- String operator[](int index) => JS("String", "#[#]", this, index);
+ String operator[](int index) => this.getItem(index);
void operator[]=(int index, String value) {
throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -5501,7 +5507,9 @@
bool any(bool f(String element)) => IterableMixinWorkaround.any(this, f);
- List<String> toList() => new List<String>.from(this);
+ List<String> toList({ bool growable: true }) =>
+ new List<String>.from(this, growable: growable);
+
Set<String> toSet() => new Set<String>.from(this);
bool get isEmpty => this.length == 0;
@@ -6620,7 +6628,7 @@
@DocsEditable
final int numberOfItems;
- Transform operator[](int index) => JS("Transform", "#[#]", this, index);
+ Transform operator[](int index) => this.getItem(index);
void operator[]=(int index, Transform value) {
throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -6663,7 +6671,9 @@
bool any(bool f(Transform element)) => IterableMixinWorkaround.any(this, f);
- List<Transform> toList() => new List<Transform>.from(this);
+ List<Transform> toList({ bool growable: true }) =>
+ new List<Transform>.from(this, growable: growable);
+
Set<Transform> toSet() => new Set<Transform>.from(this);
bool get isEmpty => this.length == 0;
@@ -7139,7 +7149,7 @@
@DocsEditable
int get length => JS("int", "#.length", this);
- ElementInstance operator[](int index) => JS("ElementInstance", "#[#]", this, index);
+ ElementInstance operator[](int index) => this.item(index);
void operator[]=(int index, ElementInstance value) {
throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -7180,7 +7190,9 @@
bool any(bool f(ElementInstance element)) => IterableMixinWorkaround.any(this, f);
- List<ElementInstance> toList() => new List<ElementInstance>.from(this);
+ List<ElementInstance> toList({ bool growable: true }) =>
+ new List<ElementInstance>.from(this, growable: growable);
+
Set<ElementInstance> toSet() => new Set<ElementInstance>.from(this);
bool get isEmpty => this.length == 0;
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index d6b19dd..d049d13 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -3356,7 +3356,9 @@
bool any(bool f(Length element)) => IterableMixinWorkaround.any(this, f);
- List<Length> toList() => new List<Length>.from(this);
+ List<Length> toList({ bool growable: true }) =>
+ new List<Length>.from(this, growable: growable);
+
Set<Length> toSet() => new Set<Length>.from(this);
bool get isEmpty => this.length == 0;
@@ -4057,7 +4059,9 @@
bool any(bool f(Number element)) => IterableMixinWorkaround.any(this, f);
- List<Number> toList() => new List<Number>.from(this);
+ List<Number> toList({ bool growable: true }) =>
+ new List<Number>.from(this, growable: growable);
+
Set<Number> toSet() => new Set<Number>.from(this);
bool get isEmpty => this.length == 0;
@@ -5234,7 +5238,9 @@
bool any(bool f(PathSeg element)) => IterableMixinWorkaround.any(this, f);
- List<PathSeg> toList() => new List<PathSeg>.from(this);
+ List<PathSeg> toList({ bool growable: true }) =>
+ new List<PathSeg>.from(this, growable: growable);
+
Set<PathSeg> toSet() => new Set<PathSeg>.from(this);
bool get isEmpty => this.length == 0;
@@ -6216,7 +6222,9 @@
bool any(bool f(String element)) => IterableMixinWorkaround.any(this, f);
- List<String> toList() => new List<String>.from(this);
+ List<String> toList({ bool growable: true }) =>
+ new List<String>.from(this, growable: growable);
+
Set<String> toSet() => new Set<String>.from(this);
bool get isEmpty => this.length == 0;
@@ -7467,7 +7475,9 @@
bool any(bool f(Transform element)) => IterableMixinWorkaround.any(this, f);
- List<Transform> toList() => new List<Transform>.from(this);
+ List<Transform> toList({ bool growable: true }) =>
+ new List<Transform>.from(this, growable: growable);
+
Set<Transform> toSet() => new Set<Transform>.from(this);
bool get isEmpty => this.length == 0;
@@ -8038,7 +8048,9 @@
bool any(bool f(ElementInstance element)) => IterableMixinWorkaround.any(this, f);
- List<ElementInstance> toList() => new List<ElementInstance>.from(this);
+ List<ElementInstance> toList({ bool growable: true }) =>
+ new List<ElementInstance>.from(this, growable: growable);
+
Set<ElementInstance> toSet() => new Set<ElementInstance>.from(this);
bool get isEmpty => this.length == 0;
diff --git a/sdk/lib/uri/encode_decode.dart b/sdk/lib/uri/encode_decode.dart
index e13d284..124c803 100644
--- a/sdk/lib/uri/encode_decode.dart
+++ b/sdk/lib/uri/encode_decode.dart
@@ -114,7 +114,7 @@
var byteToHex = (int v) => '%${hex[v >> 4]}${hex[v & 0x0f]}';
StringBuffer result = new StringBuffer();
for (int i = 0; i < text.length; i++) {
- int ch = text.charCodeAt(i);
+ int ch = text.codeUnitAt(i);
if (ch < 128 && ((canonicalTable[ch >> 4] & (1 << (ch & 0x0f))) != 0)) {
result.add(text[i]);
} else if (text[i] == " ") {
@@ -123,10 +123,10 @@
if (ch >= 0xD800 && ch < 0xDC00) {
// Low surrogate. We expect a next char high surrogate.
++i;
- int nextCh = text.length == i ? 0 : text.charCodeAt(i);
+ int nextCh = text.length == i ? 0 : text.codeUnitAt(i);
if (nextCh >= 0xDC00 && nextCh < 0xE000) {
// convert the pair to a U+10000 codepoint
- ch = 0x10000 + ((ch-0xD800) << 10) + (nextCh - 0xDC00);
+ ch = 0x10000 + ((ch - 0xD800) << 10) + (nextCh - 0xDC00);
} else {
throw new ArgumentError('Malformed URI');
}
@@ -143,11 +143,10 @@
* Convert a byte (2 character hex sequence) in string [s] starting
* at position [pos] to its ordinal value
*/
-
int _hexCharPairToByte(String s, int pos) {
int byte = 0;
for (int i = 0; i < 2; i++) {
- var charCode = s.charCodeAt(pos + i);
+ var charCode = s.codeUnitAt(pos + i);
if (0x30 <= charCode && charCode <= 0x39) {
byte = byte * 16 + charCode - 0x30;
} else {
diff --git a/sdk/lib/uri/uri_sources.gypi b/sdk/lib/uri/uri_sources.gypi
index 87e234a..b777678 100644
--- a/sdk/lib/uri/uri_sources.gypi
+++ b/sdk/lib/uri/uri_sources.gypi
@@ -5,6 +5,8 @@
# This file contains all sources for the dart:uri library.
{
'sources': [
+ 'uri.dart',
+ # The above file needs to be first as it lists the parts below.
'uri_base.dart',
'helpers.dart',
'encode_decode.dart',
diff --git a/sdk/lib/utf/utf16.dart b/sdk/lib/utf/utf16.dart
index c451b1e..9794a81 100644
--- a/sdk/lib/utf/utf16.dart
+++ b/sdk/lib/utf/utf16.dart
@@ -113,7 +113,7 @@
List<int> encodeUtf16be(String str, [bool writeBOM = false]) {
List<int> utf16CodeUnits = _stringToUtf16CodeUnits(str);
List<int> encoding =
- new List<int>.fixedLength(2 * utf16CodeUnits.length + (writeBOM ? 2 : 0));
+ new List<int>(2 * utf16CodeUnits.length + (writeBOM ? 2 : 0));
int i = 0;
if (writeBOM) {
encoding[i++] = UNICODE_UTF_BOM_HI;
@@ -133,7 +133,7 @@
List<int> encodeUtf16le(String str, [bool writeBOM = false]) {
List<int> utf16CodeUnits = _stringToUtf16CodeUnits(str);
List<int> encoding =
- new List<int>.fixedLength(2 * utf16CodeUnits.length + (writeBOM ? 2 : 0));
+ new List<int>(2 * utf16CodeUnits.length + (writeBOM ? 2 : 0));
int i = 0;
if (writeBOM) {
encoding[i++] = UNICODE_UTF_BOM_LO;
@@ -178,7 +178,7 @@
}
List<int> _stringToUtf16CodeUnits(String str) {
- return _codepointsToUtf16CodeUnits(str.charCodes);
+ return _codepointsToUtf16CodeUnits(str.codeUnits);
}
typedef _ListRangeIterator _CodeUnitsProvider();
@@ -238,7 +238,7 @@
* over-allocates the List containing results.
*/
List<int> decodeRest() {
- List<int> codeunits = new List<int>.fixedLength(remaining);
+ List<int> codeunits = new List<int>(remaining);
int i = 0;
while (moveNext()) {
codeunits[i++] = current;
@@ -246,7 +246,7 @@
if (i == codeunits.length) {
return codeunits;
} else {
- List<int> truncCodeunits = new List<int>.fixedLength(i);
+ List<int> truncCodeunits = new List<int>(i);
truncCodeunits.setRange(0, i, codeunits);
return truncCodeunits;
}
diff --git a/sdk/lib/utf/utf32.dart b/sdk/lib/utf/utf32.dart
index acf6ac3..1e43f01 100644
--- a/sdk/lib/utf/utf32.dart
+++ b/sdk/lib/utf/utf32.dart
@@ -222,7 +222,7 @@
}
List<int> decodeRest() {
- List<int> codeunits = new List<int>.fixedLength(remaining);
+ List<int> codeunits = new List<int>(remaining);
int i = 0;
while (moveNext()) {
codeunits[i++] = current;
diff --git a/sdk/lib/utf/utf8.dart b/sdk/lib/utf/utf8.dart
index 4bf216f..b44cbe4 100644
--- a/sdk/lib/utf/utf8.dart
+++ b/sdk/lib/utf/utf8.dart
@@ -86,7 +86,7 @@
}
}
- List<int> encoded = new List<int>.fixedLength(encodedLength);
+ List<int> encoded = new List<int>(encodedLength);
int insertAt = 0;
for (int value in source) {
if (value < 0 || value > UNICODE_VALID_RANGE_MAX) {
@@ -173,7 +173,7 @@
* into a [List<int>].
*/
List<int> decodeRest() {
- List<int> codepoints = new List<int>.fixedLength(utf8EncodedBytesIterator.remaining);
+ List<int> codepoints = new List<int>(utf8EncodedBytesIterator.remaining);
int i = 0;
while (moveNext()) {
codepoints[i++] = current;
@@ -181,7 +181,7 @@
if (i == codepoints.length) {
return codepoints;
} else {
- List<int> truncCodepoints = new List<int>.fixedLength(i);
+ List<int> truncCodepoints = new List<int>(i);
truncCodepoints.setRange(0, i, codepoints);
return truncCodepoints;
}
diff --git a/sdk/lib/utf/utf_core.dart b/sdk/lib/utf/utf_core.dart
index 15ca45e..30ad2dc 100644
--- a/sdk/lib/utf/utf_core.dart
+++ b/sdk/lib/utf/utf_core.dart
@@ -9,9 +9,9 @@
* Provide a list of Unicode codepoints for a given string.
*/
List<int> stringToCodepoints(String str) {
- // Note: str.charCodes gives us 16-bit code units on all Dart implementations.
+ // Note: str.codeUnits gives us 16-bit code units on all Dart implementations.
// So we need to convert.
- return _utf16CodeUnitsToCodepoints(str.charCodes);
+ return _utf16CodeUnitsToCodepoints(str.codeUnits);
}
/**
@@ -64,7 +64,7 @@
}
}
- List<int> codeUnitsBuffer = new List<int>.fixedLength(encodedLength);
+ List<int> codeUnitsBuffer = new List<int>(encodedLength);
int j = 0;
for (int value in listRange) {
if ((value >= 0 && value < UNICODE_UTF16_RESERVED_LO) ||
@@ -96,7 +96,7 @@
(new _ListRange(utf16CodeUnits, offset, length)).iterator;
Utf16CodeUnitDecoder decoder = new Utf16CodeUnitDecoder
.fromListRangeIterator(source, replacementCodepoint);
- List<int> codepoints = new List<int>.fixedLength(source.remaining);
+ List<int> codepoints = new List<int>(source.remaining);
int i = 0;
while (decoder.moveNext()) {
codepoints[i++] = decoder.current;
@@ -104,7 +104,7 @@
if (i == codepoints.length) {
return codepoints;
} else {
- List<int> codepointTrunc = new List<int>.fixedLength(i);
+ List<int> codepointTrunc = new List<int>(i);
codepointTrunc.setRange(0, i, codepoints);
return codepointTrunc;
}
diff --git a/sdk/lib/utf/utf_sources.gypi b/sdk/lib/utf/utf_sources.gypi
index 9d86ff1..b11d1f5 100644
--- a/sdk/lib/utf/utf_sources.gypi
+++ b/sdk/lib/utf/utf_sources.gypi
@@ -3,11 +3,10 @@
# BSD-style license that can be found in the LICENSE file.
# This file contains all sources for the dart:utf library.
-#
-# TODO(ager): When the VM can use the #source directive for libraries.
-# At that point utf.dart should be the only utf library file.
{
'sources': [
+ 'utf.dart',
+ # The above file needs to be first as it lists the parts below.
'utf_core.dart',
'utf_stream.dart',
'utf8.dart',
diff --git a/sdk/lib/utf/utf_stream.dart b/sdk/lib/utf/utf_stream.dart
index ad69c62..71dc76d 100644
--- a/sdk/lib/utf/utf_stream.dart
+++ b/sdk/lib/utf/utf_stream.dart
@@ -14,45 +14,15 @@
}
}
-abstract class _StringDecoder implements StreamTransformer<List<int>, String> {
- _HelperStreamController<String> _controller;
- StreamSubscription<List<int>> _subscription;
+abstract class _StringDecoder
+ extends StreamEventTransformer<List<int>, String> {
List<int> _carry;
List<int> _buffer;
int _replacementChar;
- bool _paused = false;
- _StringDecoder(int this._replacementChar) {
- _controller = new _HelperStreamController<String>(_onPauseChanged);
- }
+ _StringDecoder(int this._replacementChar);
- void _onPauseChanged() {
- _paused = _controller.isPaused;
- if (_subscription == null) return;
- if (_paused) {
- _subscription.pause();
- } else {
- _subscription.resume();
- }
- }
-
- Stream<String> bind(Stream<List<int>> stream) {
- _subscription = stream.listen(
- _onData,
- onError: _controller.signalError,
- onDone: () {
- if (_carry != null) {
- _controller.add(new String.fromCharCodes(
- new List.fixedLength(_carry.length, fill: _replacementChar)));
- }
- _controller.close();
- },
- unsubscribeOnError: false);
- if (_paused) _subscription.pause();
- return _controller.stream;
- }
-
- void _onData(List<int> bytes) {
+ void handleData(List<int> bytes, StreamSink<String> sink) {
_buffer = <int>[];
List<int> carry = _carry;
_carry = null;
@@ -94,11 +64,19 @@
}
if (_buffer.length > 0) {
// Limit to 'goodChars', if lower than actual charCodes in the buffer.
- _controller.add(new String.fromCharCodes(_buffer));
+ sink.add(new String.fromCharCodes(_buffer));
}
_buffer = null;
}
+ void handleDone(StreamSink<String> sink) {
+ if (_carry != null) {
+ sink.add(new String.fromCharCodes(
+ new List.filled(_carry.length, _replacementChar)));
+ }
+ sink.close();
+ }
+
int _processBytes(int getNext());
void _addChar(int char) {
@@ -161,25 +139,11 @@
}
-abstract class _StringEncoder implements StreamTransformer<String, List<int>> {
- _HelperStreamController<List<int>> _controller;
- StreamSubscription<String> _subscription;
+abstract class _StringEncoder
+ extends StreamEventTransformer<String, List<int>> {
- void _onPauseChanged() {
- if (_controller.isPaused) {
- _subscription.pause();
- } else {
- _subscription.resume();
- }
- }
- Stream<List<int>> bind(Stream<String> stream) {
- _controller = new _HelperStreamController(_onPauseChanged);
- _subscription = stream.listen(
- (string) => _controller.add(_processString(string)),
- onError: _controller.signalError,
- onDone: _controller.close,
- unsubscribeOnError: false);
- return _controller.stream;
+ void handleData(String data, StreamSink<List<int>> sink) {
+ sink.add(_processString(data));
}
List<int> _processString(String string);
@@ -192,7 +156,7 @@
List<int> _processString(String string) {
var bytes = [];
int pos = 0;
- List<int> codepoints = _utf16CodeUnitsToCodepoints(string.charCodes);
+ List<int> codepoints = _utf16CodeUnitsToCodepoints(string.codeUnits);
int length = codepoints.length;
for (int i = 0; i < length; i++) {
int additionalBytes;
diff --git a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
index 8559913..7b68ee5 100644
--- a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -1,3 +1,13 @@
+/**
+ * An API for storing data in the browser that can be queried with SQL.
+ *
+ * **Caution:** this specification is no longer actively maintained by the Web
+ * Applications Working Group and may be removed at any time.
+ * See [the W3C Web SQL Database specification](http://www.w3.org/TR/webdatabase/)
+ * for more information.
+ *
+ * The [dart:indexed_db] APIs is a recommended alternatives.
+ */
library dart.dom.web_sql;
import 'dart:async';
@@ -80,6 +90,18 @@
@DocsEditable
final String version;
+ /**
+ * Atomically update the database version to [newVersion], asynchronously
+ * running [callback] on the [SqlTransaction] representing this
+ * [changeVersion] transaction.
+ *
+ * If [callback] runs successfully, then [successCallback] is called.
+ * Otherwise, [errorCallback] is called.
+ *
+ * [oldVersion] should match the database's current [version] exactly.
+ *
+ * * [Database.changeVersion](http://www.w3.org/TR/webdatabase/#dom-database-changeversion) from W3C.
+ */
@DomName('Database.changeVersion')
@DocsEditable
void changeVersion(String oldVersion, String newVersion, [SqlTransactionCallback callback, SqlTransactionErrorCallback errorCallback, VoidCallback successCallback]) native;
@@ -224,7 +246,7 @@
@DocsEditable
int get length => JS("int", "#.length", this);
- Map operator[](int index) => JS("Map", "#[#]", this, index);
+ Map operator[](int index) => this.item(index);
void operator[]=(int index, Map value) {
throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -265,7 +287,9 @@
bool any(bool f(Map element)) => IterableMixinWorkaround.any(this, f);
- List<Map> toList() => new List<Map>.from(this);
+ List<Map> toList({ bool growable: true }) =>
+ new List<Map>.from(this, growable: growable);
+
Set<Map> toSet() => new Set<Map>.from(this);
bool get isEmpty => this.length == 0;
diff --git a/sdk/lib/web_sql/dartium/web_sql_dartium.dart b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
index c25f0ae..c6b7de5 100644
--- a/sdk/lib/web_sql/dartium/web_sql_dartium.dart
+++ b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
@@ -1,3 +1,13 @@
+/**
+ * An API for storing data in the browser that can be queried with SQL.
+ *
+ * **Caution:** this specification is no longer actively maintained by the Web
+ * Applications Working Group and may be removed at any time.
+ * See [the W3C Web SQL Database specification](http://www.w3.org/TR/webdatabase/)
+ * for more information.
+ *
+ * The [dart:indexed_db] APIs is a recommended alternatives.
+ */
library dart.dom.web_sql;
import 'dart:async';
@@ -82,6 +92,18 @@
@DocsEditable
String get version native "Database_version_Getter";
+ /**
+ * Atomically update the database version to [newVersion], asynchronously
+ * running [callback] on the [SqlTransaction] representing this
+ * [changeVersion] transaction.
+ *
+ * If [callback] runs successfully, then [successCallback] is called.
+ * Otherwise, [errorCallback] is called.
+ *
+ * [oldVersion] should match the database's current [version] exactly.
+ *
+ * * [Database.changeVersion](http://www.w3.org/TR/webdatabase/#dom-database-changeversion) from W3C.
+ */
@DomName('Database.changeVersion')
@DocsEditable
void changeVersion(String oldVersion, String newVersion, [SqlTransactionCallback callback, SqlTransactionErrorCallback errorCallback, VoidCallback successCallback]) native "Database_changeVersion_Callback";
@@ -287,7 +309,9 @@
bool any(bool f(Map element)) => IterableMixinWorkaround.any(this, f);
- List<Map> toList() => new List<Map>.from(this);
+ List<Map> toList({ bool growable: true }) =>
+ new List<Map>.from(this, growable: growable);
+
Set<Map> toSet() => new Set<Map>.from(this);
bool get isEmpty => this.length == 0;
diff --git a/tests/co19/co19-compiler.status b/tests/co19/co19-compiler.status
index 60c8924..5038551 100644
--- a/tests/co19/co19-compiler.status
+++ b/tests/co19/co19-compiler.status
@@ -4,133 +4,111 @@
[ $compiler == dartc ]
-# co19 issue 365 (iterator changes)
-Language/12_Statements/06_For/2_For_in_A01_t05: Fail # co19 issue 365
-LibTest/core/Set/Set.from_A01_t02: Fail # co19 issue 365
-LibTest/core/Queue/Queue.from_A01_t02: Fail # co19 issue 365
+Language/12_Statements/06_For/2_For_in_A01_t05: Fail # co19 issue 365 # co19 issue 365 (iterator changes)
+LibTest/core/Set/Set.from_A01_t02: Fail # co19 issue 365 # co19 issue 365 (iterator changes)
+LibTest/core/Queue/Queue.from_A01_t02: Fail # co19 issue 365 # co19 issue 365 (iterator changes)
-# co19 issue 336 (allow use same prefix for several imports)
-Language/13_Libraries_and_Scripts/1_Imports_A02_t29: Fail
+Language/13_Libraries_and_Scripts/1_Imports_A02_t29: Fail # co19 issue 336 (allow use same prefix for several imports)
-# co19 issue 337 (export in scripts is allowed in 0.13)
-Language/13_Libraries_and_Scripts/4_Scripts_A01_t21: Fail
-Language/13_Libraries_and_Scripts/4_Scripts_A01_t23: Fail
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t21: Fail # co19 issue 337 (export in scripts is allowed in 0.13)
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t23: Fail # co19 issue 337 (export in scripts is allowed in 0.13)
-# co19 issue 335 (assignment to final is warning, not error)
-Language/05_Variables/05_Variables_A07_t01: Fail
-Language/05_Variables/05_Variables_A07_t02: Fail
-Language/05_Variables/05_Variables_A07_t03: Fail
-Language/05_Variables/05_Variables_A07_t04: Fail
-Language/05_Variables/05_Variables_A07_t10: Fail
-Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t05: Fail
-Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A01_t06: Fail
+Language/05_Variables/05_Variables_A07_t01: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/05_Variables/05_Variables_A07_t02: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/05_Variables/05_Variables_A07_t03: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/05_Variables/05_Variables_A07_t04: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/05_Variables/05_Variables_A07_t10: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t05: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A01_t06: Fail # co19 issue 335 (assignment to final is warning, not error)
-# co19 issue 344 ('null' is constant, so can be used in 'case')
-Language/12_Statements/09_Switch_A02_t03: Fail
+Language/12_Statements/09_Switch_A02_t03: Fail # co19 issue 344 ('null' is constant, so can be used in 'case')
-# co19 343 (invalid unicode NFC)
-Language/15_Reference/1_Lexical_Rules_A01_t10: Fail
+Language/15_Reference/1_Lexical_Rules_A01_t10: Fail # co19 343 (invalid unicode NFC)
-# co19 issue 339 (type variable is not constant)
-Language/11_Expressions/01_Constants_A20_t03: Fail
+Language/11_Expressions/01_Constants_A20_t03: Fail # co19 issue 339 (type variable is not constant)
-# co19 issue 340 (deprecated catch syntax)
-Language/11_Expressions/08_Throw_A05_t01: Fail
-Language/12_Statements/10_Try_A03_t02: Fail
-Language/12_Statements/10_Try_A03_t03: Fail
+Language/11_Expressions/08_Throw_A05_t01: Fail # co19 issue 340 (deprecated catch syntax)
+Language/12_Statements/10_Try_A03_t02: Fail # co19 issue 340 (deprecated catch syntax)
+Language/12_Statements/10_Try_A03_t03: Fail # co19 issue 340 (deprecated catch syntax)
-# co19 issue 341 (class Type has no type parameters)
-Language/11_Expressions/31_Type_Test_A01_t02: Fail
-Language/11_Expressions/31_Type_Test_A01_t04: Fail
+Language/11_Expressions/31_Type_Test_A01_t02: Fail # co19 issue 341 (class Type has no type parameters)
+Language/11_Expressions/31_Type_Test_A01_t04: Fail # co19 issue 341 (class Type has no type parameters)
-# co19 issue 342 (class can be used anywhere, including left side of "as")
-Language/11_Expressions/32_Type_Cast_A01_t04: Fail
+Language/11_Expressions/32_Type_Cast_A01_t04: Fail # co19 issue 342 (class can be used anywhere, including left side of "as")
-# co19 issue 345 (optional parameters list cannot by empty)
-Language/14_Types/5_Function_Types_A04_t01: Fail
+Language/14_Types/5_Function_Types_A04_t01: Fail # co19 issue 345 (optional parameters list cannot by empty)
-# co19 issue 346 (invalid 'one ugly cascade')
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: Fail
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: Fail # co19 issue 346 (invalid 'one ugly cascade')
-# co19 issue 347 (duplicate class in implements clause)
-Language/08_Interfaces/5_Superinterfaces_A01_t02: Fail
+Language/08_Interfaces/5_Superinterfaces_A01_t02: Fail # co19 issue 347 (duplicate class in implements clause)
+
+Language/13_Libraries_and_Scripts/1_Imports_A02_t12: Fail, OK # co19 issue 320
+Language/13_Libraries_and_Scripts/1_Imports_A02_t15: Fail, OK # co19 issue 320
+Language/13_Libraries_and_Scripts/1_Imports_A02_t18: Fail, OK # co19 issue 320
+Language/13_Libraries_and_Scripts/1_Imports_A02_t19: Fail, OK # co19 issue 320
-# co19 issue 320
-Language/13_Libraries_and_Scripts/1_Imports_A02_t12: Fail, OK
-Language/13_Libraries_and_Scripts/1_Imports_A02_t15: Fail, OK
-Language/13_Libraries_and_Scripts/1_Imports_A02_t18: Fail, OK
-Language/13_Libraries_and_Scripts/1_Imports_A02_t19: Fail, OK
+Language/13_Libraries_and_Scripts/1_Imports_A02_t16: Fail, OK # co19 issue 298
+Language/13_Libraries_and_Scripts/1_Imports_A02_t17: Fail, OK # co19 issue 298
-# co19 issue 298
-Language/13_Libraries_and_Scripts/1_Imports_A02_t16: Fail, OK
-Language/13_Libraries_and_Scripts/1_Imports_A02_t17: Fail, OK
+LibTest/core/Expect/approxEquals_A04_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/equals_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/identical_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/isFalse_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/isNotNull_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/isNull_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/isTrue_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/listEquals_A03_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/notEquals_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/setEquals_A03_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/stringEquals_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/throws_A01_t04: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Future/chain_A02_t04: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Future/chain_A02_t05: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Future/transform_A02_t03: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Future/transform_A02_t04: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/every_A04_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/filter_A04_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/forEach_A03_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/List.from_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/operator_subscript_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/operator_subscript_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/operator_subscripted_assignment_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/operator_subscripted_assignment_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/setRange_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Queue/addFirst_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Set/intersection_A01_t03: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/String/toLowerCase_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/String/toUpperCase_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/String/trim_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/StringBuffer/add_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/StringBuffer/addAll_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/StringBuffer/clear_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+
+LibTest/isolate/SendPort/send_A01_t01: Fail # co19 issue 352 (use function expression with return type and name)
+
+Language/07_Classes/6_Constructors/2_Factories_A01_t02: Fail # co19 issue 354
-# co19 issue 351 (use deprecated === and !==)
-LibTest/core/Expect/approxEquals_A04_t01: Fail
-LibTest/core/Expect/equals_A02_t01: Fail
-LibTest/core/Expect/identical_A02_t01: Fail
-LibTest/core/Expect/isFalse_A02_t01: Fail
-LibTest/core/Expect/isNotNull_A02_t01: Fail
-LibTest/core/Expect/isNull_A02_t01: Fail
-LibTest/core/Expect/isTrue_A02_t01: Fail
-LibTest/core/Expect/listEquals_A03_t01: Fail
-LibTest/core/Expect/notEquals_A02_t01: Fail
-LibTest/core/Expect/setEquals_A03_t01: Fail
-LibTest/core/Expect/stringEquals_A02_t01: Fail
-LibTest/core/Expect/throws_A01_t04: Fail
-LibTest/core/Future/chain_A02_t04: Fail
-LibTest/core/Future/chain_A02_t05: Fail
-LibTest/core/Future/transform_A02_t03: Fail
-LibTest/core/Future/transform_A02_t04: Fail
-LibTest/core/List/every_A04_t01: Fail
-LibTest/core/List/filter_A04_t01: Fail
-LibTest/core/List/forEach_A03_t01: Fail
-LibTest/core/List/List.from_A01_t01: Fail
-LibTest/core/List/operator_subscript_A01_t01: Fail
-LibTest/core/List/operator_subscript_A01_t02: Fail
-LibTest/core/List/operator_subscripted_assignment_A01_t02: Fail
-LibTest/core/List/operator_subscripted_assignment_A01_t01: Fail
-LibTest/core/List/setRange_A01_t01: Fail
-LibTest/core/Queue/addFirst_A01_t01: Fail
-LibTest/core/Set/intersection_A01_t03: Fail
-LibTest/core/String/toLowerCase_A01_t02: Fail
-LibTest/core/String/toUpperCase_A01_t02: Fail
-LibTest/core/String/trim_A01_t02: Fail
-LibTest/core/StringBuffer/add_A02_t01: Fail
-LibTest/core/StringBuffer/addAll_A02_t01: Fail
-LibTest/core/StringBuffer/clear_A02_t01: Fail
-
-# co19 issue 352 (use function expression with return type and name)
-LibTest/isolate/SendPort/send_A01_t01: Fail
-
-
-# co19 issue 354
-Language/07_Classes/6_Constructors/2_Factories_A01_t02: Fail
-
-
-# co19 issue 372 (@static-clean where type warnings are expected)
-Language/07_Classes/6_Constructors_A03_t03: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t04: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t05: Fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A01_t01: Fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A02_t01: Fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A06_t01: Fail
+Language/07_Classes/6_Constructors_A03_t03: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t04: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t05: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A01_t01: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A02_t01: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A06_t01: Fail # co19 issue 372 (@static-clean where type warnings are expected)
-# testing framework or VM issue 7388 (dies on Turkish character)
-Language/11_Expressions/30_Identifier_Reference_A01_t08: Skip
+Language/11_Expressions/30_Identifier_Reference_A01_t08: Skip # testing framework or VM issue 7388 (dies on Turkish character)
Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t02: Fail, OK # deprecated parameter syntax
@@ -503,5 +481,17 @@
LibTest/core/Strings/concatAll_A03_t01: Fail # Strings class has been removed. co19 issue 380
LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/RegExp/RegExp_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/toString_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/IllegalJSRegExpException_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+
+LibTest/core/String/charCodeAt_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A02_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A03_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodes_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/splitChars_A01_t01: Fail # Deprecated string members removed (issue 382).
+
[ $runtime == drt && ($compiler == none || $compiler == frog) ]
*: Skip
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 659bf48..0445889 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -34,13 +34,12 @@
Language/12_Statements/02_Expression_Statements_A01_t08: Fail # co 19 issue 370
-# Calling unresolved class constructor:
-Language/03_Overview/2_Privacy_A01_t19: Fail
-Language/03_Overview/2_Privacy_A01_t20: Fail
-Language/07_Classes/6_Constructors_A03_t03: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t04: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t05: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t06: Fail
+Language/03_Overview/2_Privacy_A01_t19: Fail # Calling unresolved class constructor.
+Language/03_Overview/2_Privacy_A01_t20: Fail # Calling unresolved class constructor.
+Language/07_Classes/6_Constructors_A03_t03: Fail # Calling unresolved class constructor.
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t04: Fail # Calling unresolved class constructor.
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t05: Fail # Calling unresolved class constructor.
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t06: Fail # Calling unresolved class constructor.
Language/03_Overview/1_Scoping_A01_t39: Fail # http://dartbug.com/5519
Language/03_Overview/1_Scoping_A01_t40: Fail # http://dartbug.com/5519
@@ -352,7 +351,6 @@
Language/14_Types/3_Type_Declarations/1_Typedef_A07_t02: Fail, Pass # inherited from dart2js: fails in minify, self-reference typedef check not performed
Language/14_Types/3_Type_Declarations/1_Typedef_A07_t03: Fail, Pass # inherited from dart2js: fails in minify, self-reference typedef check not performed
Language/14_Types/3_Type_Declarations/1_Typedef_A07_t04: Fail # Inherited from dart2js
-Language/14_Types/5_Function_Types_A01_t03: Fail # Inherited from dart2js
Language/14_Types/5_Function_Types_A06_t01: Fail # Inherited from dart2js
Language/15_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: Fail # inherited from dart2js
Language/15_Reference/1_Lexical_Rules_A02_t06: Fail # inherited from dart2js
@@ -436,15 +434,6 @@
LibTest/core/Queue/forEach_A01_t04: Fail # behavior of forEach is undefined when underlying iterable changes, co19 issue 357
LibTest/core/List/List_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/List_A01_t02: Fail # List constructors, co19 issue 358
-LibTest/core/List/add_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addAll_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addLast_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/clear_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/insertRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/length_A04_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeLast_A02_t01: Fail # List constructors, co19 issue 358
LibTest/core/List/last_A02_t01: Fail # List.last throws a StateError, co19 issue 359
@@ -655,19 +644,28 @@
LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
-# Doesn't expect null to be allowed in Set or Map keys (issue 377).
-LibTest/core/Map/containsKey_A01_t02: Fail
-LibTest/core/Map/operator_subscript_A01_t02: Fail
-LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail
-LibTest/core/Map/remove_A01_t02: Fail
-LibTest/core/Set/add_A01_t02: Fail
-LibTest/core/Set/addAll_A01_t02: Fail
-LibTest/core/Set/contains_A01_t02: Fail
-LibTest/core/Set/containsAll_A01_t02: Fail
-LibTest/core/Set/intersection_A03_t01: Fail
-LibTest/core/Set/isSubsetOf_A01_t02: Fail
-LibTest/core/Set/remove_A01_t02: Fail
-LibTest/core/Set/removeAll_A01_t02: Fail
+LibTest/core/RegExp/RegExp_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/toString_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/IllegalJSRegExpException_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
-# Doesn't expect concurrent modification error (issue 376).
-LibTest/core/Map/forEach_A01_t07: Fail
+LibTest/core/Map/containsKey_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscript_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/add_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/addAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/contains_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/containsAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/intersection_A03_t01: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/isSubsetOf_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/removeAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+
+LibTest/core/Map/forEach_A01_t07: Fail # Doesn't expect concurrent modification error (issue 376).
+
+LibTest/core/String/charCodes_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A02_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A03_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/splitChars_A01_t01: Fail # Deprecated string members removed (issue 382).
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index e311447..ccc970e 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -156,8 +156,9 @@
LibTest/core/StringBuffer/isEmpty_A01_t01: Fail, OK # co19 issue 355
LibTest/core/StringBuffer/clear_A02_t01: Fail, OK # co19 issue 355
-# Partially implemented rediriecting constructors makes this fail.
-Language/07_Classes/6_Constructors/2_Factories_A01_t05: Fail
+Language/07_Classes/6_Constructors/2_Factories_A01_t05: Fail # Partially implemented rediriecting constructors makes this fail.
+
+Language/09_Generics/09_Generics_A04_t03: Fail # dart2js does not treat 2.0 as a double; dartbug.com/1533
[ $compiler == dart2js && ($system == linux || $system == macos)]
LibTest/math/exp_A01_t01: Fail # TODO(ahe): Please triage this failure.
@@ -244,17 +245,13 @@
LibTest/core/int/operator_addition_A01_t01: Fail, OK # co19 issue 200
LibTest/core/int/toDouble_A01_t01: Fail, OK # co19 issue 200
-# Slow tests that needs extra time to finish.
-LibTest/core/List/sort_A01_t06: Slow, Pass
+LibTest/core/List/sort_A01_t06: Slow, Pass # Slow tests that needs extra time to finish.
-# Tests that fail because they use the legacy try-catch syntax.
-# See co19 issue 184.
-LibTest/core/List/getRange_A03_t01: Fail, OK
-LibTest/core/List/setRange_A05_t01: Fail, OK
+LibTest/core/List/getRange_A03_t01: Fail, OK # Tests that fail because they use the legacy try-catch syntax. co19 issue 184.
+LibTest/core/List/setRange_A05_t01: Fail, OK # Tests that fail because they use the legacy try-catch syntax. co19 issue 184.
-# These tests need to be updated for new optional parameter syntax and semantics, co19 issue 258:
-Language/07_Classes/1_Instance_Methods_A02_t05: Fail, OK
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A13_t01: Fail, OK
+Language/07_Classes/1_Instance_Methods_A02_t05: Fail, OK # These tests need to be updated for new optional parameter syntax and semantics, co19 issue 258:
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A13_t01: Fail, OK # These tests need to be updated for new optional parameter syntax and semantics, co19 issue 258:
LibTest/isolate/SendPort/send_A02_t02: Fail, OK # co19 issue 293
LibTest/isolate/SendPort/send_A02_t03: Fail, OK # co19 issue 293
@@ -306,9 +303,7 @@
LibTest/core/int/operator_OR_A01_t01: Fail, OK # Requires bigints.
LibTest/core/int/operator_remainder_A01_t01: Fail, OK # Requires bigints.
-# The following tests use the deprecated Date interface.
-# Issue co19 - 125
-LibTest/core/Date/toString_A02_t01: Fail, OK
+LibTest/core/Date/toString_A02_t01: Fail # Argument error. Year 999999 is out of range. Needs to be specified (and then potentially reported to co19): issue 1878.
LibTest/core/Match/pattern_A01_t01: Fail, OK # co19 issue 212
LibTest/core/Match/str_A01_t01: Fail, OK # co19 issue 212
@@ -360,15 +355,6 @@
LibTest/core/Queue/forEach_A01_t04: Fail # behavior of forEach is undefined when underlying iterable changes, co19 issue 357
LibTest/core/List/List_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/List_A01_t02: Fail # List constructors, co19 issue 358
-LibTest/core/List/add_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addAll_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addLast_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/clear_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/insertRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/length_A04_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeLast_A02_t01: Fail # List constructors, co19 issue 358
LibTest/core/List/last_A02_t01: Fail # List.last throws a StateError, co19 issue 359
@@ -572,6 +558,11 @@
LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
+LibTest/core/RegExp/RegExp_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/toString_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/IllegalJSRegExpException_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+
# Issues with co19 test suite in checked mode.
[ $compiler == dart2js && $checked ]
LibTest/isolate/SendPort/call_A01_t01: Fail # Future is in async library. co19 issue 367
@@ -593,8 +584,6 @@
LibTest/core/Match/str_A01_t01: Fail, OK # Bad test, allMatches return an Iterable.
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail, OK # This is not rejected by V8.
LibTest/core/RegExp/Pattern_semantics/firstMatch_Term_A04_t01: Fail, OK # co19 issue 92.
-LibTest/core/RegExp/RegExp_A01_t03: Fail, OK # Expects exception from const constructor.
-LibTest/core/RegExp/RegExp_A01_t04: Fail, OK # Expects exception from const constructor.
LibTest/core/RegExp/allMatches_A01_t01: Fail, OK # Bad test, allMatches return an Iterable.
LibTest/core/RegExp/firstMatch_A01_t01: Fail, OK # Bad test, use Match.regexp, not Match.pattern.
LibTest/core/double/toRadixString_A01_t01: Fail, OK # Unimplemented test stub.
@@ -744,7 +733,6 @@
Language/07_Classes/3_Setters_A04_t07: Fail # http://dartbug.com/5023
Language/14_Types/5_Function_Types_A01_t01: Fail # http://dartbug.com/5022
-Language/14_Types/5_Function_Types_A01_t03: Fail # http://dartbug.com/5022
Language/13_Libraries_and_Scripts/4_Scripts_A03_t01: Fail # http://dartbug.com/5683
Language/13_Libraries_and_Scripts/4_Scripts_A03_t03: Fail # http://dartbug.com/5683
@@ -772,19 +760,23 @@
Language/14_Types/3_Type_Declarations/1_Typedef_A07_t03: Fail # dartbug.com/7202
Language/14_Types/3_Type_Declarations/1_Typedef_A07_t04: Fail # dartbug.com/7202
-# Doesn't expect null to be allowed in Set or Map keys (issue 377).
-LibTest/core/Map/containsKey_A01_t02: Fail
-LibTest/core/Map/operator_subscript_A01_t02: Fail
-LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail
-LibTest/core/Map/remove_A01_t02: Fail
-LibTest/core/Set/add_A01_t02: Fail
-LibTest/core/Set/addAll_A01_t02: Fail
-LibTest/core/Set/contains_A01_t02: Fail
-LibTest/core/Set/containsAll_A01_t02: Fail
-LibTest/core/Set/intersection_A03_t01: Fail
-LibTest/core/Set/isSubsetOf_A01_t02: Fail
-LibTest/core/Set/remove_A01_t02: Fail
-LibTest/core/Set/removeAll_A01_t02: Fail
+LibTest/core/Map/containsKey_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscript_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/add_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/addAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/contains_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/containsAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/intersection_A03_t01: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/isSubsetOf_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/removeAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
-# Doesn't expect concurrent modification error (issue 376).
-LibTest/core/Map/forEach_A01_t07: Fail
+LibTest/core/Map/forEach_A01_t07: Fail # Doesn't expect concurrent modification error (issue 376).
+
+LibTest/core/String/charCodes_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A02_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A03_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/splitChars_A01_t01: Fail # Deprecated string members removed (issue 382).
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index fb79c4e..b8ff98e 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -10,6 +10,13 @@
Language/13_Libraries_and_Scripts/1_Imports_A02_t21: Crash # Dart issue 6060
Language/13_Libraries_and_Scripts/1_Imports_A02_t22: Crash # Dart issue 6060
+Language/13_Libraries_and_Scripts/1_Imports_A04_t03: Fail # co19 issue 385
+Language/13_Libraries_and_Scripts/2_Exports_A05_t01: Fail # co19 issue 385
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t20: Fail # co19 issue 387
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t21: Fail # co19 issue 387
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t22: Fail # co19 issue 387
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t23: Fail # co19 issue 387
+
Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A01_t10: Fail # co19 issue 348
Language/07_Classes/3_Setters_A04_t01: Fail # co19 issue 383
Language/07_Classes/3_Setters_A04_t04: Fail # co19 issue 383
@@ -136,15 +143,6 @@
LibTest/core/Queue/forEach_A01_t04: Fail # behavior of forEach is undefined when underlying iterable changes, co19 issue 357
LibTest/core/List/List_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/List_A01_t02: Fail # List constructors, co19 issue 358
-LibTest/core/List/add_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addAll_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addLast_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/clear_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/insertRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/length_A04_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeLast_A02_t01: Fail # List constructors, co19 issue 358
LibTest/core/List/last_A02_t01: Fail # List.last throws a StateError, co19 issue 359
@@ -259,19 +257,17 @@
LibTest/core/Date/Date.fromMillisecondsSinceEpoch_A03_t01: Fail # TODO(vm-team): Please triage this failure.
[ $compiler == none && $runtime == vm ]
-# Not properly reporting exception in initializer expressions
-Language/11_Expressions/01_Constants_A16_t01: Fail
-Language/11_Expressions/01_Constants_A16_t02: Fail
+Language/11_Expressions/01_Constants_A16_t01: Fail # Not properly reporting exception in initializer expressions
+Language/11_Expressions/01_Constants_A16_t02: Fail # Not properly reporting exception in initializer expressions
Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t03: Fail # issue 392, potentially constant expression analysis
Language/11_Expressions/01_Constants_A17_t03: Crash # issue 1681 (recursion in compile-time constant expression)
Language/11_Expressions/01_Constants_A16_t02: Crash, Pass # Should result in OOM
-# co19 issue 183 - must not instantiate an abstract class
# Some of these tests are expected to fail for another reason. These are marked as Skip.
-Language/07_Classes/07_Classes_A02_t29: Skip # co19 issue 183
-Language/07_Classes/07_Classes_A02_t31: Skip # co19 issue 183
+Language/07_Classes/07_Classes_A02_t29: Skip # must not instantiate an abstract class, co19 issue 183
+Language/07_Classes/07_Classes_A02_t31: Skip # must not instantiate an abstract class, co19 issue 183
# co19 175 - related to issue 4522, all need fixing, some passes because of temporary warning.
Language/11_Expressions/07_Maps_A03_t01: Pass, Fail # co19 175
@@ -338,10 +334,8 @@
[ $compiler == none && $runtime == vm ]
-# The following tests use the deprecated Date interface.
-# Issue co19 - 125
-LibTest/core/Date/toString_A02_t01: Fail, OK
-LibTest/core/Date/year_A01_t01: Fail, OK
+LibTest/core/Date/toString_A02_t01: Fail # Argument error. Year 999999 is out of range. Needs to be specified (and then potentially reported to co19): issue 1878.
+LibTest/core/Date/year_A01_t01: Fail # Year out of range. Needs to be specified: issue 8808. Possibly a co19 bug.
LibTest/isolate/SendPort/send_A02_t02: Skip # co19 issue 293
LibTest/isolate/SendPort/send_A02_t03: Skip # co19 issue 293
@@ -509,22 +503,31 @@
LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
-# Doesn't expect null to be allowed in Set or Map keys (issue 377).
-LibTest/core/Map/containsKey_A01_t02: Fail
-LibTest/core/Map/operator_subscript_A01_t02: Fail
-LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail
-LibTest/core/Map/remove_A01_t02: Fail
-LibTest/core/Set/add_A01_t02: Fail
-LibTest/core/Set/addAll_A01_t02: Fail
-LibTest/core/Set/contains_A01_t02: Fail
-LibTest/core/Set/containsAll_A01_t02: Fail
-LibTest/core/Set/intersection_A03_t01: Fail
-LibTest/core/Set/isSubsetOf_A01_t02: Fail
-LibTest/core/Set/remove_A01_t02: Fail
-LibTest/core/Set/removeAll_A01_t02: Fail
+LibTest/core/RegExp/RegExp_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/toString_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/IllegalJSRegExpException_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
-# Doesn't expect concurrent modification error (issue 376).
-LibTest/core/Map/forEach_A01_t07: Fail
+LibTest/core/Map/containsKey_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscript_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/add_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/addAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/contains_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/containsAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/intersection_A03_t01: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/isSubsetOf_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/removeAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+
+LibTest/core/Map/forEach_A01_t07: Fail # Doesn't expect concurrent modification error (issue 376).
+
+LibTest/core/String/charCodes_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A02_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A03_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/splitChars_A01_t01: Fail # Deprecated string members removed (issue 382).
[ $compiler == none && $runtime == vm && $unchecked ]
LibTest/core/Future/chain_A02_t05: Fail # Future is in async library. co19 issue 367
diff --git a/tests/compiler/dart2js/deprecated_features_test.dart b/tests/compiler/dart2js/deprecated_features_test.dart
index 88dd6b7..7c8bc58 100644
--- a/tests/compiler/dart2js/deprecated_features_test.dart
+++ b/tests/compiler/dart2js/deprecated_features_test.dart
@@ -68,8 +68,7 @@
"109<Foo>::${deprecatedMessage('conflicting constructor')}\n"
"129<bar>::info: This member conflicts with a constructor.\n"
- "200<Dynamic>::${deprecatedMessage('Dynamic')}\n"
- "221<()>::${deprecatedMessage('getter parameters')}\n",
+ "205<()>::${deprecatedMessage('getter parameters')}\n",
messages.toString());
}
@@ -95,7 +94,6 @@
static bar() => new Foo.bar();
factory Fisk() {}
factory Fisk.hest() {}
- Dynamic fisk;
get x() => null;
}
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 686c8ff..149ccf3 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -56,24 +56,25 @@
class Dynamic_ {}
class LinkedHashMap {}
S() {}
+ unwrapException(e) {}
assertHelper(a){}
createRuntimeType(a) {}
throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) {}
throwAbstractClassInstantiationError(className) {}''';
const String DEFAULT_INTERCEPTORSLIB = r'''
- class JSArray {
+ class JSArray implements List {
var length;
operator[](index) {}
operator[]=(index, value) {}
var add;
}
- class JSString {
+ class JSString implements String {
var length;
operator[](index) {}
toString() {}
}
- class JSNumber {
+ class JSNumber implements num {
// All these methods return a number to please type inferencing.
operator-() => (this is JSInt) ? 42 : 42.0;
operator +(other) => (this is JSInt) ? 42 : 42.0;
@@ -94,15 +95,15 @@
operator <=(other) => true;
operator ==(other) => true;
}
- class JSInt extends JSNumber {
+ class JSInt extends JSNumber implements int {
}
- class JSDouble extends JSNumber {
+ class JSDouble extends JSNumber implements double {
}
class JSNull {
}
- class JSBool {
+ class JSBool implements bool {
}
- class JSFunction {
+ class JSFunction implements Function {
}
class ObjectInterceptor {
}
@@ -117,7 +118,7 @@
static parse(s) {}
}
class bool {}
- class String {}
+ class String implements Pattern {}
class Object {
operator ==(other) {}
String toString() {}
@@ -130,6 +131,7 @@
DateTime(year);
DateTime.utc(year);
}
+ abstract class Pattern {}
bool identical(Object a, Object b) {}''';
const String DEFAULT_ISOLATE_HELPERLIB = r'''
@@ -161,13 +163,17 @@
// We need to set the assert method to avoid calls with a 'null'
// target being interpreted as a call to assert.
jsHelperLibrary = createLibrary("helper", helperSource);
- importHelperLibrary(coreLibrary);
- libraryLoader.importLibrary(jsHelperLibrary, coreLibrary, null);
-
- assertMethod = jsHelperLibrary.find(buildSourceString('assert'));
interceptorsLibrary = createLibrary("interceptors", interceptorsSource);
isolateHelperLibrary = createLibrary("isolate_helper", isolateHelperSource);
+ // Set up the library imports.
+ importHelperLibrary(coreLibrary);
+ libraryLoader.importLibrary(jsHelperLibrary, coreLibrary, null);
+ libraryLoader.importLibrary(interceptorsLibrary, coreLibrary, null);
+ libraryLoader.importLibrary(isolateHelperLibrary, coreLibrary, null);
+
+ assertMethod = jsHelperLibrary.find(buildSourceString('assert'));
+
mainApp = mockLibrary(this, "");
initializeSpecialClasses();
// We need to make sure the Object class is resolved. When registering a
diff --git a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
new file mode 100644
index 0000000..21c0f8d
--- /dev/null
+++ b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
@@ -0,0 +1,48 @@
+// 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 'compiler_helper.dart';
+
+const String TEST = """
+returnDyn1() {
+ var a;
+ ((a = 52) == true) || ((a = 'foo') == true);
+ return a;
+}
+
+returnDyn2() {
+ var a;
+ ((a = 52) == true) && ((a = 'foo') == true);
+ return a;
+}
+
+returnDyn3() {
+ var a;
+ a = a == 54 ? 'foo' : 31;
+ return a;
+}
+
+main() {
+ returnDyn1();
+ returnDyn2();
+ returnDyn3();
+}
+""";
+
+
+void main() {
+ Uri uri = new Uri.fromComponents(scheme: 'source');
+ var compiler = compilerFor(TEST, uri);
+ compiler.runCompiler(uri);
+ var typesInferrer = compiler.typesTask.typesInferrer;
+
+ checkReturn(String name, type) {
+ var element = findElement(compiler, name);
+ Expect.equals(type, typesInferrer.returnTypeOf[element]);
+ }
+
+ checkReturn('returnDyn1', compiler.dynamicClass);
+ checkReturn('returnDyn2', compiler.dynamicClass);
+ checkReturn('returnDyn3', compiler.dynamicClass);
+}
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
new file mode 100644
index 0000000..d9351e3
--- /dev/null
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -0,0 +1,94 @@
+// 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 'compiler_helper.dart';
+
+const String TEST = """
+returnInt1() {
+ var a = 42;
+ var f = () {
+ return a;
+ };
+ return a;
+}
+
+returnDyn1() {
+ var a = 42;
+ var f = () {
+ a = 'foo';
+ };
+ return a;
+}
+
+returnInt2() {
+ var a = 42;
+ var f = () {
+ a = 54;
+ };
+ return a;
+}
+
+returnDyn2() {
+ var a = 42;
+ var f = () {
+ a = 54;
+ };
+ var g = () {
+ a = 'foo';
+ };
+ return a;
+}
+
+returnInt3() {
+ var a = 42;
+ if (a == 53) {
+ var f = () {
+ a = 32;
+ };
+ }
+ return a;
+}
+
+returnDyn3() {
+ var a = 42;
+ if (a == 53) {
+ var f = () {
+ a = 'foo';
+ };
+ }
+ return a;
+}
+
+main() {
+ returnInt1();
+ returnDyn1();
+ returnInt2();
+ returnDyn2();
+ returnInt3();
+ returnDyn3();
+}
+""";
+
+
+void main() {
+ Uri uri = new Uri.fromComponents(scheme: 'source');
+ var compiler = compilerFor(TEST, uri);
+ compiler.runCompiler(uri);
+ var typesInferrer = compiler.typesTask.typesInferrer;
+
+ checkReturn(String name, type) {
+ var element = findElement(compiler, name);
+ Expect.equals(type, typesInferrer.returnTypeOf[element]);
+ }
+
+ checkReturn('returnInt1', compiler.intClass);
+ checkReturn('returnInt2', compiler.intClass);
+ checkReturn('returnInt3', compiler.intClass);
+
+ checkReturn('returnDyn1', compiler.dynamicClass);
+ checkReturn('returnDyn2', compiler.dynamicClass);
+ checkReturn('returnDyn3', compiler.dynamicClass);
+
+ print(typesInferrer.returnTypeOf);
+}
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
new file mode 100644
index 0000000..58afca9
--- /dev/null
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -0,0 +1,62 @@
+// 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 'compiler_helper.dart';
+
+const String TEST = """
+returnNum1(a) {
+ if (a) return 1;
+ else return 2.0;
+}
+
+returnNum2(a) {
+ if (a) return 1.0;
+ else return 2;
+}
+
+returnInt(a) {
+ if (a) return 1;
+ else return 2;
+}
+
+returnDouble(a) {
+ if (a) return 1.0;
+ else return 2.0;
+}
+
+returnGiveUp(a) {
+ if (a) return 1;
+ else return 'foo';
+}
+
+main() {
+ returnNum1(true);
+ returnNum2(true);
+ returnInt(true);
+ returnDouble(true);
+ returnGiveUp(true);
+}
+""";
+
+void main() {
+ Uri uri = new Uri.fromComponents(scheme: 'source');
+ var compiler = compilerFor(TEST, uri);
+ compiler.runCompiler(uri);
+ var typesInferrer = compiler.typesTask.typesInferrer;
+
+ var element = findElement(compiler, 'returnNum1');
+ Expect.equals(compiler.numClass, typesInferrer.returnTypeOf[element]);
+
+ element = findElement(compiler, 'returnNum2');
+ Expect.equals(compiler.numClass, typesInferrer.returnTypeOf[element]);
+
+ element = findElement(compiler, 'returnInt');
+ Expect.equals(compiler.intClass, typesInferrer.returnTypeOf[element]);
+
+ element = findElement(compiler, 'returnDouble');
+ Expect.equals(compiler.doubleClass, typesInferrer.returnTypeOf[element]);
+
+ element = findElement(compiler, 'returnGiveUp');
+ Expect.equals(typesInferrer.giveUpType, typesInferrer.returnTypeOf[element]);
+}
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
new file mode 100644
index 0000000..700b5f8
--- /dev/null
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -0,0 +1,153 @@
+// 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 'compiler_helper.dart';
+
+const String TEST = """
+returnInt1() {
+ var a = 42;
+ try {
+ a = 54;
+ } catch (e){
+ }
+ return a;
+}
+
+returnDyn1() {
+ var a = 42;
+ try {
+ a = 'foo';
+ } catch (e){
+ }
+ return a;
+}
+
+returnInt2() {
+ var a = 42;
+ try {
+ a = 54;
+ } catch (e){
+ a = 2;
+ }
+ return a;
+}
+
+returnDyn2() {
+ var a = 42;
+ try {
+ a = 54;
+ } catch (e){
+ a = 'foo';
+ }
+ return a;
+}
+
+returnInt3() {
+ var a = 42;
+ try {
+ a = 54;
+ } catch (e){
+ a = 'foo';
+ } finally {
+ a = 4;
+ }
+ return a;
+}
+
+returnDyn3() {
+ var a = 42;
+ try {
+ a = 54;
+ } on String catch (e) {
+ a = 2;
+ } on Object catch (e) {
+ a = 'foo';
+ }
+ return a;
+}
+
+returnInt4() {
+ var a = 42;
+ try {
+ a = 54;
+ } on String catch (e) {
+ a = 2;
+ } on Object catch (e) {
+ a = 32;
+ }
+ return a;
+}
+
+returnDyn4() {
+ var a = 42;
+ if (a == 54) {
+ try {
+ a = 'foo';
+ } catch (e) {
+ }
+ }
+ return a;
+}
+
+returnInt5() {
+ var a = 42;
+ if (a == 54) {
+ try {
+ a = 42;
+ } catch (e) {
+ }
+ }
+ return a;
+}
+
+returnDyn5() {
+ var a = 42;
+ if (a == 54) {
+ try {
+ a = 'foo';
+ print(a);
+ a = 42;
+ } catch (e) {
+ }
+ }
+ return a;
+}
+
+
+main() {
+ returnInt1();
+ returnDyn1();
+ returnInt2();
+ returnDyn2();
+ returnInt3();
+ returnDyn3();
+ returnInt4();
+ returnDyn4();
+ returnInt5();
+}
+""";
+
+
+void main() {
+ Uri uri = new Uri.fromComponents(scheme: 'source');
+ var compiler = compilerFor(TEST, uri);
+ compiler.runCompiler(uri);
+ var typesInferrer = compiler.typesTask.typesInferrer;
+
+ checkReturn(String name, type) {
+ var element = findElement(compiler, name);
+ Expect.equals(type, typesInferrer.returnTypeOf[element]);
+ }
+
+ checkReturn('returnInt1', compiler.intClass);
+ checkReturn('returnInt2', compiler.intClass);
+ checkReturn('returnInt3', compiler.intClass);
+ checkReturn('returnInt4', compiler.intClass);
+ checkReturn('returnInt5', compiler.intClass);
+
+ checkReturn('returnDyn1', compiler.dynamicClass);
+ checkReturn('returnDyn2', compiler.dynamicClass);
+ checkReturn('returnDyn3', compiler.dynamicClass);
+ checkReturn('returnDyn4', compiler.dynamicClass);
+}
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index 3b3ae1e..ada905c 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
import "mock_compiler.dart";
+import "parser_helper.dart";
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;
@@ -23,2022 +25,2039 @@
const DOUBLE_OR_NULL = HType.DOUBLE_OR_NULL;
const STRING_OR_NULL = HType.STRING_OR_NULL;
const NULL = HType.NULL;
+
+var patternClass;
HType nonPrimitive1;
HType nonPrimitive2;
HType potentialArray;
HType potentialString;
+HType jsArrayOrNull;
void testUnion(MockCompiler compiler) {
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
CONFLICTING.union(UNKNOWN, compiler));
- Expect.equals(BOOLEAN,
+ Expect.equals(BOOLEAN,
CONFLICTING.union(BOOLEAN, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
CONFLICTING.union(NUMBER, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
CONFLICTING.union(INTEGER, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
CONFLICTING.union(DOUBLE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
CONFLICTING.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
CONFLICTING.union(STRING, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
CONFLICTING.union(READABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
CONFLICTING.union(MUTABLE_ARRAY, compiler));
- Expect.equals(EXTENDABLE_ARRAY,
+ Expect.equals(EXTENDABLE_ARRAY,
CONFLICTING.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(nonPrimitive1,
+ Expect.equals(nonPrimitive1,
CONFLICTING.union(nonPrimitive1, compiler));
- Expect.equals(nonPrimitive2,
+ Expect.equals(nonPrimitive2,
CONFLICTING.union(nonPrimitive2, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
CONFLICTING.union(potentialArray, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
CONFLICTING.union(potentialString, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
CONFLICTING.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
CONFLICTING.union(NUMBER_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
CONFLICTING.union(INTEGER_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
CONFLICTING.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
CONFLICTING.union(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
CONFLICTING.union(NULL, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
CONFLICTING.union(FIXED_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(STRING_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.union(FIXED_ARRAY, compiler));
- Expect.equals(BOOLEAN,
+ Expect.equals(BOOLEAN,
BOOLEAN.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(UNKNOWN, compiler));
- Expect.equals(BOOLEAN,
+ Expect.equals(BOOLEAN,
BOOLEAN.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(potentialString, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
BOOLEAN.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(STRING_OR_NULL, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
BOOLEAN.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN.union(FIXED_ARRAY, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
NUMBER.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(BOOLEAN, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
NUMBER.union(NUMBER, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
NUMBER.union(INTEGER, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
NUMBER.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER.union(NUMBER_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER.union(INTEGER_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(STRING_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER.union(FIXED_ARRAY, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
INTEGER.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(BOOLEAN, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
INTEGER.union(NUMBER, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
INTEGER.union(INTEGER, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
INTEGER.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
INTEGER.union(NUMBER_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
INTEGER.union(INTEGER_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
INTEGER.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(STRING_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
INTEGER.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER.union(FIXED_ARRAY, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
DOUBLE.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(BOOLEAN, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
DOUBLE.union(NUMBER, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
DOUBLE.union(INTEGER, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
DOUBLE.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
DOUBLE.union(NUMBER_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
DOUBLE.union(INTEGER_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
DOUBLE.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(STRING_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
DOUBLE.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE.union(FIXED_ARRAY, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
INDEXABLE_PRIMITIVE.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(DOUBLE, compiler));
Expect.equals(INDEXABLE_PRIMITIVE,
- INDEXABLE_PRIMITIVE.union(INDEXABLE_PRIMITIVE,
+ INDEXABLE_PRIMITIVE.union(INDEXABLE_PRIMITIVE,
compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
INDEXABLE_PRIMITIVE.union(STRING, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
INDEXABLE_PRIMITIVE.union(READABLE_ARRAY, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
INDEXABLE_PRIMITIVE.union(MUTABLE_ARRAY, compiler));
Expect.equals(INDEXABLE_PRIMITIVE,
- INDEXABLE_PRIMITIVE.union(EXTENDABLE_ARRAY,
+ INDEXABLE_PRIMITIVE.union(EXTENDABLE_ARRAY,
compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(STRING_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INDEXABLE_PRIMITIVE.union(NULL, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
INDEXABLE_PRIMITIVE.union(FIXED_ARRAY, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
STRING.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(DOUBLE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
STRING.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
STRING.union(STRING, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
STRING.union(READABLE_ARRAY, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
STRING.union(MUTABLE_ARRAY, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
STRING.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(potentialArray, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
STRING.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
STRING.union(STRING_OR_NULL, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
STRING.union(NULL, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
STRING.union(FIXED_ARRAY, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
READABLE_ARRAY.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(DOUBLE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
READABLE_ARRAY.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
READABLE_ARRAY.union(STRING, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
READABLE_ARRAY.union(READABLE_ARRAY, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
READABLE_ARRAY.union(MUTABLE_ARRAY, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
READABLE_ARRAY.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(nonPrimitive2, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
READABLE_ARRAY.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
READABLE_ARRAY.union(STRING_OR_NULL, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(jsArrayOrNull,
READABLE_ARRAY.union(NULL, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
READABLE_ARRAY.union(FIXED_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
MUTABLE_ARRAY.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(DOUBLE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
MUTABLE_ARRAY.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
MUTABLE_ARRAY.union(STRING, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
MUTABLE_ARRAY.union(READABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
MUTABLE_ARRAY.union(MUTABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
MUTABLE_ARRAY.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(nonPrimitive2, compiler));
- Expect.equals(potentialArray,MUTABLE_ARRAY.union(potentialArray,
+ Expect.equals(potentialArray,MUTABLE_ARRAY.union(potentialArray,
compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
MUTABLE_ARRAY.union(STRING_OR_NULL, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(jsArrayOrNull,
MUTABLE_ARRAY.union(NULL, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
MUTABLE_ARRAY.union(FIXED_ARRAY, compiler));
- Expect.equals(EXTENDABLE_ARRAY,
+ Expect.equals(EXTENDABLE_ARRAY,
EXTENDABLE_ARRAY.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(DOUBLE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
EXTENDABLE_ARRAY.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
EXTENDABLE_ARRAY.union(STRING, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
EXTENDABLE_ARRAY.union(READABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
EXTENDABLE_ARRAY.union(MUTABLE_ARRAY, compiler));
- Expect.equals(EXTENDABLE_ARRAY,
+ Expect.equals(EXTENDABLE_ARRAY,
EXTENDABLE_ARRAY.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(nonPrimitive2, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
EXTENDABLE_ARRAY.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
EXTENDABLE_ARRAY.union(STRING_OR_NULL, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(jsArrayOrNull,
EXTENDABLE_ARRAY.union(NULL, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
EXTENDABLE_ARRAY.union(FIXED_ARRAY, compiler));
- Expect.equals(nonPrimitive1,
+ Expect.equals(nonPrimitive1,
nonPrimitive1.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(nonPrimitive1,
+ Expect.equals(nonPrimitive1,
nonPrimitive1.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(STRING_OR_NULL, compiler));
Expect.isTrue(nonPrimitive1.union(NULL, compiler) is HBoundedType);
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive1.union(FIXED_ARRAY, compiler));
- Expect.equals(nonPrimitive2,
+ Expect.equals(nonPrimitive2,
nonPrimitive2.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(nonPrimitive1, compiler));
- Expect.equals(nonPrimitive2,
+ Expect.equals(nonPrimitive2,
nonPrimitive2.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(STRING_OR_NULL, compiler));
Expect.isTrue(nonPrimitive2.union(NULL, compiler) is HBoundedType);
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
nonPrimitive2.union(FIXED_ARRAY, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
potentialArray.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(STRING, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
potentialArray.union(READABLE_ARRAY, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
potentialArray.union(MUTABLE_ARRAY, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
potentialArray.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(nonPrimitive2, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
potentialArray.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialArray.union(STRING_OR_NULL, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
potentialArray.union(NULL, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
potentialArray.union(FIXED_ARRAY, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
potentialString.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
potentialString.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(potentialArray, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
potentialString.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
potentialString.union(STRING_OR_NULL, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
potentialString.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
potentialString.union(FIXED_ARRAY, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
BOOLEAN_OR_NULL.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(UNKNOWN, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
BOOLEAN_OR_NULL.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(potentialString, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
BOOLEAN_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(STRING_OR_NULL, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
BOOLEAN_OR_NULL.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
BOOLEAN_OR_NULL.union(FIXED_ARRAY, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(BOOLEAN, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.union(NUMBER, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.union(INTEGER, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.union(NUMBER_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.union(INTEGER_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(STRING_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NUMBER_OR_NULL.union(FIXED_ARRAY, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
INTEGER_OR_NULL.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(BOOLEAN, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
INTEGER_OR_NULL.union(NUMBER, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
INTEGER_OR_NULL.union(INTEGER, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
INTEGER_OR_NULL.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
INTEGER_OR_NULL.union(NUMBER_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
INTEGER_OR_NULL.union(INTEGER_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
INTEGER_OR_NULL.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(STRING_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
INTEGER_OR_NULL.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
INTEGER_OR_NULL.union(FIXED_ARRAY, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
DOUBLE_OR_NULL.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(BOOLEAN, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
DOUBLE_OR_NULL.union(NUMBER, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
DOUBLE_OR_NULL.union(INTEGER, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
DOUBLE_OR_NULL.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
DOUBLE_OR_NULL.union(NUMBER_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
DOUBLE_OR_NULL.union(INTEGER_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
DOUBLE_OR_NULL.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(STRING_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
DOUBLE_OR_NULL.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
DOUBLE_OR_NULL.union(FIXED_ARRAY, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
STRING_OR_NULL.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
STRING_OR_NULL.union(STRING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(READABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(MUTABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(nonPrimitive2, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(potentialArray, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
STRING_OR_NULL.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
STRING_OR_NULL.union(STRING_OR_NULL, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
STRING_OR_NULL.union(NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
STRING_OR_NULL.union(FIXED_ARRAY, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NULL.union(UNKNOWN, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
NULL.union(BOOLEAN, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NULL.union(NUMBER, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
NULL.union(INTEGER, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
NULL.union(DOUBLE, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NULL.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
NULL.union(STRING, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(jsArrayOrNull,
NULL.union(READABLE_ARRAY, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(jsArrayOrNull,
NULL.union(MUTABLE_ARRAY, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(jsArrayOrNull,
NULL.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NULL.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
NULL.union(nonPrimitive2, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
NULL.union(potentialArray, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
NULL.union(potentialString, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
NULL.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NULL.union(NUMBER_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
NULL.union(INTEGER_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
NULL.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
NULL.union(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.union(NULL, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(jsArrayOrNull,
NULL.union(FIXED_ARRAY, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
FIXED_ARRAY.union(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(UNKNOWN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(BOOLEAN, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(NUMBER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(INTEGER, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(DOUBLE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
FIXED_ARRAY.union(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
FIXED_ARRAY.union(STRING, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
FIXED_ARRAY.union(READABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
FIXED_ARRAY.union(MUTABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
FIXED_ARRAY.union(EXTENDABLE_ARRAY, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(nonPrimitive1, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(nonPrimitive2, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
FIXED_ARRAY.union(potentialArray, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(potentialString, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(BOOLEAN_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(NUMBER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(INTEGER_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(DOUBLE_OR_NULL, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
FIXED_ARRAY.union(STRING_OR_NULL, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(jsArrayOrNull,
FIXED_ARRAY.union(NULL, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
FIXED_ARRAY.union(FIXED_ARRAY, compiler));
}
void testIntersection(MockCompiler compiler) {
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(CONFLICTING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(nonPrimitive2, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
CONFLICTING.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
UNKNOWN.intersection(CONFLICTING, compiler));
- Expect.equals(UNKNOWN,
+ Expect.equals(UNKNOWN,
UNKNOWN.intersection(UNKNOWN, compiler));
- Expect.equals(BOOLEAN,
+ Expect.equals(BOOLEAN,
UNKNOWN.intersection(BOOLEAN, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
UNKNOWN.intersection(NUMBER, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
UNKNOWN.intersection(INTEGER, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
UNKNOWN.intersection(DOUBLE, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
UNKNOWN.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
UNKNOWN.intersection(STRING, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
UNKNOWN.intersection(READABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
UNKNOWN.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(EXTENDABLE_ARRAY,
+ Expect.equals(EXTENDABLE_ARRAY,
UNKNOWN.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(nonPrimitive1,
+ Expect.equals(nonPrimitive1,
UNKNOWN.intersection(nonPrimitive1, compiler));
- Expect.equals(nonPrimitive2,
+ Expect.equals(nonPrimitive2,
UNKNOWN.intersection(nonPrimitive2, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
UNKNOWN.intersection(potentialArray, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
UNKNOWN.intersection(potentialString, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
UNKNOWN.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
UNKNOWN.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
UNKNOWN.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
UNKNOWN.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
UNKNOWN.intersection(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
UNKNOWN.intersection(NULL, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
UNKNOWN.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(CONFLICTING, compiler));
- Expect.equals(BOOLEAN,
+ Expect.equals(BOOLEAN,
BOOLEAN.intersection(UNKNOWN, compiler));
- Expect.equals(BOOLEAN,
+ Expect.equals(BOOLEAN,
BOOLEAN.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(nonPrimitive2, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(potentialString, compiler));
- Expect.equals(BOOLEAN,
+ Expect.equals(BOOLEAN,
BOOLEAN.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(CONFLICTING, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
NUMBER.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(BOOLEAN, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
NUMBER.intersection(NUMBER, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
NUMBER.intersection(INTEGER, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
NUMBER.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(nonPrimitive2, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
NUMBER.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
NUMBER.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
NUMBER.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(CONFLICTING, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
INTEGER.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(BOOLEAN, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
INTEGER.intersection(NUMBER, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
INTEGER.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(nonPrimitive2, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
INTEGER.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
INTEGER.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(CONFLICTING, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
DOUBLE.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(BOOLEAN, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
DOUBLE.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(INTEGER, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
DOUBLE.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(nonPrimitive2, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
DOUBLE.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
DOUBLE.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE.intersection(FIXED_ARRAY, compiler));
-
- Expect.equals(CONFLICTING,
+
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(CONFLICTING, compiler));
- Expect.equals(INDEXABLE_PRIMITIVE,
+ Expect.equals(INDEXABLE_PRIMITIVE,
INDEXABLE_PRIMITIVE.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(DOUBLE, compiler));
Expect.equals(INDEXABLE_PRIMITIVE,
- INDEXABLE_PRIMITIVE.intersection(INDEXABLE_PRIMITIVE,
- compiler));
- Expect.equals(STRING,
- INDEXABLE_PRIMITIVE.intersection(STRING, compiler));
- Expect.equals(READABLE_ARRAY,
- INDEXABLE_PRIMITIVE.intersection(READABLE_ARRAY,
- compiler));
- Expect.equals(MUTABLE_ARRAY,
- INDEXABLE_PRIMITIVE.intersection(MUTABLE_ARRAY,
- compiler));
- Expect.equals(EXTENDABLE_ARRAY,
- INDEXABLE_PRIMITIVE.intersection(EXTENDABLE_ARRAY,
- compiler));
- Expect.equals(CONFLICTING,
- INDEXABLE_PRIMITIVE.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
- INDEXABLE_PRIMITIVE.intersection(nonPrimitive2, compiler));
- Expect.equals(READABLE_ARRAY,
- INDEXABLE_PRIMITIVE.intersection(potentialArray,
+ INDEXABLE_PRIMITIVE.intersection(INDEXABLE_PRIMITIVE,
compiler));
Expect.equals(STRING,
- INDEXABLE_PRIMITIVE.intersection(potentialString,
+ INDEXABLE_PRIMITIVE.intersection(STRING, compiler));
+ Expect.equals(READABLE_ARRAY,
+ INDEXABLE_PRIMITIVE.intersection(READABLE_ARRAY,
compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(MUTABLE_ARRAY,
+ INDEXABLE_PRIMITIVE.intersection(MUTABLE_ARRAY,
+ compiler));
+ Expect.equals(EXTENDABLE_ARRAY,
+ INDEXABLE_PRIMITIVE.intersection(EXTENDABLE_ARRAY,
+ compiler));
+ Expect.equals(CONFLICTING,
+ INDEXABLE_PRIMITIVE.intersection(nonPrimitive1, compiler));
+ Expect.equals(CONFLICTING,
+ INDEXABLE_PRIMITIVE.intersection(nonPrimitive2, compiler));
+ Expect.equals(READABLE_ARRAY,
+ INDEXABLE_PRIMITIVE.intersection(potentialArray,
+ compiler));
+ Expect.equals(STRING,
+ INDEXABLE_PRIMITIVE.intersection(potentialString,
+ compiler));
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INDEXABLE_PRIMITIVE.intersection(NULL, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
INDEXABLE_PRIMITIVE.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(CONFLICTING, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
STRING.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(DOUBLE, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
STRING.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
STRING.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(nonPrimitive2, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(potentialArray, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
STRING.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
STRING.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(CONFLICTING, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
READABLE_ARRAY.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(DOUBLE, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
READABLE_ARRAY.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(STRING, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
READABLE_ARRAY.intersection(READABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
READABLE_ARRAY.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(EXTENDABLE_ARRAY,
+ Expect.equals(EXTENDABLE_ARRAY,
READABLE_ARRAY.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(nonPrimitive2, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
READABLE_ARRAY.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
READABLE_ARRAY.intersection(NULL, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
READABLE_ARRAY.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(CONFLICTING, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
MUTABLE_ARRAY.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(DOUBLE, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
MUTABLE_ARRAY.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(STRING, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
MUTABLE_ARRAY.intersection(READABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
MUTABLE_ARRAY.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(EXTENDABLE_ARRAY,
+ Expect.equals(EXTENDABLE_ARRAY,
MUTABLE_ARRAY.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(nonPrimitive2, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
MUTABLE_ARRAY.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
MUTABLE_ARRAY.intersection(NULL, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
MUTABLE_ARRAY.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(CONFLICTING, compiler));
- Expect.equals(EXTENDABLE_ARRAY,
+ Expect.equals(EXTENDABLE_ARRAY,
EXTENDABLE_ARRAY.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(DOUBLE, compiler));
Expect.equals(EXTENDABLE_ARRAY,
- EXTENDABLE_ARRAY.intersection(INDEXABLE_PRIMITIVE,
+ EXTENDABLE_ARRAY.intersection(INDEXABLE_PRIMITIVE,
compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(STRING, compiler));
Expect.equals(EXTENDABLE_ARRAY,
- EXTENDABLE_ARRAY.intersection(READABLE_ARRAY,
+ EXTENDABLE_ARRAY.intersection(READABLE_ARRAY,
compiler));
- Expect.equals(EXTENDABLE_ARRAY,
+ Expect.equals(EXTENDABLE_ARRAY,
EXTENDABLE_ARRAY.intersection(MUTABLE_ARRAY, compiler));
Expect.equals(EXTENDABLE_ARRAY,
- EXTENDABLE_ARRAY.intersection(EXTENDABLE_ARRAY,
+ EXTENDABLE_ARRAY.intersection(EXTENDABLE_ARRAY,
compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(nonPrimitive2, compiler));
Expect.equals(EXTENDABLE_ARRAY,
- EXTENDABLE_ARRAY.intersection(potentialArray,
+ EXTENDABLE_ARRAY.intersection(potentialArray,
compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
EXTENDABLE_ARRAY.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(CONFLICTING, compiler));
- Expect.equals(nonPrimitive1,
+ Expect.equals(nonPrimitive1,
nonPrimitive1.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(nonPrimitive1,
+ Expect.equals(nonPrimitive1,
nonPrimitive1.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(nonPrimitive2, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive1.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(CONFLICTING, compiler));
- Expect.equals(nonPrimitive2,
+ Expect.equals(nonPrimitive2,
nonPrimitive2.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(nonPrimitive1, compiler));
- Expect.equals(nonPrimitive2,
+ Expect.equals(nonPrimitive2,
nonPrimitive2.intersection(nonPrimitive2, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
nonPrimitive2.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialArray.intersection(CONFLICTING, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
potentialArray.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialArray.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialArray.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialArray.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialArray.intersection(DOUBLE, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
potentialArray.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialArray.intersection(STRING, compiler));
- Expect.equals(READABLE_ARRAY,
+ Expect.equals(READABLE_ARRAY,
potentialArray.intersection(READABLE_ARRAY, compiler));
- Expect.equals(MUTABLE_ARRAY,
+ Expect.equals(MUTABLE_ARRAY,
potentialArray.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(EXTENDABLE_ARRAY,
+ Expect.equals(EXTENDABLE_ARRAY,
potentialArray.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialArray.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialArray.intersection(nonPrimitive2, compiler));
- Expect.equals(potentialArray,
+ Expect.equals(potentialArray,
potentialArray.intersection(potentialArray, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialArray.intersection(potentialString, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialArray.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialArray.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialArray.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialArray.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialArray.intersection(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialArray.intersection(NULL, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
potentialArray.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(CONFLICTING, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
potentialString.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(DOUBLE, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
potentialString.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
potentialString.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(nonPrimitive2, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialString.intersection(potentialArray, compiler));
- Expect.equals(potentialString,
+ Expect.equals(potentialString,
potentialString.intersection(potentialString, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialString.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialString.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialString.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialString.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
potentialString.intersection(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
potentialString.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
potentialString.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(CONFLICTING, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
BOOLEAN_OR_NULL.intersection(UNKNOWN, compiler));
- Expect.equals(BOOLEAN,
+ Expect.equals(BOOLEAN,
BOOLEAN_OR_NULL.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(nonPrimitive2, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
BOOLEAN_OR_NULL.intersection(potentialArray, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
BOOLEAN_OR_NULL.intersection(potentialString, compiler));
- Expect.equals(BOOLEAN_OR_NULL,
+ Expect.equals(BOOLEAN_OR_NULL,
BOOLEAN_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
BOOLEAN_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
BOOLEAN_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
BOOLEAN_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
BOOLEAN_OR_NULL.intersection(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
BOOLEAN_OR_NULL.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
BOOLEAN_OR_NULL.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(CONFLICTING, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(BOOLEAN, compiler));
- Expect.equals(NUMBER,
+ Expect.equals(NUMBER,
NUMBER_OR_NULL.intersection(NUMBER, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
NUMBER_OR_NULL.intersection(INTEGER, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
NUMBER_OR_NULL.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(nonPrimitive2, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NUMBER_OR_NULL.intersection(potentialArray, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NUMBER_OR_NULL.intersection(potentialString, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NUMBER_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NUMBER_OR_NULL,
+ Expect.equals(NUMBER_OR_NULL,
NUMBER_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
NUMBER_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
NUMBER_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NUMBER_OR_NULL.intersection(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NUMBER_OR_NULL.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NUMBER_OR_NULL.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(CONFLICTING, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
INTEGER_OR_NULL.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(BOOLEAN, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
INTEGER_OR_NULL.intersection(NUMBER, compiler));
- Expect.equals(INTEGER,
+ Expect.equals(INTEGER,
INTEGER_OR_NULL.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(nonPrimitive2, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
INTEGER_OR_NULL.intersection(potentialArray, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
INTEGER_OR_NULL.intersection(potentialString, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
INTEGER_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
INTEGER_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(INTEGER_OR_NULL,
+ Expect.equals(INTEGER_OR_NULL,
INTEGER_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
INTEGER_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
INTEGER_OR_NULL.intersection(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
INTEGER_OR_NULL.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
INTEGER_OR_NULL.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(CONFLICTING, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
DOUBLE_OR_NULL.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(BOOLEAN, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
DOUBLE_OR_NULL.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(INTEGER, compiler));
- Expect.equals(DOUBLE,
+ Expect.equals(DOUBLE,
DOUBLE_OR_NULL.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(nonPrimitive2, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
DOUBLE_OR_NULL.intersection(potentialArray, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
DOUBLE_OR_NULL.intersection(potentialString, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
DOUBLE_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
DOUBLE_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
DOUBLE_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(DOUBLE_OR_NULL,
+ Expect.equals(DOUBLE_OR_NULL,
DOUBLE_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
DOUBLE_OR_NULL.intersection(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
DOUBLE_OR_NULL.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
DOUBLE_OR_NULL.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(CONFLICTING, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
STRING_OR_NULL.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(DOUBLE, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
STRING_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(STRING,
+ Expect.equals(STRING,
STRING_OR_NULL.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(nonPrimitive2, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
STRING_OR_NULL.intersection(potentialArray, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
STRING_OR_NULL.intersection(potentialString, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
STRING_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
STRING_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
STRING_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
STRING_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(STRING_OR_NULL,
+ Expect.equals(STRING_OR_NULL,
STRING_OR_NULL.intersection(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
STRING_OR_NULL.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
STRING_OR_NULL.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(CONFLICTING, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(DOUBLE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(STRING, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(READABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(nonPrimitive2, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.intersection(potentialArray, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.intersection(potentialString, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.intersection(STRING_OR_NULL, compiler));
- Expect.equals(NULL,
+ Expect.equals(NULL,
NULL.intersection(NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
NULL.intersection(FIXED_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(CONFLICTING, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
FIXED_ARRAY.intersection(UNKNOWN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(BOOLEAN, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(NUMBER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(INTEGER, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(DOUBLE, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
FIXED_ARRAY.intersection(INDEXABLE_PRIMITIVE, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(STRING, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
FIXED_ARRAY.intersection(READABLE_ARRAY, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
FIXED_ARRAY.intersection(MUTABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(EXTENDABLE_ARRAY, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(nonPrimitive1, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(nonPrimitive2, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
FIXED_ARRAY.intersection(potentialArray, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(potentialString, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(BOOLEAN_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(NUMBER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(INTEGER_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(DOUBLE_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(STRING_OR_NULL, compiler));
- Expect.equals(CONFLICTING,
+ Expect.equals(CONFLICTING,
FIXED_ARRAY.intersection(NULL, compiler));
- Expect.equals(FIXED_ARRAY,
+ Expect.equals(FIXED_ARRAY,
FIXED_ARRAY.intersection(FIXED_ARRAY, compiler));
}
void testRegressions(MockCompiler compiler) {
- HType nonNullPotentialString = new HBoundedPotentialPrimitiveString(
- compiler.stringClass.computeType(compiler), canBeNull: false);
+ HType nonNullPotentialString = new HType.nonNullSubtype(
+ patternClass.computeType(compiler), compiler);
Expect.equals(
potentialString, STRING_OR_NULL.union(nonNullPotentialString, compiler));
}
void main() {
MockCompiler compiler = new MockCompiler();
- nonPrimitive1 = new HBoundedType(
- compiler.mapClass.computeType(compiler), canBeNull: false);
- nonPrimitive2 = new HBoundedType(
- compiler.functionClass.computeType(compiler), canBeNull: false);
- potentialArray = new HBoundedPotentialPrimitiveArray(
- compiler.listClass.computeType(compiler));
- potentialString = new HBoundedPotentialPrimitiveString(
- compiler.stringClass.computeType(compiler));
+ compiler.interceptorsLibrary.forEachLocalMember((element) {
+ if (element.isClass()) {
+ compiler.enqueuer.resolution.registerInstantiatedClass(element);
+ }
+ });
+ compiler.world.populate();
+
+ // Grab hold of a supertype for String so we can produce potential
+ // string types.
+ patternClass = compiler.coreLibrary.find(buildSourceString('Pattern'));
+
+ nonPrimitive1 = new HType.nonNullSubtype(
+ compiler.mapClass.computeType(compiler), compiler);
+ nonPrimitive2 = new HType.nonNullSubtype(
+ compiler.functionClass.computeType(compiler), compiler);
+ potentialArray = new HType.subtype(
+ compiler.listClass.computeType(compiler), compiler);
+ potentialString = new HType.subtype(
+ patternClass.computeType(compiler), compiler);
+ jsArrayOrNull = new HType.exact(
+ compiler.backend.jsArrayClass.computeType(compiler), compiler);
+
testUnion(compiler);
testIntersection(compiler);
testRegressions(compiler);
diff --git a/tests/compiler/dart2js/value_range_test.dart b/tests/compiler/dart2js/value_range_test.dart
index fdf0b6b..e1bfe73 100644
--- a/tests/compiler/dart2js/value_range_test.dart
+++ b/tests/compiler/dart2js/value_range_test.dart
@@ -40,7 +40,7 @@
main(check) {
// Make sure value is an int.
var value = check ? 42 : 54;
- var a = new List.fixedLength(value);
+ var a = new List(value);
var sum = 0;
for (int i = 0; i < value; i++) {
sum += a[i];
@@ -68,7 +68,7 @@
"""
main() {
- var a = new List.fixedLength(4);
+ var a = new List(4);
return a[0];
}
""",
@@ -76,7 +76,7 @@
"""
main() {
- var a = new List.fixedLength(4);
+ var a = new List(4);
return a.removeLast();
}
""",
@@ -84,7 +84,7 @@
"""
main(value) {
- var a = new List.fixedLength(value);
+ var a = new List(value);
return a[value];
}
""",
@@ -92,7 +92,7 @@
"""
main(value) {
- var a = new List.fixedLength(1024);
+ var a = new List(1024);
return a[1023 & value];
}
""",
@@ -100,7 +100,7 @@
"""
main(value) {
- var a = new List.fixedLength(1024);
+ var a = new List(1024);
return a[1024 & value];
}
""",
@@ -212,8 +212,8 @@
class Type {}
class Function {}
class List {
- List();
- List.fixedLength(length);
+ List([int length]);
+ List.filled(int length, fill);
}
abstract class Map {}
class Closure {}
diff --git a/tests/compiler/dart2js_extra/bailout_test.dart b/tests/compiler/dart2js_extra/bailout_test.dart
index 308658a..dd31071f 100644
--- a/tests/compiler/dart2js_extra/bailout_test.dart
+++ b/tests/compiler/dart2js_extra/bailout_test.dart
@@ -45,7 +45,7 @@
String forInBailout() {
var n = myString.length;
var res = '';
- for (int i in myString.charCodes) {
+ for (int i in myString.codeUnits) {
var o = myString;
if (false) o[1] = 2;
res = res.concat(new String.fromCharCodes([i]));
diff --git a/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart b/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart
index bf9a9dd..97b18ee 100644
--- a/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart
+++ b/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart
@@ -7,6 +7,8 @@
library deferred_class_library;
class MyClass {
+ const MyClass();
+
foo(x) {
print('MyClass.foo($x)');
return (x - 3) ~/ 2;
diff --git a/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart b/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart
new file mode 100644
index 0000000..0cbe262
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+@lazy import 'deferred_class_library.dart';
+
+const lazy = const DeferredLibrary('deferred_class_library');
+
+main() {
+ var x;
+ // TODO(ahe): What are the semantics of this:
+ // x = const MyClass();
+ Expect.isNull(x);
+ int counter = 0;
+ lazy.load().then((bool didLoad) {
+ Expect.isTrue(didLoad);
+ Expect.equals(1, ++counter);
+ print('deferred_class_library was loaded');
+ x = const MyClass();
+ Expect.equals(42, x.foo(87));
+ });
+ Expect.equals(0, counter);
+ Expect.isNull(x);
+ lazy.load().then((bool didLoad) {
+ Expect.isFalse(didLoad);
+ Expect.equals(2, ++counter);
+ print('deferred_class_library was loaded');
+ x = const MyClass();
+ Expect.equals(42, x.foo(87));
+ });
+ Expect.equals(0, counter);
+ Expect.isNull(x);
+ // TODO(ahe): What are the semantics of this:
+ // x = const MyClass();
+ Expect.isNull(x);
+}
diff --git a/tests/compiler/dart2js_extra/generics_factories_test.dart b/tests/compiler/dart2js_extra/generics_factories_test.dart
new file mode 100644
index 0000000..2de7501
--- /dev/null
+++ b/tests/compiler/dart2js_extra/generics_factories_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that factories are marked as needing rti.
+
+class A<T> {
+ foo(o) => o is T;
+ factory A.c() => new B<T>();
+ A();
+}
+
+class B<T> extends A<T> {}
+
+class C {}
+
+class D {}
+
+main() {
+ Expect.isTrue(new A<C>.c().foo(new C()));
+ Expect.isFalse(new A<C>.c().foo(new D()));
+}
diff --git a/tests/compiler/dart2js_extra/invalid_length_negative_test.dart b/tests/compiler/dart2js_extra/invalid_length_negative_test.dart
index e990bd0..9836653 100644
--- a/tests/compiler/dart2js_extra/invalid_length_negative_test.dart
+++ b/tests/compiler/dart2js_extra/invalid_length_negative_test.dart
@@ -3,5 +3,5 @@
// BSD-style license that can be found in the LICENSE file.
main() {
- new List.fixedLength("foo");
+ new List("foo");
}
diff --git a/tests/compiler/dart2js_extra/list_factory_test.dart b/tests/compiler/dart2js_extra/list_factory_test.dart
index 1d7b940..e774573 100644
--- a/tests/compiler/dart2js_extra/list_factory_test.dart
+++ b/tests/compiler/dart2js_extra/list_factory_test.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
main() {
- var a = new List.fixedLength(4);
+ var a = new List(4);
Expect.equals(4, a.length);
a[0] = 42;
a[1] = 43;
diff --git a/tests/compiler/dart2js_extra/string_escape_test.dart b/tests/compiler/dart2js_extra/string_escape_test.dart
index 27e3218..6094469 100644
--- a/tests/compiler/dart2js_extra/string_escape_test.dart
+++ b/tests/compiler/dart2js_extra/string_escape_test.dart
@@ -15,7 +15,7 @@
for (String s in examples) {
Expect.equals(6, s.length);
for (int i = 0; i < 6; i++) {
- Expect.equals(values[i], s.charCodeAt(i));
+ Expect.equals(values[i], s.codeUnitAt(i));
}
}
@@ -48,7 +48,7 @@
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
Expect.equals(256, allBytes.length);
for (int i = 0; i < 256; i++) {
- Expect.equals(i, allBytes.charCodeAt(i));
+ Expect.equals(i, allBytes.codeUnitAt(i));
}
}
@@ -67,7 +67,7 @@
for (String s in examples) {
Expect.equals(values.length, s.length);
for (int i = 0; i < values.length; i++) {
- Expect.equals(values[i], s.charCodeAt(i));
+ Expect.equals(values[i], s.codeUnitAt(i));
}
}
// No characters above 0xffff until Leg supports that.
@@ -78,7 +78,7 @@
var longValues = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0xffff, 0xffff, 0xffff];
Expect.equals(longValues.length, long.length);
for (int i = 0; i < longValues.length; i++) {
- Expect.equals(longValues[i], long.charCodeAt(i));
+ Expect.equals(longValues[i], long.codeUnitAt(i));
}
}
@@ -93,7 +93,7 @@
Expect.equals(128 - 32, asciiLiterals.length);
for (int i = 32; i < 128; i++) {
- int code = asciiLiterals.charCodeAt(i - 32);
+ int code = asciiLiterals.codeUnitAt(i - 32);
if (code != 0) {
Expect.equals(i, code);
}
@@ -116,7 +116,7 @@
testRawStrings() {
String raw1 = r'\x00';
Expect.equals(4, raw1.length);
- Expect.equals(0x5c, raw1.charCodeAt(0));
+ Expect.equals(0x5c, raw1.codeUnitAt(0));
}
main() {
diff --git a/tests/corelib/collection_contains_test.dart b/tests/corelib/collection_contains_test.dart
index da96f5d..168855b 100644
--- a/tests/corelib/collection_contains_test.dart
+++ b/tests/corelib/collection_contains_test.dart
@@ -12,7 +12,7 @@
}
Expect.isFalse(list.contains(notInList), "!$list.contains($notInList)");
}
- List fixedList = new List.fixedLength(list.length);
+ List fixedList = new List(list.length);
List growList = new List();
for (int i = 0; i < list.length; i++) {
fixedList[i] = list[i];
diff --git a/tests/corelib/collection_length_test.dart b/tests/corelib/collection_length_test.dart
new file mode 100644
index 0000000..e98cb1b
--- /dev/null
+++ b/tests/corelib/collection_length_test.dart
@@ -0,0 +1,75 @@
+// 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 map_test;
+import 'dart:collection';
+
+// Test that length/isEmpty opertions are constant time on
+// maps, strings and collections.
+
+void testString(int n) {
+ String s = "x";
+ String string = "";
+ int length = n;
+ while (true) {
+ if ((length & 1) == 1) {
+ string = string.concat(s);
+ }
+ length >>= 1;
+ if (length == 0) break;
+ s = s.concat(s);
+ }
+ testLength(string, n);
+ testLength(string.codeUnits, n);
+}
+
+void testMap(Map map, int n) {
+ for (int i = 0; i < n; i++) {
+ map[i] = i;
+ }
+ testLength(map, n);
+ testLength(map.keys, n);
+ testLength(map.values, n);
+}
+
+void testCollection(Collection collection, n) {
+ for (int i = 0; i < n; i++) {
+ collection.add(i);
+ }
+ testLength(collection, n);
+}
+
+void testList(List list, n) {
+ for (int i = 0; i < n; i++) {
+ list[i] = i;
+ }
+ testLength(list, n);
+}
+
+
+void testLength(var lengthable, int size) {
+ print(lengthable.runtimeType); // Show what hangs the test.
+ int length = 0;
+ // If length or isEmpty is not a constant-time (or very fast) operation,
+ // this will timeout.
+ for (int i = 0; i < 100000; i++) {
+ if (!lengthable.isEmpty) length += lengthable.length;
+ }
+ if (length != size * 100000) throw "Bad length: $length / size: $size";
+}
+
+
+main() {
+ const int N = 100000;
+ testMap(new HashMap(), N);
+ testMap(new LinkedHashMap(), N);
+ testMap(new SplayTreeMap(), N);
+ testCollection(new HashSet(), N);
+ testCollection(new LinkedHashSet(), N);
+ testCollection(new ListQueue(), N);
+ testList(new List()..length = N, N);
+ testList(new List(N), N);
+ testString(N);
+ // DoubleLinkedQueue has linear length, but fast isEmpty.
+}
diff --git a/tests/corelib/collection_removes_test.dart b/tests/corelib/collection_removes_test.dart
index 738ce72..d057ed8 100644
--- a/tests/corelib/collection_removes_test.dart
+++ b/tests/corelib/collection_removes_test.dart
@@ -95,7 +95,8 @@
testRetainAll(base.toList(), delta);
testRetainAll(base.toList(), deltaSet);
testRemoveMatching(base.toList(), deltaSet.contains);
- testRetainMatching(base.toList(), (e) => !deltaSet.contains(e));
+ testRetainMatching(base.toList(),
+ (e) => !deltaSet.contains(e));
testRemoveAll(base.toSet(), delta);
testRemoveAll(base.toSet(), deltaSet);
diff --git a/tests/corelib/collection_test.dart b/tests/corelib/collection_test.dart
index 202b4bb..64dfe2b 100644
--- a/tests/corelib/collection_test.dart
+++ b/tests/corelib/collection_test.dart
@@ -25,7 +25,7 @@
new CollectionTest(TEST_ELEMENTS);
// Fixed size list.
- var fixedList = new List.fixedLength(TEST_ELEMENTS.length);
+ var fixedList = new List(TEST_ELEMENTS.length);
for (int i = 0; i < TEST_ELEMENTS.length; i++) {
fixedList[i] = TEST_ELEMENTS[i];
}
diff --git a/tests/corelib/collection_to_string_test.dart b/tests/corelib/collection_to_string_test.dart
index 694aa0f..3f07236 100644
--- a/tests/corelib/collection_to_string_test.dart
+++ b/tests/corelib/collection_to_string_test.dart
@@ -299,7 +299,8 @@
/** Returns the alphabetized characters in a string. */
String alphagram(String s) {
- List<int> chars = s.charCodes;
+ // Calling [toList] to convert unmodifiable list to normal list.
+ List<int> chars = s.codeUnits.toList();
chars.sort((int a, int b) => a - b);
return new String.fromCharCodes(chars);
}
diff --git a/tests/corelib/core_runtime_types_test.dart b/tests/corelib/core_runtime_types_test.dart
index 728adb4..4c06009 100644
--- a/tests/corelib/core_runtime_types_test.dart
+++ b/tests/corelib/core_runtime_types_test.dart
@@ -153,7 +153,7 @@
static testStringOperators() {
var s = "abcdef";
assertEquals(s, "abcdef");
- assertEquals(s.charCodeAt(0), 97);
+ assertEquals(s.codeUnitAt(0), 97);
assertEquals(s[0], 'a');
assertEquals(s.length, 6);
assertTypeError(() { s[null]; });
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 8672c1c..089101b 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -35,22 +35,21 @@
math_test: Fail # issue 3333
surrogate_pair_toUpper_test: Fail # Issue 6707
-reg_exp4_test: Fail, OK # Expects exception from const constructor.
-
big_integer_vm_test: Fail, OK # VM specific test.
compare_to2_test: Fail, OK # Requires bigint support.
string_base_vm_test: Fail, OK # VM specific test.
string_replace_func_test: Skip # Bug 6554 - doesn't terminate.
+[ $compiler == dart2js && $checked ]
+string_codeunits_test: Fail # Issue 8904
+
[ $compiler == dart2js && $runtime == none ]
*: Fail, Pass # TODO(ahe): Triage these tests.
-[ $compiler == dart2js && $runtime == safari ]
-core_runtime_types_test: Fail
-
[ $compiler == dart2js && $runtime == ie9 ]
date_time7_test: Fail # BUG(3304): Maybe this doesn't time out?
+json_strict_test: Fail # IE parses slightly harmless no-standard JSON.
string_base_vm_test: Fail # BUG(3304): Maybe this doesn't time out?
[ $compiler == dart2dart ]
diff --git a/tests/corelib/duration_test.dart b/tests/corelib/duration_test.dart
index 87f2da8..51d65c3 100644
--- a/tests/corelib/duration_test.dart
+++ b/tests/corelib/duration_test.dart
@@ -5,36 +5,51 @@
main() {
Duration d;
d = new Duration(days: 1);
+ Expect.equals(86400000000, d.inMicroseconds);
Expect.equals(86400000, d.inMilliseconds);
Expect.equals(86400, d.inSeconds);
Expect.equals(1440, d.inMinutes);
Expect.equals(24, d.inHours);
Expect.equals(1, d.inDays);
d = const Duration(hours: 1);
+ Expect.equals(3600000000, d.inMicroseconds);
Expect.equals(3600000, d.inMilliseconds);
Expect.equals(3600, d.inSeconds);
Expect.equals(60, d.inMinutes);
Expect.equals(1, d.inHours);
Expect.equals(0, d.inDays);
d = new Duration(minutes: 1);
+ Expect.equals(60000000, d.inMicroseconds);
Expect.equals(60000, d.inMilliseconds);
Expect.equals(60, d.inSeconds);
Expect.equals(1, d.inMinutes);
Expect.equals(0, d.inHours);
Expect.equals(0, d.inDays);
d = const Duration(seconds: 1);
+ Expect.equals(1000000, d.inMicroseconds);
Expect.equals(1000, d.inMilliseconds);
Expect.equals(1, d.inSeconds);
Expect.equals(0, d.inMinutes);
Expect.equals(0, d.inHours);
Expect.equals(0, d.inDays);
d = new Duration(milliseconds: 1);
+ Expect.equals(1000, d.inMicroseconds);
Expect.equals(1, d.inMilliseconds);
Expect.equals(0, d.inSeconds);
Expect.equals(0, d.inMinutes);
Expect.equals(0, d.inHours);
Expect.equals(0, d.inDays);
+ d = new Duration(microseconds: 1);
+ Expect.equals(1, d.inMicroseconds);
+ Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inSeconds);
+ Expect.equals(0, d.inMinutes);
+ Expect.equals(0, d.inHours);
+ Expect.equals(0, d.inDays);
+ d = const Duration(milliseconds: 1, microseconds: 999);
+ Expect.equals(1999, d.inMicroseconds);
+ Expect.equals(1, d.inMilliseconds);
d = const Duration(seconds: 1, milliseconds: 999);
Expect.equals(1999, d.inMilliseconds);
Expect.equals(1, d.inSeconds);
@@ -48,48 +63,63 @@
Expect.equals(47, d.inHours);
Expect.equals(1, d.inDays);
d = const Duration(
- days: 0, hours: 23, minutes: 59, seconds: 59, milliseconds: 999);
+ days: 0, hours: 23, minutes: 59, seconds: 59, milliseconds: 999,
+ microseconds: 999);
Expect.equals(0, d.inDays);
d = new Duration(days: -1);
+ Expect.equals(-86400000000, d.inMicroseconds);
Expect.equals(-86400000, d.inMilliseconds);
Expect.equals(-86400, d.inSeconds);
Expect.equals(-1440, d.inMinutes);
Expect.equals(-24, d.inHours);
Expect.equals(-1, d.inDays);
d = const Duration(hours: -1);
+ Expect.equals(-3600000000, d.inMicroseconds);
Expect.equals(-3600000, d.inMilliseconds);
Expect.equals(-3600, d.inSeconds);
Expect.equals(-60, d.inMinutes);
Expect.equals(-1, d.inHours);
Expect.equals(0, d.inDays);
d = new Duration(minutes: -1);
+ Expect.equals(-60000000, d.inMicroseconds);
Expect.equals(-60000, d.inMilliseconds);
Expect.equals(-60, d.inSeconds);
Expect.equals(-1, d.inMinutes);
Expect.equals(0, d.inHours);
Expect.equals(0, d.inDays);
d = const Duration(seconds: -1);
+ Expect.equals(-1000000, d.inMicroseconds);
Expect.equals(-1000, d.inMilliseconds);
Expect.equals(-1, d.inSeconds);
Expect.equals(0, d.inMinutes);
Expect.equals(0, d.inHours);
Expect.equals(0, d.inDays);
d = new Duration(milliseconds: -1);
+ Expect.equals(-1000, d.inMicroseconds);
Expect.equals(-1, d.inMilliseconds);
Expect.equals(0, d.inSeconds);
Expect.equals(0, d.inMinutes);
Expect.equals(0, d.inHours);
Expect.equals(0, d.inDays);
+ d = new Duration(microseconds: -1);
+ Expect.equals(-1, d.inMicroseconds);
+ Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inSeconds);
+ Expect.equals(0, d.inMinutes);
+ Expect.equals(0, d.inHours);
+ Expect.equals(0, d.inDays);
d = const Duration(days: 1, hours: -24);
- Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inMicroseconds);
d = new Duration(hours: 1, minutes: -60);
- Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inMicroseconds);
d = const Duration(minutes: 1, seconds: -60);
- Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inMicroseconds);
d = new Duration(seconds: 1, milliseconds: -1000);
- Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inMicroseconds);
+ d = new Duration(milliseconds: 1, microseconds: -1000);
+ Expect.equals(0, d.inMicroseconds);
d = const Duration(hours: 25);
Expect.equals(1, d.inDays);
@@ -97,71 +127,100 @@
Expect.equals(1500, d.inMinutes);
Expect.equals(90000, d.inSeconds);
Expect.equals(90000000, d.inMilliseconds);
+ Expect.equals(90000000000, d.inMicroseconds);
d = new Duration(minutes: 61);
Expect.equals(0, d.inDays);
Expect.equals(1, d.inHours);
Expect.equals(61, d.inMinutes);
Expect.equals(3660, d.inSeconds);
Expect.equals(3660000, d.inMilliseconds);
+ Expect.equals(3660000000, d.inMicroseconds);
d = const Duration(seconds: 61);
Expect.equals(0, d.inDays);
Expect.equals(0, d.inHours);
Expect.equals(1, d.inMinutes);
Expect.equals(61, d.inSeconds);
Expect.equals(61000, d.inMilliseconds);
+ Expect.equals(61000000, d.inMicroseconds);
d = new Duration(milliseconds: 1001);
Expect.equals(0, d.inDays);
Expect.equals(0, d.inHours);
Expect.equals(0, d.inMinutes);
Expect.equals(1, d.inSeconds);
Expect.equals(1001, d.inMilliseconds);
+ Expect.equals(1001000, d.inMicroseconds);
+ d = new Duration(microseconds: 1001);
+ Expect.equals(0, d.inDays);
+ Expect.equals(0, d.inHours);
+ Expect.equals(0, d.inMinutes);
+ Expect.equals(0, d.inSeconds);
+ Expect.equals(1, d.inMilliseconds);
+ Expect.equals(1001, d.inMicroseconds);
var d1 = const Duration(milliseconds: 1000);
var d2 = const Duration(seconds: 1);
Expect.identical(d1, d2);
+ d1 = const Duration(microseconds: 1000);
+ d2 = const Duration(milliseconds: 1);
+ Expect.identical(d1, d2);
+
d1 = new Duration(hours: 1);
d2 = new Duration(hours: -1);
d = d1 + d2;
- Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inMicroseconds);
d = d1 - d2;
- Expect.equals(3600000 * 2, d.inMilliseconds);
+ Expect.equals(3600000000 * 2, d.inMicroseconds);
d2 = new Duration(hours: 1);
d = d1 + d2;
- Expect.equals(3600000 * 2, d.inMilliseconds);
+ Expect.equals(3600000000 * 2, d.inMicroseconds);
d = d1 - d2;
- Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inMicroseconds);
d = d1 * 2;
- Expect.equals(3600000 * 2, d.inMilliseconds);
+ Expect.equals(3600000000 * 2, d.inMicroseconds);
d = d1 * -1;
- Expect.equals(-3600000, d.inMilliseconds);
+ Expect.equals(-3600000000, d.inMicroseconds);
d = d1 * 0;
- Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inMicroseconds);
d = d1 ~/ 2;
- Expect.equals(1800000, d.inMilliseconds);
- d = d1 ~/ 3600001;
- Expect.equals(0, d.inMilliseconds);
- d = d1 ~/ -3600001;
- Expect.equals(0, d.inMilliseconds);
- d = d1 ~/ 3599999;
- Expect.equals(1, d.inMilliseconds);
- d = d1 ~/ -3599999;
- Expect.equals(-1, d.inMilliseconds);
+ Expect.equals(1800000000, d.inMicroseconds);
+ d = d1 ~/ 3600000001;
+ Expect.equals(0, d.inMicroseconds);
+ d = d1 ~/ -3600000001;
+ Expect.equals(0, d.inMicroseconds);
+ d = d1 ~/ 3599999999;
+ Expect.equals(1, d.inMicroseconds);
+ d = d1 ~/ -3599999999;
+ Expect.equals(-1, d.inMicroseconds);
d = d1 ~/ -1;
- Expect.equals(-3600000, d.inMilliseconds);
+ Expect.equals(-3600000000, d.inMicroseconds);
d = d1 * 0;
- Expect.equals(0, d.inMilliseconds);
+ Expect.equals(0, d.inMicroseconds);
Expect.throws(() => d1 ~/ 0,
(e) => e is IntegerDivisionByZeroException);
- d = new Duration(milliseconds: 0);
- Expect.isTrue(d < new Duration(milliseconds: 1));
- Expect.isTrue(d <= new Duration(milliseconds: 1));
+ d = new Duration(microseconds: 0);
+ Expect.isTrue(d < new Duration(microseconds: 1));
+ Expect.isTrue(d <= new Duration(microseconds: 1));
Expect.isTrue(d <= d);
- Expect.isTrue(d > new Duration(milliseconds: -1));
- Expect.isTrue(d >= new Duration(milliseconds: -1));
+ Expect.isTrue(d > new Duration(microseconds: -1));
+ Expect.isTrue(d >= new Duration(microseconds: -1));
Expect.isTrue(d >= d);
+
+ d = const Duration(days: 1, hours: 3, minutes: 17, seconds: 42,
+ milliseconds: 823, microseconds: 127);
+ Expect.equals("27:17:42.823127", d.toString());
+
+ d = const Duration(hours: 1999, minutes: 17, seconds: 42);
+ Expect.equals("1999:17:42.000000", d.toString());
+
+ d = const Duration(days: -1, hours: -3, minutes: -17, seconds: -42,
+ milliseconds: -823, microseconds: -127);
+ Expect.equals("-27:17:42.823127", d.toString());
+
+ d = const Duration(hours: -1999, minutes: -17, seconds: -42);
+ Expect.equals("-1999:17:42.000000", d.toString());
}
diff --git a/tests/corelib/for_in_test.dart b/tests/corelib/for_in_test.dart
index de51cc1..ea53727 100644
--- a/tests/corelib/for_in_test.dart
+++ b/tests/corelib/for_in_test.dart
@@ -79,7 +79,7 @@
static void testClosure() {
Set<int> set = getSmallSet();
- List<Function> closures = new List.fixedLength(set.length);
+ List<Function> closures = new List(set.length);
int index = 0;
for (var i in set) {
closures[index++] = () => i;
diff --git a/tests/corelib/indexed_list_access_test.dart b/tests/corelib/indexed_list_access_test.dart
index 791e961..2feab1e 100644
--- a/tests/corelib/indexed_list_access_test.dart
+++ b/tests/corelib/indexed_list_access_test.dart
@@ -6,7 +6,7 @@
// is not int.
main() {
- checkList(new List.fixedLength(10));
+ checkList(new List(10));
var growable = new List();
growable.add(1);
growable.add(1);
diff --git a/tests/corelib/is_operator_basic_types_test.dart b/tests/corelib/is_operator_basic_types_test.dart
index e0771bb..662b2a4 100644
--- a/tests/corelib/is_operator_basic_types_test.dart
+++ b/tests/corelib/is_operator_basic_types_test.dart
@@ -61,5 +61,5 @@
// Try to make it even harder.
var string = new String.fromCharCodes([new DateTime.now().year % 100 + 1]);
- check([string.charCodes, string, null]);
+ check([string.codeUnits, string, null]);
}
diff --git a/tests/corelib/iterable_join_test.dart b/tests/corelib/iterable_join_test.dart
index b09227f..96922a9 100644
--- a/tests/corelib/iterable_join_test.dart
+++ b/tests/corelib/iterable_join_test.dart
@@ -49,7 +49,7 @@
testJoin("0,1,2,3,4", array.takeWhile((i) => i < 5), ",");
}
testArray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
- var fixedArray = new List.fixedLength(10);
+ var fixedArray = new List(10);
for (int i = 0; i < 10; i++) {
fixedArray[i] = i;
}
diff --git a/tests/corelib/iterable_test.dart b/tests/corelib/iterable_test.dart
new file mode 100644
index 0000000..6b8fe13
--- /dev/null
+++ b/tests/corelib/iterable_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js where [List.addAll] was not typed
+// correctly.
+
+class MyIterable implements Iterable {
+ get iterator => [].iterator;
+}
+
+main() {
+ Expect.isTrue(([]..addAll(new MyIterable())).isEmpty);
+}
diff --git a/tests/corelib/json_test.dart b/tests/corelib/json_test.dart
index 75d22a3..5a36d99 100644
--- a/tests/corelib/json_test.dart
+++ b/tests/corelib/json_test.dart
@@ -36,8 +36,23 @@
compare(expected, value, "value");
}
+String escape(String s) {
+ var sb = new StringBuffer();
+ for (int i = 0; i < s.length; i++) {
+ int code = s.codeUnitAt(i);
+ if (code == '\\'.codeUnitAt(0)) sb.write(r'\\');
+ else if (code == '\"'.codeUnitAt(0)) sb.write(r'\"');
+ else if (code >= 32 && code < 127) sb.writeCharCode(code);
+ else {
+ String hex = '000${code.toRadixString(16)}';
+ sb.write(r'\u' '${hex.substring(hex.length - 4)}');
+ }
+ }
+ return '$sb';
+}
+
void testThrows(json) {
- Expect.throws(() => parse(json), badFormat);
+ Expect.throws(() => parse(json), badFormat, "json = '${escape(json)}'");
}
testNumbers() {
@@ -97,8 +112,11 @@
// Integer part cannot be omitted:
testError(integers: "");
- // Initial zero only allowed for zero integer part.
- testError(integers: ["00", "01"]);
+
+ // Test for "Initial zero only allowed for zero integer part" moved to
+ // json_strict_test.dart because IE's JSON.parse accepts additional initial
+ // zeros.
+
// Only minus allowed as sign.
testError(signs: "+");
// Requires digits after decimal point.
@@ -107,7 +125,7 @@
testError(exponents: ["e", "e+", "e-", "e.0"]);
// No whitespace inside numbers.
- testThrows("- 2.2e+2");
+ // Additional case "- 2.2e+2" in json_strict_test.dart.
testThrows("-2 .2e+2");
testThrows("-2. 2e+2");
testThrows("-2.2 e+2");
@@ -223,21 +241,20 @@
testJson('$v[${v}-2.2e2$v,$v{$v"key"$v:${v}true$v}$v,$v"ab"$v]$v',
[-2.2e2, {"key": true}, "ab"]);
+ // IE9 accepts invalid characters at the end, so some of these tests have been
+ // moved to json_strict_test.dart.
for (var i in invalids) {
testThrows('${i}"s"');
- testThrows('"s"${i}');
testThrows('42${i}');
testThrows('$i[]');
testThrows('[$i]');
testThrows('[$i"s"]');
testThrows('["s"$i]');
- testThrows('[]$i');
testThrows('$i{"k":"v"}');
testThrows('{$i"k":"v"}');
testThrows('{"k"$i:"v"}');
testThrows('{"k":$i"v"}');
testThrows('{"k":"v"$i}');
- testThrows('{"k":"v"}$i');
}
}
diff --git a/tests/corelib/linked_hash_map_test.dart b/tests/corelib/linked_hash_map_test.dart
index 4de0b3e..54eddeb 100644
--- a/tests/corelib/linked_hash_map_test.dart
+++ b/tests/corelib/linked_hash_map_test.dart
@@ -15,8 +15,8 @@
map["d"] = 4;
map["e"] = 5;
- List<String> keys = new List<String>.fixedLength(5);
- List<int> values = new List<int>.fixedLength(5);
+ List<String> keys = new List<String>(5);
+ List<int> values = new List<int>(5);
int index;
diff --git a/tests/corelib/list_as_map_test.dart b/tests/corelib/list_as_map_test.dart
new file mode 100644
index 0000000..03f5540
--- /dev/null
+++ b/tests/corelib/list_as_map_test.dart
@@ -0,0 +1,96 @@
+// 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.
+
+void testListMapCorrespondence(List list, Map map) {
+ Expect.equals(list.length, map.length);
+ for (int i = 0; i < list.length; i++) {
+ Expect.equals(list[i], map[i]);
+ }
+ Expect.isNull(map[list.length]);
+ Expect.isNull(map[-1]);
+
+ Iterable keys = map.keys;
+ Iterable values = map.values;
+ Expect.isFalse(keys is List);
+ Expect.isFalse(values is List);
+ Expect.equals(list.length, keys.length);
+ Expect.equals(list.length, values.length);
+ for (int i = 0; i < list.length; i++) {
+ Expect.equals(i, keys.elementAt(i));
+ Expect.equals(list[i], values.elementAt(i));
+ }
+
+ int forEachCount = 0;
+ map.forEach((key, value) {
+ Expect.equals(forEachCount, key);
+ Expect.equals(list[key], value);
+ forEachCount++;
+ });
+
+ for (int i = 0; i < list.length; i++) {
+ Expect.isTrue(map.containsKey(i));
+ Expect.isTrue(map.containsValue(list[i]));
+ }
+ Expect.isFalse(map.containsKey(-1));
+ Expect.isFalse(map.containsKey(list.length));
+
+ Expect.equals(list.length, forEachCount);
+
+ Expect.equals(list.isEmpty, map.isEmpty);
+}
+
+void testConstAsMap(List list) {
+ Map<int, dynamic> map = list.asMap();
+
+ testListMapCorrespondence(list, map);
+
+ Expect.throws(() => map[0] = 499,
+ (e) => e is UnsupportedError);
+ Expect.throws(() => map.putIfAbsent(0, () => 499),
+ (e) => e is UnsupportedError);
+ Expect.throws(() => map.clear(),
+ (e) => e is UnsupportedError);
+}
+
+void testFixedAsMap(List list) {
+ testConstAsMap(list);
+
+ Map<int, dynamic> map = list.asMap();
+
+ if (!list.isEmpty) {
+ list[0] = 499;
+ // Check again to make sure the map is backed by the list.
+ testListMapCorrespondence(list, map);
+ }
+}
+
+void testAsMap(List list) {
+ testFixedAsMap(list);
+
+ Map<int, dynamic> map = list.asMap();
+
+ Iterable keys = map.keys;
+ Iterable values = map.values;
+
+ list.add(42);
+ // Check again to make sure the map is backed by the list and that the
+ // length is not cached.
+ testListMapCorrespondence(list, map);
+ // Also check that the keys and values iterable from the map are backed by
+ // the list.
+ Expect.equals(list.length, keys.length);
+ Expect.equals(values.length, values.length);
+}
+
+main() {
+ testConstAsMap(const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+ testAsMap([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+ List list = new List(10);
+ for (int i = 0; i < 10; i++) list[i] = i + 1;
+ testFixedAsMap(list);
+
+ testConstAsMap(const []);
+ testAsMap([]);
+ testFixedAsMap(new List(0));
+}
diff --git a/tests/corelib/list_fixed_test.dart b/tests/corelib/list_fixed_test.dart
index b6d7440..c29d8ea 100644
--- a/tests/corelib/list_fixed_test.dart
+++ b/tests/corelib/list_fixed_test.dart
@@ -5,7 +5,7 @@
main() {
var a;
- a = new List.fixedLength(42);
+ a = new List(42);
Expect.equals(42, a.length);
Expect.throws(() => a.add(499), (e) => e is UnsupportedError);
Expect.equals(42, a.length);
@@ -15,7 +15,7 @@
Expect.throws(() => a.clear(), (e) => e is UnsupportedError);
Expect.equals(42, a.length);
- a = new List.fixedLength(42, fill: -2);
+ a = new List.filled(42, -2);
Expect.equals(42, a.length);
Expect.throws(() => a.add(499), (e) => e is UnsupportedError);
Expect.equals(42, a.length);
diff --git a/tests/corelib/list_growable_test.dart b/tests/corelib/list_growable_test.dart
index 616b450..563f187 100644
--- a/tests/corelib/list_growable_test.dart
+++ b/tests/corelib/list_growable_test.dart
@@ -12,7 +12,7 @@
Expect.equals(0, a.length);
Expect.throws(() => a[0], (e) => e is RangeError);
- a = new List(42);
+ a = new List(42).toList();
Expect.equals(42, a.length);
a.add(499);
Expect.equals(43, a.length);
@@ -22,7 +22,7 @@
Expect.equals(0, a.length);
Expect.throws(() => a[0], (e) => e is RangeError);
- a = new List<int>(42);
+ a = new List<int>(42).toList();
Expect.equals(42, a.length);
a.add(499);
Expect.equals(43, a.length);
diff --git a/tests/corelib/list_index_of_test.dart b/tests/corelib/list_index_of_test.dart
index c217f41..ca8ab4c 100644
--- a/tests/corelib/list_index_of_test.dart
+++ b/tests/corelib/list_index_of_test.dart
@@ -4,7 +4,7 @@
class ListIndexOfTest {
static testMain() {
- test(new List<int>.fixedLength(5));
+ test(new List<int>(5));
var l = new List<int>();
l.length = 5;
test(l);
diff --git a/tests/corelib/list_iterators_test.dart b/tests/corelib/list_iterators_test.dart
index c20e5eb..e7ed128 100644
--- a/tests/corelib/list_iterators_test.dart
+++ b/tests/corelib/list_iterators_test.dart
@@ -18,8 +18,8 @@
static testMain() {
checkListIterator([]);
checkListIterator([1, 2]);
- checkListIterator(new List.fixedLength(0));
- checkListIterator(new List.fixedLength(10));
+ checkListIterator(new List(0));
+ checkListIterator(new List(10));
checkListIterator(new List());
List g = new List();
g.addAll([1, 2, 3]);
diff --git a/tests/corelib/list_removeat_test.dart b/tests/corelib/list_removeat_test.dart
index df7ac16..d6a9b28 100644
--- a/tests/corelib/list_removeat_test.dart
+++ b/tests/corelib/list_removeat_test.dart
@@ -42,7 +42,7 @@
Expect.equals(3, l1.length, "length-2");
// Fixed size list.
- var l2 = new List.fixedLength(5);
+ var l2 = new List(5);
for (var i = 0; i < 5; i++) l2[i] = i;
Expect.throws(() { l2.removeAt(2); },
(e) => e is UnsupportedError,
diff --git a/tests/corelib/list_set_range_test.dart b/tests/corelib/list_set_range_test.dart
index ff91fe7..f96ede5 100644
--- a/tests/corelib/list_set_range_test.dart
+++ b/tests/corelib/list_set_range_test.dart
@@ -82,7 +82,7 @@
}
void testNonExtendableList() {
- var list = new List<int>.fixedLength(6);
+ var list = new List<int>(6);
Expect.listEquals([null, null, null, null, null, null], list);
list.setRange(0, 3, [1, 2, 3, 4]);
list.setRange(3, 3, [1, 2, 3, 4]);
diff --git a/tests/corelib/list_test.dart b/tests/corelib/list_test.dart
index 5aa5ae9..9a88a9f 100644
--- a/tests/corelib/list_test.dart
+++ b/tests/corelib/list_test.dart
@@ -49,7 +49,7 @@
}
static void testList() {
- List list = new List.fixedLength(4);
+ List list = new List(4);
Expect.equals(list.length, 4);
list[0] = 4;
expectValues(list, 4, null, null, null);
diff --git a/tests/corelib/map_test.dart b/tests/corelib/map_test.dart
index 40cfab5..d405471 100644
--- a/tests/corelib/map_test.dart
+++ b/tests/corelib/map_test.dart
@@ -5,246 +5,262 @@
library map_test;
import 'dart:collection';
-class MapTest {
-
- static testMain() {
- test(new HashMap());
- test(new LinkedHashMap());
- test(new SplayTreeMap());
- testLinkedHashMap();
- testMapLiteral();
- testNullValue();
- }
-
- static void test(Map map) {
- testDeletedElement(map);
- testMap(map, 1, 2, 3, 4, 5, 6, 7, 8);
- map.clear();
- testMap(map, "value1", "value2", "value3", "value4", "value5",
- "value6", "value7", "value8");
- }
-
- static void testLinkedHashMap() {
- LinkedHashMap map = new LinkedHashMap();
- Expect.equals(false, map.containsKey(1));
- map[1] = 1;
- map[1] = 2;
- Expect.equals(1, map.length);
- }
-
- static void testMap(Map map, key1, key2, key3, key4, key5, key6, key7, key8) {
- int value1 = 10;
- int value2 = 20;
- int value3 = 30;
- int value4 = 40;
- int value5 = 50;
- int value6 = 60;
- int value7 = 70;
- int value8 = 80;
-
- Expect.equals(0, map.length);
-
- map[key1] = value1;
- Expect.equals(value1, map[key1]);
- map[key1] = value2;
- Expect.equals(false, map.containsKey(key2));
- Expect.equals(1, map.length);
-
- map[key1] = value1;
- Expect.equals(value1, map[key1]);
- // Add enough entries to make sure the table grows.
- map[key2] = value2;
- Expect.equals(value2, map[key2]);
- Expect.equals(2, map.length);
- map[key3] = value3;
- Expect.equals(value2, map[key2]);
- Expect.equals(value3, map[key3]);
- map[key4] = value4;
- Expect.equals(value3, map[key3]);
- Expect.equals(value4, map[key4]);
- map[key5] = value5;
- Expect.equals(value4, map[key4]);
- Expect.equals(value5, map[key5]);
- map[key6] = value6;
- Expect.equals(value5, map[key5]);
- Expect.equals(value6, map[key6]);
- map[key7] = value7;
- Expect.equals(value6, map[key6]);
- Expect.equals(value7, map[key7]);
- map[key8] = value8;
- Expect.equals(value1, map[key1]);
- Expect.equals(value2, map[key2]);
- Expect.equals(value3, map[key3]);
- Expect.equals(value4, map[key4]);
- Expect.equals(value5, map[key5]);
- Expect.equals(value6, map[key6]);
- Expect.equals(value7, map[key7]);
- Expect.equals(value8, map[key8]);
- Expect.equals(8, map.length);
-
- map.remove(key4);
- Expect.equals(false, map.containsKey(key4));
- Expect.equals(7, map.length);
-
- // Test clearing the table.
- map.clear();
- Expect.equals(0, map.length);
- Expect.equals(false, map.containsKey(key1));
- Expect.equals(false, map.containsKey(key2));
- Expect.equals(false, map.containsKey(key3));
- Expect.equals(false, map.containsKey(key4));
- Expect.equals(false, map.containsKey(key5));
- Expect.equals(false, map.containsKey(key6));
- Expect.equals(false, map.containsKey(key7));
- Expect.equals(false, map.containsKey(key8));
-
- // Test adding and removing again.
- map[key1] = value1;
- Expect.equals(value1, map[key1]);
- Expect.equals(1, map.length);
- map[key2] = value2;
- Expect.equals(value2, map[key2]);
- Expect.equals(2, map.length);
- map[key3] = value3;
- Expect.equals(value3, map[key3]);
- map.remove(key3);
- Expect.equals(2, map.length);
- map[key4] = value4;
- Expect.equals(value4, map[key4]);
- map.remove(key4);
- Expect.equals(2, map.length);
- map[key5] = value5;
- Expect.equals(value5, map[key5]);
- map.remove(key5);
- Expect.equals(2, map.length);
- map[key6] = value6;
- Expect.equals(value6, map[key6]);
- map.remove(key6);
- Expect.equals(2, map.length);
- map[key7] = value7;
- Expect.equals(value7, map[key7]);
- map.remove(key7);
- Expect.equals(2, map.length);
- map[key8] = value8;
- Expect.equals(value8, map[key8]);
- map.remove(key8);
- Expect.equals(2, map.length);
-
- Expect.equals(true, map.containsKey(key1));
- Expect.equals(true, map.containsValue(value1));
-
- // Test Map.forEach.
- Map other_map = new Map();
- void testForEachMap(key, value) {
- other_map[key] = value;
- }
- map.forEach(testForEachMap);
- Expect.equals(true, other_map.containsKey(key1));
- Expect.equals(true, other_map.containsKey(key2));
- Expect.equals(true, other_map.containsValue(value1));
- Expect.equals(true, other_map.containsValue(value2));
- Expect.equals(2, other_map.length);
-
- other_map.clear();
- Expect.equals(0, other_map.length);
-
- // Test Collection.keys.
- void testForEachCollection(value) {
- other_map[value] = value;
- }
- Iterable keys = map.keys;
- keys.forEach(testForEachCollection);
- Expect.equals(true, other_map.containsKey(key1));
- Expect.equals(true, other_map.containsKey(key2));
- Expect.equals(true, other_map.containsValue(key1));
- Expect.equals(true, other_map.containsValue(key2));
- Expect.equals(true, !other_map.containsKey(value1));
- Expect.equals(true, !other_map.containsKey(value2));
- Expect.equals(true, !other_map.containsValue(value1));
- Expect.equals(true, !other_map.containsValue(value2));
- Expect.equals(2, other_map.length);
- other_map.clear();
- Expect.equals(0, other_map.length);
-
- // Test Collection.values.
- Iterable values = map.values;
- values.forEach(testForEachCollection);
- Expect.equals(true, !other_map.containsKey(key1));
- Expect.equals(true, !other_map.containsKey(key2));
- Expect.equals(true, !other_map.containsValue(key1));
- Expect.equals(true, !other_map.containsValue(key2));
- Expect.equals(true, other_map.containsKey(value1));
- Expect.equals(true, other_map.containsKey(value2));
- Expect.equals(true, other_map.containsValue(value1));
- Expect.equals(true, other_map.containsValue(value2));
- Expect.equals(2, other_map.length);
- other_map.clear();
- Expect.equals(0, other_map.length);
-
- // Test Map.putIfAbsent.
- map.clear();
- Expect.equals(false, map.containsKey(key1));
- map.putIfAbsent(key1, () => 10);
- Expect.equals(true, map.containsKey(key1));
- Expect.equals(10, map[key1]);
- Expect.equals(10,
- map.putIfAbsent(key1, () => 11));
- }
-
- static void testDeletedElement(Map map) {
- map.clear();
- for (int i = 0; i < 100; i++) {
- map[1] = 2;
- Expect.equals(1, map.length);
- map.remove(1);
- Expect.equals(0, map.length);
- }
- Expect.equals(0, map.length);
- }
-
- static void testMapLiteral() {
- Map m = {"a": 1, "b" : 2, "c": 3 };
- Expect.equals(3, m.length);
- int sum = 0;
- m.forEach((a, b) {
- sum += b;
- });
- Expect.equals(6, sum);
-
- List values = m.keys.toList();
- Expect.equals(3, values.length);
- String first = values[0];
- String second = values[1];
- String third = values[2];
- String all = "${first}${second}${third}";
- Expect.equals(3, all.length);
- Expect.equals(true, all.contains("a", 0));
- Expect.equals(true, all.contains("b", 0));
- Expect.equals(true, all.contains("c", 0));
- }
-
- static void testNullValue() {
- Map m = {"a": 1, "b" : null, "c": 3 };
-
- Expect.equals(null, m["b"]);
- Expect.equals(true, m.containsKey("b"));
- Expect.equals(3, m.length);
-
- m["a"] = null;
- m["c"] = null;
- Expect.equals(null, m["a"]);
- Expect.equals(true, m.containsKey("a"));
- Expect.equals(null, m["c"]);
- Expect.equals(true, m.containsKey("c"));
- Expect.equals(3, m.length);
-
- m.remove("a");
- Expect.equals(2, m.length);
- Expect.equals(null, m["a"]);
- Expect.equals(false, m.containsKey("a"));
- }
+void main() {
+ test(new HashMap());
+ test(new LinkedHashMap());
+ test(new SplayTreeMap());
+ test(new SplayTreeMap(Comparable.compare));
+ testLinkedHashMap();
+ testMapLiteral();
+ testNullValue();
+ testTypes();
}
-main() {
- MapTest.testMain();
+void test(Map map) {
+ testDeletedElement(map);
+ testMap(map, 1, 2, 3, 4, 5, 6, 7, 8);
+ map.clear();
+ testMap(map, "value1", "value2", "value3", "value4", "value5",
+ "value6", "value7", "value8");
+}
+
+void testLinkedHashMap() {
+ LinkedHashMap map = new LinkedHashMap();
+ Expect.equals(false, map.containsKey(1));
+ map[1] = 1;
+ map[1] = 2;
+ Expect.equals(1, map.length);
+}
+
+void testMap(Map map, key1, key2, key3, key4, key5, key6, key7, key8) {
+ int value1 = 10;
+ int value2 = 20;
+ int value3 = 30;
+ int value4 = 40;
+ int value5 = 50;
+ int value6 = 60;
+ int value7 = 70;
+ int value8 = 80;
+
+ Expect.equals(0, map.length);
+
+ map[key1] = value1;
+ Expect.equals(value1, map[key1]);
+ map[key1] = value2;
+ Expect.equals(false, map.containsKey(key2));
+ Expect.equals(1, map.length);
+
+ map[key1] = value1;
+ Expect.equals(value1, map[key1]);
+ // Add enough entries to make sure the table grows.
+ map[key2] = value2;
+ Expect.equals(value2, map[key2]);
+ Expect.equals(2, map.length);
+ map[key3] = value3;
+ Expect.equals(value2, map[key2]);
+ Expect.equals(value3, map[key3]);
+ map[key4] = value4;
+ Expect.equals(value3, map[key3]);
+ Expect.equals(value4, map[key4]);
+ map[key5] = value5;
+ Expect.equals(value4, map[key4]);
+ Expect.equals(value5, map[key5]);
+ map[key6] = value6;
+ Expect.equals(value5, map[key5]);
+ Expect.equals(value6, map[key6]);
+ map[key7] = value7;
+ Expect.equals(value6, map[key6]);
+ Expect.equals(value7, map[key7]);
+ map[key8] = value8;
+ Expect.equals(value1, map[key1]);
+ Expect.equals(value2, map[key2]);
+ Expect.equals(value3, map[key3]);
+ Expect.equals(value4, map[key4]);
+ Expect.equals(value5, map[key5]);
+ Expect.equals(value6, map[key6]);
+ Expect.equals(value7, map[key7]);
+ Expect.equals(value8, map[key8]);
+ Expect.equals(8, map.length);
+
+ map.remove(key4);
+ Expect.equals(false, map.containsKey(key4));
+ Expect.equals(7, map.length);
+
+ // Test clearing the table.
+ map.clear();
+ Expect.equals(0, map.length);
+ Expect.equals(false, map.containsKey(key1));
+ Expect.equals(false, map.containsKey(key2));
+ Expect.equals(false, map.containsKey(key3));
+ Expect.equals(false, map.containsKey(key4));
+ Expect.equals(false, map.containsKey(key5));
+ Expect.equals(false, map.containsKey(key6));
+ Expect.equals(false, map.containsKey(key7));
+ Expect.equals(false, map.containsKey(key8));
+
+ // Test adding and removing again.
+ map[key1] = value1;
+ Expect.equals(value1, map[key1]);
+ Expect.equals(1, map.length);
+ map[key2] = value2;
+ Expect.equals(value2, map[key2]);
+ Expect.equals(2, map.length);
+ map[key3] = value3;
+ Expect.equals(value3, map[key3]);
+ map.remove(key3);
+ Expect.equals(2, map.length);
+ map[key4] = value4;
+ Expect.equals(value4, map[key4]);
+ map.remove(key4);
+ Expect.equals(2, map.length);
+ map[key5] = value5;
+ Expect.equals(value5, map[key5]);
+ map.remove(key5);
+ Expect.equals(2, map.length);
+ map[key6] = value6;
+ Expect.equals(value6, map[key6]);
+ map.remove(key6);
+ Expect.equals(2, map.length);
+ map[key7] = value7;
+ Expect.equals(value7, map[key7]);
+ map.remove(key7);
+ Expect.equals(2, map.length);
+ map[key8] = value8;
+ Expect.equals(value8, map[key8]);
+ map.remove(key8);
+ Expect.equals(2, map.length);
+
+ Expect.equals(true, map.containsKey(key1));
+ Expect.equals(true, map.containsValue(value1));
+
+ // Test Map.forEach.
+ Map other_map = new Map();
+ void testForEachMap(key, value) {
+ other_map[key] = value;
+ }
+ map.forEach(testForEachMap);
+ Expect.equals(true, other_map.containsKey(key1));
+ Expect.equals(true, other_map.containsKey(key2));
+ Expect.equals(true, other_map.containsValue(value1));
+ Expect.equals(true, other_map.containsValue(value2));
+ Expect.equals(2, other_map.length);
+
+ other_map.clear();
+ Expect.equals(0, other_map.length);
+
+ // Test Collection.keys.
+ void testForEachCollection(value) {
+ other_map[value] = value;
+ }
+ Iterable keys = map.keys;
+ keys.forEach(testForEachCollection);
+ Expect.equals(true, other_map.containsKey(key1));
+ Expect.equals(true, other_map.containsKey(key2));
+ Expect.equals(true, other_map.containsValue(key1));
+ Expect.equals(true, other_map.containsValue(key2));
+ Expect.equals(true, !other_map.containsKey(value1));
+ Expect.equals(true, !other_map.containsKey(value2));
+ Expect.equals(true, !other_map.containsValue(value1));
+ Expect.equals(true, !other_map.containsValue(value2));
+ Expect.equals(2, other_map.length);
+ other_map.clear();
+ Expect.equals(0, other_map.length);
+
+ // Test Collection.values.
+ Iterable values = map.values;
+ values.forEach(testForEachCollection);
+ Expect.equals(true, !other_map.containsKey(key1));
+ Expect.equals(true, !other_map.containsKey(key2));
+ Expect.equals(true, !other_map.containsValue(key1));
+ Expect.equals(true, !other_map.containsValue(key2));
+ Expect.equals(true, other_map.containsKey(value1));
+ Expect.equals(true, other_map.containsKey(value2));
+ Expect.equals(true, other_map.containsValue(value1));
+ Expect.equals(true, other_map.containsValue(value2));
+ Expect.equals(2, other_map.length);
+ other_map.clear();
+ Expect.equals(0, other_map.length);
+
+ // Test Map.putIfAbsent.
+ map.clear();
+ Expect.equals(false, map.containsKey(key1));
+ map.putIfAbsent(key1, () => 10);
+ Expect.equals(true, map.containsKey(key1));
+ Expect.equals(10, map[key1]);
+ Expect.equals(10,
+ map.putIfAbsent(key1, () => 11));
+}
+
+void testDeletedElement(Map map) {
+ map.clear();
+ for (int i = 0; i < 100; i++) {
+ map[1] = 2;
+ Expect.equals(1, map.length);
+ map.remove(1);
+ Expect.equals(0, map.length);
+ }
+ Expect.equals(0, map.length);
+}
+
+void testMapLiteral() {
+ Map m = {"a": 1, "b" : 2, "c": 3 };
+ Expect.equals(3, m.length);
+ int sum = 0;
+ m.forEach((a, b) {
+ sum += b;
+ });
+ Expect.equals(6, sum);
+
+ List values = m.keys.toList();
+ Expect.equals(3, values.length);
+ String first = values[0];
+ String second = values[1];
+ String third = values[2];
+ String all = "${first}${second}${third}";
+ Expect.equals(3, all.length);
+ Expect.equals(true, all.contains("a", 0));
+ Expect.equals(true, all.contains("b", 0));
+ Expect.equals(true, all.contains("c", 0));
+}
+
+void testNullValue() {
+ Map m = {"a": 1, "b" : null, "c": 3 };
+
+ Expect.equals(null, m["b"]);
+ Expect.equals(true, m.containsKey("b"));
+ Expect.equals(3, m.length);
+
+ m["a"] = null;
+ m["c"] = null;
+ Expect.equals(null, m["a"]);
+ Expect.equals(true, m.containsKey("a"));
+ Expect.equals(null, m["c"]);
+ Expect.equals(true, m.containsKey("c"));
+ Expect.equals(3, m.length);
+
+ m.remove("a");
+ Expect.equals(2, m.length);
+ Expect.equals(null, m["a"]);
+ Expect.equals(false, m.containsKey("a"));
+}
+
+void testTypes() {
+ Map<int> map;
+ testMap(Map map) {
+ map[42] = "text";
+ map[43] = "text";
+ map[42] = "text";
+ map.remove(42);
+ map[42] = "text";
+ }
+ testMap(new HashMap<int, String>());
+ testMap(new LinkedHashMap<int, String>());
+ testMap(new SplayTreeMap<int, String>());
+ testMap(new SplayTreeMap<int, String>(Comparable.compare));
+ testMap(new SplayTreeMap<int, String>((int a, int b) => a.compareTo(b)));
+ testMap(new HashMap<num, String>());
+ testMap(new LinkedHashMap<num, String>());
+ testMap(new SplayTreeMap<num, String>());
+ testMap(new SplayTreeMap<num, String>(Comparable.compare));
+ testMap(new SplayTreeMap<num, String>((num a, num b) => a.compareTo(b)));
}
diff --git a/tests/corelib/range_error_test.dart b/tests/corelib/range_error_test.dart
index 62be0b8..e83bd30 100644
--- a/tests/corelib/range_error_test.dart
+++ b/tests/corelib/range_error_test.dart
@@ -14,7 +14,7 @@
testListRead(list, -1);
testListRead(list, 1);
- list = new List.fixedLength(1);
+ list = new List(1);
testListRead(list, -1);
testListRead(list, 1);
@@ -33,7 +33,7 @@
testListWrite(list, -1);
testListWrite(list, 1);
- list = new List.fixedLength(1);
+ list = new List(1);
testListWrite(list, -1);
testListWrite(list, 1);
diff --git a/tests/corelib/set_test.dart b/tests/corelib/set_test.dart
index efe8cf1..3be91d5 100644
--- a/tests/corelib/set_test.dart
+++ b/tests/corelib/set_test.dart
@@ -2,170 +2,172 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-class SetTest {
+library set_test;
- static testMain() {
- Set set = new Set();
- Expect.equals(0, set.length);
- set.add(1);
- Expect.equals(1, set.length);
- Expect.equals(true, set.contains(1));
+import "dart:collection";
- set.add(1);
- Expect.equals(1, set.length);
- Expect.equals(true, set.contains(1));
+void testMain(Set create()) {
+ Set set = create();
+ Expect.equals(0, set.length);
+ set.add(1);
+ Expect.equals(1, set.length);
+ Expect.equals(true, set.contains(1));
- set.remove(1);
- Expect.equals(0, set.length);
- Expect.equals(false, set.contains(1));
+ set.add(1);
+ Expect.equals(1, set.length);
+ Expect.equals(true, set.contains(1));
- for (int i = 0; i < 10; i++) {
- set.add(i);
- }
+ set.remove(1);
+ Expect.equals(0, set.length);
+ Expect.equals(false, set.contains(1));
- Expect.equals(10, set.length);
- for (int i = 0; i < 10; i++) {
- Expect.equals(true, set.contains(i));
- }
-
- Expect.equals(10, set.length);
-
- for (int i = 10; i < 20; i++) {
- Expect.equals(false, set.contains(i));
- }
-
- // Test Set.forEach.
- int sum = 0;
- testForEach(int val) {
- sum += (val + 1);
- }
-
- set.forEach(testForEach);
- Expect.equals(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1, sum);
-
- Expect.equals(true, set.isSubsetOf(set));
- Expect.equals(true, set.containsAll(set));
-
- // Test Set.map.
- testMap(int val) {
- return val * val;
- }
-
- Set mapped = set.map(testMap).toSet();
- Expect.equals(10, mapped.length);
-
- Expect.equals(true, mapped.contains(0));
- Expect.equals(true, mapped.contains(1));
- Expect.equals(true, mapped.contains(4));
- Expect.equals(true, mapped.contains(9));
- Expect.equals(true, mapped.contains(16));
- Expect.equals(true, mapped.contains(25));
- Expect.equals(true, mapped.contains(36));
- Expect.equals(true, mapped.contains(49));
- Expect.equals(true, mapped.contains(64));
- Expect.equals(true, mapped.contains(81));
-
- sum = 0;
- set.forEach(testForEach);
- Expect.equals(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1, sum);
-
- sum = 0;
-
- mapped.forEach(testForEach);
- Expect.equals(1 + 2 + 5 + 10 + 17 + 26 + 37 + 50 + 65 + 82, sum);
-
- // Test Set.filter.
- testFilter(int val) {
- return val.isEven;
- }
-
- Set filtered = set.where(testFilter).toSet();
-
- Expect.equals(5, filtered.length);
-
- Expect.equals(true, filtered.contains(0));
- Expect.equals(true, filtered.contains(2));
- Expect.equals(true, filtered.contains(4));
- Expect.equals(true, filtered.contains(6));
- Expect.equals(true, filtered.contains(8));
-
- sum = 0;
- filtered.forEach(testForEach);
- Expect.equals(1 + 3 + 5 + 7 + 9, sum);
-
- Expect.equals(true, set.containsAll(filtered));
- Expect.equals(true, filtered.isSubsetOf(set));
-
- // Test Set.every.
- testEvery(int val) {
- return (val < 10);
- }
-
- Expect.equals(true, set.every(testEvery));
- Expect.equals(true, filtered.every(testEvery));
-
- filtered.add(10);
- Expect.equals(false, filtered.every(testEvery));
-
- // Test Set.some.
- testSome(int val) {
- return (val == 4);
- }
-
- Expect.equals(true, set.any(testSome));
- Expect.equals(true, filtered.any(testSome));
- filtered.remove(4);
- Expect.equals(false, filtered.any(testSome));
-
- // Test Set.intersection.
- Set intersection = set.intersection(filtered);
- Expect.equals(true, set.contains(0));
- Expect.equals(true, set.contains(2));
- Expect.equals(true, set.contains(6));
- Expect.equals(true, set.contains(8));
- Expect.equals(false, intersection.contains(1));
- Expect.equals(false, intersection.contains(3));
- Expect.equals(false, intersection.contains(4));
- Expect.equals(false, intersection.contains(5));
- Expect.equals(false, intersection.contains(7));
- Expect.equals(false, intersection.contains(9));
- Expect.equals(false, intersection.contains(10));
- Expect.equals(4, intersection.length);
-
- Expect.equals(true, set.containsAll(intersection));
- Expect.equals(true, filtered.containsAll(intersection));
- Expect.equals(true, intersection.isSubsetOf(set));
- Expect.equals(true, intersection.isSubsetOf(filtered));
-
- // Test Set.addAll.
- List list = new List.fixedLength(10);
- for (int i = 0; i < 10; i++) {
- list[i] = i + 10;
- }
- set.addAll(list);
- Expect.equals(20, set.length);
- for (int i = 0; i < 20; i++) {
- Expect.equals(true, set.contains(i));
- }
-
- // Test Set.removeAll
- set.removeAll(list);
- Expect.equals(10, set.length);
- for (int i = 0; i < 10; i++) {
- Expect.equals(true, set.contains(i));
- }
- for (int i = 10; i < 20; i++) {
- Expect.equals(false, set.contains(i));
- }
-
- // Test Set.clear.
- set.clear();
- Expect.equals(0, set.length);
- set.add(11);
- Expect.equals(1, set.length);
+ for (int i = 0; i < 10; i++) {
+ set.add(i);
}
+
+ Expect.equals(10, set.length);
+ for (int i = 0; i < 10; i++) {
+ Expect.equals(true, set.contains(i));
+ }
+
+ Expect.equals(10, set.length);
+
+ for (int i = 10; i < 20; i++) {
+ Expect.equals(false, set.contains(i));
+ }
+
+ // Test Set.forEach.
+ int sum = 0;
+ testForEach(int val) {
+ sum += (val + 1);
+ }
+
+ set.forEach(testForEach);
+ Expect.equals(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1, sum);
+
+ Expect.equals(true, set.isSubsetOf(set));
+ Expect.equals(true, set.containsAll(set));
+
+ // Test Set.map.
+ testMap(int val) {
+ return val * val;
+ }
+
+ Set mapped = set.map(testMap).toSet();
+ Expect.equals(10, mapped.length);
+
+ Expect.equals(true, mapped.contains(0));
+ Expect.equals(true, mapped.contains(1));
+ Expect.equals(true, mapped.contains(4));
+ Expect.equals(true, mapped.contains(9));
+ Expect.equals(true, mapped.contains(16));
+ Expect.equals(true, mapped.contains(25));
+ Expect.equals(true, mapped.contains(36));
+ Expect.equals(true, mapped.contains(49));
+ Expect.equals(true, mapped.contains(64));
+ Expect.equals(true, mapped.contains(81));
+
+ sum = 0;
+ set.forEach(testForEach);
+ Expect.equals(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1, sum);
+
+ sum = 0;
+
+ mapped.forEach(testForEach);
+ Expect.equals(1 + 2 + 5 + 10 + 17 + 26 + 37 + 50 + 65 + 82, sum);
+
+ // Test Set.filter.
+ testFilter(int val) {
+ return val.isEven;
+ }
+
+ Set filtered = set.where(testFilter).toSet();
+
+ Expect.equals(5, filtered.length);
+
+ Expect.equals(true, filtered.contains(0));
+ Expect.equals(true, filtered.contains(2));
+ Expect.equals(true, filtered.contains(4));
+ Expect.equals(true, filtered.contains(6));
+ Expect.equals(true, filtered.contains(8));
+
+ sum = 0;
+ filtered.forEach(testForEach);
+ Expect.equals(1 + 3 + 5 + 7 + 9, sum);
+
+ Expect.equals(true, set.containsAll(filtered));
+ Expect.equals(true, filtered.isSubsetOf(set));
+
+ // Test Set.every.
+ testEvery(int val) {
+ return (val < 10);
+ }
+
+ Expect.equals(true, set.every(testEvery));
+ Expect.equals(true, filtered.every(testEvery));
+
+ filtered.add(10);
+ Expect.equals(false, filtered.every(testEvery));
+
+ // Test Set.some.
+ testSome(int val) {
+ return (val == 4);
+ }
+
+ Expect.equals(true, set.any(testSome));
+ Expect.equals(true, filtered.any(testSome));
+ filtered.remove(4);
+ Expect.equals(false, filtered.any(testSome));
+
+ // Test Set.intersection.
+ Set intersection = set.intersection(filtered);
+ Expect.equals(true, set.contains(0));
+ Expect.equals(true, set.contains(2));
+ Expect.equals(true, set.contains(6));
+ Expect.equals(true, set.contains(8));
+ Expect.equals(false, intersection.contains(1));
+ Expect.equals(false, intersection.contains(3));
+ Expect.equals(false, intersection.contains(4));
+ Expect.equals(false, intersection.contains(5));
+ Expect.equals(false, intersection.contains(7));
+ Expect.equals(false, intersection.contains(9));
+ Expect.equals(false, intersection.contains(10));
+ Expect.equals(4, intersection.length);
+
+ Expect.equals(true, set.containsAll(intersection));
+ Expect.equals(true, filtered.containsAll(intersection));
+ Expect.equals(true, intersection.isSubsetOf(set));
+ Expect.equals(true, intersection.isSubsetOf(filtered));
+
+ // Test Set.addAll.
+ List list = new List.fixedLength(10);
+ for (int i = 0; i < 10; i++) {
+ list[i] = i + 10;
+ }
+ set.addAll(list);
+ Expect.equals(20, set.length);
+ for (int i = 0; i < 20; i++) {
+ Expect.equals(true, set.contains(i));
+ }
+
+ // Test Set.removeAll
+ set.removeAll(list);
+ Expect.equals(10, set.length);
+ for (int i = 0; i < 10; i++) {
+ Expect.equals(true, set.contains(i));
+ }
+ for (int i = 10; i < 20; i++) {
+ Expect.equals(false, set.contains(i));
+ }
+
+ // Test Set.clear.
+ set.clear();
+ Expect.equals(0, set.length);
+ set.add(11);
+ Expect.equals(1, set.length);
}
main() {
- SetTest.testMain();
+ testMain(() => new Set());
+ testMain(() => new HashSet());
}
diff --git a/tests/corelib/sort_helper.dart b/tests/corelib/sort_helper.dart
index 85d0bee..e378097 100644
--- a/tests/corelib/sort_helper.dart
+++ b/tests/corelib/sort_helper.dart
@@ -23,7 +23,7 @@
}
void testSortIntLists() {
- List a = new List.fixedLength(40);
+ List a = new List(40);
for (int i = 0; i < a.length; i++) {
a[i] = i;
@@ -79,10 +79,10 @@
a[33] = 1;
testSort(a);
- var a2 = new List.fixedLength(0);
+ var a2 = new List(0);
testSort(a2);
- var a3 = new List.fixedLength(1);
+ var a3 = new List(1);
a3[0] = 1;
testSort(a3);
@@ -120,7 +120,7 @@
}
void testInsertionSort(int i1, int i2, int i3, int i4) {
- var a = new List.fixedLength(4);
+ var a = new List(4);
a[0] = i1;
a[1] = i2;
a[2] = i3;
@@ -129,7 +129,7 @@
}
void testSortDoubleLists() {
- List a = new List.fixedLength(40);
+ List a = new List(40);
for (int i = 0; i < a.length; i++) {
a[i] = 1.0 * i + 0.5;
}
diff --git a/tests/corelib/stopwatch2_test.dart b/tests/corelib/stopwatch2_test.dart
new file mode 100644
index 0000000..25d1120
--- /dev/null
+++ b/tests/corelib/stopwatch2_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Dart test program for elapsed getters in stopwatch support.
+
+main() {
+ Stopwatch sw = new Stopwatch()..start();
+ while (sw.elapsedMilliseconds < 2) {
+ /* do nothing. */
+ }
+ sw.stop();
+ Expect.equals(sw.elapsedMicroseconds, sw.elapsed.inMicroseconds);
+ Expect.equals(sw.elapsedMilliseconds, sw.elapsed.inMilliseconds);
+}
diff --git a/tests/corelib/stopwatch_test.dart b/tests/corelib/stopwatch_test.dart
index 2b9c1a6..535b495 100644
--- a/tests/corelib/stopwatch_test.dart
+++ b/tests/corelib/stopwatch_test.dart
@@ -11,7 +11,7 @@
Expect.isFalse(sw.isRunning);
sw.start();
Expect.isTrue(sw.isRunning);
- for (int i = 0; i < 10000; i++) {
+ for (int i = 0; i < 1000000; i++) {
int.parse(i.toString());
if (sw.elapsedTicks > 0) {
break;
diff --git a/tests/corelib/string_base_vm_test.dart b/tests/corelib/string_base_vm_test.dart
index f043f33..1acf12e 100644
--- a/tests/corelib/string_base_vm_test.dart
+++ b/tests/corelib/string_base_vm_test.dart
@@ -26,12 +26,12 @@
static testCreation() {
String s = "Hello";
- List<int> a = new List.fixedLength(s.length);
+ List<int> a = new List(s.length);
List<int> ga = new List();
bool exception_caught = false;
for (int i = 0; i < a.length; i++) {
- a[i] = s.charCodeAt(i);
- ga.add(s.charCodeAt(i));
+ a[i] = s.codeUnitAt(i);
+ ga.add(s.codeUnitAt(i));
}
try {
String s4 = new String.fromCharCodes([0.0]);
diff --git a/tests/corelib/string_character_test.dart b/tests/corelib/string_character_test.dart
deleted file mode 100644
index 95d272c..0000000
--- a/tests/corelib/string_character_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-main() {
- Expect.equals("A", new String.character(65));
- Expect.equals("B", new String.character(66));
- var gClef = new String.character(0x1D11E);
- Expect.equals(2, gClef.length);
- Expect.equals(0xD834, gClef.charCodeAt(0));
- Expect.equals(0xDD1E, gClef.charCodeAt(1));
-
- // Unmatched surrogates.
- var unmatched = new String.character(0xD800);
- Expect.equals(1, unmatched.length);
- Expect.equals(0xD800, unmatched.charCodeAt(0));
- unmatched = new String.character(0xDC00);
- Expect.equals(1, unmatched.length);
- Expect.equals(0xDC00, unmatched.charCodeAt(0));
-
- Expect.throws(() => new String.character(-1),
- (e) => e is ArgumentError);
-
- // Invalid code point.
- Expect.throws(() => new String.character(0x110000),
- (e) => e is ArgumentError);
-
- Expect.throws(() => new String.character(0x110001),
- (e) => e is ArgumentError);
-}
diff --git a/tests/corelib/string_codeunits_test.dart b/tests/corelib/string_codeunits_test.dart
index 81625c5..ac6eb97 100644
--- a/tests/corelib/string_codeunits_test.dart
+++ b/tests/corelib/string_codeunits_test.dart
@@ -25,17 +25,48 @@
// .map
Expect.listEquals(expectedUnits.map((x) => x.toRadixString(16)).toList(),
units.map((x) => x.toRadixString(16)).toList());
+
+ if (s == "") {
+ Expect.throws(() => units.first, (e) => e is StateError);
+ Expect.throws(() => units.last, (e) => e is StateError);
+ Expect.throws(() => units[0], (e) => e is RangeError);
+ Expect.throws(() => units[0] = 499, (e) => e is UnsupportedError);
+ Expect.listEquals([], units.getRange(0, 0));
+ Expect.equals(-1, units.indexOf(42));
+ Expect.equals(-1, units.lastIndexOf(499));
+ } else {
+ Expect.equals(s.codeUnitAt(0), units.first);
+ Expect.equals(s.codeUnitAt(s.length - 1), units.last);
+ Expect.equals(s.codeUnitAt(0), units[0]);
+ Expect.throws(() { units[0] = 499; }, (e) => e is UnsupportedError);
+ List<int> sub = units.getRange(1, units.length - 1);
+ Expect.listEquals(s.substring(1, s.length).codeUnits, sub);
+ Expect.equals(-1, units.indexOf(-1));
+ Expect.equals(0, units.indexOf(units[0]));
+ Expect.equals(-1, units.lastIndexOf(-1));
+ Expect.equals(units.length - 1, units.lastIndexOf(units[units.length - 1]));
+ }
+
+ Iterable reversed = units.reversed;
+ int i = units.length - 1;
+ for (int codeUnit in reversed) {
+ Expect.equals(units[i--], codeUnit);
+ }
}
+ test("");
test("abc");
test("\x00\u0000\u{000000}");
test("\u{ffff}\u{10000}\u{10ffff}");
String string = new String.fromCharCodes(
- [0xdc00, 0xd800, 61, 0xd800, 0xdc00, 62, 0xdc00, 0xd800]);
+ [0xdc00, 0xd800, 61, 0xd9ab, 0xd9ab, 0xddef, 0xddef, 62, 0xdc00, 0xd800]);
+ test(string);
+ string = "\x00\x7f\xff\u0100\ufeff\uffef\uffff"
+ "\u{10000}\u{12345}\u{1d800}\u{1dc00}\u{1ffef}\u{1ffff}";
test(string);
- // Setting position in the middle of a surrogate pair is not allowed.
- var r = new CodeUnits("\u{10000}");
+ // Reading each unit of a surrogate pair works.
+ var r = "\u{10000}".codeUnits;
var it = r.iterator;
Expect.isTrue(it.moveNext());
Expect.equals(0xD800, it.current);
diff --git a/tests/corelib/string_from_list_test.dart b/tests/corelib/string_from_list_test.dart
index 99642a1..23c90f2 100644
--- a/tests/corelib/string_from_list_test.dart
+++ b/tests/corelib/string_from_list_test.dart
@@ -4,7 +4,7 @@
class StringFromListTest {
static testMain() {
- Expect.equals("", new String.fromCharCodes(new List.fixedLength(0)));
+ Expect.equals("", new String.fromCharCodes(new List(0)));
Expect.equals("", new String.fromCharCodes([]));
Expect.equals("", new String.fromCharCodes(const []));
Expect.equals("AB", new String.fromCharCodes([65, 66]));
diff --git a/tests/corelib/string_fromcharcode_test.dart b/tests/corelib/string_fromcharcode_test.dart
new file mode 100644
index 0000000..7f0fd20
--- /dev/null
+++ b/tests/corelib/string_fromcharcode_test.dart
@@ -0,0 +1,30 @@
+// 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.
+
+main() {
+ Expect.equals("A", new String.fromCharCode(65));
+ Expect.equals("B", new String.fromCharCode(66));
+ var gClef = new String.fromCharCode(0x1D11E);
+ Expect.equals(2, gClef.length);
+ Expect.equals(0xD834, gClef.codeUnitAt(0));
+ Expect.equals(0xDD1E, gClef.codeUnitAt(1));
+
+ // Unmatched surrogates.
+ var unmatched = new String.fromCharCode(0xD800);
+ Expect.equals(1, unmatched.length);
+ Expect.equals(0xD800, unmatched.codeUnitAt(0));
+ unmatched = new String.fromCharCode(0xDC00);
+ Expect.equals(1, unmatched.length);
+ Expect.equals(0xDC00, unmatched.codeUnitAt(0));
+
+ Expect.throws(() => new String.fromCharCode(-1),
+ (e) => e is ArgumentError);
+
+ // Invalid code point.
+ Expect.throws(() => new String.fromCharCode(0x110000),
+ (e) => e is ArgumentError);
+
+ Expect.throws(() => new String.fromCharCode(0x110001),
+ (e) => e is ArgumentError);
+}
diff --git a/tests/corelib/string_test.dart b/tests/corelib/string_test.dart
index 1518181..2dd329c 100644
--- a/tests/corelib/string_test.dart
+++ b/tests/corelib/string_test.dart
@@ -10,7 +10,7 @@
testIllegalArgument();
testConcat();
testIndex();
- testCharCodeAt();
+ testCodeUnitAt();
testEquals();
testEndsWith();
testStartsWith();
@@ -19,7 +19,6 @@
testContains();
testReplaceAll();
testCompareTo();
- testToList();
testCharCodes();
}
@@ -56,10 +55,10 @@
}
}
- static testCharCodeAt() {
+ static testCodeUnitAt() {
String str = "string";
for (int i = 0; i < str.length; i++) {
- Expect.equals(true, str.charCodeAt(i) is int);
+ Expect.equals(true, str.codeUnitAt(i) is int);
}
}
@@ -271,25 +270,12 @@
Expect.equals(-1, "".compareTo("string"));
}
- static testToList() {
- test(str) {
- var list = str.splitChars();
- Expect.equals(str.length, list.length);
- for (int i = 0; i < str.length; i++) {
- Expect.equals(str[i], list[i]);
- }
- }
- test("abc");
- test("");
- test(" ");
- }
-
static testCharCodes() {
test(str) {
- var list = str.charCodes;
+ var list = str.codeUnits;
Expect.equals(str.length, list.length);
for (int i = 0; i < str.length; i++) {
- Expect.equals(str.charCodeAt(i), list[i]);
+ Expect.equals(str.codeUnitAt(i), list[i]);
}
}
test("abc");
diff --git a/tests/corelib/strings_test.dart b/tests/corelib/strings_test.dart
index ef17663..16630f2 100644
--- a/tests/corelib/strings_test.dart
+++ b/tests/corelib/strings_test.dart
@@ -13,9 +13,9 @@
}
static testCreation() {
String s = "Hello";
- List<int> l = new List.fixedLength(s.length);
+ List<int> l = new List(s.length);
for (int i = 0; i < l.length; i++) {
- l[i] = s.charCodeAt(i);
+ l[i] = s.codeUnitAt(i);
}
String s2 = new String.fromCharCodes(l);
Expect.equals(s, s2);
diff --git a/tests/html/canvasrenderingcontext2d_test.dart b/tests/html/canvasrenderingcontext2d_test.dart
index 6b88843..495e5e4 100644
--- a/tests/html/canvasrenderingcontext2d_test.dart
+++ b/tests/html/canvasrenderingcontext2d_test.dart
@@ -9,10 +9,10 @@
// Some rounding errors in the browsers.
checkPixel(List<int> pixel, List<int> expected) {
- expect(pixel[0], closeTo(expected[0], 1));
- expect(pixel[1], closeTo(expected[1], 1));
- expect(pixel[2], closeTo(expected[2], 1));
- expect(pixel[3], closeTo(expected[3], 1));
+ expect(pixel[0], closeTo(expected[0], 2));
+ expect(pixel[1], closeTo(expected[1], 2));
+ expect(pixel[2], closeTo(expected[2], 2));
+ expect(pixel[3], closeTo(expected[3], 2));
}
main() {
@@ -37,13 +37,13 @@
test('setFillColorHsl hue', () {
context.setFillColorHsl(0, 100, 50);
context.fillRect(0, 0, canvas.width, canvas.height);
- expect(readPixel(), [255, 0, 0, 255]);
+ checkPixel(readPixel(), [255, 0, 0, 255]);
});
test('setFillColorHsl hue 2', () {
context.setFillColorHsl(240, 100, 50);
context.fillRect(0, 0, canvas.width, canvas.height);
- expect(readPixel(), [0, 0, 255, 255]);
+ checkPixel(readPixel(), [0, 0, 255, 255]);
});
test('setFillColorHsl sat', () {
@@ -83,7 +83,7 @@
test('fillStyle', () {
context.fillStyle = "red";
context.fillRect(0, 0, canvas.width, canvas.height);
- expect(readPixel(), [255, 0, 0, 255]);
+ checkPixel(readPixel(), [255, 0, 0, 255]);
});
test('strokeStyle', () {
diff --git a/tests/html/crypto_test.dart b/tests/html/crypto_test.dart
index 0e06723..57a2930 100644
--- a/tests/html/crypto_test.dart
+++ b/tests/html/crypto_test.dart
@@ -4,33 +4,45 @@
library crypto_test;
import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
import 'dart:html';
main() {
- useHtmlConfiguration();
+ useHtmlIndividualConfiguration();
- test('exists', () {
- var crypto = window.crypto;
- expect(crypto is Crypto, isTrue);
+ group('supported', () {
+ test('supported', () {
+ expect(Crypto.supported, true);
+ });
});
- test('successful call', () {
- var crypto = window.crypto;
- var data = new Uint8Array(100);
- expect(data.every((e) => e == 0), isTrue);
- crypto.getRandomValues(data);
- // In theory this is flaky. However, in practice you will get 100 zeroes
- // in a row from a cryptographically secure random number generator so
- // rarely that we don't have to worry about it.
- expect(data.any((e) => e != 0), isTrue);
- });
+ group('functional', () {
+ if (Crypto.supported) {
+ // This will actually pass on FF since it has a Crypto API, but it is
+ // incompatible.
+ test('exists', () {
+ var crypto = window.crypto;
+ expect(crypto is Crypto, isTrue);
+ });
- test('type mismatch', () {
- var crypto = window.crypto;
- var data = new Float32Array(100);
- expect(() {
- crypto.getRandomValues(data);
- }, throws, reason: 'Only typed array views with integer types allowed');
+ test('successful call', () {
+ var crypto = window.crypto;
+ var data = new Uint8Array(100);
+ expect(data.every((e) => e == 0), isTrue);
+ crypto.getRandomValues(data);
+ // In theory this is flaky. However, in practice you will get 100 zeroes
+ // in a row from a cryptographically secure random number generator so
+ // rarely that we don't have to worry about it.
+ expect(data.any((e) => e != 0), isTrue);
+ });
+
+ test('type mismatch', () {
+ var crypto = window.crypto;
+ var data = new Float32Array(100);
+ expect(() {
+ crypto.getRandomValues(data);
+ }, throws, reason: 'Only typed array views with integer types allowed');
+ });
+ }
});
}
diff --git a/tests/html/cssstyledeclaration_test.dart b/tests/html/cssstyledeclaration_test.dart
index 1f86605..13a9730 100644
--- a/tests/html/cssstyledeclaration_test.dart
+++ b/tests/html/cssstyledeclaration_test.dart
@@ -91,4 +91,10 @@
expect(style.textDecoration, equals('underline'));
}));
});
+
+ test('Invalid values', () {
+ var element = new DivElement();
+ // Should not throw an error.
+ element.style.background = 'some_bad_value';
+ });
}
diff --git a/tests/html/fileapi_test.dart b/tests/html/fileapi_test.dart
index a2d23d5..079197f 100644
--- a/tests/html/fileapi_test.dart
+++ b/tests/html/fileapi_test.dart
@@ -92,6 +92,12 @@
successCallback: expectAsync1((FileEntry e) {
expect(e.name, equals('file4'));
expect(e.isFile, isTrue);
+
+ e.getMetadata(expectAsync1((Metadata metadata) {
+ var changeTime = metadata.modificationTime;
+ expect(new DateTime.now().difference(changeTime).inSeconds,
+ lessThan(60));
+ }));
}),
errorCallback: (e) {
fail('Got file error: ${e.code}');
diff --git a/tests/html/html.status b/tests/html/html.status
index 1f04561..773dffa 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -13,19 +13,9 @@
[ $runtime == ie9 || $runtime == ie10 || $runtime == safari || $runtime == ff || $runtime == chrome || $runtime == opera ]
*layout_test: Skip
-[ $runtime == drt || $runtime == dartium ]
-input_element_test/supported_datetime: Fail
-
[ $runtime == chrome ]
-element_types_test/supported_content: Pass, Fail # Issue 8700
-element_types_test/supported_shadow: Pass, Fail # Issue 8700
input_element_test/supported_date: Pass, Fail # Chrome stable does not support this input type.
-input_element_test/supported_datetime: Fail
-input_element_test/supported_datetime-local: Pass, Fail # Issue 8700
-input_element_test/supported_month: Pass, Fail # Issue 8700
-input_element_test/supported_week: Pass, Fail # Issue 8700
speechrecognition_test/supported: Pass, Fail # Chrome stable does not support it.
-shadow_dom_test/supported: Pass, Fail # Issue 8700
speechrecognition_test/types: Pass, Fail
touchevent_test/supported: Fail
@@ -38,7 +28,6 @@
[ $compiler == none && ($runtime == drt || $runtime == dartium) ]
request_animation_frame_test: Skip # drt hangs; requestAnimationFrame not implemented
-transferables_test: Pass, Fail # Issue 8026
[ $compiler == none && ($runtime == drt || $runtime == dartium) && $system == windows]
websql_test: Skip # Issue 4941: stderr contains a backtrace.
@@ -53,15 +42,29 @@
audiobuffersourcenode_test: Pass, Fail
[$runtime == ie10 ]
-# TODO(efortuna, blois): Triage.
audiobuffersourcenode_test: Fail
audiocontext_test: Fail
-crypto_test: Fail
+dromaeo_smoke_test: Skip #TODO(efortuna): investigating.
+element_test/click: Fail # IE does not support firing this event.
+history_test/history: Pass, Fail # issue 8183
+inner_frame_test: Skip
+isolates_test: Skip
+measurement_test: Fail, Pass
+messageevent_test: Fail
+microtask_test: Fail, Pass # Appears to be flaky
+native_gc_test: Fail, Pass # BUG(7774): Untriaged.
+serialized_script_value_test: Fail
+storage_test: Fail, Pass
+websocket_test/websocket: Fail # TODO(efortuna): Issue 7875.
+window_open_test: Skip
+xhr_cross_origin_test: Fail # TODO(efortuna): Issue 7875.
+
+# IE10 Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+crypto_test/supported: Fail
css_test/supported_CssMatrix: Fail
css_test/supported_DomPoint: Fail
document_test/supports_cssCanvasContext: Fail
-dromaeo_smoke_test: Skip #TODO(efortuna): investigating.
-element_test/click: Fail # IE does not support firing this event.
element_types_test/supported_content: Fail
element_types_test/supported_details: Fail
element_types_test/supported_keygen: Fail
@@ -70,50 +73,59 @@
element_types_test/supported_shadow: Fail
fileapi_test/supported: Fail
history_test/supported_HashChangeEvent: Fail
-inner_frame_test: Skip
+indexeddb_5_test/supportsDatabaseNames: Fail
input_element_test/supported_date: Fail
-input_element_test/supported_datetime: Fail
input_element_test/supported_datetime-local: Fail
input_element_test/supported_month: Fail
input_element_test/supported_time: Fail
input_element_test/supported_week: Fail
-isolates_test: Skip
-measurement_test: Fail, Pass
-media_stream_test/supported_media: Fail
media_stream_test/supported_MediaStreamEvent: Fail
media_stream_test/supported_MediaStreamTrackEvent: Fail
-messageevent_test: Fail
-microtask_test: Fail, Pass # Appears to be flaky
+media_stream_test/supported_media: Fail
mutationobserver_test/supported: Fail
-native_gc_test: Fail, Pass # BUG(7774): Untriaged.
notifications_test/supported: Fail
rtc_test/supported: Fail
-serialized_script_value_test: Fail
shadow_dom_test/supported: Fail
speechrecognition_test/supported: Fail
-storage_test: Fail, Pass
svgelement_test/supported_altGlyph: Fail
svgelement_test/supported_animate: Fail
-svgelement_test/supported_animateTransform: Fail
svgelement_test/supported_animateMotion: Fail
+svgelement_test/supported_animateTransform: Fail
svgelement_test/supported_foreignObject: Fail
svgelement_test/supported_set: Fail
touchevent_test/supported: Fail
webgl_1_test/supported: Fail
websql_test/supported: Fail
-websocket_test/websocket: Fail # TODO(efortuna): Issue 7875.
-window_open_test: Skip
-xhr_cross_origin_test: Fail # TODO(efortuna): Issue 7875.
xhr_test/supported_HttpRequestProgressEvent: Fail
xsltprocessor_test/supported: Fail
-history_test/history: Pass, Fail # issue 8183
-canvasrenderingcontext2d_test: Fail # issue 8678
[ $runtime == ie9 ]
-crypto_test: Fail
-document_test/supports_cssCanvasContext: Fail
+audiobuffersourcenode_test: Fail
+audiocontext_test: Fail
+blob_constructor_test: Fail
+dom_constructors_test: Fail
dromaeo_smoke_test: Skip #TODO(efortuna): investigating.
element_test/click: Fail # IE does not support firing this event.
+element_test/matches: Fail # IE9 does not support matches
+form_element_test: Fail # Issue 4793.
+inner_frame_test: Skip # Issue 5727 (timeout)
+isolates_test: Skip # BUG(4016)
+localstorage_test: Fail
+messageevent_test: Fail
+microtask_test: Pass, Fail # http://dartbug.com/8300
+postmessage_structured_test: Skip # BUG(5685): times out.
+serialized_script_value_test: Fail
+url_test: Fail # IE9 does not support createObjectURL (it is supported in IE10)
+window_open_test: Skip # BUG(4016)
+xhr_cross_origin_test: Fail # Issue 6016.
+
+# IE9 Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+cache_test/supported: Fail
+crypto_test/supported: Fail
+css_test/supported_CssMatrix: Fail
+css_test/supported_DomPoint: Fail
+document_test/supports_cssCanvasContext: Fail
element_types_test/supported_content: Fail
element_types_test/supported_datalist: Fail
element_types_test/supported_details: Fail
@@ -123,35 +135,14 @@
element_types_test/supported_progress: Fail
element_types_test/supported_shadow: Fail
element_types_test/supported_track: Fail
-form_data_test/supported: Fail
-form_element_test: Fail # Issue 4793.
-inner_frame_test: Skip # Issue 5727 (timeout)
-transition_event_test/supported: Fail
-typed_arrays_1_test/supported: Fail
-localstorage_test: Fail
-webgl_1_test/supported: Fail
-websql_test/supported: Fail
-
-microtask_test: Pass, Fail # http://dartbug.com/8300
-
-#
-# Investigate and triage the following into bug reports.
-#
-audiobuffersourcenode_test: Fail
-audiocontext_test: Fail
-blob_constructor_test: Fail
-cache_test/supported: Fail
-css_test/supported_CssMatrix: Fail
-css_test/supported_DomPoint: Fail
-dom_constructors_test: Fail
-element_test/matches: Fail # IE9 does not support matches
fileapi_test/supported: Fail
+form_data_test/supported: Fail
history_test/supported_HashChangeEvent: Fail
history_test/supported_state: Fail
indexeddb_1_test/supported: Fail
+indexeddb_5_test/supportsDatabaseNames: Fail
input_element_test/supported_date: Fail
input_element_test/supported_datetime-local: Fail
-input_element_test/supported_datetime: Fail
input_element_test/supported_email: Fail
input_element_test/supported_month: Fail
input_element_test/supported_number: Fail
@@ -161,22 +152,19 @@
input_element_test/supported_time: Fail
input_element_test/supported_url: Fail
input_element_test/supported_week: Fail
-media_stream_test/supported_media: Fail
media_stream_test/supported_MediaStreamEvent: Fail
media_stream_test/supported_MediaStreamTrackEvent: Fail
-messageevent_test: Fail
+media_stream_test/supported_media: Fail
mutationobserver_test/supported: Fail
notifications_test/supported: Fail
-postmessage_structured_test: Skip # BUG(5685): times out.
rtc_test/supported: Fail
-serialized_script_value_test: Fail
shadow_dom_test/supported: Fail
speechrecognition_test/supported: Fail
svg_test/supported_externalResourcesRequired: Fail
svgelement_test/supported_altGlyph: Fail
svgelement_test/supported_animate: Fail
-svgelement_test/supported_animateTransform: Fail
svgelement_test/supported_animateMotion: Fail
+svgelement_test/supported_animateTransform: Fail
svgelement_test/supported_feBlend: Fail
svgelement_test/supported_feColorMatrix: Fail
svgelement_test/supported_feComponentTransfer: Fail
@@ -203,94 +191,106 @@
svgelement_test/supported_foreignObject: Fail
svgelement_test/supported_set: Fail
touchevent_test/supported: Fail
-url_test: Fail # IE9 does not support createObjectURL (it is supported in IE10)
+transition_event_test/supported: Fail
+typed_arrays_1_test/supported: Fail
+webgl_1_test/supported: Fail
websocket_test/supported: Fail
-window_open_test: Skip # BUG(4016)
-isolates_test: Skip # BUG(4016)
+websql_test/supported: Fail
xhr_test/supported_HttpRequestProgressEvent: Fail
xhr_test/supported_onLoadEnd: Fail
xhr_test/supported_onProgress: Fail
-xhr_cross_origin_test: Fail # Issue 6016.
xsltprocessor_test/supported: Fail
[ $runtime == safari ]
-element_types_test/supported_content: Fail
-element_types_test/supported_datalist: Fail
-element_types_test/supported_shadow: Fail
+audiocontext_test: Crash, Fail # Issue: 7414
+datalistelement_test: Fail # Issue: 7414
+element_test/elements: Crash, Fail # Issue: 7414
element_types_test/supported_track: Pass, Fail
-fileapi_test/supported: Fail
-indexeddb_1_test/supported: Fail
-input_element_test/supported_date: Fail
-input_element_test/supported_datetime-local: Fail
-input_element_test/supported_datetime: Fail
input_element_test/supported_month: Fail, Crash
input_element_test/supported_time: Fail, Crash
input_element_test/supported_week: Fail, Crash
-media_stream_test/supported_media: Fail
+webgl_1_test: Pass, Fail # Issue 8219
+wheelevent_test: Fail # Issue: 7414
+
+# Safari Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+element_types_test/supported_content: Fail
+element_types_test/supported_datalist: Fail
+element_types_test/supported_shadow: Fail
+fileapi_test/supported: Fail
+indexeddb_1_test/supported: Fail
+indexeddb_5_test/supportsDatabaseNames: Fail
+input_element_test/supported_date: Fail
+input_element_test/supported_datetime-local: Fail
media_stream_test/supported_MediaStreamEvent: Fail
media_stream_test/supported_MediaStreamTrackEvent: Fail
-notifications_test/supported: Fail # Issue: 7414
+media_stream_test/supported_media: Fail
+notifications_test/supported: Fail
performance_api_test/supported: Fail
rtc_test/supported: Fail
shadow_dom_test/supported: Fail
speechrecognition_test/supported: Fail
touchevent_test/supported: Fail
-webgl_1_test: Pass, Fail # Issue 8219
-
-audiocontext_test: Crash, Fail # Issue: 7414
-datalistelement_test: Fail # Issue: 7414
-element_test/elements: Crash, Fail # Issue: 7414
-wheelevent_test: Fail # Issue: 7414
[ $runtime == opera ]
-crypto_test: Fail
-document_test/supports_cssCanvasContext: Fail
-document_test/document: Fail # Issue: 7413
-form_data_test: Fail # Issue: 7413
-keyboard_event_test: Fail # Issue: 7413
-element_test/eventListening: Fail # Issue: 7413
-element_test/children: Fail # Issue: 7413
audiobuffersourcenode_test: Fail
-canvas_test: Pass,Fail
audiocontext_test: Fail
blob_constructor_test: Fail
-canvas_using_html_test: Fail
canvas_test: Fail
-css_test/supported_CssMatrix: Fail
-css_test/supported_DomPoint: Fail
+canvas_test: Pass,Fail
+canvas_using_html_test: Fail
cssstyledeclaration_test: Fail
+document_test/document: Fail # Issue: 7413
element_add_test: Fail
element_constructor_1_test: Fail
+element_test/children: Fail # Issue: 7413
element_test/constructors: Fail
element_test/elements: Fail
element_test/eventListening: Crash
+element_test/eventListening: Fail # Issue: 7413
element_test/queryAll: Fail
element_webkit_test: Fail
+fileapi_test: Skip # Timeout.
+form_data_test: Fail # Issue: 7413
htmlelement_test: Fail
+inner_frame_test: Skip # Timeout.
+isolates_test: Skip # Timeout.
+js_interop_3_test: Skip # Timeout.
+js_interop_4_test: Skip # Timeout.
+keyboard_event_test: Fail # Issue: 7413
+serialized_script_value_test: Fail
+typed_arrays_arraybuffer_test: Fail
+url_test: Fail
+
+# Opera Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+crypto_test/supported: Fail
+css_test/supported_CssMatrix: Fail
+css_test/supported_DomPoint: Fail
+document_test/supports_cssCanvasContext: Fail
indexeddb_1_test/supported: Fail
+indexeddb_5_test/supportsDatabaseNames: Fail
mutationobserver_test/supported: Fail
notifications_test/supported: Fail
performance_api_test/supported: Fail
-serialized_script_value_test: Fail
speechrecognition_test/supported: Fail
svg_test/supported_externalResourcesRequired: Fail
svg_test/supported_langSpace: Fail
-typed_arrays_arraybuffer_test: Fail
-url_test: Fail
-fileapi_test: Skip # Timeout.
-inner_frame_test: Skip # Timeout.
-js_interop_3_test: Skip # Timeout.
-js_interop_4_test: Skip # Timeout.
-isolates_test: Skip # Timeout.
websql_test/supported: Fail
[ $runtime == ff ]
audiobuffersourcenode_test: Fail # FF only has Audio element.
audiocontext_test: Fail # FF only has Audio element
-crypto_test: Fail
+dart_object_local_storage_test: Skip # sessionStorage NS_ERROR_DOM_NOT_SUPPORTED_ERR
+dromaeo_smoke_test: Pass, Fail # Issue: 8257
+inner_frame_test: Skip
+webgl_1_test: Pass, Fail # Issue 8219
+
+# FireFox Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+crypto_test/supported: Fail
css_test/supported_CssMatrix: Fail
css_test/supported_DomPoint: Fail
-dart_object_local_storage_test: Skip # sessionStorage NS_ERROR_DOM_NOT_SUPPORTED_ERR
document_test/supports_cssCanvasContext: Fail
element_types_test/supported_content: Fail
element_types_test/supported_details: Fail
@@ -300,16 +300,14 @@
element_types_test/supported_shadow: Fail
element_types_test/supported_track: Fail
fileapi_test/supported: Fail
-# setup code fails. prepare. (DOM callback has errors) Caught [object Event]
-inner_frame_test: Skip
+indexeddb_5_test/supportsDatabaseNames: Fail
input_element_test/supported_date: Fail
-input_element_test/supported_datetime: Fail
input_element_test/supported_datetime-local: Fail
input_element_test/supported_month: Fail
-input_element_test/supported_time: Fail
-input_element_test/supported_week: Fail
input_element_test/supported_number: Fail
input_element_test/supported_range: Fail
+input_element_test/supported_time: Fail
+input_element_test/supported_week: Fail
media_stream_test/supported_MediaStreamEvent: Fail
media_stream_test/supported_MediaStreamTrackEvent: Fail
notifications_test/supported: Fail
@@ -319,11 +317,8 @@
svg_test/supported_externalResourcesRequired: Fail
svg_test/supported_langSpace: Fail
touchevent_test/supported: Fail
-transferables_test: Fail # Issue 3392.
-webgl_1_test: Pass, Fail # Issue 8219
websql_test/supported: Fail
xhr_test/supported_HttpRequestProgressEvent: Fail
-dromaeo_smoke_test: Pass, Fail # Issue: 8257
[ $runtime == ie9 && ($system == linux || $system == macos) ]
*: Skip
@@ -336,9 +331,6 @@
[ $runtime == vm ]
*: Skip
-[ $compiler == dart2js ]
-transferables_test: Skip # until isInstance works in dart2js
-
[ $compiler == dart2js && ($runtime == drt || $runtime == ff) ]
request_animation_frame_test: Skip # Async test hangs.
@@ -354,3 +346,13 @@
[ $compiler == dart2js && $runtime == ff ]
inner_frame_test: Skip # Timeout
+
+[ $compiler == dart2js && $runtime == drt && $unchecked ]
+indexeddb_5_test/functional: Fail, Pass # http://dartbug.com/8851
+
+[ $compiler == dart2js && $csp && ($runtime == drt || $runtime == safari || $runtime == ff || $runtime == chrome) ]
+js_interop_1_test: Skip # Test cannot run under CSP restrictions (times out).
+js_interop_2_test: Fail, OK # Test cannot run under CSP restrictions.
+js_interop_3_test: Skip # Test cannot run under CSP restrictions (times out).
+postmessage_structured_test: Skip # Test cannot run under CSP restrictions (times out).
+shadow_dom_layout_test: Fail, OK # Test cannot run under CSP restrictions.
diff --git a/tests/html/indexeddb_5_test.dart b/tests/html/indexeddb_5_test.dart
new file mode 100644
index 0000000..6b58ed0
--- /dev/null
+++ b/tests/html/indexeddb_5_test.dart
@@ -0,0 +1,192 @@
+library IndexedDB1Test;
+import '../../pkg/unittest/lib/unittest.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:indexed_db' as idb;
+import 'utils.dart';
+
+main() {
+ useHtmlIndividualConfiguration();
+
+ group('supportsDatabaseNames', () {
+ test('supported', () {
+ expect(html.window.indexedDB.supportsDatabaseNames, isTrue);
+ });
+ });
+
+ if (!idb.IdbFactory.supported) {
+ return;
+ }
+
+ group('functional', () {
+ var dbName = 'test_db';
+ var storeName = 'test_store';
+ var indexName = 'name_index';
+ var db;
+
+ futureTest('init', () {
+ return html.window.indexedDB.deleteDatabase(dbName).then((_) {
+ return html.window.indexedDB.open(dbName, version: 1,
+ onUpgradeNeeded: (e) {
+ var db = e.target.result;
+ var objectStore = db.createObjectStore(storeName,
+ autoIncrement: true);
+ var index = objectStore.createIndex(indexName, 'name_index',
+ unique: false);
+ });
+ }).then((database) {
+ db = database;
+ });
+ });
+
+ if (html.window.indexedDB.supportsDatabaseNames) {
+ futureTest('getDatabaseNames', () {
+ return html.window.indexedDB.getDatabaseNames().then((names) {
+ expect(names.contains(dbName), isTrue);
+ });
+ });
+ }
+
+ var value = {'name_index': 'one', 'value': 'add_value'};
+ futureTest('add/delete', () {
+ var transaction = db.transaction([storeName], 'readwrite');
+ var key;
+ return transaction.objectStore(storeName).add(value).then((addedKey) {
+ key = addedKey;
+ }).then((_) {
+ return transaction.completed;
+ }).then((_) {
+ transaction = db.transaction([storeName], 'readonly');
+ return transaction.objectStore(storeName).getObject(key);
+ }).then((readValue) {
+ expect(readValue['value'], value['value']);
+ return transaction.completed;
+ }).then((_) {
+ transaction = db.transaction([storeName], 'readwrite');
+ return transaction.objectStore(storeName).delete(key);
+ }).then((_) {
+ return transaction.completed;
+ }).then((_) {
+ var transaction = db.transaction([storeName], 'readonly');
+ return transaction.objectStore(storeName).count();
+ }).then((count) {
+ expect(count, 0);
+ });
+ });
+
+ futureTest('clear/count', () {
+ var transaction = db.transaction([storeName], 'readwrite');
+ transaction.objectStore(storeName).add(value);
+
+ return transaction.completed.then((_) {
+ transaction = db.transaction([storeName], 'readonly');
+ return transaction.objectStore(storeName).count();
+ }).then((count) {
+ expect(count, 1);
+ }).then((_) {
+ return transaction.completed;
+ }).then((_) {
+ transaction = db.transaction([storeName], 'readwrite');
+ transaction.objectStore(storeName).clear();
+ return transaction.completed;
+ }).then((_) {
+ var transaction = db.transaction([storeName], 'readonly');
+ return transaction.objectStore(storeName).count();
+ }).then((count) {
+ expect(count, 0);
+ });
+ });
+
+ futureTest('index', () {
+ var transaction = db.transaction([storeName], 'readwrite');
+ transaction.objectStore(storeName).add(value);
+ transaction.objectStore(storeName).add(value);
+ transaction.objectStore(storeName).add(value);
+ transaction.objectStore(storeName).add(value);
+
+ return transaction.completed.then((_) {
+ transaction = db.transaction([storeName], 'readonly');
+ var index = transaction.objectStore(storeName).index(indexName);
+ return index.count();
+ }).then((count) {
+ expect(count, 4);
+ return transaction.completed;
+ }).then((_) {
+ transaction = db.transaction([storeName], 'readonly');
+ var index = transaction.objectStore(storeName).index(indexName);
+ return index.openCursor(autoAdvance: true).length;
+ }).then((cursorsLength) {
+ expect(cursorsLength, 4);
+ return transaction.completed;
+ }).then((_) {
+ transaction = db.transaction([storeName], 'readonly');
+ var index = transaction.objectStore(storeName).index(indexName);
+ return index.openKeyCursor(autoAdvance: true).length;
+ }).then((cursorsLength) {
+ expect(cursorsLength, 4);
+ return transaction.completed;
+ }).then((_) {
+ transaction = db.transaction([storeName], 'readonly');
+ var index = transaction.objectStore(storeName).index(indexName);
+ return index.get('one');
+ }).then((readValue) {
+ expect(readValue['value'], value['value']);
+ return transaction.completed;
+ }).then((_) {
+ transaction = db.transaction([storeName], 'readwrite');
+ transaction.objectStore(storeName).clear();
+ return transaction.completed;
+ });
+ });
+
+ var deleteValue = {'name_index': 'two', 'value': 'delete_value'};
+ var updateValue = {'name_index': 'three', 'value': 'update_value'};
+ var updatedValue = {'name_index': 'three', 'value': 'updated_value'};
+ futureTest('cursor', () {
+ var transaction = db.transaction([storeName], 'readwrite');
+ transaction.objectStore(storeName).add(value);
+ transaction.objectStore(storeName).add(deleteValue);
+ transaction.objectStore(storeName).add(updateValue);
+
+ return transaction.completed.then((_) {
+ transaction = db.transaction([storeName], 'readwrite');
+ var index = transaction.objectStore(storeName).index(indexName);
+ var cursors = index.openCursor().asBroadcastStream();
+
+ cursors.listen((cursor) {
+ var value = cursor.value;
+ if (value['value'] == 'delete_value') {
+ cursor.delete().then((_) {
+ cursor.next();
+ });
+ } else if (value['value'] == 'update_value') {
+ cursor.update(updatedValue).then((_) {
+ cursor.next();
+ });
+ } else {
+ cursor.next();
+ }
+ });
+ return cursors.last;
+
+ }).then((_) {
+ return transaction.completed;
+ }).then((_) {
+ transaction = db.transaction([storeName], 'readonly');
+ var index = transaction.objectStore(storeName).index(indexName);
+ return index.get('three');
+ }).then((readValue) {
+ expect(readValue['value'], 'updated_value');
+ return transaction.completed;
+ }).then((_) {
+ transaction = db.transaction([storeName], 'readonly');
+ var index = transaction.objectStore(storeName).index(indexName);
+ return index.get('two');
+ }).then((readValue) {
+ expect(readValue, isNull);
+ return transaction.completed;
+ });
+ });
+ });
+}
diff --git a/tests/html/input_element_test.dart b/tests/html/input_element_test.dart
index 8f63658..fe90511 100644
--- a/tests/html/input_element_test.dart
+++ b/tests/html/input_element_test.dart
@@ -39,12 +39,6 @@
});
});
- group('supported_datetime', () {
- test('supported', () {
- expect(DateTimeInputElement.supported, true);
- });
- });
-
group('supported_date', () {
test('supported', () {
expect(DateInputElement.supported, true);
@@ -117,11 +111,6 @@
check(new PasswordInputElement(), 'password');
});
- test('datetime', () {
- check(new DateTimeInputElement(), 'datetime',
- DateTimeInputElement.supported);
- });
-
test('date', () {
check(new DateInputElement(), 'date', DateInputElement.supported);
});
@@ -136,6 +125,15 @@
test('time', () {
check(new TimeInputElement(), 'time', TimeInputElement.supported);
+ if (TimeInputElement.supported) {
+ var element = new TimeInputElement();
+ var now = new DateTime.now();
+ element.valueAsDate = now;
+ expect(element.valueAsDate is DateTime, isTrue);
+
+ // Bug 8813, setting it is just going to the epoch.
+ //expect(element.valueAsDate, now);
+ }
});
test('datetime-local', () {
diff --git a/tests/html/native_gc_test.dart b/tests/html/native_gc_test.dart
index 45a89e9..8ed06bb 100644
--- a/tests/html/native_gc_test.dart
+++ b/tests/html/native_gc_test.dart
@@ -16,7 +16,7 @@
for (int i = 0; i < M; ++i) {
// This memory should be freed when the listener below is
// collected.
- List l = new List.fixedLength(N);
+ List l = new List(N);
// Record the iteration number.
l[N - 1] = i;
@@ -53,7 +53,7 @@
}
void triggerMajorGC() {
- List list = new List.fixedLength(1000000);
+ List list = new List(1000000);
Element div = new DivElement();
div.onClick.listen((e) => print(list[0]));
}
diff --git a/tests/html/table_test.dart b/tests/html/table_test.dart
index fda9fcc..5c1144f 100644
--- a/tests/html/table_test.dart
+++ b/tests/html/table_test.dart
@@ -13,31 +13,49 @@
test('createTBody', () {
var table = new TableElement();
var head = table.createTHead();
- var headerRow = head.insertRow(-1);
- var headerCell = headerRow.insertCell(-1);
+ expect(table.tHead, head);
+
+ var headerRow = head.addRow();
+ var headerCell = headerRow.addCell();
headerCell.text = 'Header Cell';
- var body = table.createTBody();
- var bodyRow = body.insertRow(-1);
- var bodyCell = bodyRow.insertCell(-1);
- bodyCell.text = 'Body Cell';
+ var caption = table.createCaption();
+ expect(table.caption, caption);
+ var body = table.createTBody();
expect(table.tBodies.length, 1);
expect(table.tBodies[0], body);
+ var bodyRow = body.addRow();
+ expect(body.rows.length, 1);
+ expect(body.rows[0], bodyRow);
+
+ var bodyCell = bodyRow.addCell();
+ bodyCell.text = 'Body Cell';
+ expect(bodyRow.cells.length, 1);
+ expect(bodyRow.cells[0], bodyCell);
+
var foot = table.createTFoot();
- var footerRow = foot.insertRow(-1);
- var footerCell = footerRow.insertCell(-1);
+ expect(table.tFoot, foot);
+
+ var footerRow = foot.addRow();
+ expect(foot.rows.length, 1);
+ expect(foot.rows[0], footerRow);
+
+ var footerCell = footerRow.addCell();
footerCell.text = 'Footer Cell';
+ expect(footerRow.cells.length, 1);
+ expect(footerRow.cells[0], footerCell);
var body2 = table.createTBody();
- var bodyRow2 = body2.insertRow(-1);
- var bodyCell2 = bodyRow2.insertCell(-1);
+ var bodyRow2 = body2.addRow();
+ var bodyCell2 = bodyRow2.addCell();
bodyCell2.text = 'Body Cell2';
+ expect(body2.rows.length, 1);
+
expect(table.tBodies.length, 2);
expect(table.tBodies[1], body2);
-
});
}
diff --git a/tests/html/transferables_test.dart b/tests/html/transferables_test.dart
index 3db9c42..a487ada 100644
--- a/tests/html/transferables_test.dart
+++ b/tests/html/transferables_test.dart
@@ -14,10 +14,21 @@
predicate((x) => x is ArrayBuffer, 'is an ArrayBuffer');
test('TransferableTest', () {
- window.onMessage.listen(expectAsync1((messageEvent) {
- expect(messageEvent.data, isArrayBuffer);
- }));
+ if (!ArrayBuffer.supported) {
+ return;
+ }
+
final buffer = (new Float32Array(3)).buffer;
- window.postMessage(buffer, '*', [buffer]);
+ window.postMessage({
+ 'id': 'transferable data',
+ 'buffer': buffer
+ }, '*', [buffer]);
+
+ return window.onMessage.firstMatching(
+ (e) {
+ return e.data is Map && e.data['id'] == 'transferable data';
+ }).then((messageEvent) {
+ expect(messageEvent.data['buffer'], isArrayBuffer);
+ });
});
}
diff --git a/tests/html/url_test.dart b/tests/html/url_test.dart
index f332b30..fec1d44 100644
--- a/tests/html/url_test.dart
+++ b/tests/html/url_test.dart
@@ -26,7 +26,7 @@
var arrayBuffer = new ArrayBuffer(byteString.length);
var dataArray = new Uint8Array.fromBuffer(arrayBuffer);
for (var i = 0; i < byteString.length; i++) {
- dataArray[i] = byteString.charCodeAt(i);
+ dataArray[i] = byteString.codeUnitAt(i);
}
var blob = new Blob([arrayBuffer], 'image/png');
diff --git a/tests/html/websql_test.dart b/tests/html/websql_test.dart
index f98c6bb..601ab1a 100644
--- a/tests/html/websql_test.dart
+++ b/tests/html/websql_test.dart
@@ -1,9 +1,10 @@
library WebDBTest;
-import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_individual_config.dart';
import 'dart:async';
import 'dart:html';
import 'dart:web_sql';
+import '../../pkg/unittest/lib/unittest.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
+import 'utils.dart';
void fail(message) {
guardAsync(() {
@@ -11,81 +12,84 @@
});
}
-Future<SqlTransaction> createTransaction(SqlDatabase db) {
+Future<SqlTransaction> transaction(SqlDatabase db) {
final completer = new Completer<SqlTransaction>();
db.transaction((SqlTransaction transaction) {
completer.complete(transaction);
+ }, (SqlError error) {
+ completer.completeError(error);
});
return completer.future;
}
-createTable(tableName, columnName) => (SqlTransaction transaction) {
- final completer = new Completer<SqlTransaction>();
+Future<SqlResultSet> createTable(SqlTransaction transaction, String tableName,
+ String columnName) {
+ final completer = new Completer<SqlResultSet>();
final sql = 'CREATE TABLE $tableName ($columnName)';
transaction.executeSql(sql, [],
(SqlTransaction tx, SqlResultSet rs) {
- completer.complete(transaction);
+ completer.complete(rs);
},
(SqlTransaction tx, SqlError error) {
- fail(error.message);
+ completer.completeError(error);
});
return completer.future;
-};
+}
-insert(tableName, columnName, value) => (SqlTransaction transaction) {
- final completer = new Completer<SqlTransaction>();
+Future<SqlResultSet> insert(SqlTransaction transaction, String tableName,
+ String columnName, value) {
+ final completer = new Completer<SqlResultSet>();
final sql = 'INSERT INTO $tableName ($columnName) VALUES (?)';
transaction.executeSql(sql, [value],
(SqlTransaction tx, SqlResultSet rs) {
- completer.complete(tx);
+ completer.complete(rs);
},
(SqlTransaction tx, SqlError error) {
- fail(error.message);
+ completer.completeError(error);
});
return completer.future;
-};
+}
-queryTable(tableName, callback) => (SqlTransaction transaction) {
- final completer = new Completer<SqlTransaction>();
+Future<SqlResultSet> queryTable(SqlTransaction transaction, String tableName) {
+ final completer = new Completer<SqlResultSet>();
final sql = 'SELECT * FROM $tableName';
transaction.executeSql(sql, [],
(SqlTransaction tx, SqlResultSet rs) {
- callback(rs);
- completer.complete(tx);
+ completer.complete(rs);
},
(SqlTransaction tx, SqlError error) {
- fail(error.message);
+ completer.completeError(error);
});
return completer.future;
-};
+}
-dropTable(tableName, [bool ignoreFailure = false]) =>
- (SqlTransaction transaction) {
- final completer = new Completer<SqlTransaction>();
+Future<SqlResultSet> dropTable(SqlTransaction transaction, String tableName,
+ [bool ignoreFailure = false]) {
+ final completer = new Completer<SqlResultSet>();
final sql = 'DROP TABLE $tableName';
transaction.executeSql(sql, [],
(SqlTransaction tx, SqlResultSet rs) {
- completer.complete(tx);
+ completer.complete(rs);
},
(SqlTransaction tx, SqlError error) {
if (ignoreFailure) {
- completer.complete(tx);
+ completer.complete(null);
} else {
- fail(error.message);
+ completer.completeError(error);
}
});
return completer.future;
-};
+}
main() {
useHtmlIndividualConfiguration();
@@ -104,10 +108,10 @@
}, expectation);
});
- test('Web Database', () {
+ futureTest('Web Database', () {
// Skip if not supported.
if (!SqlDatabase.supported) {
- return;
+ return new Future.immediate(null);
}
final tableName = 'test_table';
@@ -117,22 +121,28 @@
expect(db, isNotNull, reason: 'Unable to open database');
- createTransaction(db)
+ var tx;
+ return transaction(db).then((transaction) {
+ tx = transaction;
+ }).then((_) {
// Attempt to clear out any tables which may be lurking from previous
// runs.
- .then(dropTable(tableName, true))
- .then(createTable(tableName, columnName))
- .then(insert(tableName, columnName, 'Some text data'))
- .then(queryTable(tableName, (resultSet) {
- guardAsync(() {
- expect(resultSet.rows.length, 1);
- var row = resultSet.rows.item(0);
- expect(row.containsKey(columnName), isTrue);
- expect(row[columnName], 'Some text data');
- });
- }))
- .then(dropTable(tableName))
- .then(expectAsync1((tx) {}));
+ return dropTable(tx, tableName, true);
+ }).then((_) {
+ return createTable(tx, tableName, columnName);
+ }).then((_) {
+ return insert(tx, tableName, columnName, 'Some text data');
+ }).then((_) {
+ return queryTable(tx, tableName);
+ }).then((resultSet) {
+ expect(resultSet.rows.length, 1);
+ var row = resultSet.rows.item(0);
+ expect(row.containsKey(columnName), isTrue);
+ expect(row[columnName], 'Some text data');
+ expect(resultSet.rows[0], row);
+ }).then((_) {
+ return dropTable(tx, tableName);
+ });
});
});
}
diff --git a/tests/isolate/mandel_isolate_test.dart b/tests/isolate/mandel_isolate_test.dart
index 292d6d6..abc4d83 100644
--- a/tests/isolate/mandel_isolate_test.dart
+++ b/tests/isolate/mandel_isolate_test.dart
@@ -27,7 +27,7 @@
MandelbrotState() {
_result = new List<List<int>>(N);
- _lineProcessedBy = new List<LineProcessorClient>.fixedLength(N);
+ _lineProcessedBy = new List<LineProcessorClient>(N);
_sent = 0;
_missing = N;
_validated = new Completer<bool>();
@@ -107,7 +107,7 @@
List<int> processLine(int y) {
double inverseN = 2.0 / N;
double Civ = y * inverseN - 1.0;
- List<int> result = new List<int>.fixedLength(N);
+ List<int> result = new List<int>(N);
for (int x = 0; x < N; x++) {
double Crv = x * inverseN - 1.5;
diff --git a/tests/isolate/message_test.dart b/tests/isolate/message_test.dart
index a281d81..ee00de5 100644
--- a/tests/isolate/message_test.dart
+++ b/tests/isolate/message_test.dart
@@ -100,7 +100,7 @@
List local_list1 = ["Hello", "World", "Hello", 0xffffffffff];
List local_list2 = [null, local_list1, local_list1 ];
List local_list3 = [local_list2, 2.0, true, false, 0xffffffffff];
- List sendObject = new List.fixedLength(5);
+ List sendObject = new List(5);
sendObject[0] = local_list1;
sendObject[1] = sendObject;
sendObject[2] = local_list2;
diff --git a/tests/isolate/multiple_timer_test.dart b/tests/isolate/multiple_timer_test.dart
index db2248a..27e429e 100644
--- a/tests/isolate/multiple_timer_test.dart
+++ b/tests/isolate/multiple_timer_test.dart
@@ -57,7 +57,7 @@
_message++;
}
- _order = new List<int>.fixedLength(4);
+ _order = new List<int>(4);
_order[0] = 2;
_order[1] = 0;
_order[2] = 3;
diff --git a/tests/isolate/timer_cancel_test.dart b/tests/isolate/timer_cancel_test.dart
index bc4376b..a159abc 100644
--- a/tests/isolate/timer_cancel_test.dart
+++ b/tests/isolate/timer_cancel_test.dart
@@ -35,10 +35,10 @@
repeatTimer = 0;
new Timer.repeating(ms * 1500, expectAsync1(repeatHandler));
});
-
+
test("cancel timer with same time", () {
var t2;
- var t1 = Timer.run(expectAsync0(() => t2.cancel()));
- t2 = Timer.run(expectAsync0(t1.cancel, count: 0));
+ var t1 = new Timer(ms * 0, expectAsync0(() => t2.cancel()));
+ t2 = new Timer(ms * 0, expectAsync0(t1.cancel, count: 0));
});
}
diff --git a/tests/json/json_test.dart b/tests/json/json_test.dart
index 5ec1c83..1fe74e5 100644
--- a/tests/json/json_test.dart
+++ b/tests/json/json_test.dart
@@ -90,8 +90,8 @@
// Lists.
expect(json.stringify([]), equals('[]'));
- expect(json.stringify(new List.fixedLength(0)), equals('[]'));
- expect(json.stringify(new List.fixedLength(3)), equals('[null,null,null]'));
+ expect(json.stringify(new List(0)), equals('[]'));
+ expect(json.stringify(new List(3)), equals('[null,null,null]'));
validateRoundTrip([3, -4.5, null, true, 'hi', false]);
expect(json.stringify([[3], [], [null], ['hi', true]]),
equals('[[3],[],[null],["hi",true]]'));
diff --git a/tests/language/arithmetic_test.dart b/tests/language/arithmetic_test.dart
index f230b3c..4ee0080 100644
--- a/tests/language/arithmetic_test.dart
+++ b/tests/language/arithmetic_test.dart
@@ -279,6 +279,8 @@
// Double.
Expect.equals(3.0, (2.6).round());
Expect.equals(-3.0, (-2.6).round());
+ Expect.equals(3.0, (2.5).round());
+ Expect.equals(-3.0, (-2.5).round());
Expect.equals(0.0, (0.0).round());
Expect.equals(0.0, (0.1).round());
Expect.equals(false, (0.0).round().isNegative);
diff --git a/tests/language/bailout4_test.dart b/tests/language/bailout4_test.dart
index 0bb3edf..52e9713 100644
--- a/tests/language/bailout4_test.dart
+++ b/tests/language/bailout4_test.dart
@@ -10,7 +10,7 @@
}
var a = new A();
-var b = new List.fixedLength(4);
+var b = new List(4);
int count = 0;
main() {
diff --git a/tests/language/char_escape_test.dart b/tests/language/char_escape_test.dart
index a890e4d..23c95ca 100644
--- a/tests/language/char_escape_test.dart
+++ b/tests/language/char_escape_test.dart
@@ -21,14 +21,14 @@
Expect.equals(1, v0000.length);
Expect.equals(1, v00000.length);
Expect.equals(1, v000000.length);
- Expect.equals(0, x00.charCodeAt(0));
- Expect.equals(0, u0000.charCodeAt(0));
- Expect.equals(0, v0.charCodeAt(0));
- Expect.equals(0, v00.charCodeAt(0));
- Expect.equals(0, v000.charCodeAt(0));
- Expect.equals(0, v0000.charCodeAt(0));
- Expect.equals(0, v00000.charCodeAt(0));
- Expect.equals(0, v000000.charCodeAt(0));
+ Expect.equals(0, x00.codeUnitAt(0));
+ Expect.equals(0, u0000.codeUnitAt(0));
+ Expect.equals(0, v0.codeUnitAt(0));
+ Expect.equals(0, v00.codeUnitAt(0));
+ Expect.equals(0, v000.codeUnitAt(0));
+ Expect.equals(0, v0000.codeUnitAt(0));
+ Expect.equals(0, v00000.codeUnitAt(0));
+ Expect.equals(0, v000000.codeUnitAt(0));
Expect.equals("\x00", new String.fromCharCodes([0]));
Expect.equals("\u0000", new String.fromCharCodes([0]));
Expect.equals("\u{0}", new String.fromCharCodes([0]));
@@ -54,14 +54,14 @@
Expect.equals(1, v0001.length);
Expect.equals(1, v00001.length);
Expect.equals(1, v000001.length);
- Expect.equals(1, x01.charCodeAt(0));
- Expect.equals(1, u0001.charCodeAt(0));
- Expect.equals(1, v1.charCodeAt(0));
- Expect.equals(1, v01.charCodeAt(0));
- Expect.equals(1, v001.charCodeAt(0));
- Expect.equals(1, v0001.charCodeAt(0));
- Expect.equals(1, v00001.charCodeAt(0));
- Expect.equals(1, v000001.charCodeAt(0));
+ Expect.equals(1, x01.codeUnitAt(0));
+ Expect.equals(1, u0001.codeUnitAt(0));
+ Expect.equals(1, v1.codeUnitAt(0));
+ Expect.equals(1, v01.codeUnitAt(0));
+ Expect.equals(1, v001.codeUnitAt(0));
+ Expect.equals(1, v0001.codeUnitAt(0));
+ Expect.equals(1, v00001.codeUnitAt(0));
+ Expect.equals(1, v000001.codeUnitAt(0));
Expect.equals("\x01", new String.fromCharCodes([1]));
Expect.equals("\u0001", new String.fromCharCodes([1]));
Expect.equals("\u{1}", new String.fromCharCodes([1]));
@@ -85,13 +85,13 @@
Expect.equals(1, v0055.length);
Expect.equals(1, v00055.length);
Expect.equals(1, v000055.length);
- Expect.equals(0x55, x55.charCodeAt(0));
- Expect.equals(0x55, u0055.charCodeAt(0));
- Expect.equals(0x55, v55.charCodeAt(0));
- Expect.equals(0x55, v055.charCodeAt(0));
- Expect.equals(0x55, v0055.charCodeAt(0));
- Expect.equals(0x55, v00055.charCodeAt(0));
- Expect.equals(0x55, v000055.charCodeAt(0));
+ Expect.equals(0x55, x55.codeUnitAt(0));
+ Expect.equals(0x55, u0055.codeUnitAt(0));
+ Expect.equals(0x55, v55.codeUnitAt(0));
+ Expect.equals(0x55, v055.codeUnitAt(0));
+ Expect.equals(0x55, v0055.codeUnitAt(0));
+ Expect.equals(0x55, v00055.codeUnitAt(0));
+ Expect.equals(0x55, v000055.codeUnitAt(0));
Expect.equals("\x55", new String.fromCharCodes([0x55]));
Expect.equals("\u0055", new String.fromCharCodes([0x55]));
Expect.equals("\u{55}", new String.fromCharCodes([0x55]));
@@ -114,13 +114,13 @@
Expect.equals(1, v007F.length);
Expect.equals(1, v0007F.length);
Expect.equals(1, v00007F.length);
- Expect.equals(0x7F, x7F.charCodeAt(0));
- Expect.equals(0x7F, u007F.charCodeAt(0));
- Expect.equals(0x7F, v7F.charCodeAt(0));
- Expect.equals(0x7F, v07F.charCodeAt(0));
- Expect.equals(0x7F, v007F.charCodeAt(0));
- Expect.equals(0x7F, v0007F.charCodeAt(0));
- Expect.equals(0x7F, v00007F.charCodeAt(0));
+ Expect.equals(0x7F, x7F.codeUnitAt(0));
+ Expect.equals(0x7F, u007F.codeUnitAt(0));
+ Expect.equals(0x7F, v7F.codeUnitAt(0));
+ Expect.equals(0x7F, v07F.codeUnitAt(0));
+ Expect.equals(0x7F, v007F.codeUnitAt(0));
+ Expect.equals(0x7F, v0007F.codeUnitAt(0));
+ Expect.equals(0x7F, v00007F.codeUnitAt(0));
Expect.equals("\x7F", new String.fromCharCodes([0x7F]));
Expect.equals("\u007F", new String.fromCharCodes([0x7F]));
Expect.equals("\u{7F}", new String.fromCharCodes([0x7F]));
@@ -143,13 +143,13 @@
Expect.equals(1, v0080.length);
Expect.equals(1, v00080.length);
Expect.equals(1, v000080.length);
- Expect.equals(0x80, x80.charCodeAt(0));
- Expect.equals(0x80, u0080.charCodeAt(0));
- Expect.equals(0x80, v80.charCodeAt(0));
- Expect.equals(0x80, v080.charCodeAt(0));
- Expect.equals(0x80, v0080.charCodeAt(0));
- Expect.equals(0x80, v00080.charCodeAt(0));
- Expect.equals(0x80, v000080.charCodeAt(0));
+ Expect.equals(0x80, x80.codeUnitAt(0));
+ Expect.equals(0x80, u0080.codeUnitAt(0));
+ Expect.equals(0x80, v80.codeUnitAt(0));
+ Expect.equals(0x80, v080.codeUnitAt(0));
+ Expect.equals(0x80, v0080.codeUnitAt(0));
+ Expect.equals(0x80, v00080.codeUnitAt(0));
+ Expect.equals(0x80, v000080.codeUnitAt(0));
Expect.equals("\x80", new String.fromCharCodes([0x80]));
Expect.equals("\u0080", new String.fromCharCodes([0x80]));
Expect.equals("\u{80}", new String.fromCharCodes([0x80]));
@@ -172,13 +172,13 @@
Expect.equals(1, v00AA.length);
Expect.equals(1, v000AA.length);
Expect.equals(1, v0000AA.length);
- Expect.equals(0xAA, xAA.charCodeAt(0));
- Expect.equals(0xAA, u00AA.charCodeAt(0));
- Expect.equals(0xAA, vAA.charCodeAt(0));
- Expect.equals(0xAA, v0AA.charCodeAt(0));
- Expect.equals(0xAA, v00AA.charCodeAt(0));
- Expect.equals(0xAA, v000AA.charCodeAt(0));
- Expect.equals(0xAA, v0000AA.charCodeAt(0));
+ Expect.equals(0xAA, xAA.codeUnitAt(0));
+ Expect.equals(0xAA, u00AA.codeUnitAt(0));
+ Expect.equals(0xAA, vAA.codeUnitAt(0));
+ Expect.equals(0xAA, v0AA.codeUnitAt(0));
+ Expect.equals(0xAA, v00AA.codeUnitAt(0));
+ Expect.equals(0xAA, v000AA.codeUnitAt(0));
+ Expect.equals(0xAA, v0000AA.codeUnitAt(0));
Expect.equals("\xAA", new String.fromCharCodes([0xAA]));
Expect.equals("\u00AA", new String.fromCharCodes([0xAA]));
Expect.equals("\u{AA}", new String.fromCharCodes([0xAA]));
@@ -201,13 +201,13 @@
Expect.equals(1, v00FE.length);
Expect.equals(1, v000FE.length);
Expect.equals(1, v0000FE.length);
- Expect.equals(0xFE, xFE.charCodeAt(0));
- Expect.equals(0xFE, u00FE.charCodeAt(0));
- Expect.equals(0xFE, vFE.charCodeAt(0));
- Expect.equals(0xFE, v0FE.charCodeAt(0));
- Expect.equals(0xFE, v00FE.charCodeAt(0));
- Expect.equals(0xFE, v000FE.charCodeAt(0));
- Expect.equals(0xFE, v0000FE.charCodeAt(0));
+ Expect.equals(0xFE, xFE.codeUnitAt(0));
+ Expect.equals(0xFE, u00FE.codeUnitAt(0));
+ Expect.equals(0xFE, vFE.codeUnitAt(0));
+ Expect.equals(0xFE, v0FE.codeUnitAt(0));
+ Expect.equals(0xFE, v00FE.codeUnitAt(0));
+ Expect.equals(0xFE, v000FE.codeUnitAt(0));
+ Expect.equals(0xFE, v0000FE.codeUnitAt(0));
Expect.equals("\xFE", new String.fromCharCodes([0xFE]));
Expect.equals("\u00FE", new String.fromCharCodes([0xFE]));
Expect.equals("\u{FE}", new String.fromCharCodes([0xFE]));
@@ -230,13 +230,13 @@
Expect.equals(1, v00FF.length);
Expect.equals(1, v000FF.length);
Expect.equals(1, v0000FF.length);
- Expect.equals(0xFF, xFF.charCodeAt(0));
- Expect.equals(0xFF, u00FF.charCodeAt(0));
- Expect.equals(0xFF, vFF.charCodeAt(0));
- Expect.equals(0xFF, v0FF.charCodeAt(0));
- Expect.equals(0xFF, v00FF.charCodeAt(0));
- Expect.equals(0xFF, v000FF.charCodeAt(0));
- Expect.equals(0xFF, v0000FF.charCodeAt(0));
+ Expect.equals(0xFF, xFF.codeUnitAt(0));
+ Expect.equals(0xFF, u00FF.codeUnitAt(0));
+ Expect.equals(0xFF, vFF.codeUnitAt(0));
+ Expect.equals(0xFF, v0FF.codeUnitAt(0));
+ Expect.equals(0xFF, v00FF.codeUnitAt(0));
+ Expect.equals(0xFF, v000FF.codeUnitAt(0));
+ Expect.equals(0xFF, v0000FF.codeUnitAt(0));
Expect.equals("\xFF", new String.fromCharCodes([0xFF]));
Expect.equals("\u00FF", new String.fromCharCodes([0xFF]));
Expect.equals("\u{FF}", new String.fromCharCodes([0xFF]));
@@ -253,10 +253,10 @@
Expect.equals(1, v1000.length);
Expect.equals(1, v01000.length);
Expect.equals(1, v001000.length);
- Expect.equals(0x1000, u1000.charCodeAt(0));
- Expect.equals(0x1000, v1000.charCodeAt(0));
- Expect.equals(0x1000, v01000.charCodeAt(0));
- Expect.equals(0x1000, v001000.charCodeAt(0));
+ Expect.equals(0x1000, u1000.codeUnitAt(0));
+ Expect.equals(0x1000, v1000.codeUnitAt(0));
+ Expect.equals(0x1000, v01000.codeUnitAt(0));
+ Expect.equals(0x1000, v001000.codeUnitAt(0));
Expect.equals("\u1000", new String.fromCharCodes([0x1000]));
Expect.equals("\u{1000}", new String.fromCharCodes([0x1000]));
Expect.equals("\u{01000}", new String.fromCharCodes([0x1000]));
@@ -270,10 +270,10 @@
Expect.equals(1, v5555.length);
Expect.equals(1, v05555.length);
Expect.equals(1, v005555.length);
- Expect.equals(0x5555, u5555.charCodeAt(0));
- Expect.equals(0x5555, v5555.charCodeAt(0));
- Expect.equals(0x5555, v05555.charCodeAt(0));
- Expect.equals(0x5555, v005555.charCodeAt(0));
+ Expect.equals(0x5555, u5555.codeUnitAt(0));
+ Expect.equals(0x5555, v5555.codeUnitAt(0));
+ Expect.equals(0x5555, v05555.codeUnitAt(0));
+ Expect.equals(0x5555, v005555.codeUnitAt(0));
Expect.equals("\u5555", new String.fromCharCodes([0x5555]));
Expect.equals("\u{5555}", new String.fromCharCodes([0x5555]));
Expect.equals("\u{05555}", new String.fromCharCodes([0x5555]));
@@ -287,10 +287,10 @@
Expect.equals(1, v7FFF.length);
Expect.equals(1, v07FFF.length);
Expect.equals(1, v007FFF.length);
- Expect.equals(0x7FFF, u7FFF.charCodeAt(0));
- Expect.equals(0x7FFF, v7FFF.charCodeAt(0));
- Expect.equals(0x7FFF, v07FFF.charCodeAt(0));
- Expect.equals(0x7FFF, v007FFF.charCodeAt(0));
+ Expect.equals(0x7FFF, u7FFF.codeUnitAt(0));
+ Expect.equals(0x7FFF, v7FFF.codeUnitAt(0));
+ Expect.equals(0x7FFF, v07FFF.codeUnitAt(0));
+ Expect.equals(0x7FFF, v007FFF.codeUnitAt(0));
Expect.equals("\u7FFF", new String.fromCharCodes([0x7FFF]));
Expect.equals("\u{7FFF}", new String.fromCharCodes([0x7FFF]));
Expect.equals("\u{07FFF}", new String.fromCharCodes([0x7FFF]));
@@ -304,10 +304,10 @@
Expect.equals(1, v8000.length);
Expect.equals(1, v08000.length);
Expect.equals(1, v008000.length);
- Expect.equals(0x8000, u8000.charCodeAt(0));
- Expect.equals(0x8000, v8000.charCodeAt(0));
- Expect.equals(0x8000, v08000.charCodeAt(0));
- Expect.equals(0x8000, v008000.charCodeAt(0));
+ Expect.equals(0x8000, u8000.codeUnitAt(0));
+ Expect.equals(0x8000, v8000.codeUnitAt(0));
+ Expect.equals(0x8000, v08000.codeUnitAt(0));
+ Expect.equals(0x8000, v008000.codeUnitAt(0));
Expect.equals("\u8000", new String.fromCharCodes([0x8000]));
Expect.equals("\u{8000}", new String.fromCharCodes([0x8000]));
Expect.equals("\u{08000}", new String.fromCharCodes([0x8000]));
@@ -321,10 +321,10 @@
Expect.equals(1, vAAAA.length);
Expect.equals(1, v0AAAA.length);
Expect.equals(1, v00AAAA.length);
- Expect.equals(0xAAAA, uAAAA.charCodeAt(0));
- Expect.equals(0xAAAA, vAAAA.charCodeAt(0));
- Expect.equals(0xAAAA, v0AAAA.charCodeAt(0));
- Expect.equals(0xAAAA, v00AAAA.charCodeAt(0));
+ Expect.equals(0xAAAA, uAAAA.codeUnitAt(0));
+ Expect.equals(0xAAAA, vAAAA.codeUnitAt(0));
+ Expect.equals(0xAAAA, v0AAAA.codeUnitAt(0));
+ Expect.equals(0xAAAA, v00AAAA.codeUnitAt(0));
Expect.equals("\uAAAA", new String.fromCharCodes([0xAAAA]));
Expect.equals("\u{AAAA}", new String.fromCharCodes([0xAAAA]));
Expect.equals("\u{0AAAA}", new String.fromCharCodes([0xAAAA]));
@@ -338,10 +338,10 @@
Expect.equals(1, vFFFE.length);
Expect.equals(1, v0FFFE.length);
Expect.equals(1, v00FFFE.length);
- Expect.equals(0xFFFE, uFFFE.charCodeAt(0));
- Expect.equals(0xFFFE, vFFFE.charCodeAt(0));
- Expect.equals(0xFFFE, v0FFFE.charCodeAt(0));
- Expect.equals(0xFFFE, v00FFFE.charCodeAt(0));
+ Expect.equals(0xFFFE, uFFFE.codeUnitAt(0));
+ Expect.equals(0xFFFE, vFFFE.codeUnitAt(0));
+ Expect.equals(0xFFFE, v0FFFE.codeUnitAt(0));
+ Expect.equals(0xFFFE, v00FFFE.codeUnitAt(0));
Expect.equals("\uFFFE", new String.fromCharCodes([0xFFFE]));
Expect.equals("\u{FFFE}", new String.fromCharCodes([0xFFFE]));
Expect.equals("\u{0FFFE}", new String.fromCharCodes([0xFFFE]));
@@ -355,10 +355,10 @@
Expect.equals(1, vFFFF.length);
Expect.equals(1, v0FFFF.length);
Expect.equals(1, v00FFFF.length);
- Expect.equals(0xFFFF, uFFFF.charCodeAt(0));
- Expect.equals(0xFFFF, vFFFF.charCodeAt(0));
- Expect.equals(0xFFFF, v0FFFF.charCodeAt(0));
- Expect.equals(0xFFFF, v00FFFF.charCodeAt(0));
+ Expect.equals(0xFFFF, uFFFF.codeUnitAt(0));
+ Expect.equals(0xFFFF, vFFFF.codeUnitAt(0));
+ Expect.equals(0xFFFF, v0FFFF.codeUnitAt(0));
+ Expect.equals(0xFFFF, v00FFFF.codeUnitAt(0));
Expect.equals("\uFFFF", new String.fromCharCodes([0xFFFF]));
Expect.equals("\u{FFFF}", new String.fromCharCodes([0xFFFF]));
Expect.equals("\u{0FFFF}", new String.fromCharCodes([0xFFFF]));
@@ -389,7 +389,7 @@
var bs = "\b";
Expect.isTrue(bs != "b");
Expect.equals(1, bs.length);
- Expect.equals(0x08, bs.charCodeAt(0));
+ Expect.equals(0x08, bs.codeUnitAt(0));
Expect.equals(bs, new String.fromCharCodes([0x08]));
Expect.equals("\x08", bs);
Expect.equals("\u0008", bs);
@@ -403,7 +403,7 @@
var ht = "\t";
Expect.isTrue(ht != "t");
Expect.equals(1, ht.length);
- Expect.equals(0x09, ht.charCodeAt(0));
+ Expect.equals(0x09, ht.codeUnitAt(0));
Expect.equals(ht, new String.fromCharCodes([0x09]));
Expect.equals("\x09", ht);
Expect.equals("\u0009", ht);
@@ -417,7 +417,7 @@
var lf = "\n";
Expect.isTrue(lf != "n");
Expect.equals(1, lf.length);
- Expect.equals(0x0A, lf.charCodeAt(0));
+ Expect.equals(0x0A, lf.codeUnitAt(0));
Expect.equals(lf, new String.fromCharCodes([0x0A]));
Expect.equals("\x0A", lf);
Expect.equals("\u000A", lf);
@@ -431,7 +431,7 @@
var vt = "\v";
Expect.isTrue(vt != "v");
Expect.equals(1, vt.length);
- Expect.equals(0x0B, vt.charCodeAt(0));
+ Expect.equals(0x0B, vt.codeUnitAt(0));
Expect.equals(vt, new String.fromCharCodes([0x0B]));
Expect.equals("\x0B", vt);
Expect.equals("\u000B", vt);
@@ -445,7 +445,7 @@
var ff = "\f";
Expect.isTrue(ff != "f");
Expect.equals(1, ff.length);
- Expect.equals(0x0C, ff.charCodeAt(0));
+ Expect.equals(0x0C, ff.codeUnitAt(0));
Expect.equals(ff, new String.fromCharCodes([0x0C]));
Expect.equals("\x0C", ff);
Expect.equals("\u000C", ff);
@@ -459,7 +459,7 @@
var cr = "\r";
Expect.isTrue(cr != "r");
Expect.equals(1, cr.length);
- Expect.equals(0x0D, cr.charCodeAt(0));
+ Expect.equals(0x0D, cr.codeUnitAt(0));
Expect.equals(cr, new String.fromCharCodes([0x0D]));
Expect.equals("\x0D", cr);
Expect.equals("\u000D", cr);
diff --git a/tests/language/closure_in_field_initializer_test.dart b/tests/language/closure_in_field_initializer_test.dart
new file mode 100644
index 0000000..88ca236
--- /dev/null
+++ b/tests/language/closure_in_field_initializer_test.dart
@@ -0,0 +1,14 @@
+// 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.
+
+class Foo {
+ var closures = {
+ 'a': (x, y) => x + y
+ };
+}
+
+main() {
+ var closures = new Foo().closures;
+ Expect.equals(6, closures['a'](4, 2));
+}
diff --git a/tests/language/compound_assignment_operator_test.dart b/tests/language/compound_assignment_operator_test.dart
index 52c5289..e875af1 100644
--- a/tests/language/compound_assignment_operator_test.dart
+++ b/tests/language/compound_assignment_operator_test.dart
@@ -5,7 +5,7 @@
class Indexed {
- Indexed() : _f = new List.fixedLength(10), count = 0 {
+ Indexed() : _f = new List(10), count = 0 {
_f[0] = 100;
_f[1] = 200;
}
diff --git a/tests/language/const_list_test.dart b/tests/language/const_list_test.dart
index 4422efb..e05f7a7 100644
--- a/tests/language/const_list_test.dart
+++ b/tests/language/const_list_test.dart
@@ -5,8 +5,8 @@
class ConstListTest {
static testMain() {
- List fixedList = new List.fixedLength(4);
- List fixedList2 = new List.fixedLength(4);
+ List fixedList = new List(4);
+ List fixedList2 = new List(4);
List growableList = new List();
List growableList2 = new List();
for (int i = 0; i < 4; i++) {
diff --git a/tests/language/deopt_no_feedback_test.dart b/tests/language/deopt_no_feedback_test.dart
index 9cb79c1..f307e77 100644
--- a/tests/language/deopt_no_feedback_test.dart
+++ b/tests/language/deopt_no_feedback_test.dart
@@ -8,13 +8,13 @@
test(a, i, v, flag) {
if (flag) {
// No type feedback in first pass
- return a[i] = v;
+ return a[i] = v;
} else {
return a[i] = i;
}
}
- var a = new List.fixedLength(10);
+ var a = new List(10);
for (var i = 0; i < 2000; i++) {
var r = test(a, 3, 888, false);
Expect.equals(3, r);
diff --git a/tests/language/execute_finally7_test.dart b/tests/language/execute_finally7_test.dart
index 6b68a0b..265e4c1 100644
--- a/tests/language/execute_finally7_test.dart
+++ b/tests/language/execute_finally7_test.dart
@@ -14,7 +14,7 @@
static int f1(int k) {
var b;
try {
- var a = new List.fixedLength(10);
+ var a = new List(10);
int i = 0;
while (i < 10) {
int j = i;
diff --git a/tests/language/fannkuch_test.dart b/tests/language/fannkuch_test.dart
index a38d34d..356f20f 100644
--- a/tests/language/fannkuch_test.dart
+++ b/tests/language/fannkuch_test.dart
@@ -8,7 +8,7 @@
class FannkuchTest {
static fannkuch(n) {
- var p = new List.fixedLength(n), q = new List.fixedLength(n), s = new List.fixedLength(n);
+ var p = new List(n), q = new List(n), s = new List(n);
var sign = 1, maxflips = 0, sum = 0, m = n - 1;
for (var i = 0; i < n; i++) { p[i] = i; q[i] = i; s[i] = i; }
do {
diff --git a/tests/language/field_increment_bailout_test.dart b/tests/language/field_increment_bailout_test.dart
new file mode 100644
index 0000000..8ea2caa
--- /dev/null
+++ b/tests/language/field_increment_bailout_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2js regression test for issue 8781.
+
+class N {
+ var outgoing;
+ var incoming;
+ N(this.outgoing, this.incoming);
+}
+
+class A {
+ int offset = 0;
+ var list;
+ var node;
+
+ A(node) : node = node, list = node.outgoing;
+
+ next() {
+ // dart2js used to update [offset] twice: once in the optimized
+ // version, which would bailout to the non-optimized version
+ // because [list] is not an Array, and once in the non-optimized
+ // version.
+ var edge = list[offset++];
+ if (list == node.outgoing) {
+ list = node.incoming;
+ offset = 0;
+ } else
+ list = null;
+ return edge;
+ }
+}
+
+class L {
+ final list;
+ L(this.list);
+ // Use noSuchMethod to defeat type inferencing.
+ noSuchMethod(mirror) => mirror.invokeOn(list);
+}
+
+main () {
+ var o = new A(new N(new L([1]), new L([2])));
+
+ for (var i = 1; i <= 2; i++)
+ Expect.equals(i, o.next());
+
+ Expect.equals(null, o.list);
+}
diff --git a/tests/language/fixed_length_test.dart b/tests/language/fixed_length_test.dart
index 27be71f..0e8ab56 100644
--- a/tests/language/fixed_length_test.dart
+++ b/tests/language/fixed_length_test.dart
@@ -8,8 +8,8 @@
Expect.equals(-1, foo());
}
-int foo() {
- var list = new List<int>.fixedLength(1024);
+int foo() {
+ var list = new List<int>(1024);
for(int i = 0; i < list.length; i++) list[i] = -i;
diff --git a/tests/language/full_stacktrace1_test.dart b/tests/language/full_stacktrace1_test.dart
new file mode 100644
index 0000000..37ac2bc
--- /dev/null
+++ b/tests/language/full_stacktrace1_test.dart
@@ -0,0 +1,56 @@
+void func1() {
+ throw new Exception("Test peanut gallery request for Full stacktrace");
+}
+void func2() {
+ func1();
+}
+void func3() {
+ try {
+ func2();
+ } on Object catch(e, s) {
+ print(e);
+
+ var full_trace = s.fullStackTrace;
+ Expect.isTrue(full_trace.contains("func1"));
+ Expect.isTrue(full_trace.contains("func2"));
+ Expect.isTrue(full_trace.contains("func3"));
+ Expect.isTrue(full_trace.contains("func4"));
+ Expect.isTrue(full_trace.contains("func5"));
+ Expect.isTrue(full_trace.contains("func6"));
+ Expect.isTrue(full_trace.contains("main"));
+
+ var trace = s.stackTrace;
+ Expect.isTrue(trace.contains("func1"));
+ Expect.isTrue(trace.contains("func2"));
+ Expect.isTrue(trace.contains("func3"));
+
+ Expect.isFalse(trace.contains("func4"));
+ Expect.isFalse(trace.contains("func5"));
+ Expect.isFalse(trace.contains("func6"));
+ Expect.isFalse(trace.contains("main"));
+
+ print(s);
+
+ print("Full stack trace");
+ print(full_trace);
+
+ print("Stack trace");
+ print(trace);
+ }
+}
+int func4() {
+ func3();
+ return 1;
+}
+int func5() {
+ func4();
+ return 1;
+}
+int func6() {
+ func5();
+ return 1;
+}
+main() {
+ var i = func6();
+ Expect.equals(1, i);
+}
diff --git a/tests/language/full_stacktrace2_test.dart b/tests/language/full_stacktrace2_test.dart
new file mode 100644
index 0000000..93625c9
--- /dev/null
+++ b/tests/language/full_stacktrace2_test.dart
@@ -0,0 +1,97 @@
+void func1() {
+ throw new Exception("Test peanut gallery request for Full stacktrace");
+}
+void func2() {
+ func1();
+}
+void func3() {
+ try {
+ func2();
+ } on Object catch(e, s) {
+ print(e);
+
+ var full_trace = s.fullStackTrace;
+ Expect.isTrue(full_trace.contains("func1"));
+ Expect.isTrue(full_trace.contains("func2"));
+ Expect.isTrue(full_trace.contains("func3"));
+ Expect.isTrue(full_trace.contains("func4"));
+ Expect.isTrue(full_trace.contains("func5"));
+ Expect.isTrue(full_trace.contains("func6"));
+ Expect.isTrue(full_trace.contains("func7"));
+ Expect.isTrue(full_trace.contains("main"));
+
+ var trace = s.stackTrace;
+ Expect.isTrue(trace.contains("func1"));
+ Expect.isTrue(trace.contains("func2"));
+ Expect.isTrue(trace.contains("func3"));
+
+ Expect.isFalse(trace.contains("func4"));
+ Expect.isFalse(trace.contains("func5"));
+ Expect.isFalse(trace.contains("func6"));
+ Expect.isFalse(trace.contains("func7"));
+ Expect.isFalse(trace.contains("main"));
+
+ print(s);
+
+ print("Full stack trace");
+ print(full_trace);
+
+ print("Stack trace");
+ print(trace);
+
+ throw; // This is a rethrow.
+ }
+}
+int func4() {
+ func3();
+ return 1;
+}
+int func5() {
+ try {
+ func4();
+ } on Object catch(e, s) {
+
+ var full_trace = s.fullStackTrace;
+ print(full_trace);
+ Expect.isTrue(full_trace.contains("func1"));
+ Expect.isTrue(full_trace.contains("func2"));
+ Expect.isTrue(full_trace.contains("func3"));
+ Expect.isTrue(full_trace.contains("func4"));
+ Expect.isTrue(full_trace.contains("func5"));
+ Expect.isTrue(full_trace.contains("func6"));
+ Expect.isTrue(full_trace.contains("func7"));
+ Expect.isTrue(full_trace.contains("main"));
+
+ var trace = s.stackTrace;
+ Expect.isTrue(trace.contains("func1"));
+ Expect.isTrue(trace.contains("func2"));
+ Expect.isTrue(trace.contains("func3"));
+ Expect.isTrue(trace.contains("func4"));
+ Expect.isTrue(trace.contains("func5"));
+
+ Expect.isFalse(trace.contains("func6"));
+ Expect.isFalse(trace.contains("func7"));
+ Expect.isFalse(trace.contains("main"));
+
+ print(s);
+
+ print("Full stack trace");
+ print(full_trace);
+
+ print("Stack trace");
+ print(trace);
+ }
+ return 1;
+}
+int func6() {
+ func5();
+ return 1;
+}
+int func7() {
+ func6();
+ return 1;
+}
+main() {
+ var i = func7();
+ Expect.equals(1, i);
+}
diff --git a/tests/language/full_stacktrace3_test.dart b/tests/language/full_stacktrace3_test.dart
new file mode 100644
index 0000000..64abc93
--- /dev/null
+++ b/tests/language/full_stacktrace3_test.dart
@@ -0,0 +1,94 @@
+void func1() {
+ throw new Exception("Test peanut gallery request for Full stacktrace");
+}
+void func2() {
+ func1();
+}
+void func3() {
+ try {
+ func2();
+ } on Object catch(e, s) {
+ print(e);
+ var full_trace = s.fullStackTrace;
+ Expect.isTrue(full_trace.contains("func1"));
+ Expect.isTrue(full_trace.contains("func2"));
+ Expect.isTrue(full_trace.contains("func3"));
+ Expect.isTrue(full_trace.contains("func4"));
+ Expect.isTrue(full_trace.contains("func5"));
+ Expect.isTrue(full_trace.contains("func6"));
+ Expect.isTrue(full_trace.contains("func7"));
+ Expect.isTrue(full_trace.contains("main"));
+
+ var trace = s.stackTrace;
+ Expect.isTrue(trace.contains("func1"));
+ Expect.isTrue(trace.contains("func2"));
+ Expect.isTrue(trace.contains("func3"));
+
+ Expect.isFalse(trace.contains("func4"));
+ Expect.isFalse(trace.contains("func5"));
+ Expect.isFalse(trace.contains("func6"));
+ Expect.isFalse(trace.contains("func7"));
+ Expect.isFalse(trace.contains("main"));
+
+ print(s);
+
+ print("Full stack trace");
+ print(full_trace);
+
+ print("Stack trace");
+ print(trace);
+ throw new Exception("This is not a rethrow");
+ }
+}
+int func4() {
+ func3();
+ return 1;
+}
+int func5() {
+ try {
+ func4();
+ } on Object catch(e, s) {
+ var full_trace = s.fullStackTrace;
+ Expect.isFalse(full_trace.contains("func1"));
+ Expect.isFalse(full_trace.contains("func2"));
+ Expect.isTrue(full_trace.contains("func3"));
+ Expect.isTrue(full_trace.contains("func4"));
+ Expect.isTrue(full_trace.contains("func5"));
+ Expect.isTrue(full_trace.contains("func6"));
+ Expect.isTrue(full_trace.contains("func7"));
+ Expect.isTrue(full_trace.contains("main"));
+
+ var trace = s.stackTrace;
+ Expect.isFalse(trace.contains("func1"));
+ Expect.isFalse(trace.contains("func2"));
+
+ Expect.isTrue(trace.contains("func3"));
+ Expect.isTrue(trace.contains("func4"));
+ Expect.isTrue(trace.contains("func5"));
+
+ Expect.isFalse(trace.contains("func6"));
+ Expect.isFalse(trace.contains("func7"));
+ Expect.isFalse(trace.contains("main"));
+
+ print(s);
+
+ print("Full stack trace");
+ print(full_trace);
+
+ print("Stack trace");
+ print(trace);
+ }
+ return 1;
+}
+int func6() {
+ func5();
+ return 1;
+}
+int func7() {
+ func6();
+ return 1;
+}
+main() {
+ var i = func7();
+ Expect.equals(1, i);
+}
diff --git a/tests/language/gc_test.dart b/tests/language/gc_test.dart
index 9ae29a2..b64a4e3 100644
--- a/tests/language/gc_test.dart
+++ b/tests/language/gc_test.dart
@@ -7,12 +7,12 @@
main() {
var div;
for (int i = 0; i < 200; ++i) {
- List l = new List.fixedLength(1000000);
+ List l = new List(1000000);
var m = 2;
div = (_) {
var b = l; // Was causing OutOfMemory.
};
- var lSmall = new List.fixedLength(3);
+ var lSmall = new List(3);
// Circular reference between new and old gen objects.
lSmall[0] = l;
l[0] = lSmall;
diff --git a/tests/language/generic2_test.dart b/tests/language/generic2_test.dart
new file mode 100644
index 0000000..9048978
--- /dev/null
+++ b/tests/language/generic2_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.
+
+// Test is-tests with type variables.
+
+class A<T> {
+ foo(o) => o is T;
+}
+
+class B {}
+
+class C extends A<int> {}
+
+main() {
+ Expect.isTrue(new A<Object>().foo(new B()));
+ Expect.isTrue(new A<Object>().foo(1));
+ Expect.isFalse(new A<int>().foo(new Object()));
+ Expect.isFalse(new A<int>().foo('hest'));
+ Expect.isTrue(new A<B>().foo(new B()));
+ Expect.isFalse(new A<B>().foo(new Object()));
+ Expect.isFalse(new A<B>().foo(1));
+ Expect.isTrue(new C().foo(1));
+ Expect.isFalse(new C().foo(new Object()));
+ Expect.isFalse(new C().foo('hest'));
+ Expect.isTrue(new A<List<int>>().foo(new List<int>()));
+ Expect.isFalse(new A<List<int>>().foo(new List<String>()));
+}
diff --git a/tests/language/generic_instanceof.dart b/tests/language/generic_instanceof.dart
index 5c65ec1..3f64976 100644
--- a/tests/language/generic_instanceof.dart
+++ b/tests/language/generic_instanceof.dart
@@ -37,91 +37,91 @@
}
{
Foo foo = new Foo();
- Expect.equals(true, foo.isT(new List.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<Object>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<num>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isT(new List(5)));
+ Expect.equals(true, foo.isT(new List<Object>(5)));
+ Expect.equals(true, foo.isT(new List<int>(5)));
+ Expect.equals(true, foo.isT(new List<num>(5)));
+ Expect.equals(true, foo.isT(new List<String>(5)));
}
{
Foo foo = new Foo<List>();
- Expect.equals(true, foo.isT(new List.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<Object>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<num>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isT(new List(5)));
+ Expect.equals(true, foo.isT(new List<Object>(5)));
+ Expect.equals(true, foo.isT(new List<int>(5)));
+ Expect.equals(true, foo.isT(new List<num>(5)));
+ Expect.equals(true, foo.isT(new List<String>(5)));
}
{
Foo foo = new Foo<List<Object>>();
- Expect.equals(true, foo.isT(new List.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<Object>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<num>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isT(new List(5)));
+ Expect.equals(true, foo.isT(new List<Object>(5)));
+ Expect.equals(true, foo.isT(new List<int>(5)));
+ Expect.equals(true, foo.isT(new List<num>(5)));
+ Expect.equals(true, foo.isT(new List<String>(5)));
}
{
Foo foo = new Foo<List<int>>();
- Expect.equals(true, foo.isT(new List.fixedLength(5)));
- Expect.equals(false, foo.isT(new List<Object>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
- Expect.equals(false, foo.isT(new List<num>.fixedLength(5)));
- Expect.equals(false, foo.isT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isT(new List(5)));
+ Expect.equals(false, foo.isT(new List<Object>(5)));
+ Expect.equals(true, foo.isT(new List<int>(5)));
+ Expect.equals(false, foo.isT(new List<num>(5)));
+ Expect.equals(false, foo.isT(new List<String>(5)));
}
{
Foo foo = new Foo<List<num>>();
- Expect.equals(true, foo.isT(new List.fixedLength(5)));
- Expect.equals(false, foo.isT(new List<Object>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<num>.fixedLength(5)));
- Expect.equals(false, foo.isT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isT(new List(5)));
+ Expect.equals(false, foo.isT(new List<Object>(5)));
+ Expect.equals(true, foo.isT(new List<int>(5)));
+ Expect.equals(true, foo.isT(new List<num>(5)));
+ Expect.equals(false, foo.isT(new List<String>(5)));
}
{
Foo foo = new Foo<List<String>>();
- Expect.equals(true, foo.isT(new List.fixedLength(5)));
- Expect.equals(false, foo.isT(new List<Object>.fixedLength(5)));
- Expect.equals(false, foo.isT(new List<int>.fixedLength(5)));
- Expect.equals(false, foo.isT(new List<num>.fixedLength(5)));
- Expect.equals(true, foo.isT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isT(new List(5)));
+ Expect.equals(false, foo.isT(new List<Object>(5)));
+ Expect.equals(false, foo.isT(new List<int>(5)));
+ Expect.equals(false, foo.isT(new List<num>(5)));
+ Expect.equals(true, foo.isT(new List<String>(5)));
}
{
Foo foo = new Foo();
- Expect.equals(true, foo.isListT(new List.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<Object>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<int>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<num>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isListT(new List(5)));
+ Expect.equals(true, foo.isListT(new List<Object>(5)));
+ Expect.equals(true, foo.isListT(new List<int>(5)));
+ Expect.equals(true, foo.isListT(new List<num>(5)));
+ Expect.equals(true, foo.isListT(new List<String>(5)));
}
{
Foo foo = new Foo<Object>();
- Expect.equals(true, foo.isListT(new List.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<Object>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<int>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<num>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isListT(new List(5)));
+ Expect.equals(true, foo.isListT(new List<Object>(5)));
+ Expect.equals(true, foo.isListT(new List<int>(5)));
+ Expect.equals(true, foo.isListT(new List<num>(5)));
+ Expect.equals(true, foo.isListT(new List<String>(5)));
}
{
Foo foo = new Foo<int>();
- Expect.equals(true, foo.isListT(new List.fixedLength(5)));
- Expect.equals(false, foo.isListT(new List<Object>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<int>.fixedLength(5)));
- Expect.equals(false, foo.isListT(new List<num>.fixedLength(5)));
- Expect.equals(false, foo.isListT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isListT(new List(5)));
+ Expect.equals(false, foo.isListT(new List<Object>(5)));
+ Expect.equals(true, foo.isListT(new List<int>(5)));
+ Expect.equals(false, foo.isListT(new List<num>(5)));
+ Expect.equals(false, foo.isListT(new List<String>(5)));
}
{
Foo foo = new Foo<num>();
- Expect.equals(true, foo.isListT(new List.fixedLength(5)));
- Expect.equals(false, foo.isListT(new List<Object>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<int>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<num>.fixedLength(5)));
- Expect.equals(false, foo.isListT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isListT(new List(5)));
+ Expect.equals(false, foo.isListT(new List<Object>(5)));
+ Expect.equals(true, foo.isListT(new List<int>(5)));
+ Expect.equals(true, foo.isListT(new List<num>(5)));
+ Expect.equals(false, foo.isListT(new List<String>(5)));
}
{
Foo foo = new Foo<String>();
- Expect.equals(true, foo.isListT(new List.fixedLength(5)));
- Expect.equals(false, foo.isListT(new List<Object>.fixedLength(5)));
- Expect.equals(false, foo.isListT(new List<int>.fixedLength(5)));
- Expect.equals(false, foo.isListT(new List<num>.fixedLength(5)));
- Expect.equals(true, foo.isListT(new List<String>.fixedLength(5)));
+ Expect.equals(true, foo.isListT(new List(5)));
+ Expect.equals(false, foo.isListT(new List<Object>(5)));
+ Expect.equals(false, foo.isListT(new List<int>(5)));
+ Expect.equals(false, foo.isListT(new List<num>(5)));
+ Expect.equals(true, foo.isListT(new List<String>(5)));
}
}
}
diff --git a/tests/language/generic_native_test.dart b/tests/language/generic_native_test.dart
new file mode 100644
index 0000000..53e4c78
--- /dev/null
+++ b/tests/language/generic_native_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test is-tests with type variables on native subclasses.
+
+class A<T> {
+ foo(o) => o is T;
+}
+
+class B {}
+
+class C {}
+
+main() {
+ Expect.isTrue(new A<Iterable<B>>().foo(new List<B>()));
+ Expect.isFalse(new A<Iterable<C>>().foo(new List<B>()));
+
+ Expect.isTrue(new A<Collection<B>>().foo(new List<B>()));
+ Expect.isFalse(new A<Collection<C>>().foo(new List<B>()));
+
+ Expect.isTrue(new A<Pattern>().foo('hest'));
+
+ Expect.isTrue(new A<Comparable<String>>().foo('hest'));
+ Expect.isFalse(new A<Comparable<C>>().foo('hest'));
+}
diff --git a/tests/language/generics3_test.dart b/tests/language/generics3_test.dart
new file mode 100644
index 0000000..cbc2271
--- /dev/null
+++ b/tests/language/generics3_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program testing generic type allocations and generic type tests.
+// Regression test for issue 8710.
+
+class C1<T> {}
+class C2<T> {}
+class C3<T> extends C2<C1<T>> {}
+class C4<T> extends C3<T> { f() => new C5<C1<T>>(new C1<T>()); }
+class C5<T> { C5(T x); } // Checked mode: x must be of type C1<String>.
+
+main() {
+ new C4<String>().f();
+}
diff --git a/tests/language/incr_op_test.dart b/tests/language/incr_op_test.dart
index 32730bd..be772e7 100644
--- a/tests/language/incr_op_test.dart
+++ b/tests/language/incr_op_test.dart
@@ -60,7 +60,7 @@
Expect.equals(57, IncrOpTest.y);
Expect.equals(56, --IncrOpTest.y);
- var list = new List.fixedLength(4);
+ var list = new List(4);
for (int i = 0; i < list.length; i++) {
list[i] = i;
}
diff --git a/tests/language/index_test.dart b/tests/language/index_test.dart
index 3462e4e..9e1c634 100644
--- a/tests/language/index_test.dart
+++ b/tests/language/index_test.dart
@@ -18,7 +18,7 @@
static const ID_IDLE = 0;
static testMain() {
- var a = new List.fixedLength(10);
+ var a = new List(10);
Expect.equals(10, a.length);
for (int i = 0; i < a.length; i++) {
a[i] = Helper.fibonacci(i);
diff --git a/tests/language/inst_field_initializer1_negative_test.dart b/tests/language/inst_field_initializer1_negative_test.dart
index 1c56eb0..44fcca1 100644
--- a/tests/language/inst_field_initializer1_negative_test.dart
+++ b/tests/language/inst_field_initializer1_negative_test.dart
@@ -7,7 +7,7 @@
class A {
A() {}
int x = 5;
- int arr = new List.fixedLength(x); // Illegal access to 'this'.
+ int arr = new List(x); // Illegal access to 'this'.
// Also not a compile const expression.
}
diff --git a/tests/language/instance_inline_test.dart b/tests/language/instance_inline_test.dart
index e45dde2..fefdf21 100644
--- a/tests/language/instance_inline_test.dart
+++ b/tests/language/instance_inline_test.dart
@@ -15,7 +15,7 @@
int nextByte() => charAt(++byteOffset);
int charAt(index)
- => (string.length > index) ? string.charCodeAt(index) : -1;
+ => (string.length > index) ? string.codeUnitAt(index) : -1;
}
void main() {
@@ -24,4 +24,4 @@
Expect.equals(0x7A, scanner.nextByte()); // Expect z.
Expect.equals(0x39, scanner.nextByte()); // Expect 9.
Expect.equals(-1, scanner.nextByte());
-}
\ No newline at end of file
+}
diff --git a/tests/language/instanceof2_test.dart b/tests/language/instanceof2_test.dart
index 0655b86..f93c0b3 100644
--- a/tests/language/instanceof2_test.dart
+++ b/tests/language/instanceof2_test.dart
@@ -54,7 +54,7 @@
Expect.equals(false, null is I);
{
- var a = new List.fixedLength(5);
+ var a = new List(5);
Expect.equals(true, a is List);
Expect.equals(true, a is List<Object>);
Expect.equals(true, a is List<int>);
@@ -62,7 +62,7 @@
Expect.equals(true, a is List<String>);
}
{
- var a = new List<Object>.fixedLength(5);
+ var a = new List<Object>(5);
Expect.equals(true, a is List);
Expect.equals(true, a is List<Object>);
Expect.equals(false, a is List<int>);
@@ -70,7 +70,7 @@
Expect.equals(false, a is List<String>);
}
{
- var a = new List<int>.fixedLength(5);
+ var a = new List<int>(5);
Expect.equals(true, a is List);
Expect.equals(true, a is List<Object>);
Expect.equals(true, a is List<int>);
@@ -78,7 +78,7 @@
Expect.equals(false, a is List<String>);
}
{
- var a = new List<num>.fixedLength(5);
+ var a = new List<num>(5);
Expect.equals(true, a is List);
Expect.equals(true, a is List<Object>);
Expect.equals(false, a is List<int>);
@@ -86,7 +86,7 @@
Expect.equals(false, a is List<String>);
}
{
- var a = new List<String>.fixedLength(5);
+ var a = new List<String>(5);
Expect.equals(true, a is List);
Expect.equals(true, a is List<Object>);
Expect.equals(false, a is List<int>);
diff --git a/tests/language/interceptor6_test.dart b/tests/language/interceptor6_test.dart
new file mode 100644
index 0000000..35f4bd3
--- /dev/null
+++ b/tests/language/interceptor6_test.dart
@@ -0,0 +1,10 @@
+// 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.
+
+// Check that an intercepted call on a method that does not exist does
+// not crash the compiler.
+
+main() {
+ Expect.throws(() => 42.clamp(), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/interceptor_test.dart b/tests/language/interceptor_test.dart
index e79f759..2fe247e 100644
--- a/tests/language/interceptor_test.dart
+++ b/tests/language/interceptor_test.dart
@@ -6,28 +6,28 @@
// JavaScript primitives) in dart2js work.
class A {
- charCodeAt(a) => a;
+ codeUnitAt(a) => a;
}
main() {
var res = [[], 1, 'foo', new A()];
- Expect.throws(() => res[0].charCodeAt(1));
- Expect.throws(() => (res[0].charCodeAt)(1));
+ Expect.throws(() => res[0].codeUnitAt(1));
+ Expect.throws(() => (res[0].codeUnitAt)(1));
- Expect.throws(() => res[1].charCodeAt(1));
- Expect.throws(() => (res[1].charCodeAt)(1));
+ Expect.throws(() => res[1].codeUnitAt(1));
+ Expect.throws(() => (res[1].codeUnitAt)(1));
- Expect.equals(111, res[2].charCodeAt(1));
- Expect.equals(111, (res[2].charCodeAt)(1));
- Expect.throws(() => res[2].charCodeAt(1, 4));
- Expect.throws(() => res[2].charCodeAt());
- Expect.throws(() => (res[2].charCodeAt)(1, 4));
- Expect.throws(() => (res[2].charCodeAt)());
+ Expect.equals(111, res[2].codeUnitAt(1));
+ Expect.equals(111, (res[2].codeUnitAt)(1));
+ Expect.throws(() => res[2].codeUnitAt(1, 4));
+ Expect.throws(() => res[2].codeUnitAt());
+ Expect.throws(() => (res[2].codeUnitAt)(1, 4));
+ Expect.throws(() => (res[2].codeUnitAt)());
- Expect.equals(1, res[3].charCodeAt(1));
- Expect.equals(1, (res[3].charCodeAt)(1));
- Expect.throws(() => res[3].charCodeAt(1, 4));
- Expect.throws(() => res[3].charCodeAt());
- Expect.throws(() => (res[3].charCodeAt)(1, 4));
- Expect.throws(() => (res[3].charCodeAt)());
+ Expect.equals(1, res[3].codeUnitAt(1));
+ Expect.equals(1, (res[3].codeUnitAt)(1));
+ Expect.throws(() => res[3].codeUnitAt(1, 4));
+ Expect.throws(() => res[3].codeUnitAt());
+ Expect.throws(() => (res[3].codeUnitAt)(1, 4));
+ Expect.throws(() => (res[3].codeUnitAt)());
}
diff --git a/tests/language/invocation_mirror_invoke_on2_test.dart b/tests/language/invocation_mirror_invoke_on2_test.dart
index b8bec8a..0e4deac 100644
--- a/tests/language/invocation_mirror_invoke_on2_test.dart
+++ b/tests/language/invocation_mirror_invoke_on2_test.dart
@@ -48,7 +48,7 @@
var string = "funky";
var proxy = new Proxy(string);
- Expect.equals(string.charCodeAt(0), proxy.charCodeAt(0));
+ Expect.equals(string.codeUnitAt(0), proxy.codeUnitAt(0));
Expect.equals(string.length, proxy.length);
Expect.throws(() => proxy.funky(), (e) => e is NoSuchMethodError);
diff --git a/tests/language/language.status b/tests/language/language.status
index 10d2a54..cf89e4a7 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -61,10 +61,11 @@
mixin_illegal_syntax_test/none: Fail
mixin_type_parameters_mixin_test: Fail
mixin_type_parameters_super_test: Fail
-mixin_type_parameters_mixin_extends_test: Fail
mixin_type_parameters_super_extends_test: Fail
mixin_lib_extends_field_test: Fail
+type_variable_field_initializer_closure_test: Crash # issue 8847
+
[ $compiler == none && ($system == macos || $system == linux) && $arch == ia32 && $checked ]
gc_test: Skip # Issue 1487, flaky.
@@ -291,6 +292,8 @@
# test issue 8127 (using mixin application as mixin)
mixin_mixin_test: Fail
+# test issue 8801
+super_operator_index_test/04: Fail
#
# Add new dartc annotations above in alphabetical order
@@ -302,6 +305,7 @@
[ $compiler == none && $runtime == drt ]
+type_variable_field_initializer_closure_test: Fail # issue 8847
final_variable_assignment_test/01: Fail
final_variable_assignment_test/02: Fail
final_variable_assignment_test/03: Fail
@@ -358,7 +362,6 @@
mixin_illegal_constructor_test/none: Fail # VM issue
mixin_type_parameters_mixin_test: Fail # VM issue
mixin_type_parameters_super_test: Fail # VM issue
-mixin_type_parameters_mixin_extends_test: Fail # VM issue
mixin_type_parameters_super_extends_test: Fail # VM issue
# Malformed types not handled as unresolved:
@@ -540,6 +543,8 @@
type_error_test: Fail, OK # VM bug: http://dartbug.com/5280
type_parameter_literal_test: Fail
+type_variable_field_initializer_closure_test: Crash # VM bug: issue 8847
+
[ $compiler == dart2dart && $minified ]
# TODO(tball): Assign proper bug numbers.
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 332f08d..ccd4b5c 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -26,12 +26,21 @@
class_literal_test/27: Fail # Class literals are expression now; delete this test.
class_literal_test/28: Fail # Class literals are expression now; delete this test.
class_literal_test/29: Fail # Class literals are expression now; delete this test.
+full_stacktrace1_test: Skip # Stack trace interface is not implemented yet.
+full_stacktrace2_test: Skip # Stack trace interface is not implemented yet.
+full_stacktrace3_test: Skip # Stack trace interface is not implemented yet.
+stacktrace_test: Skip # Stack trace interface is not implemented yet.
# VM specific tests that should not be run by dart2js.
*vm_test: Skip
*vm_negative_test: Skip
[ $compiler == dart2js && $checked ]
+mixin_type_parameters_super_extends_test: Fail # http://dartbug.com/8116
+mixin_type_parameters_super_test: Fail # http://dartbug.com/8116
+mixin_type_parameters_mixin_extends_test: Fail # http://dartbug.com/8116
+mixin_type_parameters_mixin_test: Fail # http://dartbug.com/8116
+
prefix16_test: Fail # dartbug.com/7354
default_factory2_test/01: Pass # For the wrong reasons.
type_variable_scope_test/none: Fail
@@ -88,6 +97,7 @@
compile_time_constant_checked3_test/06: Fail, OK
[ $compiler == dart2js ]
+type_variable_field_initializer_closure_test: Fail # Issue 8848
branch_canonicalization_test: Fail # Issue 638.
div_with_power_of_two_test: Fail # Issue 8301.
call_operator_test: Fail # Issue 7622.
@@ -164,7 +174,6 @@
function_type_alias_test: Fail # cannot resolve type Fun
function_type_parameter2_test: Fail # Internal Error: expected optional parameters
function_type_parameter_test: Fail # Internal Error: expected optional parameters
-generic_instanceof_test: Fail # cannot resolve type T
generic_test: Fail # cannot resolve type T
get_set_syntax_test/00: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
get_set_syntax_test/01: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
@@ -180,7 +189,6 @@
get_set_syntax_test/15: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
get_set_syntax_test/16: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
implicit_scope_test: Fail # duplicate definition of a="bar"
-many_generic_instanceof_test: Fail # cannot resolve type T
method_binding_test: Fail # internal error: super property read not implemented.
method_override_test: Fail # cannot resolve type GetKeysFunctionType
method_override2_test/00: Fail # accepts illegal override
@@ -200,13 +208,6 @@
on_catch_malformed_type_test: Fail # Malformed types cause compile-time errors.
-# Failing tests for mixin type parameters.
-mixin_type_parameters_mixin_test: Fail # http://dartbug.com/8116
-mixin_type_parameters_super_test: Fail # http://dartbug.com/8116
-mixin_type_parameters_mixin_extends_test: Fail # http://dartbug.com/8116
-mixin_type_parameters_super_extends_test: Fail # http://dartbug.com/8116
-
-
# External tests.
external_test/01: Fail
external_test/02: Fail
@@ -314,7 +315,6 @@
optimization_test: Fail, OK # Expects negative results of bit-operations.
expect_test: Fail, OK # JavaScript canonicalizes all strings. This test assumes that string-concatenation returns a new string.
-reg_exp3_test: Fail, OK # Expects exception from const constructor.
# Partially implemented redirecting constructors makes this throw instead
# of failing.
@@ -322,6 +322,8 @@
assign_top_method_test: Fail
+super_operator_index2_test: Fail # Issue 8800
+super_operator_index_test/01: Fail # Issue 8800
[ $compiler == dart2js && $runtime == none ]
*: Fail, Pass # TODO(ahe): Triage these tests.
@@ -346,8 +348,6 @@
[ $compiler == dart2js && $runtime == safari ]
execute_finally8_test: Fail # Issue: 7414
execute_finally9_test: Fail # Issue: 7414
-null_access_error_test: Fail # Issue: 7414
-closure3_test: Fail # Uncaught error: Instance of 'TypeError'
null_pointer_exception_test: Fail # Uncaught error: Instance of 'TypeError'
string_interpolate_npe_test: Fail # Uncaught error: Instance of 'TypeError'
arithmetic_test: Fail # Issue: 7414
diff --git a/tests/language/list_test.dart b/tests/language/list_test.dart
index a94b14b..1a9986f 100644
--- a/tests/language/list_test.dart
+++ b/tests/language/list_test.dart
@@ -5,7 +5,7 @@
class ListTest {
static void TestIterator() {
- List<int> a = new List<int>.fixedLength(10);
+ List<int> a = new List<int>(10);
int count = 0;
// Basic iteration over ObjectList.
@@ -42,7 +42,7 @@
static void testMain() {
int len = 10;
- List a = new List.fixedLength(len);
+ List a = new List(len);
Expect.equals(true, a is List);
Expect.equals(len, a.length);
a.forEach((element) { Expect.equals(null, element); });
@@ -51,17 +51,17 @@
Expect.throws(() => a[len], (e) => e is RangeError);
Expect.throws(() {
- List a = new List.fixedLength(4);
+ List a = new List(4);
a.setRange(1, 1, a, null);
});
Expect.throws(() {
- List a = new List.fixedLength(4);
+ List a = new List(4);
a.setRange(10, 1, a, 1);
}, (e) => e is RangeError);
- a = new List.fixedLength(4);
- List b = new List.fixedLength(4);
+ a = new List(4);
+ List b = new List(4);
b.setRange(0, 4, a, 0);
List<int> unsorted = [4, 3, 9, 12, -4, 9];
@@ -95,8 +95,8 @@
Expect.throws(() => unsorted[2.1],
(e) => e is ArgumentError || e is TypeError);
- Expect.throws(() => new List.fixedLength(-1));
- Expect.throws(() => new List.fixedLength(99999999999999999999999));
+ Expect.throws(() => new List(-1));
+ Expect.throws(() => new List(99999999999999999999999));
List list = new List();
// We cannot write just 'list.removeLast' due to issue 3769.
diff --git a/tests/language/local_function_test.dart b/tests/language/local_function_test.dart
index 82f5fc2..104319f 100644
--- a/tests/language/local_function_test.dart
+++ b/tests/language/local_function_test.dart
@@ -16,8 +16,8 @@
}
static int h(int n) {
k(int n) {
- var a = new List.fixedLength(n);
- var b = new List.fixedLength(n);
+ var a = new List(n);
+ var b = new List(n);
int i;
for (i = 0; i < n; i++) {
var j = i;
@@ -36,8 +36,8 @@
}
static int h2(int n) {
k(int n) {
- var a = new List.fixedLength(n);
- var b = new List.fixedLength(n);
+ var a = new List(n);
+ var b = new List(n);
for (int i = 0; i < n; i++) {
var j = i;
a[i] = () => i; // Captured i varies from 0 to n-1.
@@ -94,7 +94,7 @@
f();
}
static testNesting(int n) {
- var a = new List.fixedLength(n*n);
+ var a = new List(n*n);
f0() {
for (int i = 0; i < n; i++) {
int vi = i;
diff --git a/tests/language/many_calls_test.dart b/tests/language/many_calls_test.dart
index a8db476..c59b90f 100644
--- a/tests/language/many_calls_test.dart
+++ b/tests/language/many_calls_test.dart
@@ -53,7 +53,7 @@
class ManyCallsTest {
static testMain() {
- var list = new List.fixedLength(10);
+ var list = new List(10);
for (int i = 0; i < (list.length ~/ 2) ; i++) {
list[i] = new A();
}
diff --git a/tests/language/null_hashcode_optimized_vm_test.dart b/tests/language/null_hashcode_optimized_vm_test.dart
new file mode 100644
index 0000000..27906ca
--- /dev/null
+++ b/tests/language/null_hashcode_optimized_vm_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test that optimized Object.hashCode works for the null receiver.
+// VMOptions=--optimization_counter_threshold=100
+
+main() {
+ for (int i = 0; i < 200; i++) {
+ foo(null);
+ }
+}
+
+foo(a) => a.hashCode;
diff --git a/tests/language/optimization_test.dart b/tests/language/optimization_test.dart
index be41f4f..c399754 100644
--- a/tests/language/optimization_test.dart
+++ b/tests/language/optimization_test.dart
@@ -63,7 +63,7 @@
// Deoptimize because of overflow.
var minInt = -(1 << 30);
Expect.equals(minInt, doNeg(doNeg(minInt)));
-
+
for (int i = 0; i < 1000; i++) {
Expect.equals(false, doNot(true));
Expect.equals(true, doNot(doNot(true)));
@@ -79,7 +79,7 @@
// Deoptimize.
Expect.equals(-5, doNeg2(5));
- var fixed = new List.fixedLength(10);
+ var fixed = new List(10);
var growable = [1, 2, 3, 4, 5];
for (int i = 0; i < 2000; i++) {
diff --git a/tests/language/optimized_constant_array_string_access_test.dart b/tests/language/optimized_constant_array_string_access_test.dart
index 2e0b1ba..391d971 100644
--- a/tests/language/optimized_constant_array_string_access_test.dart
+++ b/tests/language/optimized_constant_array_string_access_test.dart
@@ -4,10 +4,10 @@
// Test optimized constant string and constant array access.
-int testConstantStringAndIndexCharCodeAt() {
+int testConstantStringAndIndexCodeUnitAt() {
int test(b) {
- if (b) return "hest".charCodeAt(400);
- return "hest".charCodeAt(2);
+ if (b) return "hest".codeUnitAt(400);
+ return "hest".codeUnitAt(2);
}
Expect.throws(() => test(true));
@@ -43,7 +43,7 @@
main() {
- testConstantStringAndIndexCharCodeAt();
+ testConstantStringAndIndexCodeUnitAt();
testConstantArrayAndIndexAt();
testNonSmiIndex();
}
diff --git a/tests/language/optimized_lists_test.dart b/tests/language/optimized_lists_test.dart
index cd2a596..cc3b862 100644
--- a/tests/language/optimized_lists_test.dart
+++ b/tests/language/optimized_lists_test.dart
@@ -13,7 +13,7 @@
test(n) {
var a = new List(); // Growable list.
- var b = new List.fixedLength(10); // Fixed size list.
+ var b = new List(10); // Fixed size list.
var c = const [1, 2, 3, 4]; // Constant aray.
// In optimized mode the class checks will be eliminated since the
// constructors above provide information about exact types.
diff --git a/tests/language/optimized_string_charcodeat_test.dart b/tests/language/optimized_string_charcodeat_test.dart
index aa2bd64..e4747f2 100644
--- a/tests/language/optimized_string_charcodeat_test.dart
+++ b/tests/language/optimized_string_charcodeat_test.dart
@@ -2,60 +2,60 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// Test optimized charCodeAt and array access.
+// Test optimized CodeUnitAt and array access.
String one_byte = "hest";
String two_byte = "høns";
-int testOneByteCharCodeAt(String x, int j) {
+int testOneByteCodeUnitAt(String x, int j) {
int test() {
- return x.charCodeAt(j);
+ return x.codeUnitAt(j);
}
for (int i = 0; i < 10000; i++) test();
return test();
}
-int testTwoByteCharCodeAt(String x, int j) {
+int testTwoByteCodeUnitAt(String x, int j) {
int test() {
- return x.charCodeAt(j);
+ return x.codeUnitAt(j);
}
for (int i = 0; i < 10000; i++) test();
return test();
}
-int testConstantStringCharCodeAt(int j) {
+int testConstantStringCodeUnitAt(int j) {
int test() {
- return "høns".charCodeAt(j);
+ return "høns".codeUnitAt(j);
}
for (int i = 0; i < 10000; i++) test();
return test();
}
-int testConstantIndexCharCodeAt(String x) {
+int testConstantIndexCodeUnitAt(String x) {
int test() {
- return x.charCodeAt(1);
+ return x.codeUnitAt(1);
}
for (int i = 0; i < 10000; i++) test();
return test();
}
-int testOneByteCharCodeAtInLoop(var x) {
+int testOneByteCodeUnitAtInLoop(var x) {
var result = 0;
for (int i = 0; i < x.length; i++) {
- result += x.charCodeAt(i);
+ result += x.codeUnitAt(i);
}
return result;
}
-int testTwoByteCharCodeAtInLoop(var x) {
+int testTwoByteCodeUnitAtInLoop(var x) {
var result = 0;
for (int i = 0; i < x.length; i++) {
- result += x.charCodeAt(i);
+ result += x.codeUnitAt(i);
}
return result;
}
@@ -63,15 +63,15 @@
main() {
for (int j = 0; j < 10; j++) {
- Expect.equals(101, testOneByteCharCodeAt(one_byte, 1));
- Expect.equals(248, testTwoByteCharCodeAt(two_byte, 1));
- Expect.equals(248, testConstantStringCharCodeAt(1));
- Expect.equals(101, testConstantIndexCharCodeAt(one_byte));
+ Expect.equals(101, testOneByteCodeUnitAt(one_byte, 1));
+ Expect.equals(248, testTwoByteCodeUnitAt(two_byte, 1));
+ Expect.equals(248, testConstantStringCodeUnitAt(1));
+ Expect.equals(101, testConstantIndexCodeUnitAt(one_byte));
}
for (int j = 0; j < 2000; j++) {
- Expect.equals(436, testOneByteCharCodeAtInLoop(one_byte));
- Expect.equals(577, testTwoByteCharCodeAtInLoop(two_byte));
+ Expect.equals(436, testOneByteCodeUnitAtInLoop(one_byte));
+ Expect.equals(577, testTwoByteCodeUnitAtInLoop(two_byte));
}
- Expect.throws(() => testOneByteCharCodeAtInLoop(123));
- Expect.throws(() => testTwoByteCharCodeAtInLoop(123));
+ Expect.throws(() => testOneByteCodeUnitAtInLoop(123));
+ Expect.throws(() => testTwoByteCodeUnitAtInLoop(123));
}
diff --git a/tests/language/script_negative_test.dart b/tests/language/script_negative_test.dart
deleted file mode 100644
index 60c2f284..0000000
--- a/tests/language/script_negative_test.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Imported library does not start with a library tag.
-
-library ScriptNegativeTest.dart;
-import "script_negative_lib.dart";
-
-main() {
- print("Should not reach here.");
-}
diff --git a/tests/language/stacktrace_test.dart b/tests/language/stacktrace_test.dart
new file mode 100644
index 0000000..98e644e
--- /dev/null
+++ b/tests/language/stacktrace_test.dart
@@ -0,0 +1,15 @@
+
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that a stack trace is properly terminated (issue 8850).
+void main() {
+ var ex = new Exception("fail");
+ try {
+ throw ex;
+ } on Exception catch(e, st) {
+ Expect.equals(ex, e);
+ Expect.isTrue(st.toString().endsWith("\n"));
+ }
+}
diff --git a/tests/language/static_inline_test.dart b/tests/language/static_inline_test.dart
index 4c5ad9a..5163b3d 100644
--- a/tests/language/static_inline_test.dart
+++ b/tests/language/static_inline_test.dart
@@ -16,7 +16,7 @@
}
static int charAt(index)
- => (string.length > index) ? string.charCodeAt(index) : -1;
+ => (string.length > index) ? string.codeUnitAt(index) : -1;
}
void main() {
@@ -26,4 +26,4 @@
Expect.equals(0x7A, scanner.nextByte(false)); // Expect z.
Expect.equals(0x39, scanner.nextByte(false)); // Expect 9.
Expect.equals(-1, scanner.nextByte(false));
-}
\ No newline at end of file
+}
diff --git a/tests/language/store_to_load_forwarding_phis_vm_test.dart b/tests/language/store_to_load_forwarding_phis_vm_test.dart
new file mode 100644
index 0000000..13654a6
--- /dev/null
+++ b/tests/language/store_to_load_forwarding_phis_vm_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test correct handling of phis with only environment uses that were inserted
+// by store to load forwarding.
+// VMOptions=--optimization_counter_threshold=100
+
+library store_to_load_forwarding_phis_vm_test;
+
+import 'dart:async';
+
+class A {
+ var _foo;
+
+ get foo {
+ if (_foo == null) {
+ _foo = new A();
+ }
+ return _foo;
+ }
+}
+
+foo(obj) {
+ var a = obj.foo;
+ return new Future.immediate(null).then((val) { });
+}
+
+main() {
+ final obj = new A();
+ for (var i = 0; i < 200; i++) {
+ foo(obj);
+ }
+}
\ No newline at end of file
diff --git a/tests/language/string_escapes_test.dart b/tests/language/string_escapes_test.dart
index 20a7beb..6e80214 100644
--- a/tests/language/string_escapes_test.dart
+++ b/tests/language/string_escapes_test.dart
@@ -15,43 +15,43 @@
static testDelimited() {
String str = "Foo\u{1}Bar\u{000001}Baz\u{D7FF}Boo";
Expect.equals(15, str.length);
- Expect.equals(1, str.charCodeAt(3));
- Expect.equals(1, str.charCodeAt(7));
- Expect.equals(0xD7FF, str.charCodeAt(11));
- Expect.equals('B'.charCodeAt(0), str.charCodeAt(12));
+ Expect.equals(1, str.codeUnitAt(3));
+ Expect.equals(1, str.codeUnitAt(7));
+ Expect.equals(0xD7FF, str.codeUnitAt(11));
+ Expect.equals('B'.codeUnitAt(0), str.codeUnitAt(12));
}
static testEscapes() {
String str = "Foo\fBar\vBaz\bBoo";
Expect.equals(15, str.length);
- Expect.equals(12, str.charCodeAt(3));
- Expect.equals('B'.charCodeAt(0), str.charCodeAt(4));
- Expect.equals(11, str.charCodeAt(7));
- Expect.equals('z'.charCodeAt(0), str.charCodeAt(10));
- Expect.equals(8, str.charCodeAt(11));
- Expect.equals('o'.charCodeAt(0), str.charCodeAt(14));
+ Expect.equals(12, str.codeUnitAt(3));
+ Expect.equals('B'.codeUnitAt(0), str.codeUnitAt(4));
+ Expect.equals(11, str.codeUnitAt(7));
+ Expect.equals('z'.codeUnitAt(0), str.codeUnitAt(10));
+ Expect.equals(8, str.codeUnitAt(11));
+ Expect.equals('o'.codeUnitAt(0), str.codeUnitAt(14));
str = "Abc\rDef\nGhi\tJkl";
Expect.equals(15, str.length);
- Expect.equals(13, str.charCodeAt(3));
- Expect.equals('D'.charCodeAt(0), str.charCodeAt(4));
- Expect.equals(10, str.charCodeAt(7));
- Expect.equals('G'.charCodeAt(0), str.charCodeAt(8));
- Expect.equals(9, str.charCodeAt(11));
- Expect.equals('J'.charCodeAt(0), str.charCodeAt(12));
+ Expect.equals(13, str.codeUnitAt(3));
+ Expect.equals('D'.codeUnitAt(0), str.codeUnitAt(4));
+ Expect.equals(10, str.codeUnitAt(7));
+ Expect.equals('G'.codeUnitAt(0), str.codeUnitAt(8));
+ Expect.equals(9, str.codeUnitAt(11));
+ Expect.equals('J'.codeUnitAt(0), str.codeUnitAt(12));
}
static testFixed2() {
String str = "Foo\xFFBar";
Expect.equals(7, str.length);
- Expect.equals(255, str.charCodeAt(3));
- Expect.equals('B'.charCodeAt(0), str.charCodeAt(4));
+ Expect.equals(255, str.codeUnitAt(3));
+ Expect.equals('B'.codeUnitAt(0), str.codeUnitAt(4));
}
static testFixed4() {
String str = "Foo\u0001Bar";
Expect.equals(7, str.length);
- Expect.equals(1, str.charCodeAt(3));
- Expect.equals('B'.charCodeAt(0), str.charCodeAt(4));
+ Expect.equals(1, str.codeUnitAt(3));
+ Expect.equals('B'.codeUnitAt(0), str.codeUnitAt(4));
}
static testLiteral() {
diff --git a/tests/language/string_test.dart b/tests/language/string_test.dart
index 52cdf71..bbeb91c 100644
--- a/tests/language/string_test.dart
+++ b/tests/language/string_test.dart
@@ -16,12 +16,12 @@
String str = "string";
for (int i = 0; i < str.length; i++) {
Expect.equals(true, str[i] is String);
- Expect.equals(true, str.charCodeAt(i) is int);
+ Expect.equals(true, str.codeUnitAt(i) is int);
}
}
static testStringsJoin() {
- List<String> a = new List<String>.fixedLength(2);
+ List<String> a = new List<String>(2);
a[0] = "Hello";
a[1] = "World";
String s = a.join("*^*");
@@ -42,7 +42,7 @@
static testCharCodes() {
String s = new String.fromCharCodes(const [0x41, 0xC1, 0x424]);
Expect.equals("A", s[0]);
- Expect.equals(0x424, s.charCodeAt(2));
+ Expect.equals(0x424, s.codeUnitAt(2));
}
}
diff --git a/tests/language/super_operator_index2_test.dart b/tests/language/super_operator_index2_test.dart
new file mode 100644
index 0000000..47cf16d
--- /dev/null
+++ b/tests/language/super_operator_index2_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for super indexing operations.
+
+class A {
+ var map = new Map();
+ operator[]=(a, b) { map[a] = b; }
+ operator[](a) => map[a];
+}
+
+class B extends A {
+ foo() {
+ super[4] = 42;
+ Expect.equals(42, super[4]);
+ super[4] += 5;
+ Expect.equals(47, super[4]);
+ }
+}
+
+main() {
+ new B().foo();
+}
diff --git a/tests/language/super_operator_index_test.dart b/tests/language/super_operator_index_test.dart
new file mode 100644
index 0000000..36c6819
--- /dev/null
+++ b/tests/language/super_operator_index_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that we emit warnings for unresolved indexing operations on super.
+
+class A {
+ operator[]=(a, b) {}
+}
+
+class B extends A {
+ foo() {
+ super[4] = 42;
+ super[4] += 5; /// 01: static type warning, runtime error
+ return super[2]; /// 02: static type warning, runtime error
+ }
+}
+
+class C {
+ operator[](a) {}
+}
+
+class D extends C {
+ foo() {
+ super[4] = 42; /// 03: static type warning, runtime error
+ super[4] += 5; /// 04: static type warning, runtime error
+ return super[2];
+ }
+}
+
+class E {
+ foo() {
+ super[4] = 42; /// 05: static type warning, runtime error
+ super[4] += 5; /// 06: static type warning, runtime error
+ return super[2]; /// 07: static type warning, runtime error
+ }
+}
+
+main() {
+ new B().foo();
+ new D().foo();
+ new E().foo();
+}
diff --git a/tests/language/type_cast_vm_test.dart b/tests/language/type_cast_vm_test.dart
index fdf4cc9..22e3437 100644
--- a/tests/language/type_cast_vm_test.dart
+++ b/tests/language/type_cast_vm_test.dart
@@ -38,7 +38,7 @@
return 0;
}
try {
- var a = new List<int>.fixedLength(1) as List<int>;
+ var a = new List<int>(1) as List<int>;
a[0] = 0;
a[index()]++; // Type check succeeds, but does not create side effects.
Expect.equals(1, a[0]);
diff --git a/tests/language/type_variable_field_initializer_closure_test.dart b/tests/language/type_variable_field_initializer_closure_test.dart
new file mode 100644
index 0000000..e4da4a5
--- /dev/null
+++ b/tests/language/type_variable_field_initializer_closure_test.dart
@@ -0,0 +1,18 @@
+// 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.
+
+// Check that an inlined field closure has access to the enclosing
+// type variables.
+
+class A<T> {
+ var c = (() => new List<T>())();
+}
+
+class B<T> extends A<T> {
+}
+
+main() {
+ Expect.isTrue(new B<int>().c is List<int>);
+ Expect.isFalse(new B<String>().c is List<int>);
+}
diff --git a/tests/language/type_variable_field_initializer_test.dart b/tests/language/type_variable_field_initializer_test.dart
new file mode 100644
index 0000000..5519409
--- /dev/null
+++ b/tests/language/type_variable_field_initializer_test.dart
@@ -0,0 +1,18 @@
+// 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.
+
+// Check that an inlined field initializer has access to the enclosing
+// type variables.
+
+class A<T> {
+ var c = new List<T>();
+}
+
+class B<T> extends A<T> {
+}
+
+main() {
+ Expect.isTrue(new B<int>().c is List<int>);
+ Expect.isFalse(new B<String>().c is List<int>);
+}
diff --git a/tests/language/type_vm_test.dart b/tests/language/type_vm_test.dart
index 1b82769..7b525a1 100644
--- a/tests/language/type_vm_test.dart
+++ b/tests/language/type_vm_test.dart
@@ -34,7 +34,7 @@
return 0;
}
try {
- List<int> a = new List<int>.fixedLength(1);
+ List<int> a = new List<int>(1);
a[0] = 0;
a[index()]++; // Type check succeeds, but does not create side effects.
Expect.equals(1, a[0]);
@@ -377,7 +377,7 @@
static int testListAssigment() {
int result = 0;
{
- var a = new List.fixedLength(5);
+ var a = new List(5);
List a0 = a;
List<Object> ao = a;
List<int> ai = a;
@@ -385,7 +385,7 @@
List<String> as = a;
}
{
- var a = new List<Object>.fixedLength(5);
+ var a = new List<Object>(5);
List a0 = a;
List<Object> ao = a;
try {
@@ -438,7 +438,7 @@
}
}
{
- var a = new List<int>.fixedLength(5);
+ var a = new List<int>(5);
List a0 = a;
List<Object> ao = a;
List<int> ai = a;
@@ -461,7 +461,7 @@
}
}
{
- var a = new List<num>.fixedLength(5);
+ var a = new List<num>(5);
List a0 = a;
List<Object> ao = a;
try {
@@ -499,7 +499,7 @@
}
}
{
- var a = new List<String>.fixedLength(5);
+ var a = new List<String>(5);
List a0 = a;
List<Object> ao = a;
try {
diff --git a/tests/language/typed_message_test.dart b/tests/language/typed_message_test.dart
index bda9814..4c23387 100644
--- a/tests/language/typed_message_test.dart
+++ b/tests/language/typed_message_test.dart
@@ -26,7 +26,7 @@
main() {
SendPort remote = spawnFunction(logMessages);
- List<int> msg = new List<int>.fixedLength(5);
+ List<int> msg = new List<int>(5);
for (int i = 0; i < 5; i++) {
msg[i] = i;
}
diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart
index 43f083a..af4a5dd 100644
--- a/tests/lib/async/future_test.dart
+++ b/tests/lib/async/future_test.dart
@@ -53,8 +53,10 @@
testComplete() {
final completer = new Completer<int>();
final future = completer.future;
+ Expect.isFalse(completer.isCompleted);
completer.complete(3);
+ Expect.isTrue(completer.isCompleted);
future.then((v) => Expect.equals(3, v));
}
@@ -68,7 +70,10 @@
int value;
future.then((int v) { value = v; });
Expect.isNull(value);
+
+ Expect.isFalse(completer.isCompleted);
completer.complete(3);
+ Expect.isTrue(completer.isCompleted);
Expect.equals(3, value);
}
@@ -135,7 +140,10 @@
var ex2;
var done = future.catchError((e) { ex2 = e.error; });
+
+ Expect.isFalse(completer.isCompleted);
completer.completeError(ex);
+ Expect.isTrue(completer.isCompleted);
var port = new ReceivePort();
done.then((_) {
@@ -153,7 +161,9 @@
future.catchError((e) { });
future.catchError((e) { reached = true; }, test: (e) => false)
.catchError((e) {});
+ Expect.isFalse(completer.isCompleted);
completer.completeError(ex);
+ Expect.isTrue(completer.isCompleted);
Expect.isFalse(reached);
}
diff --git a/tests/lib/async/futures_test.dart b/tests/lib/async/futures_test.dart
index 4e9becf..e694134 100644
--- a/tests/lib/async/futures_test.dart
+++ b/tests/lib/async/futures_test.dart
@@ -111,12 +111,13 @@
futures.add(testWaitWithMultipleErrors());
futures.add(testForEachEmpty());
futures.add(testForEach());
+ futures.add(testForEachWithException());
// Use a receive port for blocking the test.
// Note that if the test fails, the program will not end.
ReceivePort port = new ReceivePort();
Future.wait(futures).then((List list) {
- Expect.equals(8, list.length);
+ Expect.equals(9, list.length);
port.close();
});
}
diff --git a/tests/lib/async/slow_consumer2_test.dart b/tests/lib/async/slow_consumer2_test.dart
index 0c637c0..a040256 100644
--- a/tests/lib/async/slow_consumer2_test.dart
+++ b/tests/lib/async/slow_consumer2_test.dart
@@ -75,7 +75,7 @@
listSize -= sentCount - targetCount;
sentCount = targetCount;
}
- controller.add(new List.fixedLength(listSize));
+ controller.add(new List(listSize));
int ms = listSize * 1000 ~/ bytesPerSecond;
Duration duration = new Duration(milliseconds: ms);
if (!controller.isPaused) new Timer(duration, send);
diff --git a/tests/lib/async/slow_consumer3_test.dart b/tests/lib/async/slow_consumer3_test.dart
index 24386ad..7f3794b 100644
--- a/tests/lib/async/slow_consumer3_test.dart
+++ b/tests/lib/async/slow_consumer3_test.dart
@@ -53,7 +53,7 @@
int chunks = bytesTotal ~/ chunkSize;
return new Stream.fromIterable(new Iterable.generate(chunks, (_) {
// This assumes one byte per entry. In practice it will be more.
- return new List<int>.fixedLength(chunkSize);
+ return new List<int>(chunkSize);
}));
}
diff --git a/tests/lib/async/slow_consumer_test.dart b/tests/lib/async/slow_consumer_test.dart
index 2d40658..9bc05bf 100644
--- a/tests/lib/async/slow_consumer_test.dart
+++ b/tests/lib/async/slow_consumer_test.dart
@@ -77,7 +77,7 @@
listSize -= sentCount - targetCount;
sentCount = targetCount;
}
- controller.add(new List.fixedLength(listSize));
+ controller.add(new List(listSize));
int ms = listSize * 1000 ~/ bytesPerSecond;
Duration duration = new Duration(milliseconds: ms);
if (!controller.isPaused) {
diff --git a/tests/lib/async/stream_controller_test.dart b/tests/lib/async/stream_controller_test.dart
index 8cfabf5..9593e96 100644
--- a/tests/lib/async/stream_controller_test.dart
+++ b/tests/lib/async/stream_controller_test.dart
@@ -392,8 +392,22 @@
Expect.listEquals(expectedEvents.events, actualEvents.events);
}
+testClosed() {
+ for (StreamController c in [new StreamController(),
+ new StreamController.broadcast()]) {
+ Expect.isFalse(c.isClosed);
+ c.add(42);
+ Expect.isFalse(c.isClosed);
+ c.signalError("bad");
+ Expect.isFalse(c.isClosed);
+ c.close();
+ Expect.isTrue(c.isClosed);
+ }
+}
+
main() {
testMultiController();
testSingleController();
testExtraMethods();
+ testClosed();
}
diff --git a/tests/lib/async/stream_state_helper.dart b/tests/lib/async/stream_state_helper.dart
new file mode 100644
index 0000000..86d71a1
--- /dev/null
+++ b/tests/lib/async/stream_state_helper.dart
@@ -0,0 +1,291 @@
+// 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 stream_state_helper;
+
+import "../../../pkg/unittest/lib/unittest.dart";
+import "dart:async";
+import "dart:collection";
+
+class StreamProtocolTest {
+ StreamController _controller;
+ StreamSubscription _subscription;
+ List<Event> _expectations = new List<Event>();
+ int _nextExpectationIndex = 0;
+ Function _onComplete;
+
+ StreamProtocolTest([bool broadcast = false]) {
+ if (broadcast) {
+ _controller = new StreamController.broadcast(
+ onPauseStateChange: _onPause,
+ onSubscriptionStateChange: _onSubcription);
+ // TODO(lrn): Make it work with multiple subscribers too.
+ } else {
+ _controller = new StreamController(
+ onPauseStateChange: _onPause,
+ onSubscriptionStateChange: _onSubcription);
+ }
+ _onComplete = expectAsync0((){
+ _onComplete = null; // Being null marks the test to be complete.
+ });
+ }
+
+ // Actions on the stream and controller.
+ void add(var data) { _controller.add(data); }
+ void error(var error) { _controller.signalError(error); }
+ void close() { _controller.close(); }
+
+ void subscribe({bool unsubscribeOnError : false}) {
+ // TODO(lrn): Handle more subscriptions (e.g., a subscription-id
+ // per subscription, and an id on event _expectations).
+ if (_subscription != null) throw new StateError("Already subscribed");
+ _subscription = _controller.stream.listen(_onData,
+ onError: _onError,
+ onDone: _onDone,
+ unsubscribeOnError:
+ unsubscribeOnError);
+ }
+
+ void pause([Future resumeSignal]) {
+ if (_subscription == null) throw new StateError("Not subscribed");
+ _subscription.pause(resumeSignal);
+ }
+
+ void resume([Future resumeSignal]) {
+ if (_subscription == null) throw new StateError("Not subscribed");
+ _subscription.resume();
+ }
+
+ void cancel() {
+ if (_subscription == null) throw new StateError("Not subscribed");
+ _subscription.cancel();
+ _subscription = null;
+ }
+
+ // Handling of stream events.
+ void _onData(var data) {
+ _withNextExpectation((Event expect) {
+ if (!expect.matchData(data)) {
+ _fail("Expected: $expect\n"
+ "Found : [Data: $data]");
+ }
+ });
+ }
+
+ void _onError(AsyncError error) {
+ _withNextExpectation((Event expect) {
+ if (!expect.matchError(error)) {
+ _fail("Expected: $expect\n"
+ "Found : [Data: ${error.error}]");
+ }
+ });
+ }
+
+ void _onDone() {
+ _subscription = null;
+ _withNextExpectation((Event expect) {
+ if (!expect.matchDone()) {
+ _fail("Expected: $expect\n"
+ "Found : [Done]");
+ }
+ });
+ }
+
+ void _onPause() {
+ _withNextExpectation((Event expect) {
+ if (!expect.matchPauseChange(_controller)) {
+ _fail("Expected: $expect\n"
+ "Found : [Paused:${_controller.isPaused}]");
+ }
+ });
+ }
+
+ void _onSubcription() {
+ _withNextExpectation((Event expect) {
+ if (!expect.matchSubscriptionChange(_controller)) {
+ _fail("Expected: $expect\n"
+ "Found: [Subscribed:${_controller.hasSubscribers}, "
+ "Paused:${_controller.isPaused}]");
+ }
+ });
+ }
+
+ void _withNextExpectation(void action(Event expect)) {
+ if (_nextExpectationIndex == _expectations.length) {
+ action(new MismatchEvent());
+ } else {
+ Event next = _expectations[_nextExpectationIndex++];
+ action(next);
+ }
+ _checkDone();
+ }
+
+ void _checkDone() {
+ if (_nextExpectationIndex == _expectations.length) {
+ _onComplete();
+ }
+ }
+
+
+ // Adds _expectations.
+ void expectAny([void action()]) {
+ if (_onComplete == null) {
+ _fail("Adding expectation after completing");
+ }
+ _expectations.add(new LogAnyEvent(action));
+ }
+ void expectData(var data, [void action()]) {
+ if (_onComplete == null) {
+ _fail("Adding expectation after completing");
+ }
+ _expectations.add(new DataEvent(data, action));
+ }
+ void expectError(var error, [void action()]) {
+ if (_onComplete == null) {
+ _fail("Adding expectation after completing");
+ }
+ _expectations.add(new ErrorEvent(error, action));
+ }
+ void expectDone([void action()]) {
+ if (_onComplete == null) {
+ _fail("Adding expectation after completing");
+ }
+ _expectations.add(new DoneEvent(action));
+ }
+ void expectPause(bool isPaused, [void action()]) {
+ if (_onComplete == null) {
+ _fail("Adding expectation after completing");
+ }
+ _expectations.add(new PauseCallbackEvent(isPaused, action));
+ }
+ void expectSubscription(bool hasSubscribers, bool isPaused, [void action()]) {
+ if (_onComplete == null) {
+ _fail("Adding expectation after completing");
+ }
+ _expectations.add(
+ new SubscriptionCallbackEvent(hasSubscribers, isPaused, action));
+ }
+
+ void _fail(String message) {
+ if (_nextExpectationIndex == 0) {
+ throw "Unexpected event:\n$message\nNo earlier events matched.";
+ }
+ throw "Unexpected event:\n$message\nMatched so far:\n"
+ " ${_expectations.take(_nextExpectationIndex).join("\n ")}";
+ }
+}
+
+class EventCollector {
+ final Queue<Event> events = new Queue<Event>();
+
+}
+
+class Event {
+ Function _action;
+ Event(void this._action());
+
+ bool matchData(var data) {
+ if (!_testData(data)) return false;
+ if (_action != null) _action();
+ return true;
+ }
+ bool matchError(AsyncError e) {
+ if (!_testError(e)) return false;
+ if (_action != null) _action();
+ return true;
+ }
+ bool matchDone() {
+ if (!_testDone()) return false;
+ if (_action != null) _action();
+ return true;
+ }
+ bool matchPauseChange(StreamController c) {
+ if (!_testPause(c)) return false;
+ if (_action != null) _action();
+ return true;
+ }
+ bool matchSubscriptionChange(StreamController c) {
+ if (!_testSubscribe(c)) return false;
+ if (_action != null) _action();
+ return true;
+ }
+
+ bool _testData(_) => false;
+ bool _testError(_) => false;
+ bool _testDone() => false;
+ bool _testPause(_) => false;
+ bool _testSubscribe(_) => false;
+}
+
+class MismatchEvent extends Event {
+ MismatchEvent() : super(null);
+ toString() => "[No event expected]";
+}
+
+class DataEvent extends Event {
+ final data;
+ DataEvent(this.data, void action()) : super(action);
+ bool _testData(var data) => this.data == data;
+ String toString() => "[Data: $data]";
+}
+
+class ErrorEvent extends Event {
+ final error;
+ ErrorEvent(this.error, void action()) : super(action);
+ bool _testError(AsyncError error) => this.error == error.error;
+ String toString() => "[Error: $error]";
+}
+
+class DoneEvent extends Event {
+ DoneEvent(void action()) : super(action);
+ bool _testDone() => true;
+ String toString() => "[Done]";
+}
+
+class PauseCallbackEvent extends Event {
+ final bool isPaused;
+ PauseCallbackEvent(this.isPaused, void action())
+ : super(action);
+ bool _testPause(StreamController c) => isPaused == c.isPaused;
+ String toString() => "[Paused:$isPaused]";
+}
+
+class SubscriptionCallbackEvent extends Event {
+ final bool hasSubscribers;
+ final bool isPaused;
+ SubscriptionCallbackEvent(this.hasSubscribers, this.isPaused, void action())
+ : super(action);
+ bool _testSubscribe(StreamController c) {
+ return hasSubscribers == c.hasSubscribers && isPaused == c.isPaused;
+ }
+ String toString() => "[Subscribers:$hasSubscribers, Paused:$isPaused]";
+}
+
+
+class LogAnyEvent extends Event {
+ String _actual = "*Not matched yet*";
+ LogAnyEvent(void action()) : super(action);
+ bool _testData(var data) {
+ _actual = "*[Data $data]";
+ return true;
+ }
+ bool _testError(AsyncError error) {
+ _actual = "*[Error ${error.error}]";
+ return true;
+ }
+ bool _testDone() {
+ _actual = "*[Done]";
+ return true;
+ }
+ bool _testPause(StreamController c) {
+ _actual = "*[Paused:${c.isPaused}]";
+ return true;
+ }
+ bool _testSubcribe(StreamController c) {
+ _actual = "*[Subscribers:${c.hasSubscribers}, Paused:${c.isPaused}]";
+ return true;
+ }
+
+ String toString() => _actual;
+}
diff --git a/tests/lib/async/stream_state_nonzero_timer_test.dart b/tests/lib/async/stream_state_nonzero_timer_test.dart
new file mode 100644
index 0000000..d05f9fa
--- /dev/null
+++ b/tests/lib/async/stream_state_nonzero_timer_test.dart
@@ -0,0 +1,103 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test the event/callback protocol of the stream implementations.
+// Uses a non-zero timer so it fails on d8.
+
+library stream_state_nonzero_timer_test;
+
+import "dart:async";
+import "../../../pkg/unittest/lib/unittest.dart";
+import "stream_state_helper.dart";
+
+const ms5 = const Duration(milliseconds: 5);
+
+main() {
+ mainTest(false);
+ mainTest(true);
+}
+
+mainTest(bool broadcast) {
+ var p = broadcast ? "BC" : "SC";
+
+ test("$p-sub-data/pause/resume/pause/resume-done", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42, () {
+ t.pause();
+ })
+ ..expectPause(true, () { t.resume(); })
+ ..expectPause(false, () { t.pause(); })
+ ..expectPause(true, () { t.resume(); })
+ ..expectPause(false, () { t.close(); })
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe()..add(42);
+ });
+
+ test("$p-sub-data/pause-done", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42, () {
+ t.pause(new Future.delayed(ms5, () => null));
+ })
+ ..expectPause(true)
+ ..expectDone()
+ ..expectSubscription(false, false);
+ // We are calling "close" while the controller is actually paused,
+ // and it will stay paused until the pending events are sent.
+ t..subscribe()..add(42)..close();
+ });
+
+ test("$p-sub-data/pause-resume/done", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42, () {
+ t.pause(new Future.delayed(ms5, () => null));
+ })
+ ..expectPause(true)
+ ..expectPause(false, () { t.close(); })
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe()..add(42);
+ });
+
+ test("$p-sub-data/data+pause-data-resume-done", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42, () {
+ t.add(43);
+ t.pause(new Future.delayed(ms5, () => null));
+ // Should now be paused until the future finishes.
+ // After that, the controller stays paused until the pending queue
+ // is empty.
+ })
+ ..expectPause(true)
+ ..expectData(43)
+ ..expectPause(false, () { t.close(); })
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe()..add(42);
+ });
+
+ test("$p-pause-during-callback", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42, () {
+ t.pause();
+ })
+ ..expectPause(true, () {
+ t.resume();
+ })
+ ..expectPause(false, () {
+ t.pause();
+ t.resume();
+ t.close();
+ })
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe()
+ ..add(42);
+ });
+}
diff --git a/tests/lib/async/stream_state_test.dart b/tests/lib/async/stream_state_test.dart
new file mode 100644
index 0000000..f27697b
--- /dev/null
+++ b/tests/lib/async/stream_state_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test the event/callback protocol of the stream implementations.
+library stream_state_test;
+
+import "../../../pkg/unittest/lib/unittest.dart";
+import "stream_state_helper.dart";
+
+const ms5 = const Duration(milliseconds: 5);
+
+main() {
+ mainTest(false);
+ mainTest(true);
+}
+
+mainTest(bool broadcast) {
+ var p = broadcast ? "BC" : "SC";
+ test("$p-sub-data-done", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42)
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe()..add(42)..close();
+ });
+
+ test("$p-data-done-sub", () {
+ var t = new StreamProtocolTest(broadcast);
+ if (broadcast) {
+ t..expectDone();
+ } else {
+ t..expectSubscription(true, false)
+ ..expectData(42)
+ ..expectDone()
+ ..expectSubscription(false, false);
+ }
+ t..add(42)..close()..subscribe();
+ });
+
+ test("$p-sub-data/pause+resume-done", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42, () {
+ t.pause();
+ t.resume();
+ t.close();
+ })
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe()..add(42);
+ });
+
+ test("$p-sub-data-unsubonerror", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42)
+ ..expectError("bad")
+ ..expectSubscription(false, !broadcast);
+ t..subscribe(unsubscribeOnError: true)
+ ..add(42)
+ ..error("bad")
+ ..add(43)
+ ..close();
+ });
+
+ test("$p-sub-data-no-unsubonerror", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42)
+ ..expectError("bad")
+ ..expectData(43)
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe(unsubscribeOnError: false)
+ ..add(42)
+ ..error("bad")
+ ..add(43)
+ ..close();
+ });
+
+ test("$p-pause-resume-during-event", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42, () {
+ t.pause();
+ t.resume();
+ })
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe()
+ ..add(42)
+ ..close();
+ });
+
+ test("$p-cancel-sub-during-event", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42, () {
+ t.cancel();
+ t.subscribe();
+ })
+ ..expectData(43)
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe()
+ ..add(42)
+ ..add(43)
+ ..close();
+ });
+
+ test("$p-cancel-sub-during-callback", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectData(42, () {
+ t.pause();
+ })
+ ..expectPause(true, () {
+ t.cancel(); // Cancels pause
+ t.subscribe();
+ })
+ ..expectPause(false)
+ ..expectData(43)
+ ..expectDone()
+ ..expectSubscription(false, false);
+ t..subscribe()
+ ..add(42)
+ ..add(43)
+ ..close();
+ });
+
+ test("$p-sub-after-done-is-done", () {
+ var t = new StreamProtocolTest(broadcast);
+ t..expectSubscription(true, false)
+ ..expectDone()
+ ..expectSubscription(false, false)
+ ..expectDone();
+ t..subscribe()
+ ..close()
+ ..subscribe(); // Subscribe after done does not cause callbacks at all.
+ });
+}
diff --git a/tests/lib/async/stream_transform_test.dart b/tests/lib/async/stream_transform_test.dart
index 436c229..abd6f53 100644
--- a/tests/lib/async/stream_transform_test.dart
+++ b/tests/lib/async/stream_transform_test.dart
@@ -10,7 +10,7 @@
main() {
- // Regression tests for http://dartbug.com/8311
+ // Regression tests for http://dartbug.com/8310 and 8311
test("simpleDone", () {
StreamController c = new StreamController();
@@ -45,4 +45,17 @@
input.replay(c);
actual.resume();
});
+
+ test("closing after done", () {
+ var controller = new StreamController();
+ var buffer = new StringBuffer();
+ controller.stream.map((e) => e).transform(new StreamTransformer(
+ handleData: (element, sink) { sink.add(element); },
+ handleDone: (sink) { sink.close(); })
+ ).listen(expectAsync1((e) => expect(e, equals("foo"))));
+
+ controller.add("foo");
+ // Should not crash.
+ controller.close();
+ });
}
diff --git a/tests/lib/crypto/base64_test.dart b/tests/lib/crypto/base64_test.dart
index fdf24b9..0070a50 100644
--- a/tests/lib/crypto/base64_test.dart
+++ b/tests/lib/crypto/base64_test.dart
@@ -45,11 +45,11 @@
void main() {
for (var i = 0; i < inputs.length; i++) {
- var enc = CryptoUtils.bytesToBase64(inputs[i].charCodes);
+ var enc = CryptoUtils.bytesToBase64(inputs[i].codeUnits);
Expect.equals(results[i], enc);
}
- Expect.equals(CryptoUtils.bytesToBase64(longLine.charCodes, 76),
+ Expect.equals(CryptoUtils.bytesToBase64(longLine.codeUnits, 76),
longLineResult);
- Expect.equals(CryptoUtils.bytesToBase64(longLine.charCodes),
+ Expect.equals(CryptoUtils.bytesToBase64(longLine.codeUnits),
longLineResultNoBreak);
}
diff --git a/tests/lib/crypto/sha1_test.dart b/tests/lib/crypto/sha1_test.dart
index b9e9069..d977230 100644
--- a/tests/lib/crypto/sha1_test.dart
+++ b/tests/lib/crypto/sha1_test.dart
@@ -11,7 +11,7 @@
part 'sha1_short_test_vectors.dart';
List<int> createTestArr(int len) {
- var arr = new List<int>.fixedLength(len);
+ var arr = new List<int>(len);
for (var i = 0; i < len; i++) {
arr[i] = i;
}
diff --git a/tests/lib/crypto/sha256_test.dart b/tests/lib/crypto/sha256_test.dart
index 62a8dc9..767812a 100644
--- a/tests/lib/crypto/sha256_test.dart
+++ b/tests/lib/crypto/sha256_test.dart
@@ -11,7 +11,7 @@
part 'sha256_short_test_vectors.dart';
List<int> createTestArr(int len) {
- var arr = new List<int>.fixedLength(len);
+ var arr = new List<int>(len);
for (var i = 0; i < len; i++) {
arr[i] = i;
}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 73efcec..52f322a 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -17,6 +17,7 @@
async/slow_consumer3_test: Fail # Timer interface not supported; dartbug.com/7728.
async/slow_consumer_test: Fail # Timer interface not supported; dartbug.com/7728.
async/stream_from_iterable_test: Fail # Timer interface not supported; dartbug.com/7728.
+async/stream_state_nonzero_timer_test: Fail # Timer interface not supported; dartbug.com/7728.
[ $compiler == dart2js && $browser ]
crypto/sha256_test: Slow, Pass
diff --git a/tests/standalone/crypto/base64_test.dart b/tests/standalone/crypto/base64_test.dart
index a20fd20..36546d4 100644
--- a/tests/standalone/crypto/base64_test.dart
+++ b/tests/standalone/crypto/base64_test.dart
@@ -24,13 +24,13 @@
"Rpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo\r\n"
"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm"
"5hbCBwbGVhc3VyZS4=";
- Expect.equals(expected, _Base64._encode(line.charCodes));
- Expect.listEquals(line.charCodes, _Base64._decode(expected));
+ Expect.equals(expected, _Base64._encode(line.codeUnits));
+ Expect.listEquals(line.codeUnits, _Base64._decode(expected));
line = "Simple string";
expected = "U2ltcGxlIHN0cmluZw==";
- Expect.equals(expected, _Base64._encode(line.charCodes));
- Expect.listEquals(line.charCodes, _Base64._decode(expected));
+ Expect.equals(expected, _Base64._encode(line.codeUnits));
+ Expect.listEquals(line.codeUnits, _Base64._decode(expected));
for (int i = 0; i < 256; i++) {
List<int> x = [i];
diff --git a/tests/standalone/io/dart_std_io_pipe_test.dart b/tests/standalone/io/dart_std_io_pipe_test.dart
index a4d4f24..325e41b 100644
--- a/tests/standalone/io/dart_std_io_pipe_test.dart
+++ b/tests/standalone/io/dart_std_io_pipe_test.dart
@@ -23,7 +23,7 @@
void checkFileContent(String fileName, String content) {
RandomAccessFile pipeOut = new File(fileName).openSync();
int length = pipeOut.lengthSync();
- List data = new List<int>.fixedLength(length);
+ List data = new List<int>(length);
pipeOut.readListSync(data, 0, length);
Expect.equals(content, new String.fromCharCodes(data));
pipeOut.closeSync();
@@ -97,7 +97,7 @@
}
// Run the shell script.
- test(shellScript.name, scriptFile.name, "0");
- test(shellScript.name, scriptFile.name, "1");
- test(shellScript.name, scriptFile.name, "2");
+ test(shellScript.path, scriptFile.path, "0");
+ test(shellScript.path, scriptFile.path, "1");
+ test(shellScript.path, scriptFile.path, "2");
}
diff --git a/tests/standalone/io/directory_error_test.dart b/tests/standalone/io/directory_error_test.dart
index 950f025..6a8ebe9 100644
--- a/tests/standalone/io/directory_error_test.dart
+++ b/tests/standalone/io/directory_error_test.dart
@@ -170,7 +170,7 @@
File f = new File("${temp.path}/file");
var newPath = "${temp.path}/file2";
f.createSync();
- var d = new Directory(f.name);
+ var d = new Directory(f.path);
Expect.throws(() => d.renameSync(newPath),
(e) => e is DirectoryIOException);
var renameDone = d.rename(newPath);
diff --git a/tests/standalone/io/directory_test.dart b/tests/standalone/io/directory_test.dart
index 0d6500e..47a7b38 100644
--- a/tests/standalone/io/directory_test.dart
+++ b/tests/standalone/io/directory_test.dart
@@ -27,9 +27,9 @@
void testSyncListing(bool recursive) {
for (var entry in directory.listSync(recursive: recursive)) {
if (entry is File) {
- Expect.isTrue(entry.name.contains(directory.path));
- Expect.isTrue(entry.name.contains('subdir'));
- Expect.isTrue(entry.name.contains('file.txt'));
+ Expect.isTrue(entry.path.contains(directory.path));
+ Expect.isTrue(entry.path.contains('subdir'));
+ Expect.isTrue(entry.path.contains('file.txt'));
Expect.isFalse(listedFile);
listedFile = true;
} else {
@@ -54,7 +54,7 @@
directory.list(recursive: true).listen(
(FileSystemEntity entity) {
if (entity is File) {
- var path = entity.name;
+ var path = entity.path;
listedFile = true;
Expect.isTrue(path.contains(directory.path));
Expect.isTrue(path.contains('subdir'));
diff --git a/tests/standalone/io/echo_server_stream_test.dart b/tests/standalone/io/echo_server_stream_test.dart
index 3a59aba..b3a1868 100644
--- a/tests/standalone/io/echo_server_stream_test.dart
+++ b/tests/standalone/io/echo_server_stream_test.dart
@@ -24,7 +24,7 @@
EchoServerGame.start()
: _receivePort = new ReceivePort(),
_sendPort = null,
- _buffer = new List<int>.fixedLength(MSGSIZE),
+ _buffer = new List<int>(MSGSIZE),
_messages = 0 {
for (int i = 0; i < MSGSIZE; i++) {
_buffer[i] = FIRSTCHAR + i;
@@ -65,7 +65,7 @@
onDone: onClosed);
_socket.add(_buffer);
_socket.close();
- data = new List<int>.fixedLength(MSGSIZE);
+ data = new List<int>(MSGSIZE);
}
Socket.connect(TestingServer.HOST, _port).then((s) {
@@ -107,7 +107,7 @@
static const int MSGSIZE = EchoServerGame.MSGSIZE;
void onConnection(Socket connection) {
- List<int> buffer = new List<int>.fixedLength(MSGSIZE);
+ List<int> buffer = new List<int>(MSGSIZE);
int offset = 0;
void dataReceived(List<int> data) {
diff --git a/tests/standalone/io/file_input_stream_test.dart b/tests/standalone/io/file_input_stream_test.dart
index 4e2e2c4..e9de0c5 100644
--- a/tests/standalone/io/file_input_stream_test.dart
+++ b/tests/standalone/io/file_input_stream_test.dart
@@ -36,7 +36,7 @@
var keepAlive = new ReceivePort();
String fileName = getFilename("tests/standalone/io/readuntil_test.dat");
// File contains "Hello Dart\nwassup!\n"
- var expected = "Hello Dart\nwassup!\n".charCodes;
+ var expected = "Hello Dart\nwassup!\n".codeUnits;
var byteCount = 0;
(new File(fileName)).openRead().listen(
(d) => byteCount += d.length,
@@ -95,7 +95,6 @@
});
}
-
void testInputStreamDelete() {
var keepAlive = new ReceivePort();
var temp = new Directory('').createTempSync();
diff --git a/tests/standalone/io/file_invalid_arguments_test.dart b/tests/standalone/io/file_invalid_arguments_test.dart
index 4be142a..26c9557 100644
--- a/tests/standalone/io/file_invalid_arguments_test.dart
+++ b/tests/standalone/io/file_invalid_arguments_test.dart
@@ -144,10 +144,10 @@
main() {
testReadInvalidArgs('asdf');
testReadListInvalidArgs(12, 0, 1);
- testReadListInvalidArgs(new List.fixedLength(10), '0', 1);
- testReadListInvalidArgs(new List.fixedLength(10), 0, '1');
+ testReadListInvalidArgs(new List(10), '0', 1);
+ testReadListInvalidArgs(new List(10), 0, '1');
testWriteByteInvalidArgs('asdf');
testWriteListInvalidArgs(12, 0, 1);
- testWriteListInvalidArgs(new List.fixedLength(10), '0', 1);
- testWriteListInvalidArgs(new List.fixedLength(10), 0, '1');
+ testWriteListInvalidArgs(new List(10), '0', 1);
+ testWriteListInvalidArgs(new List(10), 0, '1');
}
diff --git a/tests/standalone/io/file_system_links_test.dart b/tests/standalone/io/file_system_links_test.dart
index 90e9692..652bf78 100644
--- a/tests/standalone/io/file_system_links_test.dart
+++ b/tests/standalone/io/file_system_links_test.dart
@@ -66,7 +66,7 @@
var y = '${temp.path}${Platform.pathSeparator}y';
new File(x).createSync();
createLink(x, y, true, () {
- var data = "asdf".charCodes;
+ var data = "asdf".codeUnits;
var output = new File(y).openWrite(FileMode.WRITE);
output.add(data);
output.close();
@@ -131,7 +131,7 @@
var dirs = [];
for (var entry in temp.listSync(recursive:true)) {
if (entry is File) {
- files.add(entry.name);
+ files.add(entry.path);
} else {
Expect.isTrue(entry is Directory);
dirs.add(entry.path);
@@ -147,7 +147,7 @@
var lister = temp.list(recursive: true).listen(
(entity) {
if (entity is File) {
- files.add(entity.name);
+ files.add(entity.path);
} else {
Expect.isTrue(entity is Directory);
dirs.add(entity.path);
@@ -182,7 +182,7 @@
temp.list(recursive: true).listen(
(entity) {
if (entity is File) {
- files.add(entity.name);
+ files.add(entity.path);
} else {
Expect.isTrue(entity is Directory);
dirs.add(entity.path);
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart
index a8daa32..6f97138 100644
--- a/tests/standalone/io/file_test.dart
+++ b/tests/standalone/io/file_test.dart
@@ -45,7 +45,7 @@
// Read a file and check part of it's contents.
String filename = getFilename("bin/file_test.cc");
File file = new File(filename);
- Expect.isTrue('$file'.contains(file.name));
+ Expect.isTrue('$file'.contains(file.path));
var subscription;
List<int> buffer = new List<int>();
subscription = file.openRead().listen(
@@ -121,7 +121,7 @@
asyncTestStarted();
// Create the test data - arbitrary binary data.
- List<int> buffer = new List<int>.fixedLength(100000);
+ List<int> buffer = new List<int>(100000);
for (var i = 0; i < buffer.length; ++i) {
buffer[i] = i % 256;
}
@@ -172,7 +172,7 @@
}
static Future testPipe(File file, buffer) {
- String outputFilename = '${file.name}_copy';
+ String outputFilename = '${file.path}_copy';
File outputFile = new File(outputFilename);
var input = file.openRead();
var output = outputFile.openWrite();
@@ -201,7 +201,7 @@
String filename = getFilename("bin/file_test.cc");
File file = new File(filename);
file.open(FileMode.READ).then((RandomAccessFile file) {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
file.readList(buffer, 0, 5).then((bytes_read) {
Expect.equals(5, bytes_read);
file.readList(buffer, 5, 5).then((bytes_read) {
@@ -225,12 +225,12 @@
static void testReadSync() {
// Read a file and check part of it's contents.
String filename = getFilename("bin/file_test.cc");
- RandomAccessFile file = (new File(filename)).openSync();
- List<int> buffer = new List<int>.fixedLength(42);
+ RandomAccessFile raf = (new File(filename)).openSync();
+ List<int> buffer = new List<int>(42);
int bytes_read = 0;
- bytes_read = file.readListSync(buffer, 0, 12);
+ bytes_read = raf.readListSync(buffer, 0, 12);
Expect.equals(12, bytes_read);
- bytes_read = file.readListSync(buffer, 12, 30);
+ bytes_read = raf.readListSync(buffer, 12, 30);
Expect.equals(30, bytes_read);
Expect.equals(47, buffer[0]); // represents '/' in the file.
Expect.equals(47, buffer[1]); // represents '/' in the file.
@@ -244,6 +244,17 @@
Expect.equals(103, buffer[9]); // represents 'g' in the file.
Expect.equals(104, buffer[10]); // represents 'h' in the file.
Expect.equals(116, buffer[11]); // represents 't' in the file.
+
+ filename = getFilename("tests/vm/data/fixed_length_file");
+ File file = new File(filename);
+ int len = file.lengthSync();
+ Expect.equals(0, file.openSync().readSync(0).length);
+ Expect.equals(1, file.openSync().readSync(1).length);
+ Expect.equals(len - 1, file.openSync().readSync(len - 1).length);
+ Expect.equals(len, file.openSync().readSync(len).length);
+ Expect.equals(len, file.openSync().readSync(len + 1).length);
+ Expect.equals(len, file.openSync().readSync(len * 2).length);
+ Expect.equals(len, file.openSync().readSync(len * 10).length);
}
// Test for file read and write functionality.
@@ -252,7 +263,7 @@
String inFilename = getFilename("tests/vm/data/fixed_length_file");
final File file = new File(inFilename);
file.open(FileMode.READ).then((openedFile) {
- List<int> buffer1 = new List<int>.fixedLength(42);
+ List<int> buffer1 = new List<int>(42);
openedFile.readList(buffer1, 0, 42).then((bytes_read) {
Expect.equals(42, bytes_read);
openedFile.close().then((ignore) {
@@ -268,7 +279,7 @@
file2.open(FileMode.WRITE).then((openedFile2) {
openedFile2.writeList(buffer1, 0, bytes_read).then((ignore) {
openedFile2.close().then((ignore) {
- List<int> buffer2 = new List<int>.fixedLength(bytes_read);
+ List<int> buffer2 = new List<int>(bytes_read);
final File file3 = new File(outFilename);
file3.open(FileMode.READ).then((openedFile3) {
openedFile3.readList(buffer2, 0, 42).then((bytes_read) {
@@ -308,7 +319,7 @@
File file = new File(filename);
file.createSync();
Expect.isTrue(new File(filename).existsSync());
- List<int> buffer = content.charCodes;
+ List<int> buffer = content.codeUnits;
RandomAccessFile openedFile = file.openSync(FileMode.WRITE);
openedFile.writeListSync(buffer, 0, buffer.length);
openedFile.closeSync();
@@ -331,7 +342,7 @@
String filename = tempDirectory.path.concat("/outstream_write_append");
File file = new File(filename);
file.createSync();
- List<int> buffer = content.charCodes;
+ List<int> buffer = content.codeUnits;
var output = file.openWrite();
output.add(buffer);
output.close();
@@ -363,7 +374,7 @@
String filename = tempDirectory.path.concat("/outstream_write_string");
File file = new File(filename);
file.createSync();
- List<int> buffer = content.charCodes;
+ List<int> buffer = content.codeUnits;
var output = file.openWrite();
output.addString("abcdABCD");
output.addString("abcdABCD", Encoding.UTF_8);
@@ -386,7 +397,7 @@
// Read a file.
String inFilename = getFilename("tests/vm/data/fixed_length_file");
RandomAccessFile file = (new File(inFilename)).openSync();
- List<int> buffer1 = new List<int>.fixedLength(42);
+ List<int> buffer1 = new List<int>(42);
int bytes_read = 0;
int bytes_written = 0;
bytes_read = file.readListSync(buffer1, 0, 42);
@@ -405,7 +416,7 @@
openedFile.writeListSync(buffer1, 0, bytes_read);
openedFile.closeSync();
// Now read the contents of the file just written.
- List<int> buffer2 = new List<int>.fixedLength(bytes_read);
+ List<int> buffer2 = new List<int>(bytes_read);
openedFile = (new File(outFilename)).openSync();
bytes_read = openedFile.readListSync(buffer2, 0, 42);
Expect.equals(42, bytes_read);
@@ -473,7 +484,7 @@
var openedFile2 = file2.openSync();
var length = openedFile2.lengthSync();
Expect.equals(8, length);
- List data = new List.fixedLength(length);
+ List data = new List(length);
openedFile2.readListSync(data, 0, length);
for (var i = 0; i < data.length; i++) {
Expect.equals(i, data[i]);
@@ -577,7 +588,7 @@
RandomAccessFile input = (new File(filename)).openSync();
input.position().then((position) {
Expect.equals(0, position);
- List<int> buffer = new List<int>.fixedLength(100);
+ List<int> buffer = new List<int>(100);
input.readList(buffer, 0, 12).then((bytes_read) {
input.position().then((position) {
Expect.equals(12, position);
@@ -601,7 +612,7 @@
String filename = getFilename("tests/vm/data/fixed_length_file");
RandomAccessFile input = (new File(filename)).openSync();
Expect.equals(0, input.positionSync());
- List<int> buffer = new List<int>.fixedLength(100);
+ List<int> buffer = new List<int>(100);
input.readListSync(buffer, 0, 12);
Expect.equals(12, input.positionSync());
input.readListSync(buffer, 12, 6);
@@ -688,7 +699,7 @@
Expect.equals(true, !wrongExceptionCaught);
exceptionCaught = false;
try {
- List<int> buffer = new List<int>.fixedLength(100);
+ List<int> buffer = new List<int>(100);
openedFile.readListSync(buffer, 0, 10);
} on FileIOException catch (ex) {
exceptionCaught = true;
@@ -699,7 +710,7 @@
Expect.equals(true, !wrongExceptionCaught);
exceptionCaught = false;
try {
- List<int> buffer = new List<int>.fixedLength(100);
+ List<int> buffer = new List<int>(100);
openedFile.writeListSync(buffer, 0, 10);
} on FileIOException catch (ex) {
exceptionCaught = true;
@@ -744,7 +755,7 @@
// Tests stream exception handling after file was closed.
static void testCloseExceptionStream() {
asyncTestStarted();
- List<int> buffer = new List<int>.fixedLength(42);
+ List<int> buffer = new List<int>(42);
File file =
new File(tempDirectory.path.concat("/out_close_exception_stream"));
file.createSync();
@@ -765,7 +776,7 @@
new File(tempDirectory.path.concat("/out_buffer_out_of_bounds"));
RandomAccessFile openedFile = file.openSync(FileMode.WRITE);
try {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
openedFile.readListSync(buffer, 0, 12);
} on RangeError catch (ex) {
exceptionCaught = true;
@@ -776,7 +787,7 @@
Expect.equals(true, !wrongExceptionCaught);
exceptionCaught = false;
try {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
openedFile.readListSync(buffer, 6, 6);
} on RangeError catch (ex) {
exceptionCaught = true;
@@ -787,7 +798,7 @@
Expect.equals(true, !wrongExceptionCaught);
exceptionCaught = false;
try {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
openedFile.readListSync(buffer, -1, 1);
} on RangeError catch (ex) {
exceptionCaught = true;
@@ -798,7 +809,7 @@
Expect.equals(true, !wrongExceptionCaught);
exceptionCaught = false;
try {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
openedFile.readListSync(buffer, 0, -1);
} on RangeError catch (ex) {
exceptionCaught = true;
@@ -809,7 +820,7 @@
Expect.equals(true, !wrongExceptionCaught);
exceptionCaught = false;
try {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
openedFile.writeListSync(buffer, 0, 12);
} on RangeError catch (ex) {
exceptionCaught = true;
@@ -820,7 +831,7 @@
Expect.equals(true, !wrongExceptionCaught);
exceptionCaught = false;
try {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
openedFile.writeListSync(buffer, 6, 6);
} on RangeError catch (ex) {
exceptionCaught = true;
@@ -831,7 +842,7 @@
Expect.equals(true, !wrongExceptionCaught);
exceptionCaught = false;
try {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
openedFile.writeListSync(buffer, -1, 1);
} on RangeError catch (ex) {
exceptionCaught = true;
@@ -842,7 +853,7 @@
Expect.equals(true, !wrongExceptionCaught);
exceptionCaught = false;
try {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
openedFile.writeListSync(buffer, 0, -1);
} on RangeError catch (ex) {
exceptionCaught = true;
@@ -940,11 +951,11 @@
f.readAsString(Encoding.UTF_8).then((text) {
Expect.equals(6, text.length);
var expected = [955, 120, 46, 32, 120, 10];
- Expect.listEquals(expected, text.charCodes);
+ Expect.listEquals(expected, text.codeUnits);
f.readAsString(Encoding.ISO_8859_1).then((text) {
Expect.equals(7, text.length);
var expected = [206, 187, 120, 46, 32, 120, 10];
- Expect.listEquals(expected, text.charCodes);
+ Expect.listEquals(expected, text.codeUnits);
var readAsStringFuture = f.readAsString(Encoding.ASCII);
readAsStringFuture.then((text) {
Expect.fail("Non-ascii char should cause error");
@@ -979,15 +990,15 @@
text = new File(name).readAsStringSync();
Expect.equals(6, text.length);
var expected = [955, 120, 46, 32, 120, 10];
- Expect.listEquals(expected, text.charCodes);
+ Expect.listEquals(expected, text.codeUnits);
text = new File(name).readAsStringSync(Encoding.ASCII);
// Default replacement character is '?', char code 63.
expected = [63, 63, 120, 46, 32, 120, 10];
- Expect.listEquals(expected, text.charCodes);
+ Expect.listEquals(expected, text.codeUnits);
text = new File(name).readAsStringSync(Encoding.ISO_8859_1);
expected = [206, 187, 120, 46, 32, 120, 10];
Expect.equals(7, text.length);
- Expect.listEquals(expected, text.charCodes);
+ Expect.listEquals(expected, text.codeUnits);
}
static void testReadAsTextSyncEmptyFile() {
diff --git a/tests/standalone/io/http_10_test.dart b/tests/standalone/io/http_10_test.dart
new file mode 100644
index 0000000..a923562
--- /dev/null
+++ b/tests/standalone/io/http_10_test.dart
@@ -0,0 +1,212 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:isolate";
+import "dart:io";
+
+// Client makes a HTTP 1.0 request without connection keep alive. The
+// server sets a content length but still needs to close the
+// connection as there is no keep alive.
+void testHttp10NoKeepAlive() {
+ HttpServer.bind().then((server) {
+ server.listen(
+ (HttpRequest request) {
+ Expect.isNull(request.headers.value('content-length'));
+ Expect.equals(-1, request.contentLength);
+ var response = request.response;
+ response.contentLength = 1;
+ Expect.equals("1.0", request.protocolVersion);
+ response.done
+ .then((_) => Expect.fail("Unexpected response completion"))
+ .catchError((e) => Expect.isTrue(e.error is HttpException));
+ response.addString("Z");
+ response.addString("Z");
+ response.close();
+ Expect.throws(() => response.addString("x"),
+ (e) => e is StateError);
+ },
+ onError: (e) => Expect.fail("Unexpected error $e"));
+
+ int count = 0;
+ makeRequest() {
+ Socket.connect("127.0.0.1", server.port).then((socket) {
+ socket.addString("GET / HTTP/1.0\r\n\r\n");
+
+ List<int> response = [];
+ socket.listen(
+ response.addAll,
+ onDone: () {
+ count++;
+ socket.destroy();
+ String s = new String.fromCharCodes(response).toLowerCase();
+ Expect.equals("z", s[s.length - 1]);
+ Expect.isTrue(s.indexOf("\r\ncontent-length: 1\r\n") > 0);
+ Expect.equals(-1, s.indexOf("keep-alive"));
+ if (count < 10) {
+ makeRequest();
+ } else {
+ server.close();
+ }
+ });
+ });
+ }
+ makeRequest();
+ });
+}
+
+
+// Client makes a HTTP 1.0 request and the server does not set a
+// content length so it has to close the connection to mark the end of
+// the response.
+void testHttp10ServerClose() {
+ HttpServer.bind().then((server) {
+ server.listen(
+ (HttpRequest request) {
+ Expect.isNull(request.headers.value('content-length'));
+ Expect.equals(-1, request.contentLength);
+ var response = request.response;
+ Expect.equals("1.0", request.protocolVersion);
+ response.addString("Z");
+ response.close();
+ },
+ onError: (e) => Expect.fail("Unexpected error $e"));
+
+ int count = 0;
+ makeRequest() {
+ Socket.connect("127.0.0.1", server.port).then((socket) {
+ socket.addString("GET / HTTP/1.0\r\n\r\n");
+ socket.addString("Connection: Keep-Alive\r\n\r\n");
+
+ List<int> response = [];
+ socket.listen(
+ response.addAll,
+ onDone: () {
+ socket.destroy();
+ count++;
+ String s = new String.fromCharCodes(response).toLowerCase();
+ print(s);
+ Expect.equals("z", s[s.length - 1]);
+ Expect.equals(-1, s.indexOf("content-length:"));
+ Expect.equals(-1, s.indexOf("keep-alive"));
+ if (count < 10) {
+ makeRequest();
+ } else {
+ server.close();
+ }
+ },onError: (e) => print(e));
+ });
+ }
+ makeRequest();
+ });
+}
+
+
+// Client makes a HTTP 1.0 request with connection keep alive. The
+// server sets a content length so the persistent connection can be
+// used.
+void testHttp10KeepAlive() {
+ HttpServer.bind().then((server) {
+ server.listen(
+ (HttpRequest request) {
+ Expect.isNull(request.headers.value('content-length'));
+ Expect.equals(-1, request.contentLength);
+ var response = request.response;
+ response.contentLength = 1;
+ Expect.equals("1.0", request.protocolVersion);
+ response.addString("Z");
+ response.close();
+ },
+ onError: (e) => Expect.fail("Unexpected error $e"));
+
+ Socket.connect("127.0.0.1", server.port).then((socket) {
+ void sendRequest() {
+ socket.addString("GET / HTTP/1.0\r\n");
+ socket.addString("Connection: Keep-Alive\r\n\r\n");
+ }
+
+ List<int> response = [];
+ int count = 0;
+ socket.listen(
+ (d) {
+ response.addAll(d);
+ if (response[response.length - 1] == "Z".codeUnitAt(0)) {
+ String s = new String.fromCharCodes(response).toLowerCase();
+ Expect.isTrue(s.indexOf("\r\nconnection: keep-alive\r\n") > 0);
+ Expect.isTrue(s.indexOf("\r\ncontent-length: 1\r\n") > 0);
+ count++;
+ if (count < 10) {
+ response = [];
+ sendRequest();
+ } else {
+ socket.close();
+ }
+ }
+ },
+ onDone: () {
+ socket.destroy();
+ server.close();
+ });
+ sendRequest();
+ });
+ });
+}
+
+
+// Client makes a HTTP 1.0 request with connection keep alive. The
+// server does not set a content length so it cannot honor connection
+// keep alive.
+void testHttp10KeepAliveServerCloses() {
+ HttpServer.bind().then((server) {
+ server.listen(
+ (HttpRequest request) {
+ Expect.isNull(request.headers.value('content-length'));
+ Expect.equals(-1, request.contentLength);
+ var response = request.response;
+ Expect.equals("1.0", request.protocolVersion);
+ response.addString("Z");
+ response.close();
+ },
+ onError: (e) => Expect.fail("Unexpected error $e"));
+
+ int count = 0;
+ makeRequest() {
+ Socket.connect("127.0.0.1", server.port).then((socket) {
+ socket.addString("GET / HTTP/1.0\r\n");
+ socket.addString("Connection: Keep-Alive\r\n\r\n");
+
+ List<int> response = [];
+ socket.listen(
+ response.addAll,
+ onDone: () {
+ socket.destroy();
+ count++;
+ String s = new String.fromCharCodes(response).toLowerCase();
+ Expect.equals("z", s[s.length - 1]);
+ Expect.equals(-1, s.indexOf("content-length"));
+ Expect.equals(-1, s.indexOf("connection"));
+ if (count < 10) {
+ makeRequest();
+ } else {
+ server.close();
+ }
+ });
+ });
+ }
+ makeRequest();
+ });
+}
+
+
+void main() {
+ testHttp10NoKeepAlive();
+ // TODO(8871): This test fails with short socket writes.
+ //testHttp10ServerClose();
+ testHttp10KeepAlive();
+ testHttp10KeepAliveServerCloses();
+}
diff --git a/tests/standalone/io/http_auth_test.dart b/tests/standalone/io/http_auth_test.dart
index cfc692b..c6acccb 100644
--- a/tests/standalone/io/http_auth_test.dart
+++ b/tests/standalone/io/http_auth_test.dart
@@ -168,7 +168,7 @@
String password = url.path.substring(1, 6);
if (passwordChanged) password = "${password}1";
Completer completer = new Completer();
- new Timer(10, (_) {
+ new Timer(const Duration(milliseconds: 10), () {
client.addCredentials(
url, realm, new HttpClientBasicCredentials(username, password));
completer.complete(true);
diff --git a/tests/standalone/io/http_client_connect_test.dart b/tests/standalone/io/http_client_connect_test.dart
index dd8a3bf..93bd7fa 100644
--- a/tests/standalone/io/http_client_connect_test.dart
+++ b/tests/standalone/io/http_client_connect_test.dart
@@ -30,7 +30,7 @@
void testGetDataRequest() {
HttpServer.bind().then((server) {
- var data = "lalala".charCodes;
+ var data = "lalala".codeUnits;
server.listen((request) {
request.response.add(data);
request.pipe(request.response);
diff --git a/tests/standalone/io/http_client_exception_test.dart b/tests/standalone/io/http_client_exception_test.dart
new file mode 100644
index 0000000..65c0a41
--- /dev/null
+++ b/tests/standalone/io/http_client_exception_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+
+import "dart:io";
+import "dart:isolate";
+import "dart:uri";
+
+void testInvalidUrl() {
+ HttpClient client = new HttpClient();
+ Expect.throws(
+ () => client.getUrl(Uri.parse('ftp://www.google.com')));
+}
+
+void testBadHostName() {
+ HttpClient client = new HttpClient();
+ ReceivePort port = new ReceivePort();
+ client.get("some.bad.host.name.7654321", 0, "/")
+ .then((request) {
+ Expect.fail("Should not open a request on bad hostname");
+ }).catchError((error) {
+ port.close(); // We expect onError to be called, due to bad host name.
+ }, test: (error) => error is! String);
+}
+
+void main() {
+ testInvalidUrl();
+ testBadHostName();
+}
diff --git a/tests/standalone/io/http_client_socket_reuse_test.dart b/tests/standalone/io/http_client_socket_reuse_test.dart
deleted file mode 100644
index 715624a8..0000000
--- a/tests/standalone/io/http_client_socket_reuse_test.dart
+++ /dev/null
@@ -1,43 +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.
-
-import "dart:async";
-import "dart:io";
-import "dart:uri";
-import "dart:isolate";
-
-// By running tests sequentially, we cover the socket reuse code in HttpClient.
-
-void testGoogleUrls() {
- int testsStarted = 0;
- int testsFinished = 0;
- bool allStarted = false;
- HttpClient client = new HttpClient();
-
- Future testUrl(String url) {
- testsStarted++;
- var requestUri = Uri.parse(url);
- return client.getUrl(requestUri)
- .then((HttpClientRequest request) => request.close())
- .then((HttpClientResponse response) {
- Expect.isTrue(response.statusCode < 500);
- if (requestUri.path.length == 0) {
- Expect.isTrue(response.statusCode != 404);
- }
- return response.reduce(null, (previous, element) => null);
- })
- .catchError((error) => Expect.fail("Unexpected IO error: $error"));
- }
-
- // TODO(3593): Use a Dart HTTP server for this test.
- testUrl('http://www.google.dk')
- .then((_) => testUrl('http://www.google.dk'))
- .then((_) => testUrl('http://www.google.dk/#q=foo'))
- .then((_) => testUrl('http://www.google.dk/#hl=da&q=foo'))
- .then((_) { client.close(); });
-}
-
-void main() {
- testGoogleUrls();
-}
diff --git a/tests/standalone/io/http_client_test.dart b/tests/standalone/io/http_client_test.dart
deleted file mode 100644
index c3e7db1..0000000
--- a/tests/standalone/io/http_client_test.dart
+++ /dev/null
@@ -1,75 +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.
-//
-// VMOptions=
-// VMOptions=--short_socket_read
-// VMOptions=--short_socket_write
-// VMOptions=--short_socket_read --short_socket_write
-
-import "dart:io";
-import "dart:uri";
-import "dart:isolate";
-
-void testGoogle() {
- HttpClient client = new HttpClient();
- client.get('www.google.com', 80, '/')
- .then((request) => request.close())
- .then((response) {
- Expect.isTrue(response.statusCode < 500);
- response.listen((data) {}, onDone: client.close);
- })
- .catchError((error) => Expect.fail("Unexpected IO error: $error"));
-}
-
-int testGoogleUrlCount = 0;
-void testGoogleUrl() {
- HttpClient client = new HttpClient();
-
- void testUrl(String url) {
- var requestUri = Uri.parse(url);
- client.getUrl(requestUri)
- .then((request) => request.close())
- .then((response) {
- testGoogleUrlCount++;
- Expect.isTrue(response.statusCode < 500);
- if (requestUri.path.length == 0) {
- Expect.isTrue(response.statusCode != 404);
- }
- response.listen((data) {}, onDone: () {
- if (testGoogleUrlCount == 5) client.close();
- });
- })
- .catchError((error) => Expect.fail("Unexpected IO error: $error"));
- }
-
- testUrl('http://www.google.com');
- testUrl('http://www.google.com/abc');
- testUrl('http://www.google.com/?abc');
- testUrl('http://www.google.com/abc?abc');
- testUrl('http://www.google.com/abc?abc#abc');
-}
-
-void testInvalidUrl() {
- HttpClient client = new HttpClient();
- Expect.throws(
- () => client.getUrl(Uri.parse('ftp://www.google.com')));
-}
-
-void testBadHostName() {
- HttpClient client = new HttpClient();
- ReceivePort port = new ReceivePort();
- client.get("some.bad.host.name.7654321", 0, "/")
- .then((request) {
- Expect.fail("Should not open a request on bad hostname");
- }).catchError((error) {
- port.close(); // We expect onError to be called, due to bad host name.
- }, test: (error) => error is! String);
-}
-
-void main() {
- testGoogle();
- testGoogleUrl();
- testInvalidUrl();
- testBadHostName();
-}
diff --git a/tests/standalone/io/http_close_test.dart b/tests/standalone/io/http_close_test.dart
new file mode 100644
index 0000000..de467d5
--- /dev/null
+++ b/tests/standalone/io/http_close_test.dart
@@ -0,0 +1,160 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "dart:scalarlist";
+
+
+void testClientAndServerCloseNoListen(int connections) {
+ HttpServer.bind().then((server) {
+ int closed = 0;
+ server.listen((request) {
+ request.response.close();
+ request.response.done.then((_) {
+ closed++;
+ if (closed == connections) {
+ Expect.equals(0, server.connectionsInfo().active);
+ Expect.equals(server.connectionsInfo().total,
+ server.connectionsInfo().idle);
+ server.close();
+ }
+ });
+ });
+ var client = new HttpClient();
+ for (int i = 0; i < connections; i++) {
+ client.get("localhost", server.port, "/")
+ .then((request) => request.close())
+ .then((response) {
+ });
+ }
+ });
+}
+
+
+void testClientCloseServerListen(int connections) {
+ HttpServer.bind().then((server) {
+ int closed = 0;
+ void check() {
+ closed++;
+ if (closed == connections * 2) {
+ Expect.equals(0, server.connectionsInfo().active);
+ Expect.equals(server.connectionsInfo().total,
+ server.connectionsInfo().idle);
+ server.close();
+ }
+ }
+ server.listen((request) {
+ request.listen(
+ (_) {},
+ onDone: () {
+ request.response.close();
+ request.response.done.then((_) => check());
+ });
+ });
+ var client = new HttpClient();
+ for (int i = 0; i < connections; i++) {
+ client.get("localhost", server.port, "/")
+ .then((request) => request.close())
+ .then((response) => check());
+ }
+ });
+}
+
+
+void testClientCloseDelayed(int connections) {
+ HttpServer.bind().then((server) {
+ int closed = 0;
+ void check() {
+ closed++;
+ // Wait for both server and client to see the connections as closed.
+ if (closed == connections * 2) {
+ Expect.equals(0, server.connectionsInfo().active);
+ Expect.equals(server.connectionsInfo().total,
+ server.connectionsInfo().idle);
+ server.close();
+ }
+ }
+ server.listen((request) {
+ request.pipe(request.response)
+ .then((_) => check());
+ });
+ var client = new HttpClient();
+ for (int i = 0; i < connections; i++) {
+ var req;
+ client.post("localhost", server.port, "/")
+ .then((request) {
+ req = request;
+ request.add(new Uint8List(1024));
+ return request.response;
+ })
+ .then((response) {
+ req.close();
+ // Ensure we don't accept the response until we have send the entire
+ // request.
+ response.listen(
+ (_) {},
+ onDone: () {
+ check();
+ });
+ });
+ }
+ });
+}
+
+
+void testClientCloseSendingResponse(int connections) {
+ HttpServer.bind().then((server) {
+ int closed = 0;
+ void check() {
+ closed++;
+ // Wait for both server and client to see the connections as closed.
+ if (closed == connections * 2) {
+ Expect.equals(0, server.connectionsInfo().active);
+ Expect.equals(server.connectionsInfo().total,
+ server.connectionsInfo().idle);
+ server.close();
+ }
+ }
+ server.listen((request) {
+ var timer = new Timer.repeating(const Duration(milliseconds: 20), (_) {
+ request.response.add(new Uint8List(16 * 1024));
+ });
+ request.response.done
+ .catchError((_) {})
+ .whenComplete(() {
+ check();
+ timer.cancel();
+ });
+ });
+ var client = new HttpClient();
+ for (int i = 0; i < connections; i++) {
+ client.get("localhost", server.port, "/")
+ .then((request) => request.close())
+ .then((response) {
+ // Ensure we don't accept the response until we have send the entire
+ // request.
+ var subscription = response.listen((_) {});
+ new Timer(const Duration(milliseconds: 200), () {
+ subscription.cancel();
+ check();
+ });
+ });
+ }
+ });
+}
+
+
+void main() {
+ testClientAndServerCloseNoListen(10);
+ testClientCloseServerListen(10);
+ testClientCloseDelayed(10);
+ testClientCloseSendingResponse(10);
+}
+
diff --git a/tests/standalone/io/http_connection_close_test.dart b/tests/standalone/io/http_connection_close_test.dart
index e8f3609..a2a11c7 100644
--- a/tests/standalone/io/http_connection_close_test.dart
+++ b/tests/standalone/io/http_connection_close_test.dart
@@ -35,7 +35,7 @@
Socket.connect("127.0.0.1", server.port)
.then((socket) {
- List<int> buffer = new List<int>.fixedLength(1024);
+ List<int> buffer = new List<int>(1024);
socket.addString("GET / HTTP/1.1\r\nConnection: close\r\n\r\n");
socket.listen(
(data) {},
diff --git a/tests/standalone/io/http_content_length_test.dart b/tests/standalone/io/http_content_length_test.dart
index 14d4000..16a1d03 100644
--- a/tests/standalone/io/http_content_length_test.dart
+++ b/tests/standalone/io/http_content_length_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -68,6 +68,7 @@
void testBody(int totalConnections, bool useHeader) {
HttpServer.bind("127.0.0.1", 0, totalConnections).then((server) {
+ int serverCount = 0;
server.listen(
(HttpRequest request) {
Expect.equals("2", request.headers.value('content-length'));
@@ -91,7 +92,10 @@
Expect.fail("Unexpected successful response completion");
})
.catchError((e) {
- Expect.isTrue(e.error is HttpException);
+ Expect.isTrue(e.error is HttpException, "[$e]");
+ if (++serverCount == totalConnections) {
+ server.close();
+ }
});
response.close();
Expect.throws(() => response.addString("x"),
@@ -100,7 +104,7 @@
},
onError: (e) => Expect.fail("Unexpected error $e"));
- int count = 0;
+ int clientCount = 0;
HttpClient client = new HttpClient();
for (int i = 0; i < totalConnections; i++) {
client.get("127.0.0.1", server.port, "/")
@@ -123,9 +127,8 @@
response.listen(
(d) {},
onDone: () {
- if (++count == totalConnections) {
+ if (++clientCount == totalConnections) {
client.close();
- server.close();
}
});
});
@@ -199,35 +202,31 @@
});
}
-void testHttp10() {
- HttpServer.bind("127.0.0.1", 0, 5).then((server) {
+void testSetContentLength() {
+ HttpServer.bind().then((server) {
server.listen(
(HttpRequest request) {
- Expect.isNull(request.headers.value('content-length'));
- Expect.equals(-1, request.contentLength);
var response = request.response;
- response.contentLength = 0;
- Expect.equals("1.0", request.protocolVersion);
- response.done
- .then((_) => Expect.fail("Unexpected response completion"))
- .catchError((e) => Expect.isTrue(e.error is HttpException));
- response.addString("x");
+ Expect.isNull(response.headers.value('content-length'));
+ Expect.equals(-1, response.contentLength);
+ response.headers.set("content-length", 3);
+ Expect.equals("3", response.headers.value('content-length'));
+ Expect.equals(3, response.contentLength);
+ response.addString("xxx");
response.close();
- Expect.throws(() => response.addString("x"),
- (e) => e is StateError);
- },
- onError: (e) => Expect.fail("Unexpected error $e"));
+ });
- Socket.connect("127.0.0.1", server.port).then((socket) {
- socket.addString("GET / HTTP/1.0\r\n\r\n");
- socket.close();
- socket.listen(
- (d) { },
- onDone: () {
- socket.destroy();
- server.close();
- });
- });
+ var client = new HttpClient();
+ client.get("127.0.0.1", server.port, "/")
+ .then((request) => request.close())
+ .then((response) {
+ response.listen(
+ (_) { },
+ onDone: () {
+ client.close();
+ server.close();
+ });
+ });
});
}
@@ -238,5 +237,5 @@
testBody(5, true);
testBodyChunked(5, false);
testBodyChunked(5, true);
- testHttp10();
+ testSetContentLength();
}
diff --git a/tests/standalone/io/http_date_test.dart b/tests/standalone/io/http_date_test.dart
index 5821e05..8f2ee60 100644
--- a/tests/standalone/io/http_date_test.dart
+++ b/tests/standalone/io/http_date_test.dart
@@ -5,7 +5,7 @@
import "dart:async";
import "dart:math";
-part "../../../sdk/lib/io/io_stream_consumer.dart";
+part "../../../sdk/lib/io/io_sink.dart";
part "../../../sdk/lib/io/http.dart";
part "../../../sdk/lib/io/http_impl.dart";
part "../../../sdk/lib/io/http_parser.dart";
diff --git a/tests/standalone/io/http_head_test.dart b/tests/standalone/io/http_head_test.dart
index 215872c..9325ceb 100644
--- a/tests/standalone/io/http_head_test.dart
+++ b/tests/standalone/io/http_head_test.dart
@@ -13,7 +13,7 @@
response.close();
} else if (request.uri.path == "/test200") {
response.contentLength = 200;
- List<int> data = new List<int>.fixedLength(200, fill: 0);
+ List<int> data = new List<int>.filled(200, 0);
response.add(data);
response.close();
} else {
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
index fca7a49..19829e7 100644
--- a/tests/standalone/io/http_headers_test.dart
+++ b/tests/standalone/io/http_headers_test.dart
@@ -5,7 +5,7 @@
import 'dart:async';
import 'dart:math';
-part "../../../sdk/lib/io/io_stream_consumer.dart";
+part "../../../sdk/lib/io/io_sink.dart";
part "../../../sdk/lib/io/http.dart";
part "../../../sdk/lib/io/http_headers.dart";
part "../../../sdk/lib/io/http_impl.dart";
diff --git a/tests/standalone/io/http_keep_alive_test.dart b/tests/standalone/io/http_keep_alive_test.dart
index 70b9021..c89b4ee 100644
--- a/tests/standalone/io/http_keep_alive_test.dart
+++ b/tests/standalone/io/http_keep_alive_test.dart
@@ -26,7 +26,7 @@
server.listen((request) {
bool chunked = request.queryParameters["chunked"] == "true";
int length = int.parse(request.queryParameters["length"]);
- var buffer = new List.fixedLength(length, fill: 0);
+ var buffer = new List<int>.filled(length, 0);
if (!chunked) request.response.contentLength = length;
request.response.add(buffer);
request.response.close();
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index 173fec4..ab02206 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -8,7 +8,7 @@
import 'dart:isolate';
import 'dart:uri';
-part '../../../sdk/lib/io/io_stream_consumer.dart';
+part '../../../sdk/lib/io/io_sink.dart';
part '../../../sdk/lib/io/http.dart';
part '../../../sdk/lib/io/http_impl.dart';
part '../../../sdk/lib/io/http_headers.dart';
@@ -125,7 +125,7 @@
// Test parsing the request three times delivering the data in
// different chunks.
- List<int> requestData = request.charCodes;
+ List<int> requestData = request.codeUnits;
testWrite(requestData);
testWrite(requestData, 10);
testWrite(requestData, 1);
@@ -169,7 +169,7 @@
// Test parsing the request three times delivering the data in
// different chunks.
- List<int> requestData = request.charCodes;
+ List<int> requestData = request.codeUnits;
testWrite(requestData);
testWrite(requestData, 10);
testWrite(requestData, 1);
@@ -270,7 +270,7 @@
// Test parsing the request three times delivering the data in
// different chunks.
- List<int> responseData = response.charCodes;
+ List<int> responseData = response.codeUnits;
testWrite(responseData);
testWrite(responseData, 10);
testWrite(responseData, 1);
@@ -320,7 +320,7 @@
// Test parsing the request three times delivering the data in
// different chunks.
- List<int> responseData = response.charCodes;
+ List<int> responseData = response.codeUnits;
testWrite(responseData);
testWrite(responseData, 10);
testWrite(responseData, 1);
diff --git a/tests/standalone/io/http_proxy_test.dart b/tests/standalone/io/http_proxy_test.dart
index 24a2f84..af8cdff 100644
--- a/tests/standalone/io/http_proxy_test.dart
+++ b/tests/standalone/io/http_proxy_test.dart
@@ -189,15 +189,26 @@
setupServer(1, directRequestPaths: ["/4"], secure: true).then((secureServer) {
HttpClient client = new HttpClient();
- List<String> proxy =
- ["PROXY localhost:${proxyServer.port}",
- "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080",
- "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer.port}",
- "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;"
- " PROXY localhost:${proxyServer.port}",
- "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
- "PROXY localhost:${proxyServer.port}; DIRECT"];
-
+ List<String> proxy;
+ if (Platform.operatingSystem == "windows") {
+ proxy =
+ ["PROXY localhost:${proxyServer.port}",
+ "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080",
+ "PROXY localhost:${proxyServer.port}",
+ ""
+ " PROXY localhost:${proxyServer.port}",
+ "DIRECT",
+ "PROXY localhost:${proxyServer.port}; DIRECT"];
+ } else {
+ proxy =
+ ["PROXY localhost:${proxyServer.port}",
+ "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080",
+ "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer.port}",
+ "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;"
+ " PROXY localhost:${proxyServer.port}",
+ "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
+ "PROXY localhost:${proxyServer.port}; DIRECT"];
+ }
client.findProxy = (Uri uri) {
// Pick the proxy configuration based on the request path.
int index = int.parse(uri.path.substring(1));
@@ -248,13 +259,25 @@
setupServer(2, directRequestPaths: ["/4"]).then((server) {
HttpClient client = new HttpClient();
- List<String> proxy =
- ["PROXY localhost:${proxyServer1.port}",
- "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080",
- "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer1.port}",
- "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; PROXY localhost:${proxyServer1.port}",
- "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
- "PROXY localhost:${proxyServer1.port}; DIRECT"];
+ List<String> proxy;
+ if (Platform.operatingSystem == "windows") {
+ proxy =
+ ["PROXY localhost:${proxyServer1.port}",
+ "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080",
+ "PROXY localhost:${proxyServer1.port}",
+ "PROXY localhost:${proxyServer1.port}",
+ "DIRECT",
+ "PROXY localhost:${proxyServer1.port}; DIRECT"];
+ } else {
+ proxy =
+ ["PROXY localhost:${proxyServer1.port}",
+ "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080",
+ "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer1.port}",
+ "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;"
+ " PROXY localhost:${proxyServer1.port}",
+ "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
+ "PROXY localhost:${proxyServer1.port}; DIRECT"];
+ }
client.findProxy = (Uri uri) {
// Pick the proxy configuration based on the request path.
diff --git a/tests/standalone/io/http_read_test.dart b/tests/standalone/io/http_read_test.dart
index dfef4e4..6cba2b5 100644
--- a/tests/standalone/io/http_read_test.dart
+++ b/tests/standalone/io/http_read_test.dart
@@ -174,7 +174,7 @@
request.addString(data.substring(10, data.length));
} else {
request.contentLength = data.length;
- request.add(data.charCodes);
+ request.add(data.codeUnits);
}
return request.close();
})
diff --git a/tests/standalone/io/http_request_pipeling_test.dart b/tests/standalone/io/http_request_pipeling_test.dart
new file mode 100644
index 0000000..a96fa88
--- /dev/null
+++ b/tests/standalone/io/http_request_pipeling_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:io";
+import "dart:uri";
+
+void main() {
+ final int REQUEST_COUNT = 100;
+ int count = 0;
+ HttpServer.bind().then((server) {
+ server.listen((HttpRequest request) {
+ count++;
+ request.response.addString(request.uri.path);
+ request.response.close();
+ if (request.uri.path == "/done") {
+ request.response.done.then((_) {
+ Expect.equals(REQUEST_COUNT + 1, count);
+ server.close();
+ });
+ }
+ });
+ Socket.connect("127.0.0.1", server.port).then((s) {
+ s.listen((data) { });
+ for (int i = 0; i < REQUEST_COUNT; i++) {
+ s.addString("GET /$i HTTP/1.1\r\nX-Header-1: 111\r\n\r\n");
+ }
+ s.addString("GET /done HTTP/1.1\r\nConnection: close\r\n\r\n");
+ s.close();
+ });
+ });
+}
diff --git a/tests/standalone/io/http_server_early_client_close_test.dart b/tests/standalone/io/http_server_early_client_close_test.dart
index b59857e..2f75862 100644
--- a/tests/standalone/io/http_server_early_client_close_test.dart
+++ b/tests/standalone/io/http_server_early_client_close_test.dart
@@ -57,7 +57,7 @@
List<int> d;
if (data is List<int>) d = data;
- if (data is String) d = data.charCodes;
+ if (data is String) d = data.codeUnits;
if (d == null) Expect.fail("Invalid data");
sendData(d, server.port);
@@ -116,7 +116,7 @@
var count = 0;
makeRequest() {
Socket.connect("127.0.0.1", server.port).then((socket) {
- var data = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n".charCodes;
+ var data = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n".codeUnits;
socket.add(data);
socket.close();
socket.done.then((_) {
diff --git a/tests/standalone/io/http_server_response_test.dart b/tests/standalone/io/http_server_response_test.dart
index 674c901..fc94876 100644
--- a/tests/standalone/io/http_server_response_test.dart
+++ b/tests/standalone/io/http_server_response_test.dart
@@ -7,10 +7,11 @@
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write
+import "dart:async";
import "dart:io";
import "dart:scalarlist";
-void testServerRequest(void handler(server, request)) {
+void testServerRequest(void handler(server, request), {int bytes}) {
HttpServer.bind().then((server) {
server.listen((request) {
handler(server, request);
@@ -23,11 +24,16 @@
client.get("127.0.0.1", server.port, "/")
.then((request) => request.close())
.then((response) {
- response.listen((_) {}, onDone: () {
- client.close();
- }, onError: (error) {
- Expect.isTrue(error.error is HttpParserException);
- });
+ int received = 0;
+ response.listen(
+ (data) => received += data.length,
+ onDone: () {
+ if (bytes != null) Expect.equals(received, bytes);
+ client.close();
+ },
+ onError: (error) {
+ Expect.isTrue(error.error is HttpParserException);
+ });
})
.catchError((error) {
client.close();
@@ -45,6 +51,39 @@
});
}
+void testResponseAddStream() {
+ int bytes = new File(new Options().script).lengthSync();
+
+ testServerRequest((server, request) {
+ request.response.addStream(new File(new Options().script).openRead())
+ .then((response) {
+ response.close();
+ response.done.then((_) => server.close());
+ });
+ }, bytes: bytes);
+
+ testServerRequest((server, request) {
+ request.response.addStream(new File(new Options().script).openRead())
+ .then((response) {
+ request.response.addStream(new File(new Options().script).openRead())
+ .then((response) {
+ response.close();
+ response.done.then((_) => server.close());
+ });
+ });
+ }, bytes: bytes * 2);
+
+ testServerRequest((server, request) {
+ var controller = new StreamController();
+ request.response.addStream(controller.stream)
+ .then((response) {
+ response.close();
+ response.done.then((_) => server.close());
+ });
+ controller.close();
+ }, bytes: 0);
+}
+
void testBadResponseAdd() {
testServerRequest((server, request) {
request.response.contentLength = 0;
@@ -95,6 +134,7 @@
void main() {
testResponseDone();
+ testResponseAddStream();
testBadResponseAdd();
testBadResponseClose();
}
diff --git a/tests/standalone/io/http_shutdown_test.dart b/tests/standalone/io/http_shutdown_test.dart
index c7bcc16..8c91797 100644
--- a/tests/standalone/io/http_shutdown_test.dart
+++ b/tests/standalone/io/http_shutdown_test.dart
@@ -2,6 +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.
//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
import "dart:async";
import "dart:io";
@@ -49,6 +53,7 @@
for (int i = 0; i < outputStreamWrites; i++) {
request.addString("Hello, world!");
}
+ request.done.catchError((_) {});
return request.close();
})
.then((HttpClientResponse response) {
@@ -146,6 +151,7 @@
(_) { },
onDone: () {
request.response.close();
+ request.response.done.catchError((e) {});
},
onError: (error) { });
},
@@ -162,6 +168,7 @@
// TODO(sgjesse): Make this test work with
//request.response instead of request.close() return
//return request.response;
+ request.done.catchError((e) {});
return request.close();
})
.then((response) { })
diff --git a/tests/standalone/io/https_client_certificate_test.dart b/tests/standalone/io/https_client_certificate_test.dart
index 1d9b0e4..9c519eb 100644
--- a/tests/standalone/io/https_client_certificate_test.dart
+++ b/tests/standalone/io/https_client_certificate_test.dart
@@ -28,8 +28,12 @@
HttpClient client = new HttpClient();
client.getUrl(Uri.parse("https://$HOST_NAME:${server.port}/"))
.then((request) => request.close())
- .then((response) =>
- response.reduce(<int>[], (message, data) => message..addAll(data)))
+ .then((response) {
+ Expect.equals('CN=localhost', response.certificate.subject);
+ Expect.equals('CN=myauthority', response.certificate.issuer);
+ return response.reduce(<int>[],
+ (message, data) => message..addAll(data));
+ })
.then((message) {
String received = new String.fromCharCodes(message);
Expect.equals(received, "Hello");
diff --git a/tests/standalone/io/https_client_exception_test.dart b/tests/standalone/io/https_client_exception_test.dart
new file mode 100644
index 0000000..22c743c
--- /dev/null
+++ b/tests/standalone/io/https_client_exception_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.
+
+import "dart:io";
+import "dart:isolate";
+import "dart:uri";
+
+void testBadHostName() {
+ HttpClient client = new HttpClient();
+ ReceivePort port = new ReceivePort();
+ client.getUrl(Uri.parse("https://some.bad.host.name.7654321/"))
+ .then((HttpClientRequest request) {
+ Expect.fail("Should not open a request on bad hostname");
+ })
+ .catchError((error) {
+ port.close(); // Should throw an error on bad hostname.
+ });
+}
+
+void InitializeSSL() {
+ SecureSocket.initialize();
+}
+
+void main() {
+ testBadHostName();
+ Expect.throws(InitializeSSL);
+}
diff --git a/tests/standalone/io/https_client_socket_reuse_test.dart b/tests/standalone/io/https_client_socket_reuse_test.dart
deleted file mode 100644
index 5b4244b..0000000
--- a/tests/standalone/io/https_client_socket_reuse_test.dart
+++ /dev/null
@@ -1,43 +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.
-
-import "dart:async";
-import "dart:io";
-import "dart:uri";
-import "dart:isolate";
-
-// By running tests sequentially, we cover the socket reuse code in HttpClient.
-
-void testGoogleUrls() {
- int testsStarted = 0;
- int testsFinished = 0;
- bool allStarted = false;
- HttpClient client = new HttpClient();
-
- Future testUrl(String url) {
- testsStarted++;
- var requestUri = Uri.parse(url);
- return client.getUrl(requestUri)
- .then((HttpClientRequest request) => request.close())
- .then((HttpClientResponse response) {
- Expect.isTrue(response.statusCode < 500);
- if (requestUri.path.length == 0) {
- Expect.isTrue(response.statusCode != 404);
- }
- return response.reduce(null, (previous, element) => null);
- })
- .catchError((error) => Expect.fail("Unexpected IO error: $error"));
- }
-
- // TODO(3593): Use a Dart HTTPS server for this test.
- testUrl('https://www.google.dk')
- .then((_) => testUrl('https://www.google.dk'))
- .then((_) => testUrl('https://www.google.dk/#q=foo'))
- .then((_) => testUrl('https://www.google.dk/#hl=da&q=foo'))
- .then((_) { client.close(); });
-}
-
-void main() {
- testGoogleUrls();
-}
diff --git a/tests/standalone/io/https_client_test.dart b/tests/standalone/io/https_client_test.dart
deleted file mode 100644
index 37b3d4f..0000000
--- a/tests/standalone/io/https_client_test.dart
+++ /dev/null
@@ -1,60 +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.
-
-import "dart:io";
-import "dart:uri";
-import "dart:isolate";
-
-
-void testGoogleUrl() {
- int testsStarted = 0;
- int testsFinished = 0;
- bool allStarted = false;
- HttpClient client = new HttpClient();
-
- void testUrl(String url) {
- testsStarted++;
- var requestUri = Uri.parse(url);
- client.getUrl(requestUri)
- .then((HttpClientRequest request) => request.close())
- .then((HttpClientResponse response) {
- Expect.isTrue(response.statusCode < 500);
- if (requestUri.path.length == 0) {
- Expect.isTrue(response.statusCode != 404);
- }
- response.listen((data) { }, onDone: () {
- if (++testsFinished == testsStarted && allStarted) client.close();
- });
- })
- .catchError((error) => Expect.fail("Unexpected IO error: $error"));
- }
-
- testUrl('https://www.google.dk');
- testUrl('https://www.google.dk');
- testUrl('https://www.google.dk/#q=foo');
- testUrl('https://www.google.dk/#hl=da&q=foo');
- allStarted = true;
-}
-
-void testBadHostName() {
- HttpClient client = new HttpClient();
- ReceivePort port = new ReceivePort();
- client.getUrl(Uri.parse("https://some.bad.host.name.7654321/"))
- .then((HttpClientRequest request) {
- Expect.fail("Should not open a request on bad hostname");
- })
- .catchError((error) {
- port.close(); // Should throw an error on bad hostname.
- });
-}
-
-void InitializeSSL() {
- SecureSocket.initialize();
-}
-
-void main() {
- testGoogleUrl();
- testBadHostName();
- Expect.throws(InitializeSSL);
-}
diff --git a/tests/standalone/io/mime_multipart_parser_test.dart b/tests/standalone/io/mime_multipart_parser_test.dart
index adccecb..d9457c7 100644
--- a/tests/standalone/io/mime_multipart_parser_test.dart
+++ b/tests/standalone/io/mime_multipart_parser_test.dart
@@ -5,7 +5,7 @@
import 'dart:async';
import 'dart:math';
-part '../../../sdk/lib/io/io_stream_consumer.dart';
+part '../../../sdk/lib/io/io_sink.dart';
part "../../../sdk/lib/io/http.dart";
part "../../../sdk/lib/io/http_impl.dart";
part "../../../sdk/lib/io/http_parser.dart";
@@ -47,7 +47,7 @@
if (expectedParts[partCount] != null) {
List<int> expectedPart;
if (expectedParts[partCount] is String) {
- expectedPart = expectedParts[partCount].charCodes;
+ expectedPart = expectedParts[partCount].codeUnits;
} else {
expectedPart = expectedParts[partCount];
}
@@ -83,7 +83,7 @@
// Test parsing the data three times delivering the data in
// different chunks.
- List<int> data = message.charCodes;
+ List<int> data = message.codeUnits;
testWrite(data);
testWrite(data, 10);
testWrite(data, 2);
diff --git a/tests/standalone/io/process_check_arguments_test.dart b/tests/standalone/io/process_check_arguments_test.dart
index 46b1cb4..22ccde4 100644
--- a/tests/standalone/io/process_check_arguments_test.dart
+++ b/tests/standalone/io/process_check_arguments_test.dart
@@ -25,14 +25,14 @@
scriptFile =
new File("../tests/standalone/io/process_check_arguments_script.dart");
}
- test([scriptFile.name, '3', '0', 'a']);
- test([scriptFile.name, '3', '0', 'a b']);
- test([scriptFile.name, '3', '0', 'a\tb']);
- test([scriptFile.name, '3', '1', 'a\tb"']);
- test([scriptFile.name, '3', '1', 'a"\tb']);
- test([scriptFile.name, '3', '1', 'a"\t\\\\"b"']);
- test([scriptFile.name, '4', '0', 'a\tb', 'a']);
- test([scriptFile.name, '4', '0', 'a\tb', 'a\t\t\t\tb']);
- test([scriptFile.name, '4', '0', 'a\tb', 'a b']);
+ test([scriptFile.path, '3', '0', 'a']);
+ test([scriptFile.path, '3', '0', 'a b']);
+ test([scriptFile.path, '3', '0', 'a\tb']);
+ test([scriptFile.path, '3', '1', 'a\tb"']);
+ test([scriptFile.path, '3', '1', 'a"\tb']);
+ test([scriptFile.path, '3', '1', 'a"\t\\\\"b"']);
+ test([scriptFile.path, '4', '0', 'a\tb', 'a']);
+ test([scriptFile.path, '4', '0', 'a\tb', 'a\t\t\t\tb']);
+ test([scriptFile.path, '4', '0', 'a\tb', 'a b']);
}
diff --git a/tests/standalone/io/process_non_ascii_test.dart b/tests/standalone/io/process_non_ascii_test.dart
index e7b31e3..88291be 100644
--- a/tests/standalone/io/process_non_ascii_test.dart
+++ b/tests/standalone/io/process_non_ascii_test.dart
@@ -24,7 +24,7 @@
nonAsciiTxtFile.writeAsStringSync('æøå');
var options = new ProcessOptions();
options.workingDirectory = nonAsciiDir.path;
- var script = nonAsciiFile.name;
+ var script = nonAsciiFile.path;
Process.run(executable, [script], options).then((result) {
Expect.equals(0, result.exitCode);
tempDir.deleteSync(recursive: true);
diff --git a/tests/standalone/io/process_run_output_test.dart b/tests/standalone/io/process_run_output_test.dart
index 86e833a..bc5a4e3 100644
--- a/tests/standalone/io/process_run_output_test.dart
+++ b/tests/standalone/io/process_run_output_test.dart
@@ -14,7 +14,7 @@
} else if (encoding == 'latin1') {
Expect.equals(output, 'æøå');
} else if (encoding == 'utf8') {
- Expect.listEquals(output.charCodes, [955]);
+ Expect.listEquals(output.codeUnits, [955]);
}
}
@@ -57,11 +57,11 @@
new File("../tests/standalone/io/process_std_io_script2.dart");
}
Expect.isTrue(scriptFile.existsSync());
- test(scriptFile.name, 'ascii', 'stdout');
- test(scriptFile.name, 'ascii', 'stderr');
- test(scriptFile.name, 'latin1', 'stdout');
- test(scriptFile.name, 'latin1', 'stderr');
- test(scriptFile.name, 'utf8', 'stdout');
- test(scriptFile.name, 'utf8', 'stderr');
+ test(scriptFile.path, 'ascii', 'stdout');
+ test(scriptFile.path, 'ascii', 'stderr');
+ test(scriptFile.path, 'latin1', 'stdout');
+ test(scriptFile.path, 'latin1', 'stderr');
+ test(scriptFile.path, 'utf8', 'stdout');
+ test(scriptFile.path, 'utf8', 'stderr');
}
diff --git a/tests/standalone/io/process_stderr_test.dart b/tests/standalone/io/process_stderr_test.dart
index 858bb9a..b38d1a1 100644
--- a/tests/standalone/io/process_stderr_test.dart
+++ b/tests/standalone/io/process_stderr_test.dart
@@ -21,7 +21,7 @@
Expect.equals(expectedExitCode, exitCode);
});
- List<int> data = "ABCDEFGHI\n".charCodes;
+ List<int> data = "ABCDEFGHI\n".codeUnits;
final int dataSize = data.length;
int received = 0;
@@ -64,5 +64,5 @@
scriptFile = new File("../tests/standalone/io/process_std_io_script.dart");
}
Expect.isTrue(scriptFile.existsSync());
- test(Process.start(new Options().executable, [scriptFile.name, "1"]), 0);
+ test(Process.start(new Options().executable, [scriptFile.path, "1"]), 0);
}
diff --git a/tests/standalone/io/process_stdin_transform_unsubscribe_script.dart b/tests/standalone/io/process_stdin_transform_unsubscribe_script.dart
new file mode 100644
index 0000000..0711124
--- /dev/null
+++ b/tests/standalone/io/process_stdin_transform_unsubscribe_script.dart
@@ -0,0 +1,18 @@
+// 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.
+//
+// Utility script to echo stdin to stdout or stderr or both.
+
+import "dart:io";
+
+main() {
+ var subscription;
+ subscription = stdin
+ .transform(new StringDecoder())
+ .transform(new LineTransformer())
+ .listen((String line) {
+ // Unsubscribe after the first line.
+ subscription.cancel();
+ });
+}
diff --git a/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart b/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart
new file mode 100644
index 0000000..fddc35b
--- /dev/null
+++ b/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart
@@ -0,0 +1,38 @@
+// 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.
+//
+// Process test program to test process communication.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:math';
+
+import "process_test_util.dart";
+
+void test(Future<Process> future, int expectedExitCode) {
+ future.then((process) {
+ process.exitCode.then((exitCode) {
+ Expect.equals(expectedExitCode, exitCode);
+ });
+
+ process.stdout.listen((_) {});
+ process.stderr.listen((_) {});
+ process.stdin.addString("Line1\n");
+ });
+}
+
+main() {
+ var scriptName = "process_stdin_transform_unsubscribe_script.dart";
+ var scriptFile = new File("tests/standalone/io/$scriptName");
+ if (!scriptFile.existsSync()) {
+ scriptFile = new File("../tests/standalone/io/$scriptName");
+ }
+ Expect.isTrue(scriptFile.existsSync());
+ test(Process.start(new Options().executable, [scriptFile.path]), 0);
+}
diff --git a/tests/standalone/io/process_stdout_test.dart b/tests/standalone/io/process_stdout_test.dart
index 698ab57..1cba732 100644
--- a/tests/standalone/io/process_stdout_test.dart
+++ b/tests/standalone/io/process_stdout_test.dart
@@ -21,7 +21,7 @@
Expect.equals(expectedExitCode, exitCode);
});
- List<int> data = "ABCDEFGHI\n".charCodes;
+ List<int> data = "ABCDEFGHI\n".codeUnits;
final int dataSize = data.length;
int received = 0;
@@ -64,5 +64,5 @@
scriptFile = new File("../tests/standalone/io/process_std_io_script.dart");
}
Expect.isTrue(scriptFile.existsSync());
- test(Process.start(new Options().executable, [scriptFile.name, "0"]), 0);
+ test(Process.start(new Options().executable, [scriptFile.path, "0"]), 0);
}
diff --git a/tests/standalone/io/raw_secure_server_closing_test.dart b/tests/standalone/io/raw_secure_server_closing_test.dart
index 1f8116d4..0fa8121 100644
--- a/tests/standalone/io/raw_secure_server_closing_test.dart
+++ b/tests/standalone/io/raw_secure_server_closing_test.dart
@@ -99,7 +99,7 @@
connection.shutdown(SocketDirection.SEND);
});
}
- new Timer(500, (_) {
+ new Timer(const Duration(milliseconds: 500), () {
subscription.resume();
resumed = true;
for (int i = 0; i < socketCount; i++) {
diff --git a/tests/standalone/io/raw_secure_server_socket_test.dart b/tests/standalone/io/raw_secure_server_socket_test.dart
index 73609ae..b12b87a 100644
--- a/tests/standalone/io/raw_secure_server_socket_test.dart
+++ b/tests/standalone/io/raw_secure_server_socket_test.dart
@@ -120,7 +120,7 @@
RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
Expect.isTrue(server.port > 0);
var clientEndFuture = RawSecureSocket.connect(HOST_NAME, server.port);
- new Timer(500, (_) {
+ new Timer(const Duration(milliseconds: 500), () {
server.listen((serverEnd) {
clientEndFuture.then((clientEnd) {
clientEnd.shutdown(SocketDirection.SEND);
@@ -143,7 +143,7 @@
const messageSize = 1000;
List<int> createTestData() {
- List<int> data = new List.fixedLength(messageSize);
+ List<int> data = new List<int>(messageSize);
for (int i = 0; i < messageSize; i++) {
data[i] = i & 0xff;
}
@@ -162,7 +162,7 @@
server.listen((client) {
int bytesRead = 0;
int bytesWritten = 0;
- List<int> data = new List.fixedLength(messageSize);
+ List<int> data = new List<int>(messageSize);
client.writeEventsEnabled = false;
client.listen((event) {
@@ -212,7 +212,7 @@
int bytesRead = 0;
int bytesWritten = 0;
List<int> dataSent = createTestData();
- List<int> dataReceived = new List<int>.fixedLength(dataSent.length);
+ List<int> dataReceived = new List<int>(dataSent.length);
socket.listen((event) {
switch (event) {
case RawSocketEvent.READ:
diff --git a/tests/standalone/io/raw_secure_socket_pause_test.dart b/tests/standalone/io/raw_secure_socket_pause_test.dart
index 23b2eff..0a79475 100644
--- a/tests/standalone/io/raw_secure_socket_pause_test.dart
+++ b/tests/standalone/io/raw_secure_socket_pause_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
@@ -11,71 +11,97 @@
import "dart:io";
import "dart:isolate";
+Future<HttpServer> startServer() {
+ return HttpServer.bindSecure(
+ "127.0.0.1",
+ 0,
+ backlog: 5,
+ certificateName: 'localhost_cert').then((server) {
+ server.listen((HttpRequest request) {
+ request.listen(
+ (_) { },
+ onDone: () {
+ request.response.contentLength = 100;
+ for (int i = 0; i < 10; i++) {
+ request.response.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+ }
+ request.response.close();
+ });
+ });
+ return server;
+ });
+}
+
+void InitializeSSL() {
+ var testPkcertDatabase =
+ new Path(new Options().script).directoryPath.append('pkcert/');
+ SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
+ password: 'dartdart');
+}
void main() {
- List<int> message = "GET / HTTP/1.0\r\nHost: www.google.dk\r\n\r\n".charCodes;
+ List<int> message = "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n".codeUnits;
int written = 0;
- List<String> chunks = <String>[];
- SecureSocket.initialize();
- // TODO(whesse): Use a Dart HTTPS server for this test.
- // The Dart HTTPS server works on bleeding-edge, but not on IOv2.
- // When we use a Dart HTTPS server, allow --short_socket_write. The flag
- // causes fragmentation of the client hello message, which doesn't seem to
- // work with www.google.dk.
- RawSecureSocket.connect("www.google.dk", 443).then((socket) {
- StreamSubscription subscription;
- bool paused = false;
- bool readEventsTested = false;
- bool readEventsPaused = false;
+ List<int> body = <int>[];
+ InitializeSSL();
+ startServer().then((server) {
+ RawSecureSocket.connect("localhost", server.port).then((socket) {
+ StreamSubscription subscription;
+ bool paused = false;
+ bool readEventsTested = false;
+ bool readEventsPaused = false;
- void runPauseTest() {
- subscription.pause();
- paused = true;
- new Timer(500, (_) {
- paused = false;
- subscription.resume();
- });
- }
-
- void runReadEventTest() {
- if (readEventsTested) return;
- readEventsTested = true;
- socket.readEventsEnabled = false;
- readEventsPaused = true;
- new Timer(500, (_) {
- readEventsPaused = false;
- socket.readEventsEnabled = true;
- });
- }
-
- subscription = socket.listen((RawSocketEvent event) {
- Expect.isFalse(paused);
- switch (event) {
- case RawSocketEvent.READ:
- Expect.isFalse(readEventsPaused);
- runReadEventTest();
- var data = socket.read();
- var received = new String.fromCharCodes(data);
- chunks.add(received);
- break;
- case RawSocketEvent.WRITE:
- written +=
- socket.write(message, written, message.length - written);
- if (written < message.length) {
- socket.writeEventsEnabled = true;
- } else {
- socket.shutdown(SocketDirection.SEND);
- runPauseTest();
- }
- break;
- case RawSocketEvent.READ_CLOSED:
- String fullPage = chunks.join();
- Expect.isTrue(fullPage.contains('</body></html>'));
- break;
- default: throw "Unexpected event $event";
+ void runPauseTest() {
+ subscription.pause();
+ paused = true;
+ new Timer(const Duration(milliseconds: 500), () {
+ paused = false;
+ subscription.resume();
+ });
}
- }, onError: (AsyncError a) {
- Expect.fail("onError handler of RawSecureSocket stream hit: $a");
- });
+
+ void runReadEventTest() {
+ if (readEventsTested) return;
+ readEventsTested = true;
+ socket.readEventsEnabled = false;
+ readEventsPaused = true;
+ new Timer(const Duration(milliseconds: 500), () {
+ readEventsPaused = false;
+ socket.readEventsEnabled = true;
+ });
+ }
+
+ subscription = socket.listen(
+ (RawSocketEvent event) {
+ Expect.isFalse(paused);
+ switch (event) {
+ case RawSocketEvent.READ:
+ Expect.isFalse(readEventsPaused);
+ runReadEventTest();
+ body.addAll(socket.read());
+ break;
+ case RawSocketEvent.WRITE:
+ written +=
+ socket.write(message, written, message.length - written);
+ if (written < message.length) {
+ socket.writeEventsEnabled = true;
+ } else {
+ socket.shutdown(SocketDirection.SEND);
+ runPauseTest();
+ }
+ break;
+ case RawSocketEvent.READ_CLOSED:
+ Expect.isTrue(body.length > 100);
+ Expect.equals(72, body[0]);
+ Expect.equals(9, body[body.length - 1]);
+ server.close();
+ break;
+ default: throw "Unexpected event $event";
+ }
+ },
+ onError: (AsyncError a) {
+ Expect.fail("onError handler of RawSecureSocket stream hit: $a");
+ });
+ });
});
}
diff --git a/tests/standalone/io/raw_secure_socket_test.dart b/tests/standalone/io/raw_secure_socket_test.dart
index b7f7068..1a828ce 100644
--- a/tests/standalone/io/raw_secure_socket_test.dart
+++ b/tests/standalone/io/raw_secure_socket_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
@@ -11,38 +11,68 @@
import "dart:io";
import "dart:isolate";
+Future<HttpServer> startServer() {
+ return HttpServer.bindSecure(
+ "127.0.0.1",
+ 0,
+ backlog: 5,
+ certificateName: 'localhost_cert').then((server) {
+ server.listen((HttpRequest request) {
+ request.listen(
+ (_) { },
+ onDone: () {
+ request.response.contentLength = 100;
+ for (int i = 0; i < 10; i++) {
+ request.response.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+ }
+ request.response.close();
+ });
+ });
+ return server;
+ });
+}
+
+void InitializeSSL() {
+ var testPkcertDatabase =
+ new Path(new Options().script).directoryPath.append('pkcert/');
+ SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
+ password: 'dartdart');
+}
void main() {
- List<int> message = "GET / HTTP/1.0\r\nHost: www.google.dk\r\n\r\n".charCodes;
+ List<int> message = "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n".codeUnits;
int written = 0;
- List<String> chunks = <String>[];
- SecureSocket.initialize();
- // TODO(3593): Use a Dart HTTPS server for this test.
- RawSecureSocket.connect("www.google.dk", 443).then((socket) {
- socket.listen((RawSocketEvent event) {
- switch (event) {
- case RawSocketEvent.READ:
- var data = socket.read();
- var received = new String.fromCharCodes(data);
- chunks.add(received);
- break;
- case RawSocketEvent.WRITE:
- written +=
- socket.write(message, written, message.length - written);
- if (written < message.length) {
- socket.writeEventsEnabled = true;
- } else {
- socket.shutdown(SocketDirection.SEND);
- }
- break;
- case RawSocketEvent.READ_CLOSED:
- String fullPage = chunks.join();
- Expect.isTrue(fullPage.contains('</body></html>'));
- break;
- default: throw "Unexpected event $event";
- }
- }, onError: (AsyncError a) {
- Expect.fail("onError handler of RawSecureSocket stream hit: $a");
+ List<int> body = <int>[];
+ InitializeSSL();
+ startServer().then((server) {
+ RawSecureSocket.connect("localhost", server.port).then((socket) {
+ socket.listen(
+ (RawSocketEvent event) {
+ switch (event) {
+ case RawSocketEvent.READ:
+ body.addAll(socket.read());
+ break;
+ case RawSocketEvent.WRITE:
+ written +=
+ socket.write(message, written, message.length - written);
+ if (written < message.length) {
+ socket.writeEventsEnabled = true;
+ } else {
+ socket.shutdown(SocketDirection.SEND);
+ }
+ break;
+ case RawSocketEvent.READ_CLOSED:
+ Expect.isTrue(body.length > 100, "$body\n${body.length}");
+ Expect.equals(72, body[0]);
+ Expect.equals(9, body[body.length - 1]);
+ server.close();
+ break;
+ default: throw "Unexpected event $event";
+ }
+ },
+ onError: (AsyncError a) {
+ Expect.fail("onError handler of RawSecureSocket stream hit: $a");
+ });
});
});
}
diff --git a/tests/standalone/io/raw_server_socket_cancel_test.dart b/tests/standalone/io/raw_server_socket_cancel_test.dart
new file mode 100644
index 0000000..0062a6e
--- /dev/null
+++ b/tests/standalone/io/raw_server_socket_cancel_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+
+void testCancelResubscribeServerSocket() {
+ const int socketCount = 10;
+ var acceptCount = 0;
+ var doneCount = 0;
+ var closeCount = 0;
+ var errorCount = 0;
+
+ ReceivePort port = new ReceivePort();
+
+ RawServerSocket.bind().then((server) {
+ Expect.isTrue(server.port > 0);
+
+ void checkDone() {
+ if (doneCount == socketCount &&
+ closeCount + errorCount == socketCount) {
+ port.close();
+ }
+ }
+
+ // Subscribe the server socket. Then cancel subscription and
+ // subscribe again.
+ var subscription;
+ subscription = server.listen((client) {
+ if (++acceptCount == socketCount / 2) {
+ subscription.cancel();
+ Timer.run(() {
+ subscription = server.listen((_) {
+ // Close on cancel, so no more events.
+ Expect.fail("Event after closed through cancel");
+ });
+ });
+ }
+ // Close the client socket.
+ client.close();
+ });
+
+ // Connect a number of sockets.
+ for (int i = 0; i < socketCount; i++) {
+ RawSocket.connect("127.0.0.1", server.port).then((socket) {
+ socket.writeEventsEnabled = false;
+ var subscription;
+ subscription = socket.listen((event) {
+ Expect.equals(RawSocketEvent.READ_CLOSED, event);
+ socket.close();
+ closeCount++;
+ checkDone();
+ },
+ onDone: () { doneCount++; checkDone(); },
+ onError: (e) { errorCount++; checkDone(); });
+ }).catchError((e) {
+ errorCount++; checkDone();
+ });
+ }
+ });
+}
+
+void main() {
+ testCancelResubscribeServerSocket();
+}
diff --git a/tests/standalone/io/raw_socket_test.dart b/tests/standalone/io/raw_socket_test.dart
index d14dc9e..01e8e71 100644
--- a/tests/standalone/io/raw_socket_test.dart
+++ b/tests/standalone/io/raw_socket_test.dart
@@ -137,7 +137,7 @@
const messageSize = 1000;
List<int> createTestData() {
- List<int> data = new List.fixedLength(messageSize);
+ List<int> data = new List<int>(messageSize);
for (int i = 0; i < messageSize; i++) {
data[i] = i & 0xff;
}
@@ -156,7 +156,7 @@
server.listen((client) {
int bytesRead = 0;
int bytesWritten = 0;
- List<int> data = new List.fixedLength(messageSize);
+ List<int> data = new List<int>(messageSize);
client.writeEventsEnabled = false;
client.listen((event) {
@@ -212,7 +212,7 @@
if (bytesWritten < data.length) {
socket.writeEventsEnabled = true;
} else {
- data = new List.fixedLength(messageSize);
+ data = new List<int>(messageSize);
}
break;
case RawSocketEvent.READ_CLOSED:
@@ -263,61 +263,7 @@
});
}
-testCancelResubscribeServerSocket() {
- const int socketCount = 10;
- var acceptCount = 0;
- var doneCount = 0;
- var closeCount = 0;
- var errorCount = 0;
-
- ReceivePort port = new ReceivePort();
-
- RawServerSocket.bind().then((server) {
- Expect.isTrue(server.port > 0);
-
- void checkDone() {
- if (doneCount == socketCount &&
- closeCount + errorCount == socketCount) {
- port.close();
- }
- }
-
- // Subscribe the server socket. Then cancel subscription and
- // subscribe again.
- var subscription;
- subscription = server.listen((client) {
- if (++acceptCount == socketCount / 2) {
- subscription.cancel();
- new Timer(0, (_) {
- subscription = server.listen((_) {
- // Close on cancel, so no more events.
- Expect.fail("Event after closed through cancel");
- });
- });
- }
- // Close the client socket.
- client.close();
- });
-
- // Connect a number of sockets.
- for (int i = 0; i < socketCount; i++) {
- RawSocket.connect("127.0.0.1", server.port).then((socket) {
- socket.writeEventsEnabled = false;
- var subscription;
- subscription = socket.listen((event) {
- Expect.equals(RawSocketEvent.READ_CLOSED, event);
- socket.close();
- closeCount++;
- checkDone();
- },
- onDone: () { doneCount++; checkDone(); },
- onError: (e) { errorCount++; checkDone(); });
- });
- }
- });
-}
-
-testPauseSocket() {
+void testPauseSocket() {
const messageSize = 1000;
const loopCount = 10;
Completer connected = new Completer();
@@ -332,7 +278,7 @@
RawServerSocket.bind().then((server) {
Expect.isTrue(server.port > 0);
server.listen((client) {
- List<int> data = new List.fixedLength(messageSize, fill: 0);
+ List<int> data = new List<int>.filled(messageSize, 0);
writeSubscription = client.listen((event) {
switch (event) {
case RawSocketEvent.READ:
@@ -407,6 +353,5 @@
testServerListenAfterConnect();
testSimpleReadWrite();
testPauseServerSocket();
- testCancelResubscribeServerSocket();
testPauseSocket();
}
diff --git a/tests/standalone/io/raw_socket_write_destroy_test.dart b/tests/standalone/io/raw_socket_write_destroy_test.dart
index b5e558a8..d7dc0d8 100644
--- a/tests/standalone/io/raw_socket_write_destroy_test.dart
+++ b/tests/standalone/io/raw_socket_write_destroy_test.dart
@@ -18,7 +18,7 @@
server.listen((socket) {
socket.writeEventsEnabled = false;
- var buffer = new List.fixedLength(WROTE, fill: 0);
+ var buffer = new List.filled(WROTE, 0);
int offset = 0;
void write() {
int n = socket.write(buffer, offset, buffer.length - offset);
@@ -69,7 +69,7 @@
RawSocket.connect(SERVER_ADDRESS, server.port).then((socket) {
socket.writeEventsEnabled = false;
- var buffer = new List.fixedLength(WROTE, fill: 0);
+ var buffer = new List.filled(WROTE, 0);
int offset = 0;
void write() {
int n = socket.write(buffer, offset, buffer.length - offset);
@@ -93,4 +93,4 @@
void main() {
testWriteDestroyServer();
testWriteDestroyClient();
-}
\ No newline at end of file
+}
diff --git a/tests/standalone/io/regress_8828_test.dart b/tests/standalone/io/regress_8828_test.dart
new file mode 100644
index 0000000..be134ac
--- /dev/null
+++ b/tests/standalone/io/regress_8828_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import 'dart:io';
+
+void main() {
+ HttpServer.bind().then((server) {
+ server.listen((request) {
+ request.response
+ ..addString("first line\n")
+ ..addString("")
+ ..addString("second line\n")
+ ..close();
+ });
+
+ HttpClient client = new HttpClient();
+ client.get("127.0.0.1", server.port, "/")
+ .then((HttpClientRequest request) {
+ return request.close();
+ })
+ .then((HttpClientResponse response) {
+ List<int> body = new List();
+ response.listen(body.addAll,
+ onDone: () {
+ Expect.equals("first line\nsecond line\n",
+ new String.fromCharCodes(body));
+ server.close();
+ });
+ });
+ });
+}
diff --git a/tests/standalone/io/secure_client_raw_server_test.dart b/tests/standalone/io/secure_client_raw_server_test.dart
index 331ea6c..3049b23 100644
--- a/tests/standalone/io/secure_client_raw_server_test.dart
+++ b/tests/standalone/io/secure_client_raw_server_test.dart
@@ -61,7 +61,7 @@
Completer success = new Completer();
List<String> chunks = <String>[];
SecureSocket.connect(HOST_NAME, server.port).then((socket) {
- socket.add("Hello server.".charCodes);
+ socket.add("Hello server.".codeUnits);
socket.close();
socket.listen(
(List<int> data) {
diff --git a/tests/standalone/io/secure_client_server_test.dart b/tests/standalone/io/secure_client_server_test.dart
index da48e87..bd6fe43 100644
--- a/tests/standalone/io/secure_client_server_test.dart
+++ b/tests/standalone/io/secure_client_server_test.dart
@@ -32,11 +32,11 @@
Future testClient(server) {
return SecureSocket.connect(HOST_NAME, server.port).then((socket) {
- socket.add("Hello server.".charCodes);
+ socket.add("Hello server.".codeUnits);
socket.close();
return socket.reduce(<int>[], (message, data) => message..addAll(data))
.then((message) {
- Expect.listEquals("Hello server.".charCodes, message);
+ Expect.listEquals("Hello server.".codeUnits, message);
return server;
});
});
diff --git a/tests/standalone/io/secure_multiple_client_server_test.dart b/tests/standalone/io/secure_multiple_client_server_test.dart
index 52e0b56..4b7f370 100644
--- a/tests/standalone/io/secure_multiple_client_server_test.dart
+++ b/tests/standalone/io/secure_multiple_client_server_test.dart
@@ -25,7 +25,7 @@
String received = new String.fromCharCodes(message);
Expect.isTrue(received.contains("Hello from client "));
String name = received.substring(received.indexOf("client ") + 7);
- client.add("Welcome, client $name".charCodes);
+ client.add("Welcome, client $name".codeUnits);
client.close();
});
});
@@ -35,11 +35,11 @@
Future testClient(server, name) {
return SecureSocket.connect(HOST_NAME, server.port).then((socket) {
- socket.add("Hello from client $name".charCodes);
+ socket.add("Hello from client $name".codeUnits);
socket.close();
return socket.reduce(<int>[], (message, data) => message..addAll(data))
.then((message) {
- Expect.listEquals("Welcome, client $name".charCodes, message);
+ Expect.listEquals("Welcome, client $name".codeUnits, message);
return server;
});
});
diff --git a/tests/standalone/io/secure_server_client_certificate_test.dart b/tests/standalone/io/secure_server_client_certificate_test.dart
index 5d75c6c..24e72a0 100644
--- a/tests/standalone/io/secure_server_client_certificate_test.dart
+++ b/tests/standalone/io/secure_server_client_certificate_test.dart
@@ -1,125 +1,127 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import "dart:async";
import "dart:io";
import "dart:isolate";
const SERVER_ADDRESS = "127.0.0.1";
const HOST_NAME = "localhost";
+const CERTIFICATE = "localhost_cert";
-void WriteAndClose(Socket socket, String message) {
- var data = message.charCodes;
- int written = 0;
- void write() {
- written += socket.writeList(data, written, data.length - written);
- if (written < data.length) {
- socket.onWrite = write;
- } else {
- socket.close(true);
- }
- }
- write();
+void testClientCertificate() {
+ ReceivePort port = new ReceivePort();
+ SecureServerSocket.bind(SERVER_ADDRESS,
+ 0,
+ 5,
+ CERTIFICATE,
+ requestClientCertificate: true).then((server) {
+ var clientEndFuture = SecureSocket.connect(HOST_NAME,
+ server.port,
+ sendClientCertificate: true);
+ server.listen((serverEnd) {
+ X509Certificate certificate = serverEnd.peerCertificate;
+ Expect.isNotNull(certificate);
+ Expect.equals("CN=localhost", certificate.subject);
+ Expect.equals("CN=myauthority", certificate.issuer);
+ clientEndFuture.then((clientEnd) {
+ X509Certificate certificate = clientEnd.peerCertificate;
+ Expect.isNotNull(certificate);
+ Expect.equals("CN=localhost", certificate.subject);
+ Expect.equals("CN=myauthority", certificate.issuer);
+ clientEnd.close();
+ serverEnd.close();
+ server.close();
+ port.close();
+ });
+ });
+ });
}
-class SecureTestServer {
- void onConnection(Socket connection) {
- connection.onConnect = () {
- numConnections++;
- var certificate = connection.peerCertificate;
- Expect.isTrue(certificate.subject.contains("CN="));
- };
- String received = "";
- connection.onData = () {
- received = received.concat(new String.fromCharCodes(connection.read()));
- };
- connection.onClosed = () {
- Expect.isTrue(received.contains("Hello from client "));
- String name = received.substring(received.indexOf("client ") + 7);
- WriteAndClose(connection, "Welcome, client $name");
- };
- }
-
- void errorHandlerServer(Exception e) {
- Expect.fail("Server socket error $e");
- }
-
- int start() {
- server = new SecureServerSocket(SERVER_ADDRESS,
- 0,
- 10,
- "localhost_cert",
- requireClientCertificate: true);
- Expect.isNotNull(server);
- server.onConnection = onConnection;
- server.onError = errorHandlerServer;
- return server.port;
- }
-
- void stop() {
- server.close();
- }
-
- int numConnections = 0;
- SecureServerSocket server;
+void testRequiredClientCertificate() {
+ ReceivePort port = new ReceivePort();
+ SecureServerSocket.bind(SERVER_ADDRESS,
+ 0,
+ 5,
+ CERTIFICATE,
+ requireClientCertificate: true).then((server) {
+ var clientEndFuture = SecureSocket.connect(HOST_NAME,
+ server.port,
+ sendClientCertificate: true);
+ server.listen((serverEnd) {
+ X509Certificate certificate = serverEnd.peerCertificate;
+ Expect.isNotNull(certificate);
+ Expect.equals("CN=localhost", certificate.subject);
+ Expect.equals("CN=myauthority", certificate.issuer);
+ clientEndFuture.then((clientEnd) {
+ X509Certificate certificate = clientEnd.peerCertificate;
+ Expect.isNotNull(certificate);
+ Expect.equals("CN=localhost", certificate.subject);
+ Expect.equals("CN=myauthority", certificate.issuer);
+ clientEnd.close();
+ serverEnd.close();
+ server.close();
+ port.close();
+ });
+ });
+ });
}
-class SecureTestClient {
- SecureTestClient(int this.port, String this.name) {
- socket = new SecureSocket(HOST_NAME, port, sendClientCertificate: true);
- socket.onConnect = this.onConnect;
- socket.onData = () {
- reply = reply.concat(new String.fromCharCodes(socket.read()));
- };
- socket.onClosed = done;
- reply = "";
- }
-
- void onConnect() {
- numRequests++;
- WriteAndClose(socket, "Hello from client $name");
- }
-
- void done() {
- Expect.equals("Welcome, client $name", reply);
- numReplies++;
- if (numReplies == CLIENT_NAMES.length) {
- Expect.equals(numRequests, numReplies);
- EndTest();
- }
- }
-
- static int numRequests = 0;
- static int numReplies = 0;
-
- int port;
- String name;
- SecureSocket socket;
- String reply;
+void testNoClientCertificate() {
+ ReceivePort port = new ReceivePort();
+ SecureServerSocket.bind(SERVER_ADDRESS,
+ 0,
+ 5,
+ CERTIFICATE,
+ requestClientCertificate: true).then((server) {
+ var clientEndFuture = SecureSocket.connect(HOST_NAME,
+ server.port);
+ server.listen((serverEnd) {
+ X509Certificate certificate = serverEnd.peerCertificate;
+ Expect.isNull(certificate);
+ clientEndFuture.then((clientEnd) {
+ clientEnd.close();
+ serverEnd.close();
+ server.close();
+ port.close();
+ });
+ });
+ });
}
-Function EndTest;
-
-const CLIENT_NAMES = const ['able', 'baker', 'camera', 'donut', 'echo'];
+void testNoRequiredClientCertificate() {
+ ReceivePort port = new ReceivePort();
+ bool clientError = false;
+ SecureServerSocket.bind(SERVER_ADDRESS,
+ 0,
+ 5,
+ CERTIFICATE,
+ requireClientCertificate: true).then((server) {
+ Future clientDone = SecureSocket.connect(HOST_NAME, server.port)
+ .catchError((e) { clientError = true; });
+ server.listen((serverEnd) {
+ Expect.fail("Got a unverifiable connection");
+ },
+ onError: (e) {
+ clientDone.then((_) {
+ Expect.isTrue(clientError);
+ server.close();
+ port.close();
+ });
+ });
+ });
+}
void main() {
- ReceivePort keepAlive = new ReceivePort();
Path scriptDir = new Path(new Options().script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
useBuiltinRoots: false);
- var server = new SecureTestServer();
- int port = server.start();
-
- EndTest = () {
- Expect.equals(CLIENT_NAMES.length, server.numConnections);
- server.stop();
- keepAlive.close();
- };
-
- for (var x in CLIENT_NAMES) {
- new SecureTestClient(port, x);
- }
+ testClientCertificate();
+ testRequiredClientCertificate();
+ testNoClientCertificate();
+ testNoRequiredClientCertificate();
}
diff --git a/tests/standalone/io/secure_server_closing_test.dart b/tests/standalone/io/secure_server_closing_test.dart
index 794c54f..fde898c 100644
--- a/tests/standalone/io/secure_server_closing_test.dart
+++ b/tests/standalone/io/secure_server_closing_test.dart
@@ -105,7 +105,7 @@
connection.close();
});
}
- new Timer(500, (_) {
+ new Timer(const Duration(milliseconds: 500), () {
subscription.resume();
resumed = true;
for (int i = 0; i < socketCount; i++) {
diff --git a/tests/standalone/io/secure_server_socket_test.dart b/tests/standalone/io/secure_server_socket_test.dart
index cadabf3..c66019a 100644
--- a/tests/standalone/io/secure_server_socket_test.dart
+++ b/tests/standalone/io/secure_server_socket_test.dart
@@ -119,7 +119,7 @@
SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
Expect.isTrue(server.port > 0);
var clientEndFuture = SecureSocket.connect(HOST_NAME, server.port);
- new Timer(500, (_) {
+ new Timer(const Duration(milliseconds: 500), () {
server.listen((serverEnd) {
clientEndFuture.then((clientEnd) {
clientEnd.close();
@@ -142,7 +142,7 @@
const messageSize = 1000;
List<int> createTestData() {
- List<int> data = new List.fixedLength(messageSize);
+ List<int> data = new List<int>(messageSize);
for (int i = 0; i < messageSize; i++) {
data[i] = i & 0xff;
}
@@ -161,7 +161,7 @@
server.listen((client) {
int bytesRead = 0;
int bytesWritten = 0;
- List<int> data = new List.fixedLength(messageSize);
+ List<int> data = new List<int>(messageSize);
client.listen(
(buffer) {
@@ -183,7 +183,7 @@
int bytesRead = 0;
int bytesWritten = 0;
List<int> dataSent = createTestData();
- List<int> dataReceived = new List<int>.fixedLength(dataSent.length);
+ List<int> dataReceived = new List<int>(dataSent.length);
socket.add(dataSent);
socket.close(); // Can also be delayed.
socket.listen(
diff --git a/tests/standalone/io/secure_session_resume_test.dart b/tests/standalone/io/secure_session_resume_test.dart
index b1cf5ebf..f862c64 100644
--- a/tests/standalone/io/secure_session_resume_test.dart
+++ b/tests/standalone/io/secure_session_resume_test.dart
@@ -34,7 +34,7 @@
String received = new String.fromCharCodes(message);
Expect.isTrue(received.contains("Hello from client "));
String name = received.substring(received.indexOf("client ") + 7);
- client.add("Welcome, client $name".charCodes);
+ client.add("Welcome, client $name".codeUnits);
client.close();
});
});
@@ -44,11 +44,11 @@
Future testClient(server, name) {
return SecureSocket.connect(HOST_NAME, server.port).then((socket) {
- socket.add("Hello from client $name".charCodes);
+ socket.add("Hello from client $name".codeUnits);
socket.close();
return socket.reduce(<int>[], (message, data) => message..addAll(data))
.then((message) {
- Expect.listEquals("Welcome, client $name".charCodes, message);
+ Expect.listEquals("Welcome, client $name".codeUnits, message);
return server;
});
});
diff --git a/tests/standalone/io/secure_socket_bad_certificate_test.dart b/tests/standalone/io/secure_socket_bad_certificate_test.dart
index 4e8bc0e..3f2b320 100644
--- a/tests/standalone/io/secure_socket_bad_certificate_test.dart
+++ b/tests/standalone/io/secure_socket_bad_certificate_test.dart
@@ -49,7 +49,7 @@
onBadCertificate: badCertificateCallback)
.then((socket) {
Expect.isTrue(acceptCertificate);
- socket.add("GET / HTTP/1.0\r\nHost: $host\r\n\r\n".charCodes);
+ socket.add("GET / HTTP/1.0\r\nHost: $host\r\n\r\n".codeUnits);
socket.close();
return socket.reduce(<int>[], (message, data) => message..addAll(data))
.then((message) {
diff --git a/tests/standalone/io/secure_socket_test.dart b/tests/standalone/io/secure_socket_test.dart
index fec1115..abe27b1 100644
--- a/tests/standalone/io/secure_socket_test.dart
+++ b/tests/standalone/io/secure_socket_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
@@ -7,26 +7,55 @@
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write
-import "dart:isolate";
+import "dart:async";
import "dart:io";
+Future<HttpServer> startServer() {
+ return HttpServer.bindSecure(
+ "127.0.0.1",
+ 0,
+ backlog: 5,
+ certificateName: 'localhost_cert').then((server) {
+ server.listen((HttpRequest request) {
+ request.listen(
+ (_) { },
+ onDone: () {
+ request.response.contentLength = 100;
+ for (int i = 0; i < 10; i++) {
+ request.response.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+ }
+ request.response.close();
+ });
+ });
+ return server;
+ });
+}
+
+void InitializeSSL() {
+ var testPkcertDatabase =
+ new Path(new Options().script).directoryPath.append('pkcert/');
+ SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
+ password: 'dartdart');
+}
+
void main() {
- ReceivePort keepAlive = new ReceivePort();
- SecureSocket.initialize();
- List<String> chunks = <String>[];
- SecureSocket.connect("www.google.dk", 443).then((socket) {
- socket.add("GET / HTTP/1.0\r\nHost: www.google.dk\r\n\r\n".charCodes);
- socket.close();
- socket.listen(
- (List<int> data) {
- var received = new String.fromCharCodes(data);
- chunks.add(received);
- },
- onDone: () {
- String fullPage = chunks.join();
- Expect.isTrue(fullPage.contains('</body></html>'));
- keepAlive.close();
- },
- onError: (e) => Expect.fail("Unexpected error $e"));
+ InitializeSSL();
+ List<int> body = <int>[];
+ startServer().then((server) {
+ SecureSocket.connect("localhost", server.port).then((socket) {
+ socket.add("GET / HTTP/1.0\r\nHost: localhost\r\n\r\n".codeUnits);
+ socket.close();
+ socket.listen(
+ (List<int> data) {
+ body.addAll(data);
+ },
+ onDone: () {
+ Expect.isTrue(body.length > 100, "$body\n${body.length}");
+ Expect.equals(72, body[0]);
+ Expect.equals(9, body[body.length - 1]);
+ server.close();
+ },
+ onError: (e) => Expect.fail("Unexpected error $e"));
+ });
});
}
diff --git a/tests/standalone/io/socket_close_test.dart b/tests/standalone/io/socket_close_test.dart
index dcb90a2..4d72f3c 100644
--- a/tests/standalone/io/socket_close_test.dart
+++ b/tests/standalone/io/socket_close_test.dart
@@ -101,7 +101,7 @@
onError: (error) => errorHandler(socket));
void writeHello() {
- socket.add("Hello".charCodes);
+ socket.add("Hello".codeUnits);
}
_iterations++;
@@ -224,7 +224,7 @@
}
void writeHello() {
- connection.add("Hello".charCodes);
+ connection.add("Hello".codeUnits);
}
void dataHandler(bytes) {
diff --git a/tests/standalone/io/socket_exception_test.dart b/tests/standalone/io/socket_exception_test.dart
index 7624ac7..f2fec68 100644
--- a/tests/standalone/io/socket_exception_test.dart
+++ b/tests/standalone/io/socket_exception_test.dart
@@ -87,7 +87,7 @@
Expect.isFalse(exceptionCaught);
Expect.isFalse(wrongExceptionCaught);
try {
- List<int> buffer = new List<int>.fixedLength(10);
+ List<int> buffer = new List<int>(10);
client.add(buffer);
} on StateError catch (ex) {
exceptionCaught = true;
@@ -121,7 +121,7 @@
});
Socket.connect("127.0.0.1", server.port).then((client) {
client.listen((data) {}, onDone: server.close);
- client.add(new List.fixedLength(1024 * 1024, fill: 0));
+ client.add(new List.filled(1024 * 1024, 0));
client.destroy();
});
});
@@ -143,7 +143,7 @@
Expect.equals(SIZE, count);
server.close();
});
- client.add(new List.fixedLength(SIZE, fill: 0));
+ client.add(new List.filled(SIZE, 0));
client.close();
// Start piping now.
completer.complete(null);
@@ -174,7 +174,7 @@
Expect.isTrue(errors <= 1);
server.close();
});
- client.add(new List.fixedLength(SIZE, fill: 0));
+ client.add(new List.filled(SIZE, 0));
// Destroy other socket now.
completer.complete(null);
var port = new ReceivePort();
@@ -199,7 +199,7 @@
Socket.connect("127.0.0.1", server.port).then((client) {
const int SIZE = 1024 * 1024;
int errors = 0;
- client.add(new List.fixedLength(SIZE, fill: 0));
+ client.add(new List.filled(SIZE, 0));
client.close();
client.done.catchError((error) {
server.close();
diff --git a/tests/standalone/io/socket_many_connections_test.dart b/tests/standalone/io/socket_many_connections_test.dart
index c313fe1..49aa34d 100644
--- a/tests/standalone/io/socket_many_connections_test.dart
+++ b/tests/standalone/io/socket_many_connections_test.dart
@@ -17,7 +17,7 @@
: _receivePort = new ReceivePort(),
_sendPort = null,
_connections = 0,
- _sockets = new List<Socket>.fixedLength(CONNECTIONS) {
+ _sockets = new List<Socket>(CONNECTIONS) {
_sendPort = spawnFunction(startTestServer);
initialize();
}
diff --git a/tests/standalone/io/stdout_bad_argument_test.dart b/tests/standalone/io/stdout_bad_argument_test.dart
new file mode 100644
index 0000000..95ce44d
--- /dev/null
+++ b/tests/standalone/io/stdout_bad_argument_test.dart
@@ -0,0 +1,13 @@
+// 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.
+
+import "dart:io";
+
+main() {
+ stdout.add("Hello\n");
+ stdout.done.catchError((e) {
+ exit(0);
+ });
+ stdin.listen(print);
+}
diff --git a/tests/standalone/io/stream_pipe_test.dart b/tests/standalone/io/stream_pipe_test.dart
index f663e81..46590fa 100644
--- a/tests/standalone/io/stream_pipe_test.dart
+++ b/tests/standalone/io/stream_pipe_test.dart
@@ -34,8 +34,8 @@
}
}
if (count == null) count = length1;
- var data1 = new List<int>.fixedLength(count);
- var data2 = new List<int>.fixedLength(count);
+ var data1 = new List<int>(count);
+ var data2 = new List<int>(count);
if (file1Offset != 0) file1.setPositionSync(file1Offset);
if (file2Offset != 0) file2.setPositionSync(file2Offset);
var read1 = file1.readListSync(data1, 0, count);
@@ -112,7 +112,7 @@
dstFileName,
count: srcLength));
dst.setPositionSync(srcLength);
- var data = new List<int>.fixedLength(1);
+ var data = new List<int>(1);
var read2 = dst.readListSync(data, 0, 1);
Expect.equals(32, data[0]);
src.closeSync();
diff --git a/tests/standalone/io/string_decoder_test.dart b/tests/standalone/io/string_decoder_test.dart
index 6a81f95..4952676 100644
--- a/tests/standalone/io/string_decoder_test.dart
+++ b/tests/standalone/io/string_decoder_test.dart
@@ -15,7 +15,7 @@
controller.add([0xfd, 0x80, 0x80, 0x80, 0x80, 0x80]); // U+40000000
controller.close();
- var decoder = new StringDecoder(Encoding.UTF_8, '?'.charCodeAt(0));
+ var decoder = new StringDecoder(Encoding.UTF_8, '?'.codeUnitAt(0));
var stream = controller.stream.transform(decoder);
stream.reduce(
new StringBuffer(),
@@ -27,14 +27,14 @@
.then((decoded) {
Expect.equals(7, decoded.length);
- var replacementChar = '?'.charCodeAt(0);
- Expect.equals(0xd800, decoded.charCodeAt(0));
- Expect.equals(0xdc00, decoded.charCodeAt(1));
- Expect.equals(0xdbff, decoded.charCodeAt(2));
- Expect.equals(0xdfff, decoded.charCodeAt(3));
- Expect.equals(replacementChar, decoded.charCodeAt(4));
- Expect.equals(replacementChar, decoded.charCodeAt(5));
- Expect.equals(replacementChar, decoded.charCodeAt(6));
+ var replacementChar = '?'.codeUnitAt(0);
+ Expect.equals(0xd800, decoded.codeUnitAt(0));
+ Expect.equals(0xdc00, decoded.codeUnitAt(1));
+ Expect.equals(0xdbff, decoded.codeUnitAt(2));
+ Expect.equals(0xdfff, decoded.codeUnitAt(3));
+ Expect.equals(replacementChar, decoded.codeUnitAt(4));
+ Expect.equals(replacementChar, decoded.codeUnitAt(5));
+ Expect.equals(replacementChar, decoded.codeUnitAt(6));
});
}
@@ -46,7 +46,7 @@
controller.stream.transform(new StringDecoder()).listen((string) {
Expect.equals(outputLength, string.length);
for (var i = 0; i < outputLength; i++) {
- Expect.equals(0xFFFD, string.charCodeAt(i));
+ Expect.equals(0xFFFD, string.codeUnitAt(i));
}
});
}
diff --git a/tests/standalone/io/string_transformer_test.dart b/tests/standalone/io/string_transformer_test.dart
index 16b1b3f..2a9015e 100644
--- a/tests/standalone/io/string_transformer_test.dart
+++ b/tests/standalone/io/string_transformer_test.dart
@@ -114,7 +114,7 @@
stringData,
onDone: streamClosed);
- controller.add("Line".charCodes);
+ controller.add("Line".codeUnits);
}
void testReadLine2() {
@@ -138,7 +138,7 @@
Expect.equals("Line3", line);
subStage = 0;
stage++;
- controller.add("ne4\n".charCodes);
+ controller.add("ne4\n".codeUnits);
} else {
Expect.fail("Stage 0 failed");
}
@@ -147,7 +147,7 @@
Expect.equals("Line4", line);
subStage = 0;
stage++;
- controller.add("\n\n\r\n\r\n\r\r".charCodes);
+ controller.add("\n\n\r\n\r\n\r\r".codeUnits);
} else {
Expect.fail("Stage 1 failed");
}
@@ -178,7 +178,7 @@
Expect.equals(0, subStage);
});
- controller.add("Line1\nLine2\r\nLine3\rLi".charCodes);
+ controller.add("Line1\nLine2\r\nLine3\rLi".codeUnits);
}
class TestException implements Exception {
@@ -221,7 +221,6 @@
Expect.fail("data not expected");
},
onError: (error) {
- print(error);
Expect.isTrue(error.error is FormatException);
});
diff --git a/tests/standalone/io/url_encoding_test.dart b/tests/standalone/io/url_encoding_test.dart
index cfeefe5..788dfb1 100644
--- a/tests/standalone/io/url_encoding_test.dart
+++ b/tests/standalone/io/url_encoding_test.dart
@@ -5,7 +5,7 @@
import "dart:async";
import "dart:utf";
-part '../../../sdk/lib/io/io_stream_consumer.dart';
+part '../../../sdk/lib/io/io_sink.dart';
part "../../../sdk/lib/io/http.dart";
part "../../../sdk/lib/io/http_impl.dart";
part "../../../sdk/lib/io/http_parser.dart";
diff --git a/tests/standalone/io/web_socket_no_secure_test.dart b/tests/standalone/io/web_socket_no_secure_test.dart
deleted file mode 100644
index 46e1d03..0000000
--- a/tests/standalone/io/web_socket_no_secure_test.dart
+++ /dev/null
@@ -1,281 +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.
-//
-// VMOptions=
-// VMOptions=--short_socket_read
-// VMOptions=--short_socket_write
-// VMOptions=--short_socket_read --short_socket_write
-
-// TODO(7157): Remove this test once the bug is fixed.
-// This is a copy of web_socket_test.dart with the secure connection
-// tests disabled, so it does not crash on Windows.
-import "dart:io";
-import "dart:isolate";
-import "dart:scalarlist";
-
-void testRequestResponseClientCloses(
- int totalConnections, int closeStatus, String closeReason) {
- HttpServer.bind().then((server) {
-
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- webSocket.listen((event) {
- if (event is MessageEvent) {
- webSocket.send(event.data);
- } else if (event is CloseEvent) {
- Expect.equals(closeStatus == null
- ? WebSocketStatus.NO_STATUS_RECEIVED
- : closeStatus, event.code);
- Expect.equals(closeReason == null ? "" : closeReason, event.reason);
- }
- });
- });
-
- int closeCount = 0;
- String messageText = "Hello, world!";
- for (int i = 0; i < totalConnections; i++) {
- int messageCount = 0;
- WebSocket.connect("ws://127.0.0.1:${server.port}/")
- .then((webSocket) {
- webSocket.send(messageText);
- webSocket.listen((event) {
- if (event is MessageEvent) {
- messageCount++;
- if (messageCount < 1 ) {
- Expect.equals(messageText, event.data);
- webSocket.send(event.data);
- } else {
- webSocket.close(closeStatus, closeReason);
- }
- } else if (event is CloseEvent) {
- Expect.equals(closeStatus == null
- ? WebSocketStatus.NO_STATUS_RECEIVED
- : closeStatus, event.code);
- Expect.equals("", event.reason);
- closeCount++;
- if (closeCount == totalConnections) {
- server.close();
- }
- }
- });
- });
- }
-
- });
-}
-
-
-void testRequestResponseServerCloses(
- int totalConnections, int closeStatus, String closeReason) {
- HttpServer.bind().then((server) {
-
- int closeCount = 0;
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- String messageText = "Hello, world!";
- int messageCount = 0;
- webSocket.listen((event) {
- if (event is MessageEvent) {
- messageCount++;
- if (messageCount < 10) {
- Expect.equals(messageText, event.data);
- webSocket.send(event.data);
- } else {
- webSocket.close(closeStatus, closeReason);
- }
- } else if (event is CloseEvent) {
- Expect.equals(closeStatus == null
- ? WebSocketStatus.NO_STATUS_RECEIVED
- : closeStatus, event.code);
- Expect.equals("", event.reason);
- closeCount++;
- if (closeCount == totalConnections) {
- server.close();
- }
- }
- });
- webSocket.send(messageText);
- });
-
- for (int i = 0; i < totalConnections; i++) {
- WebSocket.connect("ws://127.0.0.1:${server.port}/")
- .then((webSocket) {
- webSocket.listen((event) {
- if (event is MessageEvent) {
- webSocket.send(event.data);
- } else if (event is CloseEvent) {
- Expect.equals(closeStatus == null
- ? WebSocketStatus.NO_STATUS_RECEIVED
- : closeStatus, event.code);
- Expect.equals(
- closeReason == null ? "" : closeReason, event.reason);
- }
- });
- });
- }
-
- });
-}
-
-
-void testMessageLength(int messageLength) {
- HttpServer.bind().then((server) {
-
- Uint8List originalMessage = new Uint8List(messageLength);
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- webSocket.listen((event) {
- if (event is MessageEvent) {
- Expect.listEquals(originalMessage, event.data);
- webSocket.send(event.data);
- } else if (event is CloseEvent) {
- }
- });
- });
-
- WebSocket.connect("ws://127.0.0.1:${server.port}/")
- .then((webSocket) {
- webSocket.listen((event) {
- if (event is MessageEvent) {
- Expect.listEquals(originalMessage, event.data);
- webSocket.close();
- } else if (event is CloseEvent) {
- server.close();
- }
- });
- webSocket.send(originalMessage);
- });
-
- });
-}
-
-
-void testNoUpgrade() {
- HttpServer.bind().then((server) {
-
- // Create a server which always responds with NOT_FOUND.
- server.listen((request) {
- request.response.statusCode = HttpStatus.NOT_FOUND;
- request.response.close();
- });
-
- WebSocket.connect("ws://127.0.0.1:${server.port}/").catchError((error) {
- server.close();
- });
-
- });
-}
-
-
-void testUsePOST() {
- HttpServer.bind().then((server) {
-
- var errorPort = new ReceivePort();
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- Expect.fail("No connection expected");
- }, onError: (e) {
- errorPort.close();
- });
-
- HttpClient client = new HttpClient();
- client.post("127.0.0.1", server.port, "/")
- .then((request) => request.close())
- .then((response) {
- Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode);
- client.close();
- server.close();
- });
-
- });
-}
-
-
-class WebSocketInfo {
- int messageCount = 0;
-}
-
-
-void testW3CInterface(
- int totalConnections, int closeStatus, String closeReason) {
- HttpServer.bind().then((server) {
-
- int closeCount = 0;
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- String messageText = "Hello, world!";
- int messageCount = 0;
- webSocket.listen((event) {
- if (event is MessageEvent) {
- messageCount++;
- if (messageCount < 10) {
- Expect.equals(messageText, event.data);
- webSocket.send(event.data);
- } else {
- webSocket.close(closeStatus, closeReason);
- }
- } else if (event is CloseEvent) {
- Expect.equals(closeStatus, event.code);
- Expect.equals("", event.reason);
- closeCount++;
- if (closeCount == totalConnections) {
- server.close();
- }
- }
- });
- webSocket.send(messageText);
- });
-
- void webSocketConnection() {
- bool onopenCalled = false;
- int onmessageCalled = 0;
- bool oncloseCalled = false;
-
- WebSocket.connect("ws://127.0.0.1:${server.port}").then((webSocket) {
- Expect.isFalse(onopenCalled);
- Expect.equals(0, onmessageCalled);
- Expect.isFalse(oncloseCalled);
- onopenCalled = true;
- Expect.equals(WebSocket.OPEN, webSocket.readyState);
- webSocket.listen((event) {
- if (event is MessageEvent) {
- onmessageCalled++;
- Expect.isTrue(onopenCalled);
- Expect.isFalse(oncloseCalled);
- Expect.equals(WebSocket.OPEN, webSocket.readyState);
- webSocket.send(event.data);
- } else if (event is CloseEvent) {
- Expect.isTrue(onopenCalled);
- Expect.equals(10, onmessageCalled);
- Expect.isFalse(oncloseCalled);
- oncloseCalled = true;
- Expect.isTrue(event.wasClean);
- Expect.equals(3002, event.code);
- Expect.equals("Got tired", event.reason);
- Expect.equals(WebSocket.CLOSED, webSocket.readyState);
- }
- });
- });
- }
-
- for (int i = 0; i < totalConnections; i++) {
- webSocketConnection();
- }
-
- });
-}
-
-
-main() {
- testRequestResponseClientCloses(2, null, null);
- testRequestResponseClientCloses(2, 3001, null);
- testRequestResponseClientCloses(2, 3002, "Got tired");
- testRequestResponseServerCloses(2, null, null);
- testRequestResponseServerCloses(2, 3001, null);
- testRequestResponseServerCloses(2, 3002, "Got tired");
- testMessageLength(125);
- testMessageLength(126);
- testMessageLength(127);
- testMessageLength(65535);
- testMessageLength(65536);
- testNoUpgrade();
- testUsePOST();
-
- testW3CInterface(2, 3002, "Got tired");
-}
diff --git a/tests/standalone/io/web_socket_protocol_processor_test.dart b/tests/standalone/io/web_socket_protocol_processor_test.dart
index 6ab0da9..9c891d6 100644
--- a/tests/standalone/io/web_socket_protocol_processor_test.dart
+++ b/tests/standalone/io/web_socket_protocol_processor_test.dart
@@ -6,7 +6,7 @@
import "dart:async";
part "../../../sdk/lib/io/http.dart";
-part "../../../sdk/lib/io/io_stream_consumer.dart";
+part "../../../sdk/lib/io/io_sink.dart";
part "../../../sdk/lib/io/websocket.dart";
part "../../../sdk/lib/io/websocket_impl.dart";
@@ -75,7 +75,7 @@
frameSize += count;
// No masking.
assert(maskingKey == null);
- List<int> frame = new List<int>.fixedLength(frameSize);
+ List<int> frame = new List<int>(frameSize);
int frameIndex = 0;
frame[frameIndex++] = (fin ? 0x80 : 0x00) | opcode;
if (count < 126) {
@@ -136,7 +136,7 @@
void runTest(int from, int to, int step) {
for (int messageLength = from; messageLength < to; messageLength += step) {
- List<int> message = new List<int>.fixedLength(messageLength);
+ List<int> message = new List<int>(messageLength);
for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
testMessage(FRAME_OPCODE_TEXT, message);
testMessage(FRAME_OPCODE_BINARY, message);
@@ -202,7 +202,7 @@
void runTest(int from, int to, int step) {
for (int messageLength = from; messageLength < to; messageLength += step) {
- List<int> message = new List<int>.fixedLength(messageLength);
+ List<int> message = new List<int>(messageLength);
for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
testMessageFragmentation(FRAME_OPCODE_TEXT, message);
testMessageFragmentation(FRAME_OPCODE_BINARY, message);
diff --git a/tests/standalone/io/web_socket_test.dart b/tests/standalone/io/web_socket_test.dart
index baa6ddd..937467a 100644
--- a/tests/standalone/io/web_socket_test.dart
+++ b/tests/standalone/io/web_socket_test.dart
@@ -7,272 +7,366 @@
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write
+import "dart:async";
import "dart:io";
import "dart:isolate";
import "dart:scalarlist";
+import "dart:uri";
-void testRequestResponseClientCloses(
- int totalConnections, int closeStatus, String closeReason) {
- HttpServer.bind().then((server) {
+const String CERT_NAME = 'localhost_cert';
+const String SERVER_ADDRESS = '127.0.0.1';
+const String HOST_NAME = 'localhost';
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- webSocket.listen((event) {
- if (event is MessageEvent) {
- webSocket.send(event.data);
- } else if (event is CloseEvent) {
- Expect.equals(closeStatus == null
- ? WebSocketStatus.NO_STATUS_RECEIVED
- : closeStatus, event.code);
- Expect.equals(closeReason == null ? "" : closeReason, event.reason);
- }
- });
- });
+/**
+ * A SecurityConfiguration lets us run the tests over HTTP or HTTPS.
+ */
+class SecurityConfiguration {
+ final bool secure;
- int closeCount = 0;
- String messageText = "Hello, world!";
- for (int i = 0; i < totalConnections; i++) {
- int messageCount = 0;
- WebSocket.connect("ws://127.0.0.1:${server.port}/")
- .then((webSocket) {
+ SecurityConfiguration({bool this.secure});
+
+ Future<HttpServer> createServer({int backlog: 0}) =>
+ secure ? HttpServer.bindSecure(SERVER_ADDRESS,
+ 0,
+ backlog: backlog,
+ certificateName: CERT_NAME)
+ : HttpServer.bind(SERVER_ADDRESS,
+ 0,
+ backlog);
+
+ Future<WebSocket> createClient(int port) =>
+ WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/');
+
+ void testRequestResponseClientCloses(int totalConnections,
+ int closeStatus,
+ String closeReason) {
+ createServer().then((server) {
+ server.transform(new WebSocketTransformer()).listen((webSocket) {
+ webSocket.listen(
+ webSocket.send,
+ onDone: () {
+ Expect.equals(closeStatus == null
+ ? WebSocketStatus.NO_STATUS_RECEIVED
+ : closeStatus, webSocket.closeCode);
+ Expect.equals(closeReason == null ? "" : closeReason, webSocket.closeReason);
+ });
+ });
+
+ int closeCount = 0;
+ String messageText = "Hello, world!";
+ for (int i = 0; i < totalConnections; i++) {
+ int messageCount = 0;
+ createClient(server.port).then((webSocket) {
webSocket.send(messageText);
- webSocket.listen((event) {
- if (event is MessageEvent) {
+ webSocket.listen(
+ (message) {
+ messageCount++;
+ if (messageCount < 1 ) {
+ Expect.equals(messageText, message);
+ webSocket.send(message);
+ } else {
+ webSocket.close(closeStatus, closeReason);
+ }
+ },
+ onDone: () {
+ Expect.equals(closeStatus == null
+ ? WebSocketStatus.NO_STATUS_RECEIVED
+ : closeStatus, webSocket.closeCode);
+ Expect.equals("", webSocket.closeReason);
+ closeCount++;
+ if (closeCount == totalConnections) {
+ server.close();
+ }
+ });
+ });
+ }
+ });
+ }
+
+ void testRequestResponseServerCloses(int totalConnections,
+ int closeStatus,
+ String closeReason) {
+ createServer().then((server) {
+ int closeCount = 0;
+ server.transform(new WebSocketTransformer()).listen((webSocket) {
+ String messageText = "Hello, world!";
+ int messageCount = 0;
+ webSocket.listen(
+ (message) {
messageCount++;
- if (messageCount < 1 ) {
- Expect.equals(messageText, event.data);
- webSocket.send(event.data);
+ if (messageCount < 10) {
+ Expect.equals(messageText, message);
+ webSocket.send(message);
} else {
webSocket.close(closeStatus, closeReason);
}
- } else if (event is CloseEvent) {
+ },
+ onDone: () {
Expect.equals(closeStatus == null
? WebSocketStatus.NO_STATUS_RECEIVED
- : closeStatus, event.code);
- Expect.equals("", event.reason);
+ : closeStatus, webSocket.closeCode);
+ Expect.equals("", webSocket.closeReason);
closeCount++;
if (closeCount == totalConnections) {
server.close();
}
- }
- });
- });
- }
-
- });
-}
-
-
-void testRequestResponseServerCloses(
- int totalConnections, int closeStatus, String closeReason) {
- HttpServer.bind().then((server) {
-
- int closeCount = 0;
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- String messageText = "Hello, world!";
- int messageCount = 0;
- webSocket.listen((event) {
- if (event is MessageEvent) {
- messageCount++;
- if (messageCount < 10) {
- Expect.equals(messageText, event.data);
- webSocket.send(event.data);
- } else {
- webSocket.close(closeStatus, closeReason);
- }
- } else if (event is CloseEvent) {
- Expect.equals(closeStatus == null
- ? WebSocketStatus.NO_STATUS_RECEIVED
- : closeStatus, event.code);
- Expect.equals("", event.reason);
- closeCount++;
- if (closeCount == totalConnections) {
- server.close();
- }
- }
+ });
+ webSocket.send(messageText);
});
- webSocket.send(messageText);
+
+ for (int i = 0; i < totalConnections; i++) {
+ createClient(server.port).then((webSocket) {
+ webSocket.listen(
+ webSocket.send,
+ onDone: () {
+ Expect.equals(closeStatus == null
+ ? WebSocketStatus.NO_STATUS_RECEIVED
+ : closeStatus, event.code);
+ Expect.equals(
+ closeReason == null ? "" : closeReason, event.reason);
+ });
+ });
+ }
});
-
- for (int i = 0; i < totalConnections; i++) {
- WebSocket.connect("ws://127.0.0.1:${server.port}/")
- .then((webSocket) {
- webSocket.listen((event) {
- if (event is MessageEvent) {
- webSocket.send(event.data);
- } else if (event is CloseEvent) {
- Expect.equals(closeStatus == null
- ? WebSocketStatus.NO_STATUS_RECEIVED
- : closeStatus, event.code);
- Expect.equals(
- closeReason == null ? "" : closeReason, event.reason);
- }
- });
- });
- }
-
- });
-}
+ }
-void testMessageLength(int messageLength) {
- HttpServer.bind().then((server) {
-
- Uint8List originalMessage = new Uint8List(messageLength);
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- webSocket.listen((event) {
- if (event is MessageEvent) {
- Expect.listEquals(originalMessage, event.data);
- webSocket.send(event.data);
- } else if (event is CloseEvent) {
- }
+ void testMessageLength(int messageLength) {
+ createServer().then((server) {
+ Uint8List originalMessage = new Uint8List(messageLength);
+ server.transform(new WebSocketTransformer()).listen((webSocket) {
+ webSocket.listen(
+ (message) {
+ Expect.listEquals(originalMessage, message);
+ webSocket.send(message);
+ });
});
- });
- WebSocket.connect("ws://127.0.0.1:${server.port}/")
- .then((webSocket) {
- webSocket.listen((event) {
- if (event is MessageEvent) {
- Expect.listEquals(originalMessage, event.data);
- webSocket.close();
- } else if (event is CloseEvent) {
- server.close();
- }
- });
+ createClient(server.port).then((webSocket) {
+ webSocket.listen(
+ (message) {
+ Expect.listEquals(originalMessage, message);
+ webSocket.close();
+ },
+ onDone: server.close);
webSocket.send(originalMessage);
});
-
- });
-}
-
-
-void testNoUpgrade() {
- HttpServer.bind().then((server) {
-
- // Create a server which always responds with NOT_FOUND.
- server.listen((request) {
- request.response.statusCode = HttpStatus.NOT_FOUND;
- request.response.close();
});
+ }
- WebSocket.connect("ws://127.0.0.1:${server.port}/").catchError((error) {
- server.close();
+
+ void testDoubleCloseClient() {
+ createServer().then((server) {
+ server.transform(new WebSocketTransformer()).listen((webSocket) {
+ server.close();
+ webSocket.listen((_) { }, onDone: webSocket.close);
+ });
+
+ createClient(server.port).then((webSocket) {
+ webSocket.listen((_) { }, onDone: webSocket.close);
+ webSocket.close();
+ });
});
-
- });
-}
+ }
-void testUsePOST() {
- HttpServer.bind().then((server) {
+ void testDoubleCloseServer() {
+ createServer().then((server) {
+ server.transform(new WebSocketTransformer()).listen((webSocket) {
+ server.close();
+ webSocket.listen((_) { }, onDone: webSocket.close);
+ webSocket.close();
+ });
- var errorPort = new ReceivePort();
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- Expect.fail("No connection expected");
- }, onError: (e) {
- errorPort.close();
+ createClient(server.port).then((webSocket) {
+ webSocket.listen((_) { }, onDone: webSocket.close);
+ });
});
+ }
- HttpClient client = new HttpClient();
- client.post("127.0.0.1", server.port, "/")
- .then((request) => request.close())
- .then((response) {
- Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode);
- client.close();
+
+ void testNoUpgrade() {
+ createServer().then((server) {
+ // Create a server which always responds with NOT_FOUND.
+ server.listen((request) {
+ request.response.statusCode = HttpStatus.NOT_FOUND;
+ request.response.close();
+ });
+
+ createClient(server.port).catchError((error) {
server.close();
});
-
- });
-}
-
-
-class WebSocketInfo {
- int messageCount = 0;
-}
-
-
-void testW3CInterface(
- int totalConnections, int closeStatus, String closeReason) {
- HttpServer.bind().then((server) {
-
- int closeCount = 0;
- server.transform(new WebSocketTransformer()).listen((webSocket) {
- String messageText = "Hello, world!";
- int messageCount = 0;
- webSocket.listen((event) {
- if (event is MessageEvent) {
- messageCount++;
- if (messageCount < 10) {
- Expect.equals(messageText, event.data);
- webSocket.send(event.data);
- } else {
- webSocket.close(closeStatus, closeReason);
- }
- } else if (event is CloseEvent) {
- Expect.equals(closeStatus, event.code);
- Expect.equals("", event.reason);
- closeCount++;
- if (closeCount == totalConnections) {
- server.close();
- }
- }
- });
- webSocket.send(messageText);
});
+ }
- void webSocketConnection() {
- bool onopenCalled = false;
- int onmessageCalled = 0;
- bool oncloseCalled = false;
- WebSocket.connect("ws://127.0.0.1:${server.port}").then((webSocket) {
- Expect.isFalse(onopenCalled);
- Expect.equals(0, onmessageCalled);
- Expect.isFalse(oncloseCalled);
- onopenCalled = true;
- Expect.equals(WebSocket.OPEN, webSocket.readyState);
- webSocket.listen((event) {
- if (event is MessageEvent) {
- onmessageCalled++;
- Expect.isTrue(onopenCalled);
- Expect.isFalse(oncloseCalled);
- Expect.equals(WebSocket.OPEN, webSocket.readyState);
- webSocket.send(event.data);
- } else if (event is CloseEvent) {
- Expect.isTrue(onopenCalled);
- Expect.equals(10, onmessageCalled);
- Expect.isFalse(oncloseCalled);
- oncloseCalled = true;
- Expect.isTrue(event.wasClean);
- Expect.equals(3002, event.code);
- Expect.equals("Got tired", event.reason);
- Expect.equals(WebSocket.CLOSED, webSocket.readyState);
- }
- });
+ void testUsePOST() {
+ createServer().then((server) {
+ var errorPort = new ReceivePort();
+ server.transform(new WebSocketTransformer()).listen((webSocket) {
+ Expect.fail("No connection expected");
+ }, onError: (e) {
+ errorPort.close();
});
- }
- for (int i = 0; i < totalConnections; i++) {
- webSocketConnection();
- }
+ HttpClient client = new HttpClient();
+ client.postUrl(Uri.parse(
+ "${secure ? 'https:' : 'http:'}//$HOST_NAME:${server.port}/"))
+ .then((request) => request.close())
+ .then((response) {
+ Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode);
+ client.close();
+ server.close();
+ });
+ });
+ }
- });
+ void testConnections(int totalConnections,
+ int closeStatus,
+ String closeReason) {
+ createServer().then((server) {
+ int closeCount = 0;
+ server.transform(new WebSocketTransformer()).listen((webSocket) {
+ String messageText = "Hello, world!";
+ int messageCount = 0;
+ webSocket.listen(
+ (message) {
+ messageCount++;
+ if (messageCount < 10) {
+ Expect.equals(messageText, message);
+ webSocket.send(message);
+ } else {
+ webSocket.close(closeStatus, closeReason);
+ }
+ },
+ onDone: () {
+ Expect.equals(closeStatus, webSocket.closeCode);
+ Expect.equals("", webSocket.closeReason);
+ closeCount++;
+ if (closeCount == totalConnections) {
+ server.close();
+ }
+ });
+ webSocket.send(messageText);
+ });
+
+ void webSocketConnection() {
+ bool onopenCalled = false;
+ int onmessageCalled = 0;
+ bool oncloseCalled = false;
+
+ createClient(server.port).then((webSocket) {
+ Expect.isFalse(onopenCalled);
+ Expect.equals(0, onmessageCalled);
+ Expect.isFalse(oncloseCalled);
+ onopenCalled = true;
+ Expect.equals(WebSocket.OPEN, webSocket.readyState);
+ webSocket.listen(
+ (message) {
+ onmessageCalled++;
+ Expect.isTrue(onopenCalled);
+ Expect.isFalse(oncloseCalled);
+ Expect.equals(WebSocket.OPEN, webSocket.readyState);
+ webSocket.send(message);
+ },
+ onDone: () {
+ Expect.isTrue(onopenCalled);
+ Expect.equals(10, onmessageCalled);
+ Expect.isFalse(oncloseCalled);
+ oncloseCalled = true;
+ Expect.isTrue(event.wasClean);
+ Expect.equals(3002, event.code);
+ Expect.equals("Got tired", event.reason);
+ Expect.equals(WebSocket.CLOSED, webSocket.readyState);
+ });
+ });
+ }
+
+ for (int i = 0; i < totalConnections; i++) {
+ webSocketConnection();
+ }
+ });
+ }
+
+ testIndivitualUpgrade(int connections) {
+ createServer().then((server) {
+ server.listen((request) {
+ if (WebSocketTransformer.isUpgradeRequest(request)) {
+ WebSocketTransformer.upgrade(request).then((webSocket) {
+ webSocket.listen((_) { webSocket.close(); });
+ webSocket.send("Hello");
+ });
+ } else {
+ Expect.isFalse(WebSocketTransformer.isUpgradeRequest(request));
+ request.response.statusCode = HttpStatus.OK;
+ request.response.close();
+ }
+ });
+
+ var futures = [];
+
+ var wsProtocol = '${secure ? "wss" : "ws"}';
+ var baseWsUrl = '$wsProtocol://$HOST_NAME:${server.port}/';
+ var httpProtocol = '${secure ? "https" : "http"}';
+ var baseHttpUrl = '$httpProtocol://$HOST_NAME:${server.port}/';
+ HttpClient client = new HttpClient();
+
+ for (int i = 0; i < connections; i++) {
+ var completer = new Completer();
+ futures.add(completer.future);
+ WebSocket.connect('${baseWsUrl}')
+ .then((websocket) {
+ websocket.listen((_) { websocket.close(); },
+ onDone: completer.complete);
+ });
+
+ futures.add(client.openUrl("GET", new Uri.fromString('${baseHttpUrl}'))
+ .then((request) => request.close())
+ .then((response) {
+ response.listen((_) { });
+ Expect.equals(HttpStatus.OK, response.statusCode);
+ }));
+ }
+
+ Future.wait(futures).then((_) {
+ server.close();
+ client.close();
+ });
+ });
+ }
+
+ void runTests() {
+ testRequestResponseClientCloses(2, null, null);
+ testRequestResponseClientCloses(2, 3001, null);
+ testRequestResponseClientCloses(2, 3002, "Got tired");
+ testRequestResponseServerCloses(2, null, null);
+ testRequestResponseServerCloses(2, 3001, null);
+ testRequestResponseServerCloses(2, 3002, "Got tired");
+ testMessageLength(125);
+ testMessageLength(126);
+ testMessageLength(127);
+ testMessageLength(65535);
+ testMessageLength(65536);
+ testDoubleCloseClient();
+ testDoubleCloseServer();
+ testNoUpgrade();
+ testUsePOST();
+ testConnections(10, 3002, "Got tired");
+ testIndivitualUpgrade(5);
+ }
+}
+
+
+void initializeSSL() {
+ var testPkcertDatabase =
+ new Path(new Options().script).directoryPath.append("pkcert/");
+ SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
+ password: "dartdart");
}
main() {
- testRequestResponseClientCloses(2, null, null);
- testRequestResponseClientCloses(2, 3001, null);
- testRequestResponseClientCloses(2, 3002, "Got tired");
- testRequestResponseServerCloses(2, null, null);
- testRequestResponseServerCloses(2, 3001, null);
- testRequestResponseServerCloses(2, 3002, "Got tired");
- testMessageLength(125);
- testMessageLength(126);
- testMessageLength(127);
- testMessageLength(65535);
- testMessageLength(65536);
- testNoUpgrade();
- testUsePOST();
-
- testW3CInterface(2, 3002, "Got tired");
+ new SecurityConfiguration(secure: false).runTests();
+ initializeSSL();
+ new SecurityConfiguration(secure: true).runTests();
}
diff --git a/tests/standalone/io/windows_environment_test.dart b/tests/standalone/io/windows_environment_test.dart
index 1812c25..dfe5af6 100644
--- a/tests/standalone/io/windows_environment_test.dart
+++ b/tests/standalone/io/windows_environment_test.dart
@@ -20,7 +20,7 @@
var scriptDir = new Path(options.script).directoryPath;
var script = scriptDir.append('windows_environment_script.dart');
Process.run('cmd',
- ['/c', funkyFile.name, dart, script.toNativePath()]).then((p) {
+ ['/c', funkyFile.path, dart, script.toNativePath()]).then((p) {
Expect.equals(0, p.exitCode);
tempDir.deleteSync(recursive: true);
});
diff --git a/tests/standalone/out_of_memory_test.dart b/tests/standalone/out_of_memory_test.dart
index 016ab2b..1fb36f9 100644
--- a/tests/standalone/out_of_memory_test.dart
+++ b/tests/standalone/out_of_memory_test.dart
@@ -6,7 +6,7 @@
var number_of_ints = 134000000;
var exception_thrown = false;
try {
- List<int> buf = new List<int>.fixedLength(number_of_ints);
+ List<int> buf = new List<int>(number_of_ints);
} on OutOfMemoryError catch (exc) {
exception_thrown = true;
}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 0bedddf..de4b7a4 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -12,30 +12,25 @@
io/test_runner_exit_code_test: fail
io/test_runner_test: fail
-[ $runtime == vm ]
-io/secure_server_client_certificate_test: fail
-
[ $runtime == vm && ( $system == windows ) ]
-io/web_socket_test: Fail, Pass # Issue 8495.
-io/https_client_certificate_test: Pass, Timeout # Issue 8674
-io/raw_socket_test: Pass, Timeout # Issue 8675
-io/socket_test: Pass, Timeout # Issue 8676
-io/socket_exception_test: Pass, Timeout # Issue 8677
-io/https_client_test: Pass, Timeout # Issue 8674
-io/https_server_test: Pass, Timeout # Issue 8674
-io/https_client_socket_reuse_test: Pass, Timeout # Issue 8674
-io/http_client_request_test: Pass, Fail # Issue 8681
-io/http_proxy_test: Pass, Timeout # Issue 7773
+io/raw_server_socket_cancel_test: Pass, Fail, Timeout # Issue 8675
+io/raw_socket_test: Pass, Fail # Issue 8901
[ $runtime == vm ]
package/package_isolate_test: Fail # http://dartbug.com/7520.
+# Fails with a connection refused error on the buildbot.
+# Issue 8232.
+debugger/basic_debugger_test: Pass, Fail
+
+
[ $runtime == vm && $checked ]
# These tests have type errors on purpose.
io/process_invalid_arguments_test: Fail, OK
io/directory_invalid_arguments_test: Fail, OK
io/file_invalid_arguments_test: Fail, OK
io/socket_invalid_arguments_test: Fail, OK
+io/stdout_bad_argument_test: Fail, OK
# These test have type errors on purpose and take very long to run in
# checked mode with no benefit. Skip.
io/file_fuzz_test: Skip
@@ -44,11 +39,6 @@
[ $runtime == vm && $system == macos ]
io/regress_7191_test: Pass, Timeout # http://dartbug.com/8091
-[ $runtime == vm ]
-# Fails with a connection refused error on the buildbot.
-# Issue 8232.
-debugger/basic_debugger_test: Pass, Fail
-
# This test fails with "Too many open files" on the Mac OS buildbot.
# This is expected as MacOS by default runs with a very low number
# of allowed open files ('ulimit -n' says something like 256).
@@ -96,9 +86,6 @@
io/process_exit_negative_test: Fail # This is a compilation-time negative test.
-[ $compiler == frog ]
-*: Skip
-
[ $compiler == dart2js ]
number_identity_test: Skip # Bigints and int/double diff. not supported.
typed_array_test: Skip # This is a VM test
diff --git a/tests/utils/recursive_import_test.dart b/tests/utils/recursive_import_test.dart
index 6654e17..62bf362 100644
--- a/tests/utils/recursive_import_test.dart
+++ b/tests/utils/recursive_import_test.dart
@@ -31,6 +31,21 @@
class JSInvocationMirror {} // Should be in helper.
""";
+const INTERCEPTORS_LIB = """
+library interceptors;
+class JSArray {
+ get length => null;
+ removeLast() => null;
+ add(x) { }
+}
+class JSString {
+ get length => null;
+ split(x) => null;
+ concat(x) => null;
+ toString() => null;
+}
+""";
+
const String RECURSIVE_MAIN = """
library fisk;
import 'recurse/fisk.dart';
@@ -56,6 +71,8 @@
source = '';
} else if (uri.path.endsWith('isolate_helper.dart')) {
source = 'class _WorkerStub {}';
+ } else if (uri.path.endsWith('interceptors.dart')) {
+ source = INTERCEPTORS_LIB;
} else {
source = "library lib${uri.path.replaceAll('/', '.')};";
}
diff --git a/tests/utils/utf_test.dart b/tests/utils/utf_test.dart
index 6441789..10401a3 100644
--- a/tests/utils/utf_test.dart
+++ b/tests/utils/utf_test.dart
@@ -7,8 +7,8 @@
main() {
String str = codepointsToString([0x1d537]);
- // String.charCodes gives 16-bit code units, but stringToCodepoints gives
+ // String.codeUnits gives 16-bit code units, but stringToCodepoints gives
// back the original code points.
- Expect.listEquals([0xd835, 0xdd37], str.charCodes);
+ Expect.listEquals([0xd835, 0xdd37], str.codeUnits);
Expect.listEquals([0x1d537], stringToCodepoints(str));
}
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index 4d6e186..8119908 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -11,6 +11,9 @@
recursive_import_test: Fail # http://dartbug.com/2264
dart2js_test: Fail # http://dartbug.com/2264
+[ $compiler == dartc ]
+dart2js_test: Fail # http://dartbug.com/8802
+
[ $compiler == dart2js && $browser ]
*: Skip
diff --git a/tools/VERSION b/tools/VERSION
index 2288fc6..0419e66 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 4
-BUILD 0
+BUILD 1
PATCH 0
diff --git a/tools/bots/bot.py b/tools/bots/bot.py
index aea443f..0d9284b 100644
--- a/tools/bots/bot.py
+++ b/tools/bots/bot.py
@@ -42,7 +42,8 @@
"""
def __init__(self, compiler, runtime, mode, system, checked=False,
host_checked=False, minified=False, shard_index=None,
- total_shards=None, is_buildbot=False, test_set=None):
+ total_shards=None, is_buildbot=False, test_set=None,
+ csp=None):
self.compiler = compiler
self.runtime = runtime
self.mode = mode
@@ -54,6 +55,7 @@
self.total_shards = total_shards
self.is_buildbot = is_buildbot
self.test_set = test_set
+ self.csp = csp
def PrintBuildInfo(self):
shard_description = ""
@@ -214,7 +216,7 @@
cmd.extend(flags)
cmd.extend(targets)
- print 'Running: %s' % (' '.join(cmd))
+ print 'Running: %s' % (' '.join(map(lambda arg: '"%s"' % arg, cmd)))
RunProcess(cmd)
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index fbcaeb3..45636c7 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -22,7 +22,7 @@
DART2JS_BUILDER = (
r'dart2js-(linux|mac|windows)(-(jsshell))?-(debug|release)(-(checked|host-checked))?(-(host-checked))?(-(minified))?-?(\d*)-?(\d*)')
WEB_BUILDER = (
- r'dart2js-(ie9|ie10|ff|safari|chrome|opera)-(win7|win8|mac10\.8|mac10\.7|linux)(-(all|html))?(-(\d+)-(\d+))?')
+ r'dart2js-(ie9|ie10|ff|safari|chrome|opera)-(win7|win8|mac10\.8|mac10\.7|linux)(-(all|html))?(-(csp))?(-(\d+)-(\d+))?')
def GetBuildInfo(builder_name, is_buildbot):
@@ -39,6 +39,7 @@
shard_index = None
total_shards = None
test_set = None
+ csp = None
dart2js_pattern = re.match(DART2JS_BUILDER, builder_name)
web_pattern = re.match(WEB_BUILDER, builder_name)
@@ -49,8 +50,10 @@
system = web_pattern.group(2)
mode = 'release'
test_set = web_pattern.group(4)
- shard_index = web_pattern.group(6)
- total_shards = web_pattern.group(7)
+ if web_pattern.group(6) == 'csp':
+ csp = True
+ shard_index = web_pattern.group(8)
+ total_shards = web_pattern.group(9)
elif dart2js_pattern:
compiler = 'dart2js'
system = dart2js_pattern.group(1)
@@ -91,7 +94,7 @@
return None
return bot.BuildInfo(compiler, runtime, mode, system, checked, host_checked,
minified, shard_index, total_shards, is_buildbot,
- test_set)
+ test_set, csp)
def NeedsXterm(compiler, runtime):
@@ -146,7 +149,7 @@
cmd.extend(flags)
cmd.extend(targets)
- print 'running %s' % (' '.join(cmd))
+ print 'Running: %s' % (' '.join(map(lambda arg: '"%s"' % arg, cmd)))
bot.RunProcess(cmd)
@@ -294,6 +297,8 @@
if build_info.minified: test_flags += ['--minified']
+ if build_info.csp: test_flags += ['--csp']
+
TestCompiler(build_info.runtime, build_info.mode, build_info.system,
list(test_flags), build_info.is_buildbot, build_info.test_set)
diff --git a/tools/bots/pub.py b/tools/bots/pub.py
index c5e89fb..f778cad 100755
--- a/tools/bots/pub.py
+++ b/tools/bots/pub.py
@@ -47,7 +47,7 @@
print 'Building package-root: %s' % (' '.join(args))
bot.RunProcess(args)
- bot.RunTest('pub', build_info, ['pub', 'pkg'])
+ bot.RunTest('pub', build_info, ['pub', 'pkg', 'dartdoc'])
if __name__ == '__main__':
diff --git a/tools/copy_dart.py b/tools/copy_dart.py
index b60ad89..9918e2e 100755
--- a/tools/copy_dart.py
+++ b/tools/copy_dart.py
@@ -14,14 +14,17 @@
re_directive = re.compile(
r'^(library|import|part|native|resource)\s+(.*);$')
+re_comment = re.compile(
+ r'^(///|/\*| \*).*$')
class Library(object):
- def __init__(self, name, imports, sources, natives, code):
+ def __init__(self, name, imports, sources, natives, code, comment):
self.name = name
self.imports = imports
self.sources = sources
self.natives = natives
self.code = code
+ self.comment = comment
def parseLibrary(library):
""" Parses a .dart source file that is the root of a library, and returns
@@ -33,6 +36,7 @@
sources = []
natives = []
inlinecode = []
+ librarycomment = []
if exists(library):
# TODO(sigmund): stop parsing when import/source
for line in fileinput.input(library):
@@ -51,9 +55,14 @@
else:
raise Exception('unknown directive %s in %s' % (directive, line))
else:
- inlinecode.append(line)
+ # Check for library comment.
+ if not libraryname and re_comment.match(line):
+ librarycomment.append(line)
+ else:
+ inlinecode.append(line)
fileinput.close()
- return Library(libraryname, imports, sources, natives, inlinecode)
+ return Library(libraryname, imports, sources, natives, inlinecode,
+ librarycomment)
def normjoin(*args):
return os.path.normpath(os.path.join(*args))
@@ -114,6 +123,8 @@
# Create file containing all imports, and inlining all sources
with open(outpath, 'w') as f:
if library.name:
+ if library.comment:
+ f.write('%s' % (''.join(library.comment)))
f.write("library %s;\n\n" % library.name)
else:
f.write("library %s;\n\n" % basename(lib))
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 4e87ffb..e24902a 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -222,7 +222,7 @@
# Create and populate pkg/{args, intl, logging, meta, unittest, ...}
#
- for library in ['args', 'http', 'intl', 'logging', 'meta', 'oauth2', 'path',
+ for library in ['args', 'http', 'intl', 'logging', 'meta', 'oauth2', 'pathos',
'serialization', 'unittest', 'yaml']:
copytree(join(HOME, 'pkg', library), join(PKG, library),
@@ -243,7 +243,7 @@
copyfile(analyzer_src_jar, analyzer_dest_jar)
jarsToCopy = [ join("args4j", "2.0.12", "args4j-2.0.12.jar"),
- join("guava", "r09", "guava-r09.jar"),
+ join("guava", "r13", "guava-13.0.1.jar"),
join("json", "r2_20080312", "json.jar") ]
for jarToCopy in jarsToCopy:
dest_dir = join (ANALYZER_DEST, os.path.dirname(jarToCopy))
diff --git a/tools/ddbg.dart b/tools/ddbg.dart
index 7d95f79..2295ae8 100644
--- a/tools/ddbg.dart
+++ b/tools/ddbg.dart
@@ -15,7 +15,7 @@
Socket vmSock;
String vmData;
-OutputStream vmStream;
+StreamSubscription<String> streamSubscription;
int seqNum = 0;
int isolate_id = -1;
@@ -56,7 +56,7 @@
void quitShell() {
- vmStream.close();
+ streamSubscription.cancel();
vmSock.close();
stdin.close();
}
@@ -69,7 +69,7 @@
if (verbose) {
print("sending: '${json.stringify(cmd)}'");
}
- vmStream.writeString(json.stringify(cmd));
+ vmSock.addString(json.stringify(cmd));
return completer.future;
}
@@ -528,25 +528,25 @@
void debuggerMain() {
outstandingCommands = new Map<int, Completer>();
- vmSock = new Socket("127.0.0.1", 5858);
- vmStream = vmSock.outputStream;
- var stdinStream = new StringInputStream(stdin);
- stdinStream.onLine = () {
- processCommand(stdinStream.readLine());
- };
- var vmInStream = vmSock.inputStream;
- vmInStream.onData = () {
- String s = decodeUtf8(vmInStream.read());
- processVmData(s);
- };
- vmInStream.onError = (err) {
- print("Error in debug connection: $err");
- quitShell();
- };
- vmInStream.onClosed = () {
- print("VM debugger connection closed");
- quitShell();
- };
+ Socket.connect("127.0.0.1", 5858).then((s) {
+ vmSock = s;
+ Stream<String> stringStream = vmSock.transform(new StringDecoder());
+ streamSubscription = stringStream.listen(
+ (String data) {
+ processVmData(data);
+ },
+ onDone: () {
+ print("VM debugger connection closed");
+ quitShell();
+ },
+ onError: (err) {
+ print("Error in debug connection: $err");
+ quitShell();
+ });
+ stdin.transform(new StringDecoder())
+ .transform(new LineTransformer())
+ .listen((String line) => processCommand(line));
+ });
}
void main() {
@@ -555,16 +555,10 @@
if (arguments.length > 0) {
arguments = <String>['--debug', '--verbose_debug']..addAll(arguments);
Process.start(options.executable, arguments).then((Process process) {
- process.onExit = (int exitCode) {
- print('${arguments.join(" ")} exited with $exitCode');
- };
process.stdin.close();
- // Redirecting both stdout and stderr of the child process to
- // stdout. This should help users keep track of which errors
- // are coming from the debugger, and which errors are coming
- // from the process being debugged.
- process.stderr.pipe(stdout);
- process.stdout.pipe(stdout);
+ process.exitCode.then((int exitCode) {
+ print('${arguments.join(" ")} exited with $exitCode');
+ });
debuggerMain();
});
} else {
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index 9a34601..936da3b 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -528,5 +528,25 @@
]
}
}
+ },
+ "dart.dom.web_sql": {
+ "Database": {
+ "members": {
+ "changeVersion": [
+ "/**",
+ " * Atomically update the database version to [newVersion], asynchronously",
+ " * running [callback] on the [SqlTransaction] representing this",
+ " * [changeVersion] transaction.",
+ " *",
+ " * If [callback] runs successfully, then [successCallback] is called.",
+ " * Otherwise, [errorCallback] is called.",
+ " *",
+ " * [oldVersion] should match the database's current [version] exactly.",
+ " *",
+ " * * [Database.changeVersion](http://www.w3.org/TR/webdatabase/#dom-database-changeversion) from W3C.",
+ " */"
+ ]
+ }
+ }
}
}
\ No newline at end of file
diff --git a/tools/dom/docs/html_docs.json b/tools/dom/docs/html_docs.json
deleted file mode 100644
index 8f23289..0000000
--- a/tools/dom/docs/html_docs.json
+++ /dev/null
@@ -1,2399 +0,0 @@
-{
-"AbstractWorker.dart":
- {
-
- },
-"AnalyserNode.dart":
- {
-
- },
-"AnchorElement.dart":
- {
-
- },
-"Animation.dart":
- {
-
- },
-"AnimationEvent.dart":
- {
-
- },
-"AppletElement.dart":
- {
-
- },
-"ApplicationCache.dart":
- {
-
- },
-"AreaElement.dart":
- {
-
- },
-"ArrayBuffer.dart":
- {
-
- },
-"ArrayBufferView.dart":
- {
-
- },
-"Attr.dart":
- {
-
- },
-"AudioBuffer.dart":
- {
-
- },
-"AudioBufferCallback.dart":
- {
-
- },
-"AudioBufferSourceNode.dart":
- {
-
- },
-"AudioContext.dart":
- {
-
- },
-"AudioDestinationNode.dart":
- {
-
- },
-"AudioElement.dart":
- {
-
- },
-"AudioGain.dart":
- {
-
- },
-"AudioListener.dart":
- {
-
- },
-"AudioNode.dart":
- {
-
- },
-"AudioParam.dart":
- {
-
- },
-"AudioProcessingEvent.dart":
- {
-
- },
-"AudioSourceNode.dart":
- {
-
- },
-"BRElement.dart":
- {
-
- },
-"BarInfo.dart":
- {
-
- },
-"BaseElement.dart":
- {
-
- },
-"BaseFontElement.dart":
- {
-
- },
-"BatteryManager.dart":
- {
-
- },
-"BeforeLoadEvent.dart":
- {
-
- },
-"BiquadFilterNode.dart":
- {
-
- },
-"Blob.dart":
- {
-
- },
-"BodyElement.dart":
- {
-
- },
-"ButtonElement.dart":
- {
-
- },
-"CDATASection.dart":
- {
-
- },
-"CDataSection.dart":
- {
-
- },
-"CSSCharsetRule.dart":
- {
-
- },
-"CSSFontFaceRule.dart":
- {
-
- },
-"CSSImportRule.dart":
- {
-
- },
-"CSSKeyframeRule.dart":
- {
-
- },
-"CSSKeyframesRule.dart":
- {
-
- },
-"CSSMatrix.dart":
- {
-
- },
-"CSSMediaRule.dart":
- {
-
- },
-"CSSPageRule.dart":
- {
-
- },
-"CSSPrimitiveValue.dart":
- {
-
- },
-"CSSRule.dart":
- {
-
- },
-"CSSStyleDeclaration.dart":
- {
-
- },
-"CSSStyleRule.dart":
- {
-
- },
-"CSSStyleSheet.dart":
- {
-
- },
-"CSSTransformValue.dart":
- {
-
- },
-"CSSUnknownRule.dart":
- {
-
- },
-"CSSValue.dart":
- {
-
- },
-"CanvasElement.dart":
- {
- " @JSName('toDataURL')":
- [
- " /**",
- " * Returns a data URI containing a representation of the image in the ",
- " * format specified by type (defaults to 'image/png'). ",
- " * ",
- " * Data Uri format is as follow `data:[<MIME-type>][;charset=<encoding>][;base64],<data>`",
- " * ",
- " * Optional parameter [quality] in the range of 0.0 and 1.0 can be used when requesting [type]",
- " * 'image/jpeg' or 'image/webp'. If [quality] is not passed the default",
- " * value is used. Note: the default value varies by browser.",
- " * ",
- " * If the height or width of this canvas element is 0, then 'data:' is returned,",
- " * representing no data.",
- " * ",
- " * If the type requested is not 'image/png', and the returned value is ",
- " * 'data:image/png', then the requested type is not supported.",
- " * ",
- " * Example usage:",
- " * ",
- " * CanvasElement canvas = new CanvasElement();",
- " * var ctx = canvas.context2d",
- " * ..fillStyle = \"rgb(200,0,0)\"",
- " * ..fillRect(10, 10, 55, 50);",
- " * var dataUrl = canvas.toDataURL(\"image/jpeg\", 0.95);",
- " * // The Data Uri would look similar to",
- " * // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA",
- " * // AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO",
- " * // 9TXL0Y4OHwAAAABJRU5ErkJggg=='",
- " * //Create a new image element from the data URI.",
- " * var img = new ImageElement();",
- " * img.src = dataUrl;",
- " * document.body.children.add(img);",
- " * ",
- " * See also:",
- " * ",
- " * * [Data URI Scheme](http://en.wikipedia.org/wiki/Data_URI_scheme) from Wikipedia.",
- " * ",
- " * * [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/DOM/HTMLCanvasElement) from MDN.",
- " * ",
- " * * [toDataUrl](http://dev.w3.org/html5/spec/the-canvas-element.html#dom-canvas-todataurl) from W3C.",
- " */"
- ],
- " int height;":
- [
- " /// The height of this canvas element in CSS pixels."
- ],
- " int width;":
- [
- " /// The width of this canvas element in CSS pixels."
- ]
- },
-"CanvasGradient.dart":
- {
- " void addColorStop(num offset, String color) native;":
- [
- " /**",
- " * Adds a color stop to this gradient at the offset.",
- " *",
- " * The [offset] can range between 0.0 and 1.0.",
- " *",
- " * See also:",
- " *",
- " * * [Multiple Color Stops](https://developer.mozilla.org/en-US/docs/CSS/linear-gradient#Gradient_with_multiple_color_stops) from MDN.",
- " */"
- ],
- "class CanvasGradient native \"*CanvasGradient\" {":
- [
- "/**",
- " * An opaque canvas object representing a gradient.",
- " *",
- " * Created by calling [createLinearGradient] or [createRadialGradient] on a",
- " * [CanvasRenderingContext2D] object.",
- " *",
- " * Example usage:",
- " *",
- " * var canvas = new CanvasElement(width: 600, height: 600);",
- " * var ctx = canvas.context2d;",
- " * ctx.clearRect(0, 0, 600, 600);",
- " * ctx.save();",
- " * // Create radial gradient.",
- " * CanvasGradient gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, 600);",
- " * gradient.addColorStop(0, '#000');",
- " * gradient.addColorStop(1, 'rgb(255, 255, 255)');",
- " * // Assign gradients to fill.",
- " * ctx.fillStyle = gradient;",
- " * // Draw a rectangle with a gradient fill.",
- " * ctx.fillRect(0, 0, 600, 600);",
- " * ctx.save();",
- " * document.body.children.add(canvas);",
- " *",
- " * See also:",
- " *",
- " * * [CanvasGradient](https://developer.mozilla.org/en-US/docs/DOM/CanvasGradient) from MDN.",
- " * * [CanvasGradient](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvasgradient) from whatwg.",
- " * * [CanvasGradient](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvasgradient) from W3C.",
- " */"
- ]
- },
-"CanvasPattern.dart":
- {
- "class CanvasPattern native \"*CanvasPattern\" {":
- [
- "/**",
- " * An opaque object representing a pattern of image, canvas, or video.",
- " *",
- " * Created by calling [createPattern] on a [CanvasRenderingContext2D] object.",
- " *",
- " * Example usage:",
- " *",
- " * var canvas = new CanvasElement(width: 600, height: 600);",
- " * var ctx = canvas.context2d;",
- " * var img = new ImageElement();",
- " * // Image src needs to be loaded before pattern is applied.",
- " * img.on.load.add((event) {",
- " * // When the image is loaded, create a pattern",
- " * // from the ImageElement.",
- " * CanvasPattern pattern = ctx.createPattern(img, 'repeat');",
- " * ctx.rect(0, 0, canvas.width, canvas.height);",
- " * ctx.fillStyle = pattern;",
- " * ctx.fill();",
- " * });",
- " * img.src = \"images/foo.jpg\";",
- " * document.body.children.add(canvas);",
- " *",
- " * See also:",
- " * * [CanvasPattern](https://developer.mozilla.org/en-US/docs/DOM/CanvasPattern) from MDN.",
- " * * [CanvasPattern](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvaspattern) from whatwg.",
- " * * [CanvasPattern](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvaspattern) from W3C.",
- " */"
- ]
- },
-"CanvasRenderingContext.dart":
- {
- " final CanvasElement canvas;":
- [
- " /// Reference to the canvas element to which this context belongs."
- ],
- "class CanvasRenderingContext native \"*CanvasRenderingContext\" {":
- [
- "/**",
- " * A rendering context for a canvas element.",
- " *",
- " * This context is extended by [CanvasRenderingContext2D] and",
- " * [WebGLRenderingContext].",
- " */"
- ]
- },
-"CanvasRenderingContext2D.dart":
- {
-
- },
-"ChannelMergerNode.dart":
- {
-
- },
-"ChannelSplitterNode.dart":
- {
-
- },
-"CharacterData.dart":
- {
-
- },
-"ClientRect.dart":
- {
-
- },
-"Clipboard.dart":
- {
-
- },
-"CloseEvent.dart":
- {
-
- },
-"Comment.dart":
- {
-
- },
-"CompositionEvent.dart":
- {
-
- },
-"Console.dart":
- {
-
- },
-"ContentElement.dart":
- {
-
- },
-"ConvolverNode.dart":
- {
-
- },
-"Coordinates.dart":
- {
-
- },
-"Counter.dart":
- {
-
- },
-"Crypto.dart":
- {
-
- },
-"CssCharsetRule.dart":
- {
-
- },
-"CssFontFaceRule.dart":
- {
-
- },
-"CssImportRule.dart":
- {
-
- },
-"CssKeyframeRule.dart":
- {
-
- },
-"CssKeyframesRule.dart":
- {
-
- },
-"CssMatrix.dart":
- {
-
- },
-"CssMediaRule.dart":
- {
-
- },
-"CssPageRule.dart":
- {
-
- },
-"CssPrimitiveValue.dart":
- {
-
- },
-"CssRule.dart":
- {
-
- },
-"CssStyleDeclaration.dart":
- {
-
- },
-"CssStyleRule.dart":
- {
-
- },
-"CssStyleSheet.dart":
- {
-
- },
-"CssTransformValue.dart":
- {
-
- },
-"CssUnknownRule.dart":
- {
-
- },
-"CssValue.dart":
- {
-
- },
-"CustomEvent.dart":
- {
-
- },
-"DListElement.dart":
- {
-
- },
-"DOMApplicationCache.dart":
- {
-
- },
-"DOMError.dart":
- {
-
- },
-"DOMException.dart":
- {
-
- },
-"DOMFileSystem.dart":
- {
-
- },
-"DOMFileSystemSync.dart":
- {
-
- },
-"DOMImplementation.dart":
- {
-
- },
-"DOMMimeType.dart":
- {
-
- },
-"DOMMimeTypeArray.dart":
- {
-
- },
-"DOMParser.dart":
- {
-
- },
-"DOMPlugin.dart":
- {
-
- },
-"DOMPluginArray.dart":
- {
-
- },
-"DOMSelection.dart":
- {
-
- },
-"DOMSettableTokenList.dart":
- {
-
- },
-"DOMStringMap.dart":
- {
-
- },
-"DOMTokenList.dart":
- {
-
- },
-"DataListElement.dart":
- {
-
- },
-"DataTransferItem.dart":
- {
-
- },
-"DataTransferItemList.dart":
- {
-
- },
-"DataView.dart":
- {
-
- },
-"Database.dart":
- {
-
- },
-"DatabaseCallback.dart":
- {
-
- },
-"DatabaseSync.dart":
- {
-
- },
-"DedicatedWorkerContext.dart":
- {
-
- },
-"DelayNode.dart":
- {
-
- },
-"DetailsElement.dart":
- {
-
- },
-"DeviceMotionEvent.dart":
- {
-
- },
-"DeviceOrientationEvent.dart":
- {
-
- },
-"DirectoryElement.dart":
- {
-
- },
-"DirectoryEntry.dart":
- {
-
- },
-"DirectoryEntrySync.dart":
- {
-
- },
-"DirectoryReader.dart":
- {
-
- },
-"DirectoryReaderSync.dart":
- {
-
- },
-"DivElement.dart":
- {
- "class DivElement extends Element native \"*HTMLDivElement\" {":
- [
- "/**",
- " * Represents an HTML <div> element.",
- " *",
- " * The [DivElement] is a generic container for content and does not have any",
- " * special significance. It is functionally similar to [SpanElement].",
- " *",
- " * The [DivElement] is a block-level element, as opposed to [SpanElement],",
- " * which is an inline-level element.",
- " *",
- " * Example usage:",
- " *",
- " * DivElement div = new DivElement();",
- " * div.text = 'Here's my new DivElem",
- " * document.body.elements.add(elem);",
- " *",
- " * See also:",
- " *",
- " * * [HTML <div> element](http://www.w3.org/TR/html-markup/div.html) from W3C.",
- " * * [Block-level element](http://www.w3.org/TR/CSS2/visuren.html#block-boxes) from W3C.",
- " * * [Inline-level element](http://www.w3.org/TR/CSS2/visuren.html#inline-boxes) from W3C.",
- " */"
- ]
- },
-"Document.dart":
- {
- " @JSName('body')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('caretRangeFromPoint')":
- [
- " /// Use the [Range] constructor instead."
- ],
- " @JSName('createElement')":
- [
- " /// Deprecated: use new Element.tag(tagName) instead."
- ],
- " @JSName('createTouchList')":
- [
- " /// Use the [TouchList] constructor isntead."
- ],
- " @JSName('elementFromPoint')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('getElementById')":
- [
- " /// Deprecated: use query(\"#$elementId\") instead."
- ],
- " @JSName('head')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('lastModified')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('querySelector')":
- [
- " /// Deprecated: renamed to the shorter name [query]."
- ],
- " @JSName('querySelectorAll')":
- [
- " /// Deprecated: use query(\"#$elementId\") instead."
- ],
- " @JSName('referrer')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('styleSheets')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('title')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('webkitCancelFullScreen')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('webkitExitFullscreen')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('webkitExitPointerLock')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('webkitFullscreenElement')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('webkitFullscreenEnabled')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('webkitHidden')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('webkitIsFullScreen')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('webkitPointerLockElement')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " @JSName('webkitVisibilityState')":
- [
- " /// Moved to [HtmlDocument]."
- ],
- " Window get window => _convertNativeToDart_Window(this._window);":
- [
- " /// Returns the [Window] associated with the document."
- ]
- },
-"DocumentFragment.dart":
- {
-
- },
-"DocumentType.dart":
- {
-
- },
-"DomError.dart":
- {
-
- },
-"DomException.dart":
- {
-
- },
-"DomImplementation.dart":
- {
-
- },
-"DomMimeType.dart":
- {
-
- },
-"DomMimeTypeArray.dart":
- {
-
- },
-"DomParser.dart":
- {
-
- },
-"DomPlugin.dart":
- {
-
- },
-"DomPluginArray.dart":
- {
-
- },
-"DomSelection.dart":
- {
-
- },
-"DomSettableTokenList.dart":
- {
-
- },
-"DomStringList.dart":
- {
-
- },
-"DomStringMap.dart":
- {
-
- },
-"DomTokenList.dart":
- {
-
- },
-"DynamicsCompressorNode.dart":
- {
-
- },
-"EXTTextureFilterAnisotropic.dart":
- {
-
- },
-"Element.dart":
- {
-
- },
-"ElementTimeControl.dart":
- {
-
- },
-"ElementTraversal.dart":
- {
-
- },
-"EmbedElement.dart":
- {
-
- },
-"EntityReference.dart":
- {
-
- },
-"EntriesCallback.dart":
- {
-
- },
-"Entry.dart":
- {
-
- },
-"EntryCallback.dart":
- {
-
- },
-"EntrySync.dart":
- {
-
- },
-"ErrorCallback.dart":
- {
-
- },
-"ErrorEvent.dart":
- {
-
- },
-"Event.dart":
- {
-
- },
-"EventException.dart":
- {
-
- },
-"EventSource.dart":
- {
-
- },
-"EventTarget.dart":
- {
-
- },
-"ExtTextureFilterAnisotropic.dart":
- {
-
- },
-"FieldSetElement.dart":
- {
-
- },
-"File.dart":
- {
-
- },
-"FileCallback.dart":
- {
-
- },
-"FileEntry.dart":
- {
-
- },
-"FileEntrySync.dart":
- {
-
- },
-"FileError.dart":
- {
-
- },
-"FileException.dart":
- {
-
- },
-"FileList.dart":
- {
-
- },
-"FileReader.dart":
- {
-
- },
-"FileReaderSync.dart":
- {
-
- },
-"FileSystem.dart":
- {
-
- },
-"FileSystemCallback.dart":
- {
-
- },
-"FileSystemSync.dart":
- {
-
- },
-"FileWriter.dart":
- {
-
- },
-"FileWriterCallback.dart":
- {
-
- },
-"FileWriterSync.dart":
- {
-
- },
-"Float32Array.dart":
- {
-
- },
-"Float64Array.dart":
- {
-
- },
-"FontElement.dart":
- {
-
- },
-"FormData.dart":
- {
-
- },
-"FormElement.dart":
- {
-
- },
-"FrameElement.dart":
- {
-
- },
-"FrameSetElement.dart":
- {
-
- },
-"GainNode.dart":
- {
-
- },
-"Gamepad.dart":
- {
-
- },
-"Geolocation.dart":
- {
-
- },
-"Geoposition.dart":
- {
-
- },
-"HRElement.dart":
- {
-
- },
-"HTMLAllCollection.dart":
- {
-
- },
-"HTMLCollection.dart":
- {
-
- },
-"HTMLOptionsCollection.dart":
- {
-
- },
-"HashChangeEvent.dart":
- {
-
- },
-"HeadElement.dart":
- {
-
- },
-"HeadingElement.dart":
- {
-
- },
-"HtmlAllCollection.dart":
- {
-
- },
-"HtmlCollection.dart":
- {
-
- },
-"HtmlDocument.dart":
- {
-
- },
-"HtmlElement.dart":
- {
-
- },
-"HtmlOptionsCollection.dart":
- {
-
- },
-"HttpRequest.dart":
- {
- " @Creates('ArrayBuffer|Blob|Document|=Object|=List|String|num')":
- [
- " /**",
- " * The data received as a reponse from the request.",
- " *",
- " * The data could be in the",
- " * form of a [String], [ArrayBuffer], [Document], [Blob], or json (also a ",
- " * [String]). `null` indicates request failure.",
- " */"
- ],
- " @JSName('responseXML')":
- [
- " /**",
- " * The request response, or null on failure.",
- " * ",
- " * The response is processed as",
- " * `text/xml` stream, unless responseType = 'document' and the request is",
- " * synchronous.",
- " */"
- ],
- " EventListenerList get abort => this['abort'];":
- [
- " /**",
- " * Event listeners to be notified when request has been aborted,",
- " * generally due to calling `httpRequest.abort()`.",
- " */"
- ],
- " EventListenerList get error => this['error'];":
- [
- " /**",
- " * Event listeners to be notified when a request has failed, such as when a",
- " * cross-domain error occurred or the file wasn't found on the server.",
- " */"
- ],
- " EventListenerList get load => this['load'];":
- [
- " /**",
- " * Event listeners to be notified once the request has completed",
- " * *successfully*.",
- " */"
- ],
- " EventListenerList get loadEnd => this['loadend'];":
- [
- " /**",
- " * Event listeners to be notified once the request has completed (on",
- " * either success or failure).",
- " */"
- ],
- " EventListenerList get loadStart => this['loadstart'];":
- [
- " /**",
- " * Event listeners to be notified when the request starts, once",
- " * `httpRequest.send()` has been called.",
- " */"
- ],
- " EventListenerList get progress => this['progress'];":
- [
- " /**",
- " * Event listeners to be notified when data for the request ",
- " * is being sent or loaded.",
- " *",
- " * Progress events are fired every 50ms or for every byte transmitted,",
- " * whichever is less frequent.",
- " */"
- ],
- " EventListenerList get readyStateChange => this['readystatechange'];":
- [
- " /**",
- " * Event listeners to be notified every time the [HttpRequest]",
- " * object's `readyState` changes values.",
- " */"
- ],
- " HttpRequestEvents get on =>":
- [
- " /**",
- " * Get the set of [HttpRequestEvents] that this request can respond to.",
- " * Usually used when adding an EventListener, such as in",
- " * `document.window.on.keyDown.add((e) => print('keydown happened'))`.",
- " */"
- ],
- " String getAllResponseHeaders() native;":
- [
- " /**",
- " * Retrieve all the response headers from a request.",
- " * ",
- " * `null` if no headers have been received. For multipart requests,",
- " * `getAllResponseHeaders` will return the response headers for the current",
- " * part of the request.",
- " * ",
- " * See also [HTTP response headers](http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Responses)",
- " * for a list of common response headers.",
- " */"
- ],
- " String getResponseHeader(String header) native;":
- [
- " /**",
- " * Return the response header named `header`, or `null` if not found.",
- " * ",
- " * See also [HTTP response headers](http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Responses)",
- " * for a list of common response headers.",
- " */"
- ],
- " String responseType;":
- [
- " /**",
- " * [String] telling the server the desired response format. ",
- " *",
- " * Default is `String`.",
- " * Other options are one of 'arraybuffer', 'blob', 'document', 'json',",
- " * 'text'. Some newer browsers will throw `NS_ERROR_DOM_INVALID_ACCESS_ERR` if",
- " * `responseType` is set while performing a synchronous request.",
- " *",
- " * See also: [MDN responseType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType)",
- " */"
- ],
- " bool withCredentials;":
- [
- " /**",
- " * True if cross-site requests should use credentials such as cookies",
- " * or authorization headers; false otherwise. ",
- " *",
- " * This value is ignored for same-site requests.",
- " */"
- ],
- " factory HttpRequest() => _HttpRequestFactoryProvider.createHttpRequest();":
- [
- " /**",
- " * General constructor for any type of request (GET, POST, etc).",
- " *",
- " * This call is used in conjunction with [open]:",
- " * ",
- " * var request = new HttpRequest();",
- " * request.open('GET', 'http://dartlang.org')",
- " * request.on.load.add((event) => print('Request complete'));",
- " * ",
- " * is the (more verbose) equivalent of",
- " * ",
- " * var request = new HttpRequest.get('http://dartlang.org',",
- " * (event) => print('Request complete'));",
- " */"
- ],
- " final HttpRequestUpload upload;":
- [
- " /**",
- " * [EventTarget] that can hold listeners to track the progress of the request.",
- " * The events fired will be members of [HttpRequestUploadEvents].",
- " */"
- ],
- " final String responseText;":
- [
- " /**",
- " * The response in string form or null on failure.",
- " */"
- ],
- " final String statusText;":
- [
- " /**",
- " * The request response string (such as \"200 OK\").",
- " * See also: [Http Status Codes](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes)",
- " */"
- ],
- " final int readyState;":
- [
- " /**",
- " * Indicator of the current state of the request:",
- " *",
- " * <table>",
- " * <tr>",
- " * <td>Value</td>",
- " * <td>State</td>",
- " * <td>Meaning</td>",
- " * </tr>",
- " * <tr>",
- " * <td>0</td>",
- " * <td>unsent</td>",
- " * <td><code>open()</code> has not yet been called</td>",
- " * </tr>",
- " * <tr>",
- " * <td>1</td>",
- " * <td>opened</td>",
- " * <td><code>send()</code> has not yet been called</td>",
- " * </tr>",
- " * <tr>",
- " * <td>2</td>",
- " * <td>headers received</td>",
- " * <td><code>sent()</code> has been called; response headers and <code>status</code> are available</td>",
- " * </tr>",
- " * <tr>",
- " * <td>3</td> <td>loading</td> <td><code>responseText</code> holds some data</td>",
- " * </tr>",
- " * <tr>",
- " * <td>4</td> <td>done</td> <td>request is complete</td>",
- " * </tr>",
- " * </table>",
- " */"
- ],
- " final int status;":
- [
- " /**",
- " * The http result code from the request (200, 404, etc).",
- " * See also: [Http Status Codes](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes)",
- " */"
- ],
- " void abort() native;":
- [
- " /**",
- " * Stop the current request.",
- " *",
- " * The request can only be stopped if readyState is `HEADERS_RECIEVED` or ",
- " * `LOADING`. If this method is not in the process of being sent, the method",
- " * has no effect.",
- " */"
- ],
- " void open(String method, String url, [bool async, String user, String password]) native;":
- [
- " /**",
- " * Specify the desired `url`, and `method` to use in making the request.",
- " * ",
- " * By default the request is done asyncronously, with no user or password",
- " * authentication information. If `async` is false, the request will be send",
- " * synchronously.",
- " * ",
- " * Calling `open` again on a currently active request is equivalent to",
- " * calling `abort`.",
- " */"
- ],
- " void overrideMimeType(String override) native;":
- [
- " /**",
- " * Specify a particular MIME type (such as `text/xml`) desired for the",
- " * response.",
- " * ",
- " * This value must be set before the request has been sent. See also the list",
- " * of [common MIME types](http://en.wikipedia.org/wiki/Internet_media_type#List_of_common_media_types)",
- " */"
- ],
- " void send([data]) native;":
- [
- " /**",
- " * Send the request with any given `data`.",
- " *",
- " * See also: ",
- " * [send() docs](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#send())",
- " * from MDN.",
- " */"
- ],
- " void setRequestHeader(String header, String value) native;":
- [
- " /** Sets HTTP `header` to `value`. */"
- ],
- "class HttpRequestEvents extends Events {":
- [
- "/**",
- " * A class that supports listening for and dispatching events that can fire when",
- " * making an HTTP request. ",
- " * ",
- " * Here's an example of adding an event handler that executes once an HTTP",
- " * request has fully loaded:",
- " * ",
- " * httpRequest.on.loadEnd.add((e) => myCustomLoadEndHandler(e));",
- " *",
- " * Each property of this class is a read-only pointer to an [EventListenerList].",
- " * That list holds all of the [EventListener]s that have registered for that",
- " * particular type of event that fires from an HttpRequest.",
- " */"
- ]
- },
-"HttpRequestException.dart":
- {
-
- },
-"HttpRequestProgressEvent.dart":
- {
-
- },
-"HttpRequestUpload.dart":
- {
-
- },
-"IDBAny.dart":
- {
-
- },
-"IDBCursor.dart":
- {
-
- },
-"IDBCursorWithValue.dart":
- {
-
- },
-"IDBDatabase.dart":
- {
-
- },
-"IDBDatabaseException.dart":
- {
-
- },
-"IDBFactory.dart":
- {
-
- },
-"IDBIndex.dart":
- {
-
- },
-"IDBKey.dart":
- {
-
- },
-"IDBKeyRange.dart":
- {
-
- },
-"IDBObjectStore.dart":
- {
-
- },
-"IDBOpenDBRequest.dart":
- {
-
- },
-"IDBRequest.dart":
- {
-
- },
-"IDBTransaction.dart":
- {
-
- },
-"IDBUpgradeNeededEvent.dart":
- {
-
- },
-"IDBVersionChangeEvent.dart":
- {
-
- },
-"IDBVersionChangeRequest.dart":
- {
-
- },
-"IFrameElement.dart":
- {
-
- },
-"IceCallback.dart":
- {
-
- },
-"IceCandidate.dart":
- {
-
- },
-"ImageData.dart":
- {
-
- },
-"ImageElement.dart":
- {
-
- },
-"InputElement.dart":
- {
-
- },
-"Int16Array.dart":
- {
-
- },
-"Int32Array.dart":
- {
-
- },
-"Int8Array.dart":
- {
-
- },
-"JavaScriptCallFrame.dart":
- {
-
- },
-"KeyboardEvent.dart":
- {
-
- },
-"KeygenElement.dart":
- {
-
- },
-"LIElement.dart":
- {
-
- },
-"LabelElement.dart":
- {
-
- },
-"LegendElement.dart":
- {
-
- },
-"LinkElement.dart":
- {
-
- },
-"LocalHistory.dart":
- {
-
- },
-"LocalLocation.dart":
- {
-
- },
-"LocalMediaStream.dart":
- {
-
- },
-"LocalWindow.dart":
- {
-
- },
-"MapElement.dart":
- {
-
- },
-"MarqueeElement.dart":
- {
-
- },
-"MediaController.dart":
- {
-
- },
-"MediaElement.dart":
- {
-
- },
-"MediaElementAudioSourceNode.dart":
- {
-
- },
-"MediaError.dart":
- {
-
- },
-"MediaKeyError.dart":
- {
-
- },
-"MediaKeyEvent.dart":
- {
-
- },
-"MediaList.dart":
- {
-
- },
-"MediaQueryList.dart":
- {
-
- },
-"MediaQueryListListener.dart":
- {
-
- },
-"MediaSource.dart":
- {
-
- },
-"MediaStream.dart":
- {
-
- },
-"MediaStreamAudioSourceNode.dart":
- {
-
- },
-"MediaStreamEvent.dart":
- {
-
- },
-"MediaStreamTrack.dart":
- {
-
- },
-"MediaStreamTrackEvent.dart":
- {
-
- },
-"MediaStreamTrackList.dart":
- {
-
- },
-"MemoryInfo.dart":
- {
-
- },
-"MenuElement.dart":
- {
- "class MenuElement extends Element native \"*HTMLMenuElement\" {":
- [
- "/**",
- " * An HTML <menu> element.",
- " *",
- " * A <menu> element represents an unordered list of menu commands.",
- " *",
- " * See also:",
- " *",
- " * * [Menu Element](https://developer.mozilla.org/en-US/docs/HTML/Element/menu) from MDN.",
- " * * [Menu Element](http://www.w3.org/TR/html5/the-menu-element.html#the-menu-element) from the W3C.",
- " */"
- ]
- },
-"MessageChannel.dart":
- {
-
- },
-"MessageEvent.dart":
- {
-
- },
-"MessagePort.dart":
- {
-
- },
-"MetaElement.dart":
- {
-
- },
-"Metadata.dart":
- {
-
- },
-"MetadataCallback.dart":
- {
-
- },
-"MeterElement.dart":
- {
-
- },
-"ModElement.dart":
- {
-
- },
-"MouseEvent.dart":
- {
-
- },
-"MutationCallback.dart":
- {
-
- },
-"MutationEvent.dart":
- {
-
- },
-"MutationObserver.dart":
- {
-
- },
-"MutationRecord.dart":
- {
-
- },
-"NamedNodeMap.dart":
- {
-
- },
-"Navigator.dart":
- {
-
- },
-"NavigatorUserMediaError.dart":
- {
-
- },
-"NavigatorUserMediaErrorCallback.dart":
- {
-
- },
-"NavigatorUserMediaSuccessCallback.dart":
- {
-
- },
-"Node.dart":
- {
-
- },
-"NodeFilter.dart":
- {
-
- },
-"NodeIterator.dart":
- {
-
- },
-"NodeList.dart":
- {
-
- },
-"Notation.dart":
- {
-
- },
-"Notification.dart":
- {
-
- },
-"NotificationCenter.dart":
- {
-
- },
-"NotificationPermissionCallback.dart":
- {
-
- },
-"OESElementIndexUint.dart":
- {
-
- },
-"OESStandardDerivatives.dart":
- {
-
- },
-"OESTextureFloat.dart":
- {
-
- },
-"OESVertexArrayObject.dart":
- {
-
- },
-"OListElement.dart":
- {
-
- },
-"ObjectElement.dart":
- {
-
- },
-"OesElementIndexUint.dart":
- {
-
- },
-"OesStandardDerivatives.dart":
- {
-
- },
-"OesTextureFloat.dart":
- {
-
- },
-"OesVertexArrayObject.dart":
- {
-
- },
-"OfflineAudioCompletionEvent.dart":
- {
-
- },
-"OptGroupElement.dart":
- {
-
- },
-"OptionElement.dart":
- {
-
- },
-"OscillatorNode.dart":
- {
-
- },
-"OutputElement.dart":
- {
-
- },
-"OverflowEvent.dart":
- {
-
- },
-"PagePopupController.dart":
- {
-
- },
-"PageTransitionEvent.dart":
- {
-
- },
-"PannerNode.dart":
- {
-
- },
-"ParagraphElement.dart":
- {
-
- },
-"ParamElement.dart":
- {
-
- },
-"PeerConnection00.dart":
- {
-
- },
-"Performance.dart":
- {
-
- },
-"PerformanceNavigation.dart":
- {
-
- },
-"PerformanceTiming.dart":
- {
-
- },
-"Point.dart":
- {
-
- },
-"PopStateEvent.dart":
- {
-
- },
-"PositionCallback.dart":
- {
-
- },
-"PositionError.dart":
- {
-
- },
-"PositionErrorCallback.dart":
- {
-
- },
-"PreElement.dart":
- {
-
- },
-"ProcessingInstruction.dart":
- {
-
- },
-"ProgressElement.dart":
- {
-
- },
-"ProgressEvent.dart":
- {
-
- },
-"QuoteElement.dart":
- {
-
- },
-"RGBColor.dart":
- {
-
- },
-"RTCDataChannel.dart":
- {
-
- },
-"RTCDataChannelEvent.dart":
- {
-
- },
-"RTCErrorCallback.dart":
- {
-
- },
-"RTCIceCandidate.dart":
- {
-
- },
-"RTCIceCandidateEvent.dart":
- {
-
- },
-"RTCPeerConnection.dart":
- {
-
- },
-"RTCSessionDescription.dart":
- {
-
- },
-"RTCSessionDescriptionCallback.dart":
- {
-
- },
-"RTCStatsCallback.dart":
- {
-
- },
-"RTCStatsElement.dart":
- {
-
- },
-"RTCStatsReport.dart":
- {
-
- },
-"RTCStatsResponse.dart":
- {
-
- },
-"RadioNodeList.dart":
- {
-
- },
-"Range.dart":
- {
-
- },
-"RangeException.dart":
- {
-
- },
-"Rect.dart":
- {
-
- },
-"RequestAnimationFrameCallback.dart":
- {
-
- },
-"RgbColor.dart":
- {
-
- },
-"RtcDataChannel.dart":
- {
-
- },
-"RtcDataChannelEvent.dart":
- {
-
- },
-"RtcIceCandidate.dart":
- {
-
- },
-"RtcIceCandidateEvent.dart":
- {
-
- },
-"RtcPeerConnection.dart":
- {
-
- },
-"RtcSessionDescription.dart":
- {
-
- },
-"RtcStatsElement.dart":
- {
-
- },
-"RtcStatsReport.dart":
- {
-
- },
-"RtcStatsResponse.dart":
- {
-
- },
-"SQLError.dart":
- {
-
- },
-"SQLException.dart":
- {
-
- },
-"SQLResultSet.dart":
- {
-
- },
-"SQLResultSetRowList.dart":
- {
-
- },
-"SQLStatementCallback.dart":
- {
-
- },
-"SQLStatementErrorCallback.dart":
- {
-
- },
-"SQLTransaction.dart":
- {
-
- },
-"SQLTransactionCallback.dart":
- {
-
- },
-"SQLTransactionErrorCallback.dart":
- {
-
- },
-"SQLTransactionSync.dart":
- {
-
- },
-"SQLTransactionSyncCallback.dart":
- {
-
- },
-"Screen.dart":
- {
-
- },
-"ScriptElement.dart":
- {
-
- },
-"ScriptProcessorNode.dart":
- {
-
- },
-"ScriptProfile.dart":
- {
-
- },
-"ScriptProfileNode.dart":
- {
-
- },
-"SelectElement.dart":
- {
-
- },
-"SessionDescription.dart":
- {
-
- },
-"ShadowElement.dart":
- {
-
- },
-"ShadowRoot.dart":
- {
-
- },
-"SharedWorker.dart":
- {
-
- },
-"SharedWorkerContext.dart":
- {
-
- },
-"SourceBuffer.dart":
- {
-
- },
-"SourceBufferList.dart":
- {
-
- },
-"SourceElement.dart":
- {
-
- },
-"SpanElement.dart":
- {
-
- },
-"SpeechGrammar.dart":
- {
-
- },
-"SpeechGrammarList.dart":
- {
-
- },
-"SpeechInputEvent.dart":
- {
-
- },
-"SpeechInputResult.dart":
- {
-
- },
-"SpeechRecognition.dart":
- {
-
- },
-"SpeechRecognitionAlternative.dart":
- {
-
- },
-"SpeechRecognitionError.dart":
- {
-
- },
-"SpeechRecognitionEvent.dart":
- {
-
- },
-"SpeechRecognitionResult.dart":
- {
-
- },
-"SqlError.dart":
- {
-
- },
-"SqlException.dart":
- {
-
- },
-"SqlResultSet.dart":
- {
-
- },
-"SqlResultSetRowList.dart":
- {
-
- },
-"SqlTransaction.dart":
- {
-
- },
-"SqlTransactionSync.dart":
- {
-
- },
-"Storage.dart":
- {
-
- },
-"StorageEvent.dart":
- {
-
- },
-"StorageInfo.dart":
- {
-
- },
-"StorageInfoErrorCallback.dart":
- {
-
- },
-"StorageInfoQuotaCallback.dart":
- {
-
- },
-"StorageInfoUsageCallback.dart":
- {
-
- },
-"StringCallback.dart":
- {
-
- },
-"StyleElement.dart":
- {
-
- },
-"StyleMedia.dart":
- {
-
- },
-"StyleSheet.dart":
- {
-
- },
-"TableCaptionElement.dart":
- {
-
- },
-"TableCellElement.dart":
- {
-
- },
-"TableColElement.dart":
- {
-
- },
-"TableElement.dart":
- {
-
- },
-"TableRowElement.dart":
- {
-
- },
-"TableSectionElement.dart":
- {
-
- },
-"Text.dart":
- {
-
- },
-"TextAreaElement.dart":
- {
-
- },
-"TextEvent.dart":
- {
-
- },
-"TextMetrics.dart":
- {
-
- },
-"TextTrack.dart":
- {
-
- },
-"TextTrackCue.dart":
- {
-
- },
-"TextTrackCueList.dart":
- {
-
- },
-"TextTrackList.dart":
- {
-
- },
-"TimeRanges.dart":
- {
-
- },
-"TimeoutHandler.dart":
- {
-
- },
-"TitleElement.dart":
- {
-
- },
-"Touch.dart":
- {
-
- },
-"TouchEvent.dart":
- {
-
- },
-"TouchList.dart":
- {
-
- },
-"TrackElement.dart":
- {
-
- },
-"TrackEvent.dart":
- {
-
- },
-"TransitionEvent.dart":
- {
-
- },
-"TreeWalker.dart":
- {
-
- },
-"UIEvent.dart":
- {
-
- },
-"UListElement.dart":
- {
-
- },
-"Uint16Array.dart":
- {
-
- },
-"Uint32Array.dart":
- {
-
- },
-"Uint8Array.dart":
- {
-
- },
-"Uint8ClampedArray.dart":
- {
-
- },
-"UnknownElement.dart":
- {
-
- },
-"Url.dart":
- {
-
- },
-"ValidityState.dart":
- {
-
- },
-"VideoElement.dart":
- {
-
- },
-"VoidCallback.dart":
- {
-
- },
-"WaveShaperNode.dart":
- {
-
- },
-"WaveTable.dart":
- {
-
- },
-"WebGLActiveInfo.dart":
- {
-
- },
-"WebGLBuffer.dart":
- {
-
- },
-"WebGLCompressedTextureS3TC.dart":
- {
-
- },
-"WebGLContextAttributes.dart":
- {
-
- },
-"WebGLContextEvent.dart":
- {
-
- },
-"WebGLDebugRendererInfo.dart":
- {
-
- },
-"WebGLDebugShaders.dart":
- {
-
- },
-"WebGLDepthTexture.dart":
- {
-
- },
-"WebGLFramebuffer.dart":
- {
-
- },
-"WebGLLoseContext.dart":
- {
-
- },
-"WebGLProgram.dart":
- {
-
- },
-"WebGLRenderbuffer.dart":
- {
-
- },
-"WebGLRenderingContext.dart":
- {
-
- },
-"WebGLShader.dart":
- {
-
- },
-"WebGLShaderPrecisionFormat.dart":
- {
-
- },
-"WebGLTexture.dart":
- {
-
- },
-"WebGLUniformLocation.dart":
- {
-
- },
-"WebGLVertexArrayObject.dart":
- {
-
- },
-"WebGLVertexArrayObjectOES.dart":
- {
-
- },
-"WebKitCSSFilterValue.dart":
- {
-
- },
-"WebKitCssFilterValue.dart":
- {
-
- },
-"WebKitNamedFlow.dart":
- {
-
- },
-"WebSocket.dart":
- {
-
- },
-"WheelEvent.dart":
- {
-
- },
-"Worker.dart":
- {
-
- },
-"WorkerContext.dart":
- {
-
- },
-"WorkerLocation.dart":
- {
-
- },
-"WorkerNavigator.dart":
- {
-
- },
-"XMLSerializer.dart":
- {
-
- },
-"XPathEvaluator.dart":
- {
-
- },
-"XPathException.dart":
- {
-
- },
-"XPathExpression.dart":
- {
-
- },
-"XPathNSResolver.dart":
- {
-
- },
-"XPathResult.dart":
- {
-
- },
-"XSLTProcessor.dart":
- {
-
- },
-"XmlSerializer.dart":
- {
-
- },
-"XsltProcessor.dart":
- {
-
- }
-}
diff --git a/tools/dom/docs/lib/docs.dart b/tools/dom/docs/lib/docs.dart
index 74529c4..9e89782 100644
--- a/tools/dom/docs/lib/docs.dart
+++ b/tools/dom/docs/lib/docs.dart
@@ -15,9 +15,10 @@
/// The various HTML libraries.
const List<String> HTML_LIBRARY_NAMES = const ['dart:html',
+ 'dart:indexed_db',
'dart:svg',
'dart:web_audio',
- 'dart:indexed_db'];
+ 'dart:web_sql'];
/**
* Converts the libraries in [HTML_LIBRARY_NAMES] to a json file at [jsonPath]
* given the library path at [libPath].
@@ -185,4 +186,4 @@
} else {
return <String>[];
}
-}
\ No newline at end of file
+}
diff --git a/tools/dom/docs/svg_docs.json b/tools/dom/docs/svg_docs.json
deleted file mode 100644
index d0dec29..0000000
--- a/tools/dom/docs/svg_docs.json
+++ /dev/null
@@ -1,606 +0,0 @@
-{
-"PathSegLinetoVerticalRel.dart":
- {
-
- },
-"DefsElement.dart":
- {
-
- },
-"LineElement.dart":
- {
-
- },
-"SwitchElement.dart":
- {
-
- },
-"Rect.dart":
- {
-
- },
-"Matrix.dart":
- {
-
- },
-"VKernElement.dart":
- {
-
- },
-"RenderingIntent.dart":
- {
-
- },
-"AnimatedBoolean.dart":
- {
-
- },
-"Angle.dart":
- {
-
- },
-"MissingGlyphElement.dart":
- {
-
- },
-"ZoomEvent.dart":
- {
-
- },
-"RadialGradientElement.dart":
- {
-
- },
-"AltGlyphDefElement.dart":
- {
-
- },
-"PathSegCurvetoQuadraticRel.dart":
- {
-
- },
-"FEPointLightElement.dart":
- {
-
- },
-"ScriptElement.dart":
- {
-
- },
-"GradientElement.dart":
- {
-
- },
-"FETileElement.dart":
- {
-
- },
-"PathSegList.dart":
- {
-
- },
-"AnimateTransformElement.dart":
- {
-
- },
-"TSpanElement.dart":
- {
-
- },
-"FEGaussianBlurElement.dart":
- {
-
- },
-"PathSegCurvetoQuadraticAbs.dart":
- {
-
- },
-"AnimateElement.dart":
- {
-
- },
-"ExternalResourcesRequired.dart":
- {
-
- },
-"FontFaceNameElement.dart":
- {
-
- },
-"UriReference.dart":
- {
-
- },
-"Length.dart":
- {
-
- },
-"FEMergeElement.dart":
- {
-
- },
-"Point.dart":
- {
-
- },
-"AnimatedTransformList.dart":
- {
-
- },
-"ViewSpec.dart":
- {
-
- },
-"Transformable.dart":
- {
-
- },
-"FEDisplacementMapElement.dart":
- {
-
- },
-"PathSegArcRel.dart":
- {
-
- },
-"Stylable.dart":
- {
-
- },
-"PathSegLinetoRel.dart":
- {
-
- },
-"PathSegCurvetoCubicSmoothRel.dart":
- {
-
- },
-"FEMorphologyElement.dart":
- {
-
- },
-"ElementInstance.dart":
- {
-
- },
-"AnimateMotionElement.dart":
- {
-
- },
-"AElement.dart":
- {
-
- },
-"FontElement.dart":
- {
-
- },
-"AnimatedInteger.dart":
- {
-
- },
-"PathElement.dart":
- {
-
- },
-"FEColorMatrixElement.dart":
- {
-
- },
-"PathSegLinetoHorizontalAbs.dart":
- {
-
- },
-"NumberList.dart":
- {
-
- },
-"RectElement.dart":
- {
-
- },
-"MPathElement.dart":
- {
-
- },
-"PathSegClosePath.dart":
- {
-
- },
-"FEFloodElement.dart":
- {
-
- },
-"FontFaceSrcElement.dart":
- {
-
- },
-"Number.dart":
- {
-
- },
-"PolylineElement.dart":
- {
-
- },
-"AnimatedLengthList.dart":
- {
-
- },
-"FECompositeElement.dart":
- {
-
- },
-"FontFaceFormatElement.dart":
- {
-
- },
-"TransformList.dart":
- {
-
- },
-"FEDropShadowElement.dart":
- {
-
- },
-"SvgSvgElement.dart":
- {
-
- },
-"PreserveAspectRatio.dart":
- {
-
- },
-"ForeignObjectElement.dart":
- {
-
- },
-"FESpotLightElement.dart":
- {
-
- },
-"DescElement.dart":
- {
-
- },
-"FontFaceUriElement.dart":
- {
-
- },
-"ImageElement.dart":
- {
-
- },
-"AnimatedPreserveAspectRatio.dart":
- {
-
- },
-"PathSegCurvetoQuadraticSmoothAbs.dart":
- {
-
- },
-"GElement.dart":
- {
-
- },
-"PathSegMovetoRel.dart":
- {
-
- },
-"Paint.dart":
- {
-
- },
-"AnimatedEnumeration.dart":
- {
-
- },
-"FEFuncAElement.dart":
- {
-
- },
-"CircleElement.dart":
- {
-
- },
-"SetElement.dart":
- {
-
- },
-"TitleElement.dart":
- {
-
- },
-"PatternElement.dart":
- {
-
- },
-"AnimatedString.dart":
- {
-
- },
-"FEFuncRElement.dart":
- {
-
- },
-"SvgDocument.dart":
- {
-
- },
-"FEMergeNodeElement.dart":
- {
-
- },
-"SvgException.dart":
- {
-
- },
-"UseElement.dart":
- {
-
- },
-"PathSegLinetoVerticalAbs.dart":
- {
-
- },
-"FontFaceElement.dart":
- {
-
- },
-"PathSegCurvetoCubicRel.dart":
- {
-
- },
-"Color.dart":
- {
-
- },
-"PathSegArcAbs.dart":
- {
-
- },
-"FilterPrimitiveStandardAttributes.dart":
- {
-
- },
-"AnimationElement.dart":
- {
-
- },
-"AltGlyphElement.dart":
- {
-
- },
-"MarkerElement.dart":
- {
-
- },
-"FEDiffuseLightingElement.dart":
- {
-
- },
-"FETurbulenceElement.dart":
- {
-
- },
-"SvgElement.dart":
- {
-
- },
-"Transform.dart":
- {
-
- },
-"Locatable.dart":
- {
-
- },
-"UnitTypes.dart":
- {
-
- },
-"ViewElement.dart":
- {
-
- },
-"FEConvolveMatrixElement.dart":
- {
-
- },
-"FEDistantLightElement.dart":
- {
-
- },
-"PolygonElement.dart":
- {
-
- },
-"MetadataElement.dart":
- {
-
- },
-"ZoomAndPan.dart":
- {
-
- },
-"ClipPathElement.dart":
- {
-
- },
-"TextPositioningElement.dart":
- {
-
- },
-"StopElement.dart":
- {
-
- },
-"SymbolElement.dart":
- {
-
- },
-"HKernElement.dart":
- {
-
- },
-"GlyphRefElement.dart":
- {
-
- },
-"PathSegCurvetoCubicAbs.dart":
- {
-
- },
-"GlyphElement.dart":
- {
-
- },
-"MaskElement.dart":
- {
-
- },
-"TextContentElement.dart":
- {
-
- },
-"FilterElement.dart":
- {
-
- },
-"FEFuncGElement.dart":
- {
-
- },
-"EllipseElement.dart":
- {
-
- },
-"Tests.dart":
- {
-
- },
-"AnimatedLength.dart":
- {
-
- },
-"PathSegCurvetoQuadraticSmoothRel.dart":
- {
-
- },
-"StyleElement.dart":
- {
-
- },
-"CursorElement.dart":
- {
-
- },
-"FitToViewBox.dart":
- {
-
- },
-"TextElement.dart":
- {
-
- },
-"FEFuncBElement.dart":
- {
-
- },
-"FEOffsetElement.dart":
- {
-
- },
-"FEImageElement.dart":
- {
-
- },
-"LangSpace.dart":
- {
-
- },
-"FESpecularLightingElement.dart":
- {
-
- },
-"PointList.dart":
- {
-
- },
-"LinearGradientElement.dart":
- {
-
- },
-"PathSegMovetoAbs.dart":
- {
-
- },
-"AnimatedNumberList.dart":
- {
-
- },
-"PathSegLinetoHorizontalRel.dart":
- {
-
- },
-"LengthList.dart":
- {
-
- },
-"ComponentTransferFunctionElement.dart":
- {
-
- },
-"StringList.dart":
- {
-
- },
-"FEComponentTransferElement.dart":
- {
-
- },
-"PathSegCurvetoCubicSmoothAbs.dart":
- {
-
- },
-"PathSegLinetoAbs.dart":
- {
-
- },
-"AnimatedNumber.dart":
- {
-
- },
-"TextPathElement.dart":
- {
-
- },
-"AnimatedRect.dart":
- {
-
- },
-"AnimatedAngle.dart":
- {
-
- },
-"AltGlyphItemElement.dart":
- {
-
- },
-"TRefElement.dart":
- {
-
- },
-"AnimateColorElement.dart":
- {
-
- },
-"PathSeg.dart":
- {
-
- },
-"FEBlendElement.dart":
- {
-
- }
-}
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 713efe3..0450497 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -41,7 +41,7 @@
[Suppressed] DOMString toDataURL([TreatNullAs=NullString, TreatUndefinedAs=NullString,Optional=DefaultIsUndefined] in DOMString type) raises(DOMException);
[Custom] DOMString toDataURL([TreatNullAs=NullString, TreatUndefinedAs=NullString,Optional=DefaultIsUndefined] in DOMString type, [Optional] in float quality) raises(DOMException);
- [Suppressed] DOMObject getContext(in DOMString contextId);
+ [Suppressed] any getContext(in DOMString contextId);
[Custom] CanvasRenderingContext getContext(in DOMString contextId, [Optional] in Dictionary attrs);
};
@@ -54,8 +54,6 @@
interface HTMLSelectElement {
[Suppressed] void add([Optional=DefaultIsUndefined] in HTMLElement element, [Optional=DefaultIsUndefined] in HTMLElement before);
[Suppressed, Custom] void remove();
- [Custom] void remove(in long index);
- [Custom] void remove(in HTMLOptionElement option);
};
[Supplemental]
@@ -209,8 +207,8 @@
// We have to use custom code because our code generator does not support int8_t type.
// int8_t getInt8(in unsigned long byteOffset);
// uint8_t getUint8(in unsigned long byteOffset);
- [Suppressed] DOMObject getInt8();
- [Suppressed] DOMObject getUint8();
+ [Suppressed] any getInt8();
+ [Suppressed] any getUint8();
byte getInt8(in unsigned long byteOffset)
raises (DOMException);
octet getUint8(in unsigned long byteOffset)
@@ -322,7 +320,7 @@
interface SQLResultSetRowList {
// Change the return type to Dictionary so that rows are exposed in the Dart
// API as a Maps, with the appropriate conversion in JavaScript.
- [Suppressed] DOMObject item(in unsigned long index);
+ [Suppressed] any item(in unsigned long index);
[Custom] Dictionary item(in unsigned long index);
};
@@ -341,5 +339,24 @@
[Custom] void send(ArrayBufferView data) raises(DOMException);
};
+[Supplemental]
+interface XMLHttpRequest {
+ [Custom] void send()
+ raises(DOMException);
+ [Custom] void send(in ArrayBuffer data) // FIXME: this should be eventually deprecated.
+ raises(DOMException);
+ [Custom] void send(in ArrayBufferView data)
+ raises(DOMException);
+ [Conditional=BLOB, Custom] void send(in Blob data)
+ raises(DOMException);
+ [Custom] void send(in Document data)
+ raises(DOMException);
+ [Custom] void send([StrictTypeChecking] in DOMString data)
+ raises(DOMException);
+ [Custom] void send(in DOMFormData data)
+ raises(DOMException);
+};
+
+
[Suppressed]
interface Entity {};
diff --git a/tools/dom/scripts/databasebuilder.py b/tools/dom/scripts/databasebuilder.py
index 81d6c0e..96e724d 100755
--- a/tools/dom/scripts/databasebuilder.py
+++ b/tools/dom/scripts/databasebuilder.py
@@ -87,7 +87,7 @@
def _resolve_type_defs(self, idl_file):
type_def_map = {}
# build map
- for type_def in idl_file.all(IDLTypeDef):
+ for type_def in idl_file.typeDefs:
if type_def.type.id != type_def.id: # sanity check
type_def_map[type_def.id] = type_def.type.id
# use the map
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index fa6fcac..20f6905 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -421,6 +421,10 @@
'dynamic', 'dynamic')
dart2js_conversions = monitored.Dict('generator.dart2js_conversions', {
+ 'Date get':
+ Conversion('_convertNativeToDart_DateTime', 'dynamic', 'DateTime'),
+ 'Date set':
+ Conversion('_convertDartToNative_DateTime', 'DateTime', 'dynamic'),
# Wrap non-local Windows. We need to check EventTarget (the base type)
# as well. Note, there are no functions that take a non-local Window
# as a parameter / setter.
@@ -583,6 +587,7 @@
'IDBRequest.source': ["@Creates('Null')"],
'IDBFactory.open': ["@Creates('Database')"],
+ 'IDBFactory.webkitGetDatabaseNames': ["@Creates('DomStringList')"],
'IDBObjectStore.put': ["@_annotation_Creates_IDBKey"],
'IDBObjectStore.add': ["@_annotation_Creates_IDBKey"],
@@ -635,6 +640,15 @@
'SQLResultSetRowList.item': ["@Creates('=Object')"],
+ 'WebGLRenderingContext.getParameter': [
+ # Taken from http://www.khronos.org/registry/webgl/specs/latest/
+ # Section 5.14.3 Setting and getting state
+ "@Creates('Null|num|String|bool|=List|Float32Array|Int32Array|Uint32Array"
+ "|WebGLFramebuffer|WebGLRenderbuffer|WebGLTexture')",
+ "@Returns('Null|num|String|bool|=List|Float32Array|Int32Array|Uint32Array"
+ "|WebGLFramebuffer|WebGLRenderbuffer|WebGLTexture')",
+ ],
+
'XMLHttpRequest.response': [
"@Creates('ArrayBuffer|Blob|Document|=Object|=List|String|num')",
],
@@ -710,6 +724,7 @@
dart_annotations = monitored.Dict('generator.dart_annotations', {
'ArrayBuffer': _all_but_ie9_annotations,
'ArrayBufferView': _all_but_ie9_annotations,
+ 'Crypto': _webkit_experimental_annotations,
'Database': _web_sql_annotations,
'DatabaseSync': _web_sql_annotations,
'DOMApplicationCache': [
@@ -1200,7 +1215,10 @@
type = 'RefPtr<%s>' % type
if type == 'String':
type = 'DartStringAdapter'
- return '%s', type, 'DartUtilities', 'dartTo%s' % self._capitalized_native_type()
+ target_type = self._capitalized_native_type()
+ if self.idl_type() == 'Date':
+ target_type = 'Date'
+ return '%s', type, 'DartUtilities', 'dartTo%s' % target_type
def parameter_type(self):
if self.native_type() == 'String':
@@ -1211,8 +1229,14 @@
return []
def to_dart_conversion(self, value, interface_name=None, attributes=None):
- function_name = self._capitalized_native_type()
- function_name = function_name[0].lower() + function_name[1:]
+ # TODO(antonm): if there are more instances of the case
+ # when conversion depends on both Dart type and C++ type,
+ # consider introducing a corresponding argument/class.
+ if self.idl_type() == 'Date':
+ function_name = 'date'
+ else:
+ function_name = self._capitalized_native_type()
+ function_name = function_name[0].lower() + function_name[1:]
function_name = 'DartUtilities::%sToDart' % function_name
if attributes and 'TreatReturnedNullStringAs' in attributes:
function_name += 'WithNullCheck'
@@ -1321,7 +1345,7 @@
'any': TypeData(clazz='Primitive', dart_type='Object', native_type='ScriptValue'),
'Array': TypeData(clazz='Primitive', dart_type='List'),
'custom': TypeData(clazz='Primitive', dart_type='dynamic'),
- 'Date': TypeData(clazz='Primitive', dart_type='Date', native_type='double'),
+ 'Date': TypeData(clazz='Primitive', dart_type='DateTime', native_type='double'),
'DOMObject': TypeData(clazz='Primitive', dart_type='Object', native_type='ScriptValue'),
'DOMString': TypeData(clazz='Primitive', dart_type='String', native_type='String'),
# TODO(vsm): This won't actually work until we convert the Map to
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index c312a9f..705232a 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -154,11 +154,36 @@
'Geolocation.getCurrentPosition',
'Geolocation.watchPosition',
'HashChangeEvent.initHashChangeEvent',
+ 'HTMLTableElement.createCaption',
+ 'HTMLTableElement.createTBody',
+ 'HTMLTableElement.createTFoot',
+ 'HTMLTableElement.createTHead',
+ 'HTMLTableElement.insertRow',
+ 'HTMLTableElement.rows',
+ 'HTMLTableElement.tBodies',
+ 'HTMLTableRowElement.cells',
+ 'HTMLTableRowElement.insertCell',
+ 'HTMLTableSectionElement.insertRow',
+ 'HTMLTableSectionElement.rows',
+ 'IDBCursor.delete',
+ 'IDBCursor.update',
+ 'IDBDatabase.createObjectStore',
'IDBFactory.deleteDatabase',
+ 'IDBFactory.webkitGetDatabaseNames',
'IDBFactory.open',
- 'IDBObjectStore.put',
+ 'IDBIndex.count',
+ 'IDBIndex.get',
+ 'IDBIndex.getKey',
+ 'IDBIndex.openCursor',
+ 'IDBIndex.openKeyCursor',
+ 'IDBObjectStore.add',
+ 'IDBObjectStore.clear',
+ 'IDBObjectStore.count',
+ 'IDBObjectStore.createIndex',
+ 'IDBObjectStore.delete',
'IDBObjectStore.getObject',
'IDBObjectStore.openCursor',
+ 'IDBObjectStore.put',
'KeyboardEvent.initKeyboardEvent',
'KeyboardEvent.keyIdentifier',
'MessageEvent.initMessageEvent',
diff --git a/tools/dom/scripts/idlnode.py b/tools/dom/scripts/idlnode.py
index 7442912..f8dc742 100755
--- a/tools/dom/scripts/idlnode.py
+++ b/tools/dom/scripts/idlnode.py
@@ -258,9 +258,11 @@
modules = self._convert_all(ast, 'Module', IDLModule)
self.implementsStatements = self._convert_all(ast, 'ImplStmt',
IDLImplementsStatement)
+ self.typeDefs = self._convert_all(ast, 'TypeDef', IDLTypeDef)
for module in modules:
self.interfaces.extend(module.interfaces)
self.implementsStatements.extend(module.implementsStatements)
+ self.typeDefs.extend(module.typeDefs)
class IDLModule(IDLNode):
diff --git a/tools/dom/scripts/idlparser.py b/tools/dom/scripts/idlparser.py
index a3ee82f..e3c47b3 100755
--- a/tools/dom/scripts/idlparser.py
+++ b/tools/dom/scripts/idlparser.py
@@ -70,7 +70,7 @@
OR(Module, Interface, ExceptionDef, TypeDef, ImplStmt,
ValueTypeDef, Const, Enum),
# WebKit:
- OR(Module, Interface, Enum))
+ OR(Module, Interface, Enum, TypeDef))
def Enum():
def StringLiteral():
diff --git a/tools/dom/scripts/idlsync.py b/tools/dom/scripts/idlsync.py
index 1439399..94f435e 100755
--- a/tools/dom/scripts/idlsync.py
+++ b/tools/dom/scripts/idlsync.py
@@ -31,7 +31,6 @@
WEBKIT_REV_PATTERN = r'"dartium_webkit_revision": "(\d+)",'
WEBCORE_SUBPATH = 'Source/WebCore'
LOCAL_WEBKIT_IDL_PATH = os.path.join(DART_PATH, 'third_party', 'WebCore')
-LOCAL_WEBKIT_README = os.path.join(LOCAL_WEBKIT_IDL_PATH, 'README')
LOCAL_WEBKIT_README = """\
This directory contains a copy of WebKit/WebCore IDL files.
See the attached LICENSE-* files in this directory.
@@ -48,10 +47,19 @@
CHROME_URL_PATTERN = r'"chromium_url": "(\S+)",'
CHROME_REV_PATTERN = r'"chromium_revision": "(\d+)",'
CHROME_IDL_SUBPATH = 'trunk/src/chrome/common/extensions/api'
-CHROME_TOOLS_SUBPATH = 'trunk/src/tools/json_schema_compiler'
+CHROME_TOOLS_SUBPATH = 'trunk/src/tools'
+CHROME_COMPILER_SUBPATH = 'trunk/src/tools/json_schema_compiler'
+CHROME_IDL_PARSER_SUBPATH = 'trunk/src/ppapi/generators'
+CHROME_PLY_SUBPATH = 'trunk/src/third_party/ply'
LOCAL_CHROME_IDL_PATH = os.path.join(DART_PATH, 'third_party', 'chrome', 'idl')
LOCAL_CHROME_TOOLS_PATH = os.path.join(DART_PATH, 'third_party', 'chrome',
'tools')
+LOCAL_CHROME_COMPILER_PATH = os.path.join(DART_PATH, 'third_party', 'chrome',
+ 'tools', 'json_schema_compiler')
+LOCAL_CHROME_IDL_PARSER_PATH = os.path.join(DART_PATH, 'third_party', 'chrome',
+ 'ppapi', 'generators')
+LOCAL_CHROME_PLY_PATH = os.path.join(DART_PATH, 'third_party', 'chrome',
+ 'third_party', 'ply')
LOCAL_CHROME_README = """\
This directory contains a copy of Chromium IDL and generation scripts
used to generate Dart APIs for Chrome Apps.
@@ -63,6 +71,8 @@
Please see the corresponding LICENSE file at
%(url)s/trunk/src/LICENSE.
"""
+DEPTH_FILES = 'files'
+DEPTH_INFINITY = 'infinity'
# Regular expressions corresponding to URL/revision patters in the
# DEPS file.
@@ -73,15 +83,28 @@
# List of components to update.
UPDATE_LIST = [
- # (component, remote subpath, local path, local readme file)
+ # (component, remote subpath, local path, local readme file, depth)
# WebKit IDL.
- ('webkit', WEBCORE_SUBPATH, LOCAL_WEBKIT_IDL_PATH, LOCAL_WEBKIT_README),
+ ('webkit', WEBCORE_SUBPATH, LOCAL_WEBKIT_IDL_PATH, LOCAL_WEBKIT_README,
+ DEPTH_INFINITY),
# Chrome IDL.
- ('chrome', CHROME_IDL_SUBPATH, LOCAL_CHROME_IDL_PATH, LOCAL_CHROME_README),
- # Chrome IDL compiler files.
+ ('chrome', CHROME_IDL_SUBPATH, LOCAL_CHROME_IDL_PATH, LOCAL_CHROME_README,
+ DEPTH_INFINITY),
+ # Chrome PPAPI generators. Contains idl_parser.py which is used by the
+ # Chrome IDL compiler.
+ ('chrome', CHROME_IDL_PARSER_SUBPATH, LOCAL_CHROME_IDL_PARSER_PATH,
+ LOCAL_CHROME_README, DEPTH_FILES),
+ # ply files.
+ ('chrome', CHROME_PLY_SUBPATH, LOCAL_CHROME_PLY_PATH, LOCAL_CHROME_README,
+ DEPTH_INFINITY),
+ # Top level Chrome tools folder. Contains json_comment_eater.py which is
+ # needed by the Chrome IDL compiler.
('chrome', CHROME_TOOLS_SUBPATH, LOCAL_CHROME_TOOLS_PATH,
- LOCAL_CHROME_README),
+ LOCAL_CHROME_README, DEPTH_FILES),
+ # Chrome IDL compiler files.
+ ('chrome', CHROME_COMPILER_SUBPATH, LOCAL_CHROME_COMPILER_PATH,
+ LOCAL_CHROME_README, DEPTH_INFINITY),
]
@@ -111,9 +134,9 @@
return (url, revision)
-def RefreshIDL(url, revision, remote_path, local_path):
+def RefreshFiles(url, revision, remote_path, local_path, depth):
"""Refreshes refreshes files in the local_path to specific url /
- revision / remote_path."""
+ revision / remote_path, exporting to depth"""
cwd = os.getcwd()
try:
if os.path.exists(local_path):
@@ -122,7 +145,8 @@
if not os.path.exists(head):
os.makedirs(head)
os.chdir(head)
- RunCommand(['svn', 'export', '-r', revision, url + '/' + remote_path, tail])
+ RunCommand(['svn', 'export', '--depth', depth, '-r', revision,
+ url + '/' + remote_path, tail])
finally:
os.chdir(cwd)
@@ -174,13 +198,13 @@
def main():
deps = GetDeps()
update = ParseOptions()
- for (component, remote_path, local_path, readme) in UPDATE_LIST:
+ for (component, remote_path, local_path, readme, depth) in UPDATE_LIST:
if component in update.keys():
revision = update[component]
url, latest = GetSvnRevision(deps, component)
if revision is None:
revision = latest
- RefreshIDL(url, revision, remote_path, local_path)
+ RefreshFiles(url, revision, remote_path, local_path, depth)
PruneExtraFiles(local_path)
GenerateReadme(local_path, readme, url, revision)
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index e3ba590..7a0c5dd 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -359,6 +359,8 @@
js_support_checks = dict({
'ArrayBuffer': "JS('bool', 'typeof window.ArrayBuffer != \"undefined\"')",
+ 'Crypto':
+ "JS('bool', '!!(window.crypto && window.crypto.getRandomValues)')",
'Database': "JS('bool', '!!(window.openDatabase)')",
'DOMApplicationCache': "JS('bool', '!!(window.applicationCache)')",
'DOMFileSystem': "JS('bool', '!!(window.webkitRequestFileSystem)')",
@@ -669,10 +671,27 @@
#
# class YImpl extends ListBase<T> { copies of transitive XImpl methods; }
#
- self._members_emitter.Emit(
- '\n'
- ' $TYPE operator[](int index) => JS("$TYPE", "#[#]", this, index);\n',
- TYPE=self.SecureOutputType(element_type))
+
+ ext_attrs = self._interface.ext_attrs
+ has_indexed_getter = ('IndexedGetter' in ext_attrs or
+ 'CustomIndexedSetter' in ext_attrs)
+
+ if has_indexed_getter:
+ self._members_emitter.Emit(
+ '\n'
+ ' $TYPE operator[](int index) => '
+ 'JS("$TYPE", "#[#]", this, index);\n',
+ TYPE=self.SecureOutputType(element_type))
+ else:
+ if any(op.id == 'getItem' for op in self._interface.operations):
+ indexed_getter = 'this.getItem(index)'
+ elif any(op.id == 'item' for op in self._interface.operations):
+ indexed_getter = 'this.item(index)'
+ self._members_emitter.Emit(
+ '\n'
+ ' $TYPE operator[](int index) => $INDEXED_GETTER;\n',
+ INDEXED_GETTER=indexed_getter,
+ TYPE=self.SecureOutputType(element_type))
if 'CustomIndexedSetter' in self._interface.ext_attrs:
self._members_emitter.Emit(
@@ -801,9 +820,9 @@
def _AddConvertingGetter(self, attr, html_name, conversion):
self._members_emitter.Emit(
- '\n $RETURN_TYPE get $HTML_NAME => $CONVERT(this._$(HTML_NAME));'
+ '\n $RETURN_TYPE get $HTML_NAME => $CONVERT(this._get_$(HTML_NAME));'
"\n @JSName('$NAME')"
- '\n $(ANNOTATIONS)final $NATIVE_TYPE _$HTML_NAME;'
+ '\n $(ANNOTATIONS)final $NATIVE_TYPE _get_$HTML_NAME;'
'\n',
ANNOTATIONS=self._Annotations(attr.type.id, html_name),
CONVERT=conversion.function_name,
@@ -816,9 +835,9 @@
self._members_emitter.Emit(
# TODO(sra): Use metadata to provide native name.
'\n void set $HTML_NAME($INPUT_TYPE value) {'
- '\n this._$HTML_NAME = $CONVERT(value);'
+ '\n this._set_$HTML_NAME = $CONVERT(value);'
'\n }'
- '\n void set _$HTML_NAME(/*$NATIVE_TYPE*/ value) {'
+ '\n void set _set_$HTML_NAME(/*$NATIVE_TYPE*/ value) {'
'\n JS("void", "#.$NAME = #", this, value);'
'\n }'
'\n',
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index 51dd3b5..65528b4 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -114,7 +114,8 @@
String get first => readClasses().first;
String get last => readClasses().last;
String get single => readClasses().single;
- List<String> toList() => readClasses().toList();
+ List<String> toList({ bool growable: true }) =>
+ readClasses().toList(growable: growable);
Set<String> toSet() => readClasses().toSet();
String min([int compare(String a, String b)]) =>
readClasses().min(compare);
diff --git a/tools/dom/src/KeyboardEventController.dart b/tools/dom/src/KeyboardEventController.dart
index 73a7602..4235b75 100644
--- a/tools/dom/src/KeyboardEventController.dart
+++ b/tools/dom/src/KeyboardEventController.dart
@@ -35,7 +35,7 @@
EventTarget _target;
// The distance to shift from upper case alphabet Roman letters to lower case.
- final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0];
+ final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
StreamSubscription _keyUpSubscription, _keyDownSubscription,
_keyPressSubscription;
@@ -170,8 +170,8 @@
if (prevEvent._shadowCharCode == event.charCode) {
return prevEvent.keyCode;
}
- if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".charCodes[0]
- && event.charCode <= "Z".charCodes[0] && event.charCode +
+ if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".codeUnits[0]
+ && event.charCode <= "Z".codeUnits[0] && event.charCode +
_ROMAN_ALPHABET_OFFSET == prevEvent._shadowCharCode) {
return prevEvent.keyCode;
}
diff --git a/tools/dom/src/Serialization.dart b/tools/dom/src/Serialization.dart
index 0d1cc82..df29f58 100644
--- a/tools/dom/src/Serialization.dart
+++ b/tools/dom/src/Serialization.dart
@@ -98,7 +98,7 @@
_serializeList(List list) {
int len = list.length;
- var result = new List.fixedLength(len);
+ var result = new List(len);
for (int i = 0; i < len; i++) {
result[i] = _dispatch(list[i]);
}
diff --git a/tools/dom/src/WrappedList.dart b/tools/dom/src/WrappedList.dart
new file mode 100644
index 0000000..7b27218
--- /dev/null
+++ b/tools/dom/src/WrappedList.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.dom.html;
+
+/**
+ * A list which just wraps another list, for either intercepting list calls or
+ * retyping the list (for example, from List<A> to List<B> where B extends A).
+ */
+class _WrappedList<E> implements List<E> {
+ final List _list;
+
+ _WrappedList(this._list);
+
+ // Iterable APIs
+
+ Iterator<E> get iterator => new _WrappedIterator(_list.iterator);
+
+ Iterable map(f(E element)) => _list.map(f);
+
+ Iterable<E> where(bool f(E element)) => _list.where(f);
+
+ Iterable expand(Iterable f(E element)) => _list.expand(f);
+
+ bool contains(E element) => _list.contains(element);
+
+ void forEach(void f(E element)) { _list.forEach(f); }
+
+ dynamic reduce(initialValue, combine(previousValue, E element)) =>
+ _list.reduce(initialValue, combine);
+
+ bool every(bool f(E element)) => _list.every(f);
+
+ String join([String separator]) => _list.join(separator);
+
+ bool any(bool f(E element)) => _list.any(f);
+
+ List<E> toList({ bool growable: true }) =>
+ new List.from(_list, growable: growable);
+
+ Set<E> toSet() => _list.toSet();
+
+ int get length => _list.length;
+
+ E min([int compare(E a, E b)]) => _list.min(compare);
+
+ E max([int compare(E a, E b)]) => _list.max(compare);
+
+ bool get isEmpty => _list.isEmpty;
+
+ Iterable<E> take(int n) => _list.take(n);
+
+ Iterable<E> takeWhile(bool test(E value)) => _list.takeWhile(test);
+
+ Iterable<E> skip(int n) => _list.skip(n);
+
+ Iterable<E> skipWhile(bool test(E value)) => _list.skipWhile(test);
+
+ E get first => _list.first;
+
+ E get last => _list.last;
+
+ E get single => _list.single;
+
+ E firstMatching(bool test(E value), { E orElse() }) =>
+ _list.firstMatching(test, orElse: orElse);
+
+ E lastMatching(bool test(E value), {E orElse()}) =>
+ _list.lastMatching(test, orElse: orElse);
+
+ E singleMatching(bool test(E value)) => _list.singleMatching(test);
+
+ E elementAt(int index) => _list.elementAt(index);
+
+ // Collection APIs
+
+ void add(E element) { _list.add(element); }
+
+ void addAll(Iterable<E> elements) { _list.addAll(elements); }
+
+ void remove(Object element) { _list.remove(element); }
+
+ void removeAll(Iterable elements) { _list.removeAll(elements); }
+
+ void retainAll(Iterable elements) { _list.retainAll(elements); }
+
+ void removeMatching(bool test(E element)) { _list.removeMatching(test); }
+
+ void retainMatching(bool test(E element)) { _list.retainMatching(test); }
+
+ void clear() { _list.clear(); }
+
+ // List APIs
+
+ E operator [](int index) => _list[index];
+
+ void operator []=(int index, E value) { _list[index] = value; }
+
+ void set length(int newLength) { _list.length = newLength; }
+
+ void addLast(E value) { _list.addLast(value); }
+
+ Iterable<E> get reversed => _list.reversed;
+
+ void sort([int compare(E a, E b)]) { _list.sort(compare); }
+
+ int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
+
+ int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
+
+ E removeAt(int index) => _list.removeAt(index);
+
+ E removeLast() => _list.removeLast();
+
+ List<E> getRange(int start, int length) => _list.getRange(start, length);
+
+ void setRange(int start, int length, List<E> from, [int startFrom]) {
+ _list.setRange(start, length, from, startFrom);
+ }
+
+ void removeRange(int start, int length) { _list.removeRange(start, length); }
+
+ void insertRange(int start, int length, [E fill]) {
+ _list.insertRange(start, length, fill);
+ }
+
+ Map<int, E> asMap() => IterableMixinWorkaround.asMapList(_list);
+}
+
+/**
+ * Iterator wrapper for _WrappedList.
+ */
+class _WrappedIterator<E> implements Iterator<E> {
+ Iterator _iterator;
+
+ _WrappedIterator(this._iterator);
+
+ bool moveNext() {
+ return _iterator.moveNext();
+ }
+
+ E get current => _iterator.current;
+}
diff --git a/tools/dom/src/dart2js_Conversions.dart b/tools/dom/src/dart2js_Conversions.dart
index 8b75d71..7e9ee41 100644
--- a/tools/dom/src/dart2js_Conversions.dart
+++ b/tools/dom/src/dart2js_Conversions.dart
@@ -11,6 +11,15 @@
part of html;
+DateTime _convertNativeToDart_DateTime(date) {
+ var millisSinceEpoch = JS('int', '#.getTime()', date);
+ return new DateTime.fromMillisecondsSinceEpoch(millisSinceEpoch, isUtc: true);
+}
+
+_convertDartToNative_DateTime(DateTime date) {
+ return JS('', 'new Date(#)', date.millisecondsSinceEpoch);
+}
+
WindowBase _convertNativeToDart_Window(win) {
return _DOMWindowCrossFrame._createSafe(win);
}
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index 2f91ab1..cd98baf 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -5,10 +5,15 @@
part of html;
class _Utils {
+ static double dateTimeToDouble(DateTime dateTime) =>
+ dateTime.millisecondsSinceEpoch.toDouble();
+ static DateTime doubleToDateTime(double dateTime) =>
+ new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt());
+
static List convertToList(List list) {
// FIXME: [possible optimization]: do not copy the array if Dart_IsArray is fine w/ it.
final length = list.length;
- List result = new List.fixedLength(length);
+ List result = new List(length);
result.setRange(0, length, list);
return result;
}
diff --git a/tools/dom/templates/html/dart2js/chrome_dart2js.darttemplate b/tools/dom/templates/html/dart2js/chrome_dart2js.darttemplate
index 6449f29..5b2ec9b 100644
--- a/tools/dom/templates/html/dart2js/chrome_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/chrome_dart2js.darttemplate
@@ -12,8 +12,8 @@
/// These functions allow direct access to the Packaged App APIs, allowing
/// Chrome Packaged Apps to be written using Dart.
///
-/// For more information on these APIs, see the Chrome.* APIs Documentation:
-/// http://developer.chrome.com/extensions/api_index.html
+/// For more information on these APIs, see the
+/// [Chrome APIs Documentation](http://developer.chrome.com/extensions/api_index.html)
library chrome;
import 'dart:_foreign_helper' show JS;
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 2823cdd..728b9d0 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -42,6 +42,7 @@
part '$AUXILIARY_DIR/Isolates.dart';
part '$AUXILIARY_DIR/Microtask.dart';
part '$AUXILIARY_DIR/Serialization.dart';
+part '$AUXILIARY_DIR/WrappedList.dart';
part '$AUXILIARY_DIR/shared_FactoryProviders.dart';
part '$AUXILIARY_DIR/dart2js_Conversions.dart';
part '$AUXILIARY_DIR/dart2js_DOMImplementation.dart';
diff --git a/tools/dom/templates/html/dart2js/impl_Console.darttemplate b/tools/dom/templates/html/dart2js/impl_Console.darttemplate
index 0bc592c..25d08e1 100644
--- a/tools/dom/templates/html/dart2js/impl_Console.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_Console.darttemplate
@@ -8,7 +8,7 @@
static Console safeConsole = new Console();
- bool get _isConsoleDefined => JS('bool', "typeof console != 'undefined'");
+ bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
@DomName('Console.memory')
MemoryInfo get memory => _isConsoleDefined ?
diff --git a/tools/dom/templates/html/dart2js/impl_HTMLTableElement.darttemplate b/tools/dom/templates/html/dart2js/impl_HTMLTableElement.darttemplate
deleted file mode 100644
index b41ec58..0000000
--- a/tools/dom/templates/html/dart2js/impl_HTMLTableElement.darttemplate
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of $LIBRARYNAME;
-
-$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
-$!MEMBERS
-
- Element createTBody() {
- if (JS('bool', '!!#.createTBody', this)) {
- return this._createTBody();
- }
- var tbody = new Element.tag('tbody');
- this.children.add(tbody);
- return tbody;
- }
-
- @JSName('createTBody')
- Element _createTBody() native;
-}
diff --git a/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate b/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
index 2c6fec6..6a599c1 100644
--- a/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
@@ -2,6 +2,16 @@
// https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
// Auto-generated dart:audio library.
+/**
+ * An API for storing data in the browser that can be queried with SQL.
+ *
+ * **Caution:** this specification is no longer actively maintained by the Web
+ * Applications Working Group and may be removed at any time.
+ * See [the W3C Web SQL Database specification](http://www.w3.org/TR/webdatabase/)
+ * for more information.
+ *
+ * The [dart:indexed_db] APIs is a recommended alternatives.
+ */
library dart.dom.web_sql;
import 'dart:async';
diff --git a/tools/dom/templates/html/dartium/chrome_dartium.darttemplate b/tools/dom/templates/html/dartium/chrome_dartium.darttemplate
index 38db7cd..03a6cb4 100644
--- a/tools/dom/templates/html/dartium/chrome_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/chrome_dartium.darttemplate
@@ -5,4 +5,11 @@
// DO NOT EDIT
// Auto-generated dart:chrome library.
+/// Native wrappers for the Chrome Packaged App APIs.
+///
+/// These functions allow direct access to the Packaged App APIs, allowing
+/// Chrome Packaged Apps to be written using Dart.
+///
+/// For more information on these APIs, see the
+/// [Chrome APIs Documentation](http://developer.chrome.com/extensions/api_index.html)
library chrome;
diff --git a/tools/dom/templates/html/dartium/html_dartium.darttemplate b/tools/dom/templates/html/dartium/html_dartium.darttemplate
index 4e2b5e7..77ca4f5 100644
--- a/tools/dom/templates/html/dartium/html_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/html_dartium.darttemplate
@@ -5,6 +5,7 @@
// DO NOT EDIT
// Auto-generated dart:html library.
+/// The Dart HTML library.
library dart.dom.html;
import 'dart:async';
@@ -32,6 +33,7 @@
part '$AUXILIARY_DIR/KeyName.dart';
part '$AUXILIARY_DIR/ReadyState.dart';
part '$AUXILIARY_DIR/Timer.dart';
+part '$AUXILIARY_DIR/WrappedList.dart';
part '$AUXILIARY_DIR/_HttpRequestUtils.dart';
part '$AUXILIARY_DIR/shared_FactoryProviders.dart';
part '$AUXILIARY_DIR/dartium_KeyEvent.dart';
diff --git a/tools/dom/templates/html/dartium/web_sql_dartium.darttemplate b/tools/dom/templates/html/dartium/web_sql_dartium.darttemplate
index 0556070..bfb9155 100644
--- a/tools/dom/templates/html/dartium/web_sql_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/web_sql_dartium.darttemplate
@@ -2,6 +2,16 @@
// https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
// Auto-generated dart:audio library.
+/**
+ * An API for storing data in the browser that can be queried with SQL.
+ *
+ * **Caution:** this specification is no longer actively maintained by the Web
+ * Applications Working Group and may be removed at any time.
+ * See [the W3C Web SQL Database specification](http://www.w3.org/TR/webdatabase/)
+ * for more information.
+ *
+ * The [dart:indexed_db] APIs is a recommended alternatives.
+ */
library dart.dom.web_sql;
import 'dart:async';
diff --git a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
index 6c73249..040a646 100644
--- a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
@@ -53,11 +53,14 @@
$if DART2JS
void setProperty(String propertyName, String value, [String priority]) {
- JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
- // Bug #2772, IE9 requires a poke to actually apply the value.
- if (JS('bool', '!!#.setAttribute', this)) {
- JS('void', '#.setAttribute(#, #)', this, propertyName, value);
- }
+ // try/catch for IE9 which throws on unsupported values.
+ try {
+ JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
+ // Bug #2772, IE9 requires a poke to actually apply the value.
+ if (JS('bool', '!!#.setAttribute', this)) {
+ JS('void', '#.setAttribute(#, #)', this, propertyName, value);
+ }
+ } catch (e) {}
}
/**
diff --git a/tools/dom/templates/html/impl/impl_Document.darttemplate b/tools/dom/templates/html/impl/impl_Document.darttemplate
index ad71764..c1714b0 100644
--- a/tools/dom/templates/html/impl/impl_Document.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Document.darttemplate
@@ -61,7 +61,7 @@
final mutableMatches = $dom_getElementsByName(
selectors.substring(7,selectors.length - 2));
int len = mutableMatches.length;
- final copyOfMatches = new List<Element>.fixedLength(len);
+ final copyOfMatches = new List<Element>(len);
for (int i = 0; i < len; ++i) {
copyOfMatches[i] = mutableMatches[i];
}
@@ -69,7 +69,7 @@
} else if (new RegExp("^[*a-zA-Z0-9]+\$").hasMatch(selectors)) {
final mutableMatches = $dom_getElementsByTagName(selectors);
int len = mutableMatches.length;
- final copyOfMatches = new List<Element>.fixedLength(len);
+ final copyOfMatches = new List<Element>(len);
for (int i = 0; i < len; ++i) {
copyOfMatches[i] = mutableMatches[i];
}
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 3e0080a..35e8e2f 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -15,8 +15,14 @@
: _childElements = element.$dom_children,
_element = element;
- List<Element> toList() {
- final output = new List<Element>.fixedLength(_childElements.length);
+ List<Element> toList({ bool growable: true }) {
+ List<Element> output;
+ if (growable) {
+ output = <Element>[];
+ output.length = _childElements.length;
+ } else {
+ output = new List<Element>(_childElements.length);
+ }
for (int i = 0, len = _childElements.length; i < len; i++) {
output[i] = _childElements[i];
}
@@ -254,6 +260,10 @@
Element max([int compare(Element a, Element b)]) {
return IterableMixinWorkaround.max(this, compare);
}
+
+ Map<int, Element> asMap() {
+ return IterableMixinWorkaround.asMapList(this);
+ }
}
// TODO(jacobr): this is an inefficient implementation but it is hard to see
@@ -312,7 +322,8 @@
return false;
}
- List<Element> toList() => new List<Element>.from(this);
+ List<Element> toList({ bool growable: true }) =>
+ new List<Element>.from(this, growable: growable);
Set<Element> toSet() => new Set<Element>.from(this);
Iterable<Element> take(int n) {
@@ -454,6 +465,10 @@
Element max([int compare(Element a, Element b)]) {
return IterableMixinWorkaround.max(this, compare);
}
+
+ Map<int, Element> asMap() {
+ return IterableMixinWorkaround.asMapList(this);
+ }
}
class _FrozenElementListIterator implements Iterator<Element> {
diff --git a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
index f2777b6..c64f11a 100644
--- a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
@@ -16,17 +16,6 @@
document.$dom_body = value;
}
- /**
- * Registers a custom Element subclass as an available HTML tag.
- *
- * Not yet implemented.
- */
- @Experimental
- void register(String tagName, Type elementClass) {
- // TODO: tagName validation
- throw new Exception('Not yet implemented');
- }
-
@DomName('Document.caretRangeFromPoint')
Range caretRangeFromPoint(int x, int y) {
return document.$dom_caretRangeFromPoint(x, y);
diff --git a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
index deced63..bcac38d 100644
--- a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
@@ -12,7 +12,6 @@
TelephoneInputElement,
EmailInputElement,
PasswordInputElement,
- DateTimeInputElement,
DateInputElement,
MonthInputElement,
WeekInputElement,
@@ -303,32 +302,6 @@
}
/**
- * A date and time (year, month, day, hour, minute, second, fraction of a
- * second) with the time zone set to UTC.
- *
- * Use [supported] to check if this is supported on the current platform.
- */
-@SupportedBrowser(SupportedBrowser.CHROME, '25')
-@Experimental
-abstract class DateTimeInputElement implements RangeInputElementBase {
- factory DateTimeInputElement() => new InputElement(type: 'datetime');
-
- @DomName('HTMLInputElement.valueAsDate')
- DateTime valueAsDate;
-
- @DomName('HTMLInputElement.readOnly')
- bool readOnly;
-
- @DomName('HTMLInputElement.required')
- bool required;
-
- /// Returns true if this input type is supported on the current platform.
- static bool get supported {
- return (new InputElement(type: 'datetime')).type == 'datetime';
- }
-}
-
-/**
* A date (year, month, day) with no time zone.
*
* Use [supported] to check if this is supported on the current platform.
diff --git a/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate
new file mode 100644
index 0000000..32cd109
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+@DocsEditable
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+
+ @DomName('HTMLTableElement.tBodies')
+ List<TableSectionElement> get tBodies =>
+ new _WrappedList<TableSectionElement>($dom_tBodies);
+
+ @DomName('HTMLTableElement.rows')
+ List<TableRowElement> get rows =>
+ new _WrappedList<TableRowElement>($dom_rows);
+
+ TableRowElement addRow() {
+ return insertRow(-1);
+ }
+
+ TableCaptionElement createCaption() => $dom_createCaption();
+ TableSectionElement createTBody() => $dom_createTBody();
+ TableSectionElement createTFoot() => $dom_createTFoot();
+ TableSectionElement createTHead() => $dom_createTHead();
+ TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+$if DART2JS
+ TableSectionElement $dom_createTBody() {
+ if (JS('bool', '!!#.createTBody', this)) {
+ return this._createTBody();
+ }
+ var tbody = new Element.tag('tbody');
+ this.children.add(tbody);
+ return tbody;
+ }
+
+ @JSName('createTBody')
+ TableSectionElement _createTBody() native;
+$endif
+
+$!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate
new file mode 100644
index 0000000..af5ef17
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+@DocsEditable
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+
+ @DomName('HTMLTableRowElement.cells')
+ List<TableCellElement> get cells =>
+ new _WrappedList<TableCellElement>($dom_cells);
+
+ TableCellElement addCell() {
+ return insertCell(-1);
+ }
+
+ TableCellElement insertCell(int index) => $dom_insertCell(index);
+
+$!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate
new file mode 100644
index 0000000..cb5dd96
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+@DocsEditable
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+
+ @DomName('HTMLTableSectionElement.rows')
+ List<TableRowElement> get rows =>
+ new _WrappedList<TableRowElement>($dom_rows);
+
+ TableRowElement addRow() {
+ return insertRow(-1);
+ }
+
+ TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+$!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate b/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate
new file mode 100644
index 0000000..3464b5b
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate
@@ -0,0 +1,27 @@
+// 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 $LIBRARYNAME;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+ @DomName('IDBCursor.delete')
+ Future delete() {
+ try {
+ return _completeRequest($dom_delete());
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBCursor.value')
+ Future update(value) {
+ try {
+ return _completeRequest($dom_update(value));
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ $!MEMBERS
+}
diff --git a/tools/dom/templates/html/dart2js/impl_IDBDatabase.darttemplate b/tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate
similarity index 64%
rename from tools/dom/templates/html/dart2js/impl_IDBDatabase.darttemplate
rename to tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate
index cc7154d..fc77a04 100644
--- a/tools/dom/templates/html/dart2js/impl_IDBDatabase.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate
@@ -1,11 +1,27 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of $LIBRARYNAME;
+@DocsEditable
$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+ @DomName('IDBDatabase.createObjectStore')
+ @DocsEditable
+ ObjectStore createObjectStore(String name,
+ {String keyPath, bool autoIncrement}) {
+ var options = {};
+ if (keyPath != null) {
+ options['keyPath'] = keyPath;
+ }
+ if (autoIncrement != null) {
+ options['autoIncrement'] = autoIncrement;
+ }
+ return $dom_createObjectStore(name, options);
+ }
+
+$if DART2JS
Transaction transaction(storeName_OR_storeNames, String mode) {
if (mode != 'readonly' && mode != 'readwrite') {
throw new ArgumentError(mode);
@@ -22,5 +38,6 @@
@JSName('transaction')
Transaction _transaction(stores, mode) native;
+$endif
$!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
index 7220e51..01031d6 100644
--- a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
@@ -62,6 +62,31 @@
}
}
+ @DomName('IDBFactory.getDatabaseNames')
+ @SupportedBrowser(SupportedBrowser.CHROME)
+ @Experimental
+ Future<List<String>> getDatabaseNames() {
+ try {
+ var request = $dom_webkitGetDatabaseNames();
+
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ /**
+ * Checks to see if getDatabaseNames is supported by the current platform.
+ */
+ bool get supportsDatabaseNames {
+$if DART2JS
+ return supported && JS('bool',
+ '!!(#.getDatabaseNames || #.webkitGetDatabaseNames)', this, this);
+$else
+ return true;
+$endif
+ }
+
$!MEMBERS
}
diff --git a/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate b/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate
new file mode 100644
index 0000000..08c5d07
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate
@@ -0,0 +1,100 @@
+// 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 $LIBRARYNAME;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+ @DomName('IDBIndex.count')
+ Future<int> count([key_OR_range]) {
+ try {
+ var request;
+ if (key_OR_range != null) {
+ request = $dom_count(key_OR_range);
+ } else {
+ request = $dom_count();
+ }
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBIndex.get')
+ Future get(key) {
+ try {
+ var request = $dom_get(key);
+
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBIndex.getKey')
+ Future getKey(key) {
+ try {
+ var request = $dom_getKey(key);
+
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ /**
+ * Creates a stream of cursors over the records in this object store.
+ *
+ * See also:
+ *
+ * * [ObjectStore.openCursor]
+ */
+ Stream<CursorWithValue> openCursor({key, KeyRange range, String direction,
+ bool autoAdvance}) {
+ var key_OR_range = null;
+ if (key != null) {
+ if (range != null) {
+ throw new ArgumentError('Cannot specify both key and range.');
+ }
+ key_OR_range = key;
+ } else {
+ key_OR_range = range;
+ }
+ var request;
+ if (direction == null) {
+ request = $dom_openCursor(key_OR_range);
+ } else {
+ request = $dom_openCursor(key_OR_range, direction);
+ }
+ return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+ }
+
+ /**
+ * Creates a stream of cursors over the records in this object store.
+ *
+ * See also:
+ *
+ * * [ObjectStore.openCursor]
+ */
+ Stream<Cursor> openKeyCursor({key, KeyRange range, String direction,
+ bool autoAdvance}) {
+ var key_OR_range = null;
+ if (key != null) {
+ if (range != null) {
+ throw new ArgumentError('Cannot specify both key and range.');
+ }
+ key_OR_range = key;
+ } else {
+ key_OR_range = range;
+ }
+ var request;
+ if (direction == null) {
+ request = $dom_openKeyCursor(key_OR_range);
+ } else {
+ request = $dom_openKeyCursor(key_OR_range, direction);
+ }
+ return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+ }
+
+ $!MEMBERS
+}
diff --git a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
index ec7d9b3..6f22f93 100644
--- a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
@@ -6,6 +6,54 @@
$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+ @DomName('IDBObjectStore.add')
+ Future add(value, [key]) {
+ try {
+ var request;
+ if (key != null) {
+ request = $dom_add(value, key);
+ } else {
+ request = $dom_add(value);
+ }
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBObjectStore.clear')
+ Future clear() {
+ try {
+ return _completeRequest($dom_clear());
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBObjectStore.delete')
+ Future delete(key_OR_keyRange){
+ try {
+ return _completeRequest($dom_delete(key_OR_keyRange));
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
+ @DomName('IDBObjectStore.count')
+ Future<int> count([key_OR_range]) {
+ try {
+ var request;
+ if (key_OR_range != null) {
+ request = $dom_count(key_OR_range);
+ } else {
+ request = $dom_count();
+ }
+ return _completeRequest(request);
+ } catch (e, stacktrace) {
+ return new Future.immediateError(e, stacktrace);
+ }
+ }
+
@DomName('IDBObjectStore.put')
Future put(value, [key]) {
try {
@@ -76,6 +124,19 @@
return _cursorStreamFromResult(request, autoAdvance);
}
+ @DomName('IDBObjectStore.createIndex')
+ Index createIndex(String name, keyPath, {bool unique, bool multiEntry}) {
+ var options = {};
+ if (unique != null) {
+ options['unique'] = unique;
+ }
+ if (multiEntry != null) {
+ options['multiEntry'] = multiEntry;
+ }
+
+ return $dom_createIndex(name, keyPath, options);
+ }
+
$!MEMBERS
/**
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index aee4497..b113a5a 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -70,7 +70,13 @@
void addAll(Iterable<Node> iterable) {
if (iterable is _ChildNodeListLazy) {
- iterable = new List.from(iterable);
+ if (iterable._this != _this) {
+ // Optimized route for copying between nodes.
+ for (var i = 0, len = iterable.length; i < len; ++i) {
+ _this.$dom_appendChild(iterable[0]);
+ }
+ }
+ return;
}
for (Node node in iterable) {
_this.$dom_appendChild(node);
@@ -157,7 +163,8 @@
bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
- List<Node> toList() => new List<Node>.from(this);
+ List<Node> toList({ bool growable: true }) =>
+ new List<Node>.from(this, growable: growable);
Set<Node> toSet() => new Set<Node>.from(this);
bool get isEmpty => this.length == 0;
@@ -240,6 +247,8 @@
}
Node operator[](int index) => _this.$dom_childNodes[index];
+
+ Map<int, Node> asMap() => IterableMixinWorkaround.asMapList(this);
}
$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 083aebd..682813b 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -20,7 +20,7 @@
* frame unwinds, causing the future to complete after all processing has
* completed for the current event, but before any subsequent events.
*/
- void setImmediate(TimeoutHandler callback) {
+ void setImmediate(TimeoutHandler callback) {
_addMicrotaskCallback(callback);
}
/**
@@ -28,8 +28,11 @@
* registered under [name].
*/
SendPortSync lookupPort(String name) {
- var port =
- json.parse(document.documentElement.attributes['dart-port:$name']);
+ var portStr = document.documentElement.attributes['dart-port:$name'];
+ if (portStr == null) {
+ return null;
+ }
+ var port = json.parse(portStr);
return _deserialize(port);
}
@@ -51,7 +54,7 @@
* If you need to later cancel this animation, use [requestAnimationFrame]
* instead.
*
- * Note: The code that runs when the future completes should call
+ * Note: The code that runs when the future completes should call
* [animationFrame] again for the animation to continue.
*/
Future<num> get animationFrame {
@@ -127,7 +130,7 @@
/**
* Called to draw an animation frame and then request the window to repaint
- * after [callback] has finished (creating the animation).
+ * after [callback] has finished (creating the animation).
*
* Use this method only if you need to later call [cancelAnimationFrame]. If
* not, the preferred Dart idiom is to set animation frames by calling
diff --git a/tools/dom/templates/immutable_list_mixin.darttemplate b/tools/dom/templates/immutable_list_mixin.darttemplate
index 850c2f8..7f2497f 100644
--- a/tools/dom/templates/immutable_list_mixin.darttemplate
+++ b/tools/dom/templates/immutable_list_mixin.darttemplate
@@ -42,7 +42,9 @@
bool any(bool f($E element)) => IterableMixinWorkaround.any(this, f);
- List<$E> toList() => new List<$E>.from(this);
+ List<$E> toList({ bool growable: true }) =>
+ new List<$E>.from(this, growable: growable);
+
Set<$E> toSet() => new Set<$E>.from(this);
bool get isEmpty => this.length == 0;
@@ -185,4 +187,7 @@
List<$E> getRange(int start, int rangeLength) =>
Lists.getRange(this, start, rangeLength, <$E>[]);
+ Map<int, $E> asMap() =>
+ IterableMixinWorkaround.asMapList(this);
+
// -- end List<$E> mixins.
diff --git a/tools/line_doc_comments.dart b/tools/line_doc_comments.dart
index a51d84d..50727ee 100755
--- a/tools/line_doc_comments.dart
+++ b/tools/line_doc_comments.dart
@@ -4,7 +4,7 @@
library line_doc_comments;
import 'dart:io';
-import '../pkg/path/lib/path.dart' as path;
+import '../pkg/pathos/lib/path.dart' as path;
final oneLineBlock = new RegExp(r'^(\s*)/\*\*\s?(.*)\*/\s*$');
final startBlock = new RegExp(r'^(\s*)/\*\*(.*)$');
diff --git a/tools/test-runtime.dart b/tools/test-runtime.dart
index 32e4e07..3f30059 100755
--- a/tools/test-runtime.dart
+++ b/tools/test-runtime.dart
@@ -50,6 +50,7 @@
var verbose = firstConf['verbose'];
var printTiming = firstConf['time'];
var listTests = firstConf['list'];
+ var useContentSecurityPolicy = firstConf['csp'];
if (!firstConf['append_logs']) {
var file = new File(TestUtils.flakyFileName());
@@ -72,13 +73,27 @@
print(output_words.join(' '));
}
+ var runningBrowserTests = configurations.any((config) {
+ return TestUtils.isBrowserRuntime(config['runtime']);
+ });
+
var testSuites = new List<TestSuite>();
- TestingServerRunner.setBuildDir(firstConf);
- TestingServerRunner.setPackageRootDir(firstConf);
for (var conf in configurations) {
+ if (!listTests && runningBrowserTests) {
+ // Start global http servers that serve the entire dart repo.
+ // The http server is available on window.location.port, and a second
+ // server for cross-domain tests can be found by calling
+ // getCrossOriginPortNumber().
+ var servers = new TestingServers(new Path(TestUtils.buildDir(conf)),
+ useContentSecurityPolicy);
+ servers.startServers('127.0.0.1');
+ conf['_servers_'] = servers;
+ }
+
if (selectors.containsKey('co19')) {
testSuites.add(new Co19TestSuite(conf));
}
+
if (conf['runtime'] == 'vm' && selectors.containsKey('vm')) {
// vm tests contain both cc tests (added here) and dart tests (added in
// [TEST_SUITE_DIRECTORIES]).
@@ -93,15 +108,13 @@
}
}
- // Start global http server that serves the entire dart repo.
- // The http server is available on localhost:9876 for any
- // test that needs to load resources from the repo over http.
- if (!listTests) {
- // Only start the server if we are running browser tests.
- var runningBrowserTests = configurations.any((config) {
- return TestUtils.isBrowserRuntime(config['runtime']);
- });
- if (runningBrowserTests) startHttpServer('127.0.0.1', 9876);
+ void allTestsFinished() {
+ for (var conf in configurations) {
+ if (conf.containsKey('_servers_')) {
+ conf['_servers_'].stopServers();
+ }
+ }
+ DebugLogger.close();
}
var maxBrowserProcesses = maxProcesses;
@@ -114,7 +127,7 @@
startTime,
printTiming,
testSuites,
- () => TestingServerRunner.terminateHttpServers(),
+ allTestsFinished,
verbose,
listTests);
}
diff --git a/tools/test.dart b/tools/test.dart
index 398230d..00eb7f1 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -66,6 +66,7 @@
new Path('utils/tests/css'),
new Path('utils/tests/peg'),
new Path('utils/tests/pub'),
+ new Path('sdk/lib/_internal/dartdoc'),
];
main() {
@@ -83,6 +84,7 @@
var verbose = firstConf['verbose'];
var printTiming = firstConf['time'];
var listTests = firstConf['list'];
+ var useContentSecurityPolicy = firstConf['csp'];
if (!firstConf['append_logs']) {
var file = new File(TestUtils.flakyFileName());
@@ -109,35 +111,31 @@
print(output_words.join(' '));
}
- // Start global http servers that serve the entire dart repo.
- // The http server is available on window.location.port, and a second server
- // for cross-domain tests can be found by calling getCrossOriginPortNumber().
- if (!listTests) {
- // Only start the server if we are running browser tests.
- var runningBrowserTests = configurations.any((config) {
- return TestUtils.isBrowserRuntime(config['runtime']);
- });
- if (runningBrowserTests) {
- TestingServerRunner.startHttpServer('127.0.0.1');
- // We start two servers so that we can test cross-domain tests.
- TestingServerRunner.startHttpServer('127.0.0.1',
- allowedPort: TestingServerRunner.serverList[0].port);
- }
- }
+ var runningBrowserTests = configurations.any((config) {
+ return TestUtils.isBrowserRuntime(config['runtime']);
+ });
var testSuites = new List<TestSuite>();
- // FIXME(kustermann,ricow): This is broken and should be fixed ASAP.
- // Issue: 8366
- TestingServerRunner.setBuildDir(firstConf);
- TestingServerRunner.setPackageRootDir(firstConf);
var maxBrowserProcesses = maxProcesses;
for (var conf in configurations) {
+ if (!listTests && runningBrowserTests) {
+ // Start global http servers that serve the entire dart repo.
+ // The http server is available on window.location.port, and a second
+ // server for cross-domain tests can be found by calling
+ // getCrossOriginPortNumber().
+ var servers = new TestingServers(new Path(TestUtils.buildDir(conf)),
+ useContentSecurityPolicy);
+ servers.startServers('127.0.0.1');
+ conf['_servers_'] = servers;
+ }
+
// There should not be more than one InternetExplorerDriver instance
// running at a time. For details, see
// http://code.google.com/p/selenium/wiki/InternetExplorerDriver.
if (conf['runtime'].startsWith('ie')) {
maxBrowserProcesses = 1;
}
+
for (String key in selectors.keys) {
if (key == 'co19') {
testSuites.add(new Co19TestSuite(conf));
@@ -155,14 +153,17 @@
final name = testSuiteDir.filename;
if (selectors.containsKey(name)) {
testSuites.add(
- new StandardTestSuite.forDirectory(conf, testSuiteDir,
- serverList: TestingServerRunner.serverList));
+ new StandardTestSuite.forDirectory(conf, testSuiteDir));
}
}
}
void allTestsFinished() {
- TestingServerRunner.terminateHttpServers();
+ for (var conf in configurations) {
+ if (conf.containsKey('_servers_')) {
+ conf['_servers_'].stopServers();
+ }
+ }
DebugLogger.close();
}
diff --git a/tools/testing/dart/http_server.dart b/tools/testing/dart/http_server.dart
index 6ab495b..d065e0b 100644
--- a/tools/testing/dart/http_server.dart
+++ b/tools/testing/dart/http_server.dart
@@ -18,7 +18,7 @@
/// Interface of the HTTP server:
///
-/// /echo: This will stream the data received in the request stream back
+/// /echo: This will stream the data received in the request stream back
/// to the client.
/// /root_dart/X: This will serve the corresponding file from the dart
/// directory (i.e. '$DartDirectory/X').
@@ -37,7 +37,6 @@
// http://host:port/root_packages/X -> $BuildDir/packages/X
// Issue: 8368
-
main() {
/** Convenience method for local testing. */
var parser = new ArgParser();
@@ -47,15 +46,13 @@
parser.addOption('crossOriginPort', abbr: 'c',
help: 'A different port that accepts request from the main server port.',
defaultsTo: '0');
- parser.addOption('mode', abbr: 'm', help: 'Testing mode.',
- defaultsTo: 'release');
- parser.addOption('arch', abbr: 'a', help: 'Testing architecture.',
- defaultsTo: 'ia32');
parser.addFlag('help', abbr: 'h', negatable: false,
help: 'Print this usage information.');
- parser.addOption('package-root', help: 'The package root to use.');
+ parser.addOption('build-directory', help: 'The build directory to use.');
parser.addOption('network', help: 'The network interface to use.',
defaultsTo: '127.0.0.1');
+ parser.addFlag('csp', help: 'Use Content Security Policy restrictions.',
+ defaultsTo: false);
var args = parser.parse(new Options().arguments);
if (args['help']) {
print(parser.getUsage());
@@ -68,81 +65,99 @@
.join(new Path('../../test.dart'))
.canonicalize()
.toNativePath();
- // Note: args['package-root'] is always the build directory. We have the
- // implicit assumption that it contains the 'packages' subdirectory.
- // TODO: We should probably rename 'package-root' to 'build-directory'.
- TestingServerRunner._packageRootDir = new Path(args['package-root']);
- TestingServerRunner._buildDirectory = new Path(args['package-root']);
- var network = args['network'];
- TestingServerRunner.startHttpServer(network,
- port: int.parse(args['port']));
- print('Server listening on port '
- '${TestingServerRunner.serverList[0].port}.');
- TestingServerRunner.startHttpServer(network,
- allowedPort: TestingServerRunner.serverList[0].port, port:
- int.parse(args['crossOriginPort']));
- print(
- 'Server listening on port ${TestingServerRunner.serverList[1].port}.');
+ var servers = new TestingServers(new Path(args['build-directory']),
+ args['csp']);
+ var port = int.parse(args['port']);
+ var crossOriginPort = int.parse(args['crossOriginPort']);
+ servers.startServers(args['network'],
+ port: port,
+ crossOriginPort: crossOriginPort);
+ DebugLogger.info('Server listening on port ${servers.port}');
+ DebugLogger.info('Server listening on port ${servers.crossOriginPort}');
}
}
+
/**
* Runs a set of servers that are initialized specifically for the needs of our
* test framework, such as dealing with package-root.
*/
-class TestingServerRunner {
- static List serverList = [];
- static Path _packageRootDir = null;
- static Path _buildDirectory = null;
+class TestingServers {
+ List _serverList = [];
+ Path _buildDirectory = null;
+ final bool useContentSecurityPolicy;
- // Added as a getter so that the function will be called again each time the
- // default request handler closure is executed.
- static Path get packageRootDir => _packageRootDir;
- static Path get buildDirectory => _buildDirectory;
-
- static setPackageRootDir(Map configuration) {
- _packageRootDir = TestUtils.absolutePath(
- new Path(TestUtils.buildDir(configuration)));
+ TestingServers(Path buildDirectory, this.useContentSecurityPolicy) {
+ _buildDirectory = TestUtils.absolutePath(buildDirectory);
}
- static setBuildDir(Map configuration) {
- _buildDirectory = TestUtils.absolutePath(
- new Path(TestUtils.buildDir(configuration)));
+ int get port => _serverList[0].port;
+ int get crossOriginPort => _serverList[1].port;
+
+ /**
+ * [startServers] will start two Http servers.
+ * The first server listens on [port] and sets
+ * "Access-Control-Allow-Origin: *"
+ * The second server listens on [crossOriginPort] and sets
+ * "Access-Control-Allow-Origin: client:port1
+ * "Access-Control-Allow-Credentials: true"
+ */
+ void startServers(String host, {int port: 0, int crossOriginPort: 0}) {
+ _startHttpServer(host, port: port);
+ _startHttpServer(host,
+ port: crossOriginPort,
+ allowedPort:_serverList[0].port);
}
- static startHttpServer(String host, {int allowedPort:-1, int port: 0}) {
+ String httpServerCommandline() {
+ var dart = TestUtils.dartTestExecutable.toNativePath();
+ var dartDir = TestUtils.dartDir();
+ var script = dartDir.join(new Path("tools/testing/dart/http_server.dart"));
+ var buildDirectory = _buildDirectory.toNativePath();
+ var csp = useContentSecurityPolicy ? '--csp ' : '';
+
+ return '$dart $script -p $port -c $crossOriginPort $csp'
+ '--build-directory=$buildDirectory';
+ }
+
+ void stopServers() {
+ for (var server in _serverList) {
+ server.close();
+ }
+ }
+
+ void _startHttpServer(String host, {int port: 0, int allowedPort: -1}) {
var httpServer = new HttpServer();
httpServer.onError = (e) {
DebugLogger.error('HttpServer: an error occured: $e');
};
httpServer.defaultRequestHandler = (request, response) {
- handleFileOrDirectoryRequest(request, response, allowedPort);
+ _handleFileOrDirectoryRequest(request, response, allowedPort);
};
httpServer.addRequestHandler(
- (req) => req.path == "/echo", handleEchoRequest);
+ (req) => req.path == "/echo", _handleEchoRequest);
httpServer.listen(host, port);
- serverList.add(httpServer);
+ _serverList.add(httpServer);
}
-
- static void handleFileOrDirectoryRequest(HttpRequest request,
- HttpResponse response,
- int allowedPort) {
- var path = getFilePathFromRequestPath(request.path);
+ void _handleFileOrDirectoryRequest(HttpRequest request,
+ HttpResponse response,
+ int allowedPort) {
+ var path = _getFilePathFromRequestPath(request.path);
if (path != null) {
var file = new File.fromPath(path);
file.exists().then((exists) {
if (exists) {
- sendFileContent(request, response, allowedPort, path, file);
+ _sendFileContent(request, response, allowedPort, path, file);
} else {
var directory = new Directory.fromPath(path);
directory.exists().then((exists) {
if (exists) {
- listDirectory(directory).then((entries) {
- sendDirectoryListing(entries, request, response);
+ _listDirectory(directory).then((entries) {
+ _sendDirectoryListing(entries, request, response);
});
} else {
- sendNotFound(request, response);
+ _sendNotFound(request, response);
}
});
}
@@ -152,19 +167,19 @@
var entries = [new _Entry('root_dart', 'root_dart/'),
new _Entry('root_build', 'root_build/'),
new _Entry('echo', 'echo')];
- sendDirectoryListing(entries, request, response);
+ _sendDirectoryListing(entries, request, response);
} else {
- sendNotFound(request, response);
+ _sendNotFound(request, response);
}
}
}
- static void handleEchoRequest(HttpRequest request, HttpResponse response) {
+ void _handleEchoRequest(HttpRequest request, HttpResponse response) {
response.headers.set("Access-Control-Allow-Origin", "*");
request.inputStream.pipe(response.outputStream);
}
- static Path getFilePathFromRequestPath(String urlRequestPath) {
+ Path _getFilePathFromRequestPath(String urlRequestPath) {
// Go to the top of the file to see an explanation of the URL path scheme.
var requestPath = new Path(urlRequestPath.substring(1)).canonicalize();
var pathSegments = requestPath.segments();
@@ -185,7 +200,7 @@
if (packagesIndex != -1) {
var start = packagesIndex + 1;
var length = pathSegments.length - start;
- basePath = _packageRootDir.append(packagesDirName);
+ basePath = _buildDirectory.append(packagesDirName);
relativePath = new Path(
pathSegments.getRange(start, length).join('/'));
}
@@ -196,7 +211,7 @@
return null;
}
- static Future<List<_Entry>> listDirectory(Directory directory) {
+ Future<List<_Entry>> _listDirectory(Directory directory) {
var completer = new Completer();
var entries = [];
@@ -215,16 +230,9 @@
return completer.future;
}
- /**
- * Sends a simple listing of all the files and sub-directories within
- * directory.
- *
- * This is intended to make it easier to browse tests when manually running
- * tests against this test server.
- */
- static void sendDirectoryListing(entries,
- HttpRequest request,
- HttpResponse response) {
+ void _sendDirectoryListing(List<_Entry> entries,
+ HttpRequest request,
+ HttpResponse response) {
response.headers.set('Content-Type', 'text/html');
var header = '''<!DOCTYPE html>
<html>
@@ -254,11 +262,11 @@
response.outputStream.close();
}
- static void sendFileContent(HttpRequest request,
- HttpResponse response,
- int allowedPort,
- Path path,
- File file) {
+ void _sendFileContent(HttpRequest request,
+ HttpResponse response,
+ int allowedPort,
+ Path path,
+ File file) {
if (allowedPort != -1) {
var origin = new Uri(request.headers.value('Origin'));
// Allow loading from http://*:$allowedPort in browsers.
@@ -271,6 +279,16 @@
// requests *with credentials* will fail because you can't use "*").
response.headers.set("Access-Control-Allow-Origin", "*");
}
+ if (useContentSecurityPolicy) {
+ // Chrome respects the standardized Content-Security-Policy header,
+ // whereas Firefox and IE10 use X-Content-Security-Policy. Safari
+ // still uses the WebKit- prefixed version.
+ for (var header in ["Content-Security-Policy",
+ "X-Content-Security-Policy",
+ "X-WebKit-CSP"]) {
+ response.headers.set(header, "script-src 'self'; object-src 'self'");
+ }
+ }
if (path.filename.endsWith('.html')) {
response.headers.set('Content-Type', 'text/html');
} else if (path.filename.endsWith('.js')) {
@@ -281,7 +299,7 @@
file.openInputStream().pipe(response.outputStream);
}
- static void sendNotFound(HttpRequest request, HttpResponse response) {
+ void _sendNotFound(HttpRequest request, HttpResponse response) {
// NOTE: Since some tests deliberately try to access non-existent files.
// We might want to remove this warning (otherwise it will show
// up in the debug.log every time).
@@ -299,10 +317,6 @@
}
}
}
-
- static terminateHttpServers() {
- for (var server in serverList) server.close();
- }
}
// Helper class for displaying directory listings.
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 44b7f2e..d6ca633 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -138,6 +138,13 @@
false,
'bool'),
new _TestOptionSpecification(
+ 'csp',
+ 'Run tests under Content Security Policy restrictions',
+ ['--csp'],
+ [],
+ false,
+ 'bool'),
+ new _TestOptionSpecification(
'timeout',
'Timeout in seconds',
['-t', '--timeout'],
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index 3de6e2f..b6d5d29 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -202,20 +202,15 @@
}
if (test is BrowserTestCase) {
// Additional command for rerunning the steps locally after the fact.
- output.add('To retest, run: '
- '${TestUtils.dartTestExecutable.toNativePath()} '
- '${TestUtils.dartDir().toNativePath()}/tools/testing/dart/'
- 'http_server.dart -m ${test.configuration["mode"]} '
- '-a ${test.configuration["arch"]} '
- '-p ${http_server.TestingServerRunner.serverList[0].port} '
- '-c ${http_server.TestingServerRunner.serverList[1].port} '
- '--package-root=${http_server.TestingServerRunner.packageRootDir}');
+ var command =
+ test.configuration["_servers_"].httpServerCommandline();
+ output.add('To retest, run: $command');
}
for (Command c in test.commands) {
output.add('');
String message = (c == test.commands.last
? "Command line" : "Compilation command");
- output.add('$message: ${c.commandLine}');
+ output.add('$message: $c');
}
return output;
}
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 6ebd60c..262440f 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -107,7 +107,9 @@
// TODO(efortuna): Remove this when fixed (Issue 1306).
executable = executable.replaceAll('/', '\\');
}
- commandLine = "$executable ${arguments.join(' ')}";
+ var quotedArguments = [];
+ arguments.forEach((argument) => quotedArguments.add('"$argument"'));
+ commandLine = "$executable ${quotedArguments.join(' ')}";
}
String toString() => commandLine;
@@ -303,10 +305,6 @@
newArguments.addAll(c.arguments);
final newCommand = new Command(newExecutablePath, newArguments);
newCommands.add(newCommand);
- // If there are extra spaces inside the prefix or suffix, this fails.
- String expected =
- '$prefix ${c.executable} $suffix ${c.arguments.join(' ')}';
- Expect.stringEquals(expected.trim(), newCommand.commandLine);
}
commands = newCommands;
}
@@ -1600,18 +1598,13 @@
int i = 1;
if (test is BrowserTestCase) {
// Additional command for rerunning the steps locally after the fact.
- print('$i. ${TestUtils.dartTestExecutable.toNativePath()} '
- '${TestUtils.dartDir().toNativePath()}/tools/testing/dart/'
- 'http_server.dart -m ${test.configuration["mode"]} '
- '-a ${test.configuration["arch"]} '
- '-p ${http_server.TestingServerRunner.serverList[0].port} '
- '-c ${http_server.TestingServerRunner.serverList[1].port} '
- '--package-root='
- '${http_server.TestingServerRunner.packageRootDir}');
+ var command =
+ test.configuration["_servers_"].httpServerCommandline();
+ print('$i. $command');
i++;
}
for (Command command in test.commands) {
- print('$i. ${command.commandLine}');
+ print('$i. $command');
i++;
}
}
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index f6ff12c..12e8929 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -410,11 +410,6 @@
final Path dartDir;
Predicate<String> isTestFilePredicate;
final bool listRecursively;
- /**
- * The set of servers that have been started to run these tests (Could be
- * none).
- */
- List serverList;
static final RegExp multiTestRegExp = new RegExp(r"/// [0-9][0-9]:(.*)");
@@ -423,8 +418,7 @@
Path suiteDirectory,
this.statusFilePaths,
{this.isTestFilePredicate,
- bool recursive: false,
- this.serverList: const []})
+ bool recursive: false})
: super(configuration, suiteName),
dartDir = TestUtils.dartDir(),
listRecursively = recursive,
@@ -461,14 +455,14 @@
* been started up by the test harness, to be used by browser tests.
*/
factory StandardTestSuite.forDirectory(
- Map configuration, Path directory, {List serverList : const []}) {
+ Map configuration, Path directory) {
final name = directory.filename;
return new StandardTestSuite(configuration,
name, directory,
['$directory/$name.status', '$directory/${name}_dart2js.status'],
isTestFilePredicate: (filename) => filename.endsWith('_test.dart'),
- recursive: true, serverList: serverList);
+ recursive: true);
}
Collection<Uri> get dart2JsBootstrapDependencies {
@@ -843,13 +837,13 @@
subtestNames,
subtestIndex) {
// Note: If we run test.py with the "--list" option, no http servers
- // will be started. Therefore serverList is an empty list in this
- // case. So we use PORT/CROSS_ORIGIN_PORT instead of real ports.
+ // will be started. So we use PORT/CROSS_ORIGIN_PORT instead of real ports.
var serverPort = "PORT";
var crossOriginPort = "CROSS_ORIGIN_PORT";
if (!configuration['list']) {
- serverPort = serverList[0].port.toString();
- crossOriginPort = serverList[1].port.toString();
+ Expect.isTrue(configuration.containsKey('_servers_'));
+ serverPort = configuration['_servers_'].port;
+ crossOriginPort = configuration['_servers_'].crossOriginPort;
}
var url= 'http://127.0.0.1:$serverPort$pathComponent'
@@ -1024,7 +1018,7 @@
dartDir.append('tools/testing/run_selenium.py').toNativePath(),
'--browser=$runtime',
'--timeout=${configuration["timeout"] - 2}',
- '--out="$fullHtmlPath"'];
+ '--out=$fullHtmlPath'];
if (runtime == 'dartium') {
args.add('--executable=$dartiumFilename');
}
@@ -1102,7 +1096,6 @@
if (packageRoot != null) {
args.add(packageRoot);
}
- if (compiler == 'dart2dart') args.add('--out=$outputFile');
args.add('--out=$outputFile');
args.add(inputFile);
break;
@@ -1151,8 +1144,9 @@
// '$compile-$runtime' directory name.
var checked = configuration['checked'] ? '-checked' : '';
var minified = configuration['minified'] ? '-minified' : '';
+ var csp = configuration['csp'] ? '-csp' : '';
var dirName = "${configuration['compiler']}-${configuration['runtime']}"
- "$checked$minified";
+ "$checked$minified$csp";
Path generatedTestPath = new Path(buildDir)
.append('generated_tests')
.append(dirName)
@@ -1665,7 +1659,7 @@
'$buildDir/analyzer/dart_analyzer_tests.jar',
// Third party libraries.
'$dartDir/third_party/args4j/2.0.12/args4j-2.0.12.jar',
- '$dartDir/third_party/guava/r09/guava-r09.jar',
+ '$dartDir/third_party/guava/r13/guava-13.0.1.jar',
'$dartDir/third_party/rhino/1_7R3/js.jar',
'$dartDir/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar',
'$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar',
@@ -1820,6 +1814,9 @@
configuration["minified"]) {
args.add("--minify");
}
+ if (compiler == "dart2js" && configuration["csp"]) {
+ args.add("--disallow-unsafe-eval");
+ }
return args;
}
diff --git a/utils/apidoc/apidoc.dart b/utils/apidoc/apidoc.dart
index fcaf106..802471c 100644
--- a/utils/apidoc/apidoc.dart
+++ b/utils/apidoc/apidoc.dart
@@ -116,6 +116,11 @@
var path = new Path(entity.path);
var libName = path.filename;
+ // Ignore hidden directories (like .svn) as well as pkg.xcodeproj.
+ if (libName.startsWith('.') || libName.endsWith('.xcodeproj')) {
+ return;
+ }
+
// TODO(rnystrom): Get rid of oldStylePath support when all
// packages are using new layout. See #5106.
var oldStylePath = path.append('${libName}.dart');
diff --git a/utils/apidoc/apidoc.gyp b/utils/apidoc/apidoc.gyp
index b5c0689..dd5d3a7 100644
--- a/utils/apidoc/apidoc.gyp
+++ b/utils/apidoc/apidoc.gyp
@@ -38,6 +38,9 @@
'../../sdk/bin/dart2js',
'../../sdk/bin/dart2js.bat',
],
+ 'inputs': [
+ '<!@(["python", "../../tools/list_files.py", "\\.(css|png|dart)$", "."])',
+ ],
'outputs': [
'<(PRODUCT_DIR)/api_docs/index.html',
'<(PRODUCT_DIR)/api_docs/client-static.js',
@@ -52,7 +55,7 @@
'--exclude-lib=dartdoc',
'--exclude-lib=http',
'--exclude-lib=oauth2',
- '--exclude-lib=path',
+ '--exclude-lib=pathos',
'--exclude-lib=webdriver',
'--exclude-lib=yaml',
'--include-lib=matcher',
diff --git a/utils/apidoc/mdn/extract.dart b/utils/apidoc/mdn/extract.dart
index d9622b5..da3a7f3 100644
--- a/utils/apidoc/mdn/extract.dart
+++ b/utils/apidoc/mdn/extract.dart
@@ -748,7 +748,7 @@
// Figure out which column in the table contains member names by
// tracking how many member names each column contains.
- final numMatches = new List<int>.fixedLength(i);
+ final numMatches = new List<int>(i);
for (int j = 0; j < i; j++) {
numMatches[j] = 0;
}
diff --git a/utils/css/parser.dart b/utils/css/parser.dart
index 4e0c187..d799e43 100644
--- a/utils/css/parser.dart
+++ b/utils/css/parser.dart
@@ -999,7 +999,7 @@
var result = 0;
for (int i = 0; i < hex.length; i++) {
- var digit = _hexDigit(hex.charCodeAt(i));
+ var digit = _hexDigit(hex.codeUnitAt(i));
if (digit < 0) {
throw new HexNumberException();
}
diff --git a/utils/css/tokenizer.dart b/utils/css/tokenizer.dart
index fccb3c04..63573df 100644
--- a/utils/css/tokenizer.dart
+++ b/utils/css/tokenizer.dart
@@ -191,8 +191,8 @@
// Need to override so CSS version of isIdentifierPart is used.
Token finishIdentifier(int ch) {
while (_index < _text.length) {
-// if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) {
- if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index))) {
+// if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index++))) {
+ if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index))) {
// _index--;
break;
} else {
@@ -211,7 +211,7 @@
}
Token finishImportant() {
-
+
}
Token finishNumber() {
@@ -233,7 +233,7 @@
bool maybeEatDigit() {
if (_index < _text.length
- && TokenizerHelpers.isDigit(_text.charCodeAt(_index))) {
+ && TokenizerHelpers.isDigit(_text.codeUnitAt(_index))) {
_index += 1;
return true;
}
@@ -242,7 +242,7 @@
void eatHexDigits() {
while (_index < _text.length) {
- if (TokenizerHelpers.isHexDigit(_text.charCodeAt(_index))) {
+ if (TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) {
_index += 1;
} else {
return;
@@ -252,7 +252,7 @@
bool maybeEatHexDigit() {
if (_index < _text.length
- && TokenizerHelpers.isHexDigit(_text.charCodeAt(_index))) {
+ && TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) {
_index += 1;
return true;
}
@@ -293,7 +293,7 @@
/** Static helper methods. */
/** Static helper methods. */
class TokenizerHelpers {
-
+
static bool isIdentifierStart(int c) {
return ((c >= 97/*a*/ && c <= 122/*z*/) || (c >= 65/*A*/ && c <= 90/*Z*/) ||
c == 95/*_*/ || c == 45 /*-*/);
diff --git a/utils/css/tokenizer_base.dart b/utils/css/tokenizer_base.dart
index af666b4..f98f245 100644
--- a/utils/css/tokenizer_base.dart
+++ b/utils/css/tokenizer_base.dart
@@ -52,7 +52,7 @@
int _nextChar() {
if (_index < _text.length) {
- return _text.charCodeAt(_index++);
+ return _text.codeUnitAt(_index++);
} else {
return 0;
}
@@ -60,7 +60,7 @@
int _peekChar() {
if (_index < _text.length) {
- return _text.charCodeAt(_index);
+ return _text.codeUnitAt(_index);
} else {
return 0;
}
@@ -68,7 +68,7 @@
bool _maybeEatChar(int ch) {
if (_index < _text.length) {
- if (_text.charCodeAt(_index) == ch) {
+ if (_text.codeUnitAt(_index) == ch) {
_index++;
return true;
} else {
@@ -99,7 +99,7 @@
Token finishWhitespace() {
_index--;
while (_index < _text.length) {
- final ch = _text.charCodeAt(_index++);
+ final ch = _text.codeUnitAt(_index++);
if (ch == 32/*' '*/ || ch == 9/*'\t'*/ || ch == 13/*'\r'*/) {
// do nothing
} else if (ch == 10/*'\n'*/) {
@@ -158,7 +158,7 @@
void eatDigits() {
while (_index < _text.length) {
- if (TokenizerHelpers.isDigit(_text.charCodeAt(_index))) {
+ if (TokenizerHelpers.isDigit(_text.codeUnitAt(_index))) {
_index++;
} else {
return;
@@ -189,7 +189,7 @@
}
var result = 0;
while (_index < maxIndex) {
- final digit = _hexDigit(_text.charCodeAt(_index));
+ final digit = _hexDigit(_text.codeUnitAt(_index));
if (digit == -1) {
if (hexLength == null) {
return result;
@@ -197,7 +197,7 @@
return -1;
}
}
- _hexDigit(_text.charCodeAt(_index));
+ _hexDigit(_text.codeUnitAt(_index));
// Multiply by 16 rather than shift by 4 since that will result in a
// correct value for numbers that exceed the 32 bit precision of JS
// 'integers'.
@@ -438,7 +438,7 @@
Token finishIdentifier(int ch) {
while (_index < _text.length) {
- if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) {
+ if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index++))) {
_index--;
break;
}
diff --git a/utils/css/tokenkind.dart b/utils/css/tokenkind.dart
index 32e994e..6112e82 100644
--- a/utils/css/tokenkind.dart
+++ b/utils/css/tokenkind.dart
@@ -93,7 +93,7 @@
static const int COMBINATOR_TILDE = 517; // ~ combinator
static const int UNARY_OP_NONE = 518; // No unary operator present.
-
+
// Attribute match types:
static const int INCLUDES = 530; // '~='
static const int DASH_MATCH = 531; // '|='
@@ -383,8 +383,8 @@
int idx = offset;
bool match = true;
for (int identIdx = 0; identIdx < ident.length; identIdx++) {
- int identChar = ident.charCodeAt(identIdx);
- int char = text.charCodeAt(idx++);
+ int identChar = ident.codeUnitAt(identIdx);
+ int char = text.codeUnitAt(idx++);
// Compare lowercase to lowercase then check if char is uppercase.
match = match && (char == identChar ||
((char >= ASCII_UPPER_A && char <= ASCII_UPPER_Z) &&
@@ -448,8 +448,8 @@
int idx = 0;
bool match = true;
for (int identIdx = 0; identIdx < ident.length; identIdx++) {
- int identChar = ident.charCodeAt(identIdx);
- int char = text.charCodeAt(idx++);
+ int identChar = ident.codeUnitAt(identIdx);
+ int char = text.codeUnitAt(idx++);
// Compare lowercase to lowercase then check if char is uppercase.
match = match && (char == identChar ||
((char >= ASCII_UPPER_A && char <= ASCII_UPPER_Z) &&
@@ -545,39 +545,39 @@
// All tokens must be in TokenKind order.
tokens.add(-1); // TokenKind.UNUSED
tokens.add(0); // TokenKind.END_OF_FILE match base
- tokens.add(TokenKind.kindToString(TokenKind.LPAREN).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.RPAREN).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.LBRACK).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.RBRACK).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.LBRACE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.RBRACE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.DOT).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.SEMICOLON).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.AT).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.HASH).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.PLUS).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.GREATER).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.TILDE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.ASTERISK).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.NAMESPACE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.COLON).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.PRIVATE_NAME).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.COMMA).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.SPACE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.TAB).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.NEWLINE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.RETURN).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.PERCENT).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.SINGLE_QUOTE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.DOUBLE_QUOTE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.SLASH).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.EQUALS).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.OR).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.CARET).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.DOLLAR).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.LESS).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.BANG).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.MINUS).charCodeAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.LPAREN).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.RPAREN).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.LBRACK).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.RBRACK).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.LBRACE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.RBRACE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.DOT).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.SEMICOLON).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.AT).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.HASH).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.PLUS).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.GREATER).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.TILDE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.ASTERISK).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.NAMESPACE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.COLON).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.PRIVATE_NAME).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.COMMA).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.SPACE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.TAB).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.NEWLINE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.RETURN).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.PERCENT).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.SINGLE_QUOTE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.DOUBLE_QUOTE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.SLASH).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.EQUALS).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.OR).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.CARET).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.DOLLAR).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.LESS).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.BANG).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.MINUS).codeUnitAt(0));
assert(tokens.length == TokenKind.END_TOKENS);
}
diff --git a/utils/lib/file_system_vm.dart b/utils/lib/file_system_vm.dart
index cc0c05c..12fb712 100644
--- a/utils/lib/file_system_vm.dart
+++ b/utils/lib/file_system_vm.dart
@@ -20,7 +20,7 @@
String readAll(String filename) {
var file = (new File(filename)).openSync();
var length = file.lengthSync();
- var buffer = new List<int>.fixedLength(length);
+ var buffer = new List<int>(length);
var bytes = file.readListSync(buffer, 0, length);
file.closeSync();
return new String.fromCharCodes(new Utf8Decoder(buffer).decodeRest());
diff --git a/utils/peg/pegparser.dart b/utils/peg/pegparser.dart
index 9072e2d..bd329c7 100644
--- a/utils/peg/pegparser.dart
+++ b/utils/peg/pegparser.dart
@@ -62,14 +62,14 @@
// Find the range of character codes and construct an array of flags for codes
// within the range.
- List<int> codes = characters.charCodes;
+ List<int> codes = characters.codeUnits;
codes.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
int lo = codes[0];
int hi = codes[codes.length - 1];
if (lo == hi)
return CHARCODE(lo);
int len = hi - lo + 1;
- var flags = new List<bool>.fixedLength(len);
+ var flags = new List<bool>(len);
for (int i = 0; i < len; ++i)
flags[i] = false;
for (int code in codes)
@@ -452,7 +452,7 @@
_match(_ParserState state, int pos) {
if (pos == state._end)
return null;
- int code = state._text.charCodeAt(pos);
+ int code = state._text.codeUnitAt(pos);
if (_predicate(code))
return [pos + 1, null];
return null;
@@ -511,7 +511,7 @@
if (pos + _len > state._end)
return null;
for (int i = 0; i < _len; i++) {
- if (state._text.charCodeAt(pos + i) != _string.charCodeAt(i))
+ if (state._text.codeUnitAt(pos + i) != _string.codeUnitAt(i))
return null;
}
return [pos + _len, null];
diff --git a/utils/pub/command_lish.dart b/utils/pub/command_lish.dart
index d2a033b..356ed52 100644
--- a/utils/pub/command_lish.dart
+++ b/utils/pub/command_lish.dart
@@ -11,7 +11,7 @@
import '../../pkg/args/lib/args.dart';
import '../../pkg/http/lib/http.dart' as http;
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'directory_tree.dart';
import 'exit_codes.dart' as exit_codes;
import 'git.dart' as git;
diff --git a/utils/pub/command_uploader.dart b/utils/pub/command_uploader.dart
index a8c2100..6541653 100644
--- a/utils/pub/command_uploader.dart
+++ b/utils/pub/command_uploader.dart
@@ -9,7 +9,7 @@
import 'dart:uri';
import '../../pkg/args/lib/args.dart';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'entrypoint.dart';
import 'exit_codes.dart' as exit_codes;
import 'http.dart';
diff --git a/utils/pub/directory_tree.dart b/utils/pub/directory_tree.dart
index cffff62..3610e72 100644
--- a/utils/pub/directory_tree.dart
+++ b/utils/pub/directory_tree.dart
@@ -5,7 +5,7 @@
/// A simple library for rendering a list of files as a directory tree.
library directory_tree;
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'log.dart' as log;
/// Draws a directory tree for the given list of files. Given a list of files
diff --git a/utils/pub/entrypoint.dart b/utils/pub/entrypoint.dart
index ab65950..e1bed5f 100644
--- a/utils/pub/entrypoint.dart
+++ b/utils/pub/entrypoint.dart
@@ -6,7 +6,7 @@
import 'dart:async';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'io.dart';
import 'lock_file.dart';
@@ -193,8 +193,8 @@
}
if (errors.length > 0) {
- log.error("Some packages are not compatible with your SDK version "
- "${sdk.version}:\n"
+ log.error("Some packages that were installed are not compatible with "
+ "your SDK version ${sdk.version} and may not work:\n"
"${errors.join('\n')}\n\n"
"You may be able to resolve this by upgrading to the latest Dart "
"SDK\n"
diff --git a/utils/pub/git_source.dart b/utils/pub/git_source.dart
index 2b54c72..bbe7952 100644
--- a/utils/pub/git_source.dart
+++ b/utils/pub/git_source.dart
@@ -6,7 +6,7 @@
import 'dart:async';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'git.dart' as git;
import 'io.dart';
diff --git a/utils/pub/hosted_source.dart b/utils/pub/hosted_source.dart
index 44f7195..ef64d59 100644
--- a/utils/pub/hosted_source.dart
+++ b/utils/pub/hosted_source.dart
@@ -11,7 +11,7 @@
// TODO(nweiz): Make this import better.
import '../../pkg/http/lib/http.dart' as http;
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'http.dart';
import 'io.dart';
@@ -95,7 +95,7 @@
var parsed = _parseDescription(id.description);
var url = parsed.last.replaceAll(new RegExp(r"^https?://"), "");
var urlDir = replace(url, new RegExp(r'[<>:"\\/|?*%]'), (match) {
- return '%${match[0].charCodeAt(0)}';
+ return '%${match[0].codeUnitAt(0)}';
});
return new Future.immediate(
diff --git a/utils/pub/io.dart b/utils/pub/io.dart
index 2a4be97..6e5ef86 100644
--- a/utils/pub/io.dart
+++ b/utils/pub/io.dart
@@ -11,7 +11,7 @@
import 'dart:json';
import 'dart:uri';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import '../../pkg/http/lib/http.dart' show ByteStream;
import 'error_group.dart';
import 'exit_codes.dart' as exit_codes;
@@ -161,7 +161,7 @@
lister.listen(
(entity) {
if (entity is File) {
- var file = entity.name;
+ var file = entity.path;
if (!includeHiddenFiles && path.basename(file).startsWith('.')) {
return;
}
@@ -188,7 +188,7 @@
log.fine("Listed directory $dir:\n${contents.join('\n')}");
completer.complete(contents);
},
- onError: (error) => completer.completeError(error, stackTrace));
+ onError: (error) => completer.completeError(error));
return completer.future.then((contents) {
return Future.wait(children).then((childContents) {
@@ -383,7 +383,7 @@
/// should just be a fragment like, "Are you sure you want to proceed".
Future<bool> confirm(String message) {
log.fine('Showing confirm message: $message');
- stdoutSink.add("$message (y/n)? ".charCodes);
+ stdoutSink.add("$message (y/n)? ".codeUnits);
return streamFirst(stdinLines)
.then((line) => new RegExp(r"^[yY]").hasMatch(line));
}
@@ -591,21 +591,19 @@
/// Note that timing out will not cancel the asynchronous operation behind
/// [input].
Future timeout(Future input, int milliseconds, String description) {
- bool completed = false;
var completer = new Completer();
- var timer = new Timer(new Duration(milliseconds: milliseconds), (_) {
- completed = true;
+ var timer = new Timer(new Duration(milliseconds: milliseconds), () {
completer.completeError(new TimeoutException(
'Timed out while $description.'));
});
input.then((value) {
- if (completed) return;
+ if (completer.isCompleted) return;
timer.cancel();
completer.complete(value);
}).catchError((e) {
- if (completed) return;
+ if (completer.isCompleted) return;
timer.cancel();
- completer.completeError(e.error, e.stackTrace);
+ completer.completeError(e);
});
return completer.future;
}
@@ -716,8 +714,8 @@
/// Returns a [ByteStream] that will emit the contents of the archive.
ByteStream createTarGz(List contents, {baseDir}) {
var buffer = new StringBuffer();
- buffer.add('Creating .tag.gz stream containing:\n');
- contents.forEach((file) => buffer.add('$file\n'));
+ buffer.write('Creating .tag.gz stream containing:\n');
+ contents.forEach((file) => buffer.write('$file\n'));
log.fine(buffer.toString());
var controller = new StreamController<List<int>>();
diff --git a/utils/pub/log.dart b/utils/pub/log.dart
index 9a555ea..5f1c578 100644
--- a/utils/pub/log.dart
+++ b/utils/pub/log.dart
@@ -117,22 +117,22 @@
void processResult(String executable, PubProcessResult result) {
// Log it all as one message so that it shows up as a single unit in the logs.
var buffer = new StringBuffer();
- buffer.add("Finished $executable. Exit code ${result.exitCode}.");
+ buffer.write("Finished $executable. Exit code ${result.exitCode}.");
dumpOutput(String name, List<String> output) {
if (output.length == 0) {
- buffer.add("Nothing output on $name.");
+ buffer.write("Nothing output on $name.");
} else {
- buffer.add("$name:");
+ buffer.write("$name:");
var numLines = 0;
for (var line in output) {
if (++numLines > 1000) {
- buffer.add('[${output.length - 1000}] more lines of output '
- 'truncated...]');
+ buffer.write('[${output.length - 1000}] more lines of output '
+ 'truncated...]');
break;
}
- buffer.add(line);
+ buffer.write(line);
}
}
}
@@ -153,11 +153,11 @@
void dumpTranscript() {
if (_transcript == null) return;
- stderrSink.add('---- Log transcript ----\n'.charCodes);
+ stderrSink.add('---- Log transcript ----\n'.codeUnits);
for (var entry in _transcript) {
_logToStderrWithLabel(entry);
}
- stderrSink.add('---- End log transcript ----\n'.charCodes);
+ stderrSink.add('---- End log transcript ----\n'.codeUnits);
}
/// Sets the verbosity to "normal", which shows errors, warnings, and messages.
@@ -213,15 +213,15 @@
for (var line in entry.lines) {
if (showLabel) {
if (firstLine) {
- sink.add(entry.level.name.charCodes);
- sink.add(': '.charCodes);
+ sink.add(entry.level.name.codeUnits);
+ sink.add(': '.codeUnits);
} else {
- sink.add(' | '.charCodes);
+ sink.add(' | '.codeUnits);
}
}
- sink.add(line.charCodes);
- sink.add('\n'.charCodes);
+ sink.add(line.codeUnits);
+ sink.add('\n'.codeUnits);
firstLine = false;
}
diff --git a/utils/pub/oauth2.dart b/utils/pub/oauth2.dart
index f2ec1b5..cc80d86 100644
--- a/utils/pub/oauth2.dart
+++ b/utils/pub/oauth2.dart
@@ -10,7 +10,7 @@
// TODO(nweiz): Make this a "package:" URL, or something nicer than this.
import '../../pkg/oauth2/lib/oauth2.dart';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'http.dart';
import 'io.dart';
diff --git a/utils/pub/package.dart b/utils/pub/package.dart
index 8731655..8e96cbd 100644
--- a/utils/pub/package.dart
+++ b/utils/pub/package.dart
@@ -6,7 +6,7 @@
import 'dart:async';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'io.dart';
import 'pubspec.dart';
diff --git a/utils/pub/path_source.dart b/utils/pub/path_source.dart
index 69471f8..bfa09e7 100644
--- a/utils/pub/path_source.dart
+++ b/utils/pub/path_source.dart
@@ -7,7 +7,9 @@
import 'dart:async';
import 'dart:io';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
+
+import 'log.dart' as log;
import 'io.dart';
import 'package.dart';
@@ -30,6 +32,13 @@
});
}
+ bool descriptionsEqual(description1, description2) {
+ // Compare real paths after normalizing and resolving symlinks.
+ var path1 = new File(description1["path"]).fullPathSync();
+ var path2 = new File(description2["path"]).fullPathSync();
+ return path1 == path2;
+ }
+
Future<bool> install(PackageId id, String destination) {
return defer(() {
try {
@@ -44,7 +53,7 @@
}
/// Parses a path dependency. This takes in a path string and returns a map.
- /// The "path" key will be the original path but resolves relative to the
+ /// The "path" key will be the original path but resolved relative to the
/// containing path. The "relative" key will be `true` if the original path
/// was relative.
///
diff --git a/utils/pub/pub.dart b/utils/pub/pub.dart
index 00abe4c..f18d9c9 100644
--- a/utils/pub/pub.dart
+++ b/utils/pub/pub.dart
@@ -10,7 +10,7 @@
import 'dart:math';
import '../../pkg/args/lib/args.dart';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'command_help.dart';
import 'command_install.dart';
@@ -227,7 +227,7 @@
globalOptions = globalOptions_;
try {
- commandOptions = commandParser.parse(commandArgs);
+ commandOptions = commandParser.parse(commandArgs);
} on FormatException catch (e) {
log.error(e.message);
log.error('Use "pub help" for more information.');
diff --git a/utils/pub/pubspec.dart b/utils/pub/pubspec.dart
index 55b775d..81678af 100644
--- a/utils/pub/pubspec.dart
+++ b/utils/pub/pubspec.dart
@@ -5,7 +5,7 @@
library pubspec;
import '../../pkg/yaml/lib/yaml.dart';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'io.dart';
import 'package.dart';
diff --git a/utils/pub/sdk.dart b/utils/pub/sdk.dart
index 1db2a04..59eea86 100644
--- a/utils/pub/sdk.dart
+++ b/utils/pub/sdk.dart
@@ -7,7 +7,7 @@
import 'dart:io';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'io.dart';
import 'log.dart' as log;
diff --git a/utils/pub/sdk_source.dart b/utils/pub/sdk_source.dart
index 1544152..1d6a881 100644
--- a/utils/pub/sdk_source.dart
+++ b/utils/pub/sdk_source.dart
@@ -6,7 +6,7 @@
import 'dart:async';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'io.dart';
import 'package.dart';
diff --git a/utils/pub/source.dart b/utils/pub/source.dart
index 0568d95..0e3af3e 100644
--- a/utils/pub/source.dart
+++ b/utils/pub/source.dart
@@ -6,7 +6,7 @@
import 'dart:async';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'io.dart';
import 'package.dart';
diff --git a/utils/pub/system_cache.dart b/utils/pub/system_cache.dart
index 8bd3178..7670b76 100644
--- a/utils/pub/system_cache.dart
+++ b/utils/pub/system_cache.dart
@@ -7,7 +7,7 @@
import 'dart:io';
import 'dart:async';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
import 'git_source.dart';
import 'hosted_source.dart';
diff --git a/utils/pub/utils.dart b/utils/pub/utils.dart
index f7589da..098916e 100644
--- a/utils/pub/utils.dart
+++ b/utils/pub/utils.dart
@@ -72,10 +72,10 @@
/// Pads [source] to [length] by adding spaces at the end.
String padRight(String source, int length) {
final result = new StringBuffer();
- result.add(source);
+ result.write(source);
while (result.length < length) {
- result.add(' ');
+ result.write(' ');
}
return result.toString();
@@ -122,11 +122,11 @@
var buffer = new StringBuffer();
var start = 0;
for (var match in matcher.allMatches(source)) {
- buffer.add(source.substring(start, match.start));
+ buffer.write(source.substring(start, match.start));
start = match.end;
- buffer.add(fn(match));
+ buffer.write(fn(match));
}
- buffer.add(source.substring(start));
+ buffer.write(source.substring(start));
return buffer.toString();
}
@@ -141,7 +141,7 @@
/// Returns the hex-encoded sha1 hash of [source].
String sha1(String source) {
var sha = new SHA1();
- sha.add(source.charCodes);
+ sha.add(source.codeUnits);
return CryptoUtils.bytesToHex(sha.close());
}
@@ -158,8 +158,7 @@
/// Returns a [Future] that completes in [milliseconds].
Future sleep(int milliseconds) {
var completer = new Completer();
- new Timer(new Duration(milliseconds: milliseconds),
- (_) => completer.complete());
+ new Timer(new Duration(milliseconds: milliseconds), completer.complete);
return completer.future;
}
@@ -237,38 +236,25 @@
/// newline is ignored.
Stream<String> streamToLines(Stream<String> stream) {
var buffer = new StringBuffer();
- return wrapStream(stream.transform(new StreamTransformer(
+ return stream.transform(new StreamTransformer(
handleData: (chunk, sink) {
var lines = chunk.split(_lineRegexp);
var leftover = lines.removeLast();
for (var line in lines) {
if (!buffer.isEmpty) {
- buffer.add(line);
+ buffer.write(line);
line = buffer.toString();
- buffer.clear();
+ buffer = new StringBuffer();
}
sink.add(line);
}
- buffer.add(leftover);
+ buffer.write(leftover);
},
handleDone: (sink) {
if (!buffer.isEmpty) sink.add(buffer.toString());
sink.close();
- })));
-}
-
-// TODO(nweiz): remove this when issue 8310 is fixed.
-/// Returns a [Stream] identical to [stream], but piped through a new
-/// [StreamController]. This exists to work around issue 8310.
-Stream wrapStream(Stream stream) {
- var controller = stream.isBroadcast
- ? new StreamController.broadcast()
- : new StreamController();
- stream.listen(controller.add,
- onError: (e) => controller.signalError(e),
- onDone: controller.close);
- return controller.stream;
+ }));
}
/// Like [Iterable.where], but allows [test] to return [Future]s and uses the
diff --git a/utils/pub/validator/compiled_dartdoc.dart b/utils/pub/validator/compiled_dartdoc.dart
index 2d340ba..cd83e76 100644
--- a/utils/pub/validator/compiled_dartdoc.dart
+++ b/utils/pub/validator/compiled_dartdoc.dart
@@ -6,7 +6,7 @@
import 'dart:async';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../entrypoint.dart';
import '../io.dart';
diff --git a/utils/pub/validator/directory.dart b/utils/pub/validator/directory.dart
index 1d1c2b8..cabf45d 100644
--- a/utils/pub/validator/directory.dart
+++ b/utils/pub/validator/directory.dart
@@ -6,7 +6,7 @@
import 'dart:async';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../entrypoint.dart';
import '../io.dart';
diff --git a/utils/pub/validator/lib.dart b/utils/pub/validator/lib.dart
index 5a637a4..9a5b9d0 100644
--- a/utils/pub/validator/lib.dart
+++ b/utils/pub/validator/lib.dart
@@ -7,7 +7,7 @@
import 'dart:async';
import 'dart:io';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../entrypoint.dart';
import '../io.dart';
diff --git a/utils/pub/validator/license.dart b/utils/pub/validator/license.dart
index 63b9aa8..29fb318 100644
--- a/utils/pub/validator/license.dart
+++ b/utils/pub/validator/license.dart
@@ -6,7 +6,7 @@
import 'dart:async';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../entrypoint.dart';
import '../io.dart';
diff --git a/utils/pub/validator/name.dart b/utils/pub/validator/name.dart
index c183f9c..c953d78 100644
--- a/utils/pub/validator/name.dart
+++ b/utils/pub/validator/name.dart
@@ -7,7 +7,7 @@
import 'dart:async';
import 'dart:io';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../entrypoint.dart';
import '../io.dart';
@@ -91,12 +91,12 @@
var lastMatchEnd = 0;
for (var match in new RegExp(r"[a-z]([A-Z])").allMatches(source)) {
builder
- ..add(source.substring(lastMatchEnd, match.start + 1))
- ..add("_")
- ..add(match.group(1).toLowerCase());
+ ..write(source.substring(lastMatchEnd, match.start + 1))
+ ..write("_")
+ ..write(match.group(1).toLowerCase());
lastMatchEnd = match.end;
}
- builder.add(source.substring(lastMatchEnd));
+ builder.write(source.substring(lastMatchEnd));
return builder.toString().toLowerCase();
}
}
diff --git a/utils/pub/validator/utf8_readme.dart b/utils/pub/validator/utf8_readme.dart
index e586230..edfdde3 100644
--- a/utils/pub/validator/utf8_readme.dart
+++ b/utils/pub/validator/utf8_readme.dart
@@ -7,7 +7,7 @@
import 'dart:async';
import 'dart:utf';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../entrypoint.dart';
import '../io.dart';
diff --git a/utils/pub/version_solver.dart b/utils/pub/version_solver.dart
index a45af91..45d47e8 100644
--- a/utils/pub/version_solver.dart
+++ b/utils/pub/version_solver.dart
@@ -601,14 +601,14 @@
String toString() {
var buffer = new StringBuffer();
- buffer.add("Package '$package' has no versions that match $constraint "
+ buffer.write("Package '$package' has no versions that match $constraint "
"derived from:\n");
var keys = new List.from(_dependencies.keys);
keys.sort();
for (var key in keys) {
- buffer.add("- '$key' depends on version "
+ buffer.write("- '$key' depends on version "
"${_dependencies[key].constraint}\n");
}
@@ -641,13 +641,13 @@
String toString() {
var buffer = new StringBuffer();
- buffer.add("Incompatible version constraints on '$package':\n");
+ buffer.write("Incompatible version constraints on '$package':\n");
var keys = new List.from(_dependencies.keys);
keys.sort();
for (var key in keys) {
- buffer.add("- '$key' depends on version "
+ buffer.write("- '$key' depends on version "
"${_dependencies[key].constraint}\n");
}
diff --git a/utils/template/codegen.dart b/utils/template/codegen.dart
index 6f566a6..5d8ed2f 100644
--- a/utils/template/codegen.dart
+++ b/utils/template/codegen.dart
@@ -757,7 +757,7 @@
bool identifier = true;
if (m.start > 0) {
- int charCode = expr.charCodeAt(m.start - 1);
+ int charCode = expr.codeUnitAt(m.start - 1);
// Starts with ' or " then it's not an identifier.
identifier = charCode != 34 /* " */ && charCode != 39 /* ' */;
}
diff --git a/utils/template/tokenizer.dart b/utils/template/tokenizer.dart
index 8c1b7f2..cb1b516 100644
--- a/utils/template/tokenizer.dart
+++ b/utils/template/tokenizer.dart
@@ -133,8 +133,8 @@
// Need to override so CSS version of isIdentifierPart is used.
Token finishIdentifier() {
while (_index < _text.length) {
-// if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) {
- if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index))) {
+// if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index++))) {
+ if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index))) {
// _index--;
break;
} else {
@@ -209,7 +209,7 @@
bool maybeEatDigit() {
if (_index < _text.length && TokenizerHelpers.isDigit(
- _text.charCodeAt(_index))) {
+ _text.codeUnitAt(_index))) {
_index += 1;
return true;
}
@@ -218,7 +218,7 @@
void eatHexDigits() {
while (_index < _text.length) {
- if (TokenizerHelpers.isHexDigit(_text.charCodeAt(_index))) {
+ if (TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) {
_index += 1;
} else {
return;
@@ -228,7 +228,7 @@
bool maybeEatHexDigit() {
if (_index < _text.length && TokenizerHelpers.isHexDigit(
- _text.charCodeAt(_index))) {
+ _text.codeUnitAt(_index))) {
_index += 1;
return true;
}
diff --git a/utils/template/tokenizer_base.dart b/utils/template/tokenizer_base.dart
index 65b96cd..eb1bcdf 100644
--- a/utils/template/tokenizer_base.dart
+++ b/utils/template/tokenizer_base.dart
@@ -52,7 +52,7 @@
int _nextChar() {
if (_index < _text.length) {
- return _text.charCodeAt(_index++);
+ return _text.codeUnitAt(_index++);
} else {
return 0;
}
@@ -60,7 +60,7 @@
int _peekChar() {
if (_index < _text.length) {
- return _text.charCodeAt(_index);
+ return _text.codeUnitAt(_index);
} else {
return 0;
}
@@ -68,7 +68,7 @@
bool _maybeEatChar(int ch) {
if (_index < _text.length) {
- if (_text.charCodeAt(_index) == ch) {
+ if (_text.codeUnitAt(_index) == ch) {
_index++;
return true;
} else {
@@ -99,7 +99,7 @@
Token finishWhitespace() {
_index--;
while (_index < _text.length) {
- final ch = _text.charCodeAt(_index++);
+ final ch = _text.codeUnitAt(_index++);
if (ch == 32/*' '*/ || ch == 9/*'\t'*/ || ch == 13/*'\r'*/) {
// do nothing
} else if (ch == 10/*'\n'*/) {
@@ -158,7 +158,7 @@
void eatDigits() {
while (_index < _text.length) {
- if (TokenizerHelpers.isDigit(_text.charCodeAt(_index))) {
+ if (TokenizerHelpers.isDigit(_text.codeUnitAt(_index))) {
_index++;
} else {
return;
@@ -189,7 +189,7 @@
}
var result = 0;
while (_index < maxIndex) {
- final digit = _hexDigit(_text.charCodeAt(_index));
+ final digit = _hexDigit(_text.codeUnitAt(_index));
if (digit == -1) {
if (hexLength == null) {
return result;
@@ -197,7 +197,7 @@
return -1;
}
}
- _hexDigit(_text.charCodeAt(_index));
+ _hexDigit(_text.codeUnitAt(_index));
// Multiply by 16 rather than shift by 4 since that will result in a
// correct value for numbers that exceed the 32 bit precision of JS
// 'integers'.
@@ -441,14 +441,14 @@
_interpStack.depth = 0;
while (_index < _text.length) {
if (!TokenizerHelpers.isInterpIdentifierPart(
- _text.charCodeAt(_index++))) {
+ _text.codeUnitAt(_index++))) {
_index--;
break;
}
}
} else {
while (_index < _text.length) {
- if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) {
+ if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index++))) {
_index--;
break;
}
diff --git a/utils/template/tokenkind.dart b/utils/template/tokenkind.dart
index 6f6ea19..29da694 100644
--- a/utils/template/tokenkind.dart
+++ b/utils/template/tokenkind.dart
@@ -312,8 +312,8 @@
int idx = offset;
bool match = true;
for (int identIdx = 0; identIdx < ident.length; identIdx++) {
- int identChar = ident.charCodeAt(identIdx);
- int char = text.charCodeAt(idx++);
+ int identChar = ident.codeUnitAt(identIdx);
+ int char = text.codeUnitAt(idx++);
// Compare lowercase to lowercase then check if char is uppercase.
match = match && (char == identChar ||
((char >= ASCII_UPPER_A && char <= ASCII_UPPER_Z) &&
@@ -425,29 +425,29 @@
// All tokens must be in TokenKind order.
tokens.add(-1); // TokenKind.UNUSED
tokens.add(0); // TokenKind.END_OF_FILE match base
- tokens.add(TokenKind.kindToString(TokenKind.LPAREN).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.RPAREN).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.LBRACK).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.RBRACK).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.LBRACE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.RBRACE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.DOT).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.SEMICOLON).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.SPACE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.TAB).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.NEWLINE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.RETURN).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.COMMA).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.LESS_THAN).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.GREATER_THAN).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.SLASH).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.DOLLAR).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.HASH).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.MINUS).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.EQUAL).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.DOUBLE_QUOTE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.SINGLE_QUOTE).charCodeAt(0));
- tokens.add(TokenKind.kindToString(TokenKind.ASTERISK).charCodeAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.LPAREN).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.RPAREN).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.LBRACK).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.RBRACK).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.LBRACE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.RBRACE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.DOT).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.SEMICOLON).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.SPACE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.TAB).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.NEWLINE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.RETURN).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.COMMA).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.LESS_THAN).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.GREATER_THAN).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.SLASH).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.DOLLAR).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.HASH).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.MINUS).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.EQUAL).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.DOUBLE_QUOTE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.SINGLE_QUOTE).codeUnitAt(0));
+ tokens.add(TokenKind.kindToString(TokenKind.ASTERISK).codeUnitAt(0));
assert(tokens.length == TokenKind.END_TOKENS);
}
diff --git a/utils/testrunner/layout_test_controller.dart b/utils/testrunner/layout_test_controller.dart
index ddaa0cf..622e210 100644
--- a/utils/testrunner/layout_test_controller.dart
+++ b/utils/testrunner/layout_test_controller.dart
@@ -232,7 +232,7 @@
process.close();
var labelMarker = 'CONSOLE MESSAGE: #TEST ';
var contentMarker = 'Content-Length: ';
- var eol = '\n'.charCodeAt(0);
+ var eol = '\n'.codeUnitAt(0);
var pos = -1;
var label = null;
var done = false;
diff --git a/utils/tests/peg/peg_test.dart b/utils/tests/peg/peg_test.dart
index c285b01..59d2d55 100644
--- a/utils/tests/peg/peg_test.dart
+++ b/utils/tests/peg/peg_test.dart
@@ -68,9 +68,9 @@
TEXT(LEX(MANY(OR(['0','1']))),
(str, start, end) {
var r = 0;
- var zero = '0'.charCodeAt(0);
+ var zero = '0'.codeUnitAt(0);
for (int i = start; i < end; i++)
- r = r * 2 + (str.charCodeAt(i) - zero);
+ r = r * 2 + (str.codeUnitAt(i) - zero);
return r;
});
diff --git a/utils/tests/pub/command_line_config.dart b/utils/tests/pub/command_line_config.dart
index b7b7b34..df4a28a 100644
--- a/utils/tests/pub/command_line_config.dart
+++ b/utils/tests/pub/command_line_config.dart
@@ -6,7 +6,7 @@
import 'dart:io';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../../../pkg/unittest/lib/unittest.dart';
import '../../pub/utils.dart';
@@ -50,7 +50,7 @@
_printStackTrace(testCase.stackTrace);
- currentTestCase = null;
+ super.onTestResult(testCase);
}
void onSummary(int passed, int failed, int errors, List<TestCase> results,
@@ -105,9 +105,9 @@
if (string.length >= length) return string;
var result = new StringBuffer();
- result.add(string);
+ result.write(string);
for (var i = 0; i < length - string.length; i++) {
- result.add(' ');
+ result.write(' ');
}
return result.toString();
diff --git a/utils/tests/pub/install/hosted/repair_cache_test.dart b/utils/tests/pub/install/hosted/repair_cache_test.dart
index 8f2f79f..1636c0f 100644
--- a/utils/tests/pub/install/hosted/repair_cache_test.dart
+++ b/utils/tests/pub/install/hosted/repair_cache_test.dart
@@ -4,7 +4,7 @@
library pub_tests;
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
import '../../../../pub/io.dart';
import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/absolute_path_test.dart b/utils/tests/pub/install/path/absolute_path_test.dart
index cef0a76..2445b26 100644
--- a/utils/tests/pub/install/path/absolute_path_test.dart
+++ b/utils/tests/pub/install/path/absolute_path_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.
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/absolute_symlink_test.dart b/utils/tests/pub/install/path/absolute_symlink_test.dart
index 37aec85..3e65f19 100644
--- a/utils/tests/pub/install/path/absolute_symlink_test.dart
+++ b/utils/tests/pub/install/path/absolute_symlink_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.
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
import '../../../../pub/exit_codes.dart' as exit_codes;
import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/no_pubspec_test.dart b/utils/tests/pub/install/path/no_pubspec_test.dart
index 92f54fd..8481617 100644
--- a/utils/tests/pub/install/path/no_pubspec_test.dart
+++ b/utils/tests/pub/install/path/no_pubspec_test.dart
@@ -4,7 +4,7 @@
import 'dart:io';
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/nonexistent_dir_test.dart b/utils/tests/pub/install/path/nonexistent_dir_test.dart
index 4a129f4..915a683 100644
--- a/utils/tests/pub/install/path/nonexistent_dir_test.dart
+++ b/utils/tests/pub/install/path/nonexistent_dir_test.dart
@@ -4,7 +4,7 @@
import 'dart:io';
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
import '../../../../pub/exit_codes.dart' as exit_codes;
import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/path_is_file_test.dart b/utils/tests/pub/install/path/path_is_file_test.dart
index 8717b49..093e9f5 100644
--- a/utils/tests/pub/install/path/path_is_file_test.dart
+++ b/utils/tests/pub/install/path/path_is_file_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.
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
import '../../../../pub/exit_codes.dart' as exit_codes;
import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/relative_path_test.dart b/utils/tests/pub/install/path/relative_path_test.dart
index 497283b..691beed 100644
--- a/utils/tests/pub/install/path/relative_path_test.dart
+++ b/utils/tests/pub/install/path/relative_path_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.
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
import '../../../../pub/exit_codes.dart' as exit_codes;
import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/relative_symlink_test.dart b/utils/tests/pub/install/path/relative_symlink_test.dart
index 9460d7d..66c41c8 100644
--- a/utils/tests/pub/install/path/relative_symlink_test.dart
+++ b/utils/tests/pub/install/path/relative_symlink_test.dart
@@ -4,7 +4,7 @@
import 'dart:io';
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
import '../../../../pub/exit_codes.dart' as exit_codes;
import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/shared_dependency_symlink_test.dart b/utils/tests/pub/install/path/shared_dependency_symlink_test.dart
new file mode 100644
index 0000000..fddff6b
--- /dev/null
+++ b/utils/tests/pub/install/path/shared_dependency_symlink_test.dart
@@ -0,0 +1,59 @@
+// 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:io';
+
+import '../../../../../pkg/pathos/lib/path.dart' as path;
+
+import '../../test_pub.dart';
+
+main() {
+ // new File().fullPathSync() does not resolve through NTFS junction points,
+ // so this feature does not work on Windows.
+ if (Platform.operatingSystem == "windows") return;
+
+ initConfig();
+ integration("shared dependency with symlink", () {
+ dir("shared", [
+ libDir("shared"),
+ libPubspec("shared", "0.0.1")
+ ]).scheduleCreate();
+
+ dir("foo", [
+ libDir("foo"),
+ libPubspec("foo", "0.0.1", deps: [
+ {"path": "../shared"}
+ ])
+ ]).scheduleCreate();
+
+ dir("bar", [
+ libDir("bar"),
+ libPubspec("bar", "0.0.1", deps: [
+ {"path": "../link/shared"}
+ ])
+ ]).scheduleCreate();
+
+ dir(appPath, [
+ pubspec({
+ "name": "myapp",
+ "dependencies": {
+ "foo": {"path": "../foo"},
+ "bar": {"path": "../bar"}
+ }
+ })
+ ]).scheduleCreate();
+
+ dir("link").scheduleCreate();
+ scheduleSymlink("shared", path.join("link", "shared"));
+
+ schedulePub(args: ["install"],
+ output: new RegExp(r"Dependencies installed!$"));
+
+ dir(packagesPath, [
+ dir("foo", [file("foo.dart", 'main() => "foo";')]),
+ dir("bar", [file("bar.dart", 'main() => "bar";')]),
+ dir("shared", [file("shared.dart", 'main() => "shared";')])
+ ]).scheduleValidate();
+ });
+}
\ No newline at end of file
diff --git a/utils/tests/pub/install/path/shared_dependency_test.dart b/utils/tests/pub/install/path/shared_dependency_test.dart
new file mode 100644
index 0000000..b7e1596
--- /dev/null
+++ b/utils/tests/pub/install/path/shared_dependency_test.dart
@@ -0,0 +1,130 @@
+// 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 '../../../../../pkg/pathos/lib/path.dart' as path;
+
+import '../../test_pub.dart';
+
+main() {
+ initConfig();
+ integration("shared dependency with same path", () {
+ dir("shared", [
+ libDir("shared"),
+ libPubspec("shared", "0.0.1")
+ ]).scheduleCreate();
+
+ dir("foo", [
+ libDir("foo"),
+ libPubspec("foo", "0.0.1", deps: [
+ {"path": "../shared"}
+ ])
+ ]).scheduleCreate();
+
+ dir("bar", [
+ libDir("bar"),
+ libPubspec("bar", "0.0.1", deps: [
+ {"path": "../shared"}
+ ])
+ ]).scheduleCreate();
+
+ dir(appPath, [
+ pubspec({
+ "name": "myapp",
+ "dependencies": {
+ "foo": {"path": "../foo"},
+ "bar": {"path": "../bar"}
+ }
+ })
+ ]).scheduleCreate();
+
+ schedulePub(args: ["install"],
+ output: new RegExp(r"Dependencies installed!$"));
+
+ dir(packagesPath, [
+ dir("foo", [file("foo.dart", 'main() => "foo";')]),
+ dir("bar", [file("bar.dart", 'main() => "bar";')]),
+ dir("shared", [file("shared.dart", 'main() => "shared";')])
+ ]).scheduleValidate();
+ });
+
+ integration("shared dependency with paths that normalize the same", () {
+ dir("shared", [
+ libDir("shared"),
+ libPubspec("shared", "0.0.1")
+ ]).scheduleCreate();
+
+ dir("foo", [
+ libDir("foo"),
+ libPubspec("foo", "0.0.1", deps: [
+ {"path": "../shared"}
+ ])
+ ]).scheduleCreate();
+
+ dir("bar", [
+ libDir("bar"),
+ libPubspec("bar", "0.0.1", deps: [
+ {"path": "../././shared"}
+ ])
+ ]).scheduleCreate();
+
+ dir(appPath, [
+ pubspec({
+ "name": "myapp",
+ "dependencies": {
+ "foo": {"path": "../foo"},
+ "bar": {"path": "../bar"}
+ }
+ })
+ ]).scheduleCreate();
+
+ schedulePub(args: ["install"],
+ output: new RegExp(r"Dependencies installed!$"));
+
+ dir(packagesPath, [
+ dir("foo", [file("foo.dart", 'main() => "foo";')]),
+ dir("bar", [file("bar.dart", 'main() => "bar";')]),
+ dir("shared", [file("shared.dart", 'main() => "shared";')])
+ ]).scheduleValidate();
+ });
+
+ integration("shared dependency with absolute and relative path", () {
+ dir("shared", [
+ libDir("shared"),
+ libPubspec("shared", "0.0.1")
+ ]).scheduleCreate();
+
+ dir("foo", [
+ libDir("foo"),
+ libPubspec("foo", "0.0.1", deps: [
+ {"path": "../shared"}
+ ])
+ ]).scheduleCreate();
+
+ dir("bar", [
+ libDir("bar"),
+ libPubspec("bar", "0.0.1", deps: [
+ {"path": path.join(sandboxDir, "shared")}
+ ])
+ ]).scheduleCreate();
+
+ dir(appPath, [
+ pubspec({
+ "name": "myapp",
+ "dependencies": {
+ "foo": {"path": "../foo"},
+ "bar": {"path": "../bar"}
+ }
+ })
+ ]).scheduleCreate();
+
+ schedulePub(args: ["install"],
+ output: new RegExp(r"Dependencies installed!$"));
+
+ dir(packagesPath, [
+ dir("foo", [file("foo.dart", 'main() => "foo";')]),
+ dir("bar", [file("bar.dart", 'main() => "bar";')]),
+ dir("shared", [file("shared.dart", 'main() => "shared";')])
+ ]).scheduleValidate();
+ });
+}
\ No newline at end of file
diff --git a/utils/tests/pub/io_test.dart b/utils/tests/pub/io_test.dart
index 990dd6c..526283d 100644
--- a/utils/tests/pub/io_test.dart
+++ b/utils/tests/pub/io_test.dart
@@ -4,7 +4,7 @@
library io_test;
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../../../pkg/unittest/lib/unittest.dart';
import '../../pub/io.dart';
diff --git a/utils/tests/pub/pub.status b/utils/tests/pub/pub.status
index 254abd7..7184677 100644
--- a/utils/tests/pub/pub.status
+++ b/utils/tests/pub/pub.status
@@ -6,8 +6,11 @@
oauth2_test: Pass,Fail
pub_uploader_test: Pass,Fail
+pub_lish_test: Pass, Fail # Issue 8868
+validator_test: Pass, Fail # Issue 8868
+
# Pub only runs on the VM, so just rule out all compilers.
-[ $compiler == dart2js || $compiler == dart2dart || $compiler == dartc ]
+[ $compiler == dart2js || $compiler == dart2dart ]
*: Skip
# Pub only runs on the standalone VM, not the browser.
diff --git a/utils/tests/pub/real_version_test.dart b/utils/tests/pub/real_version_test.dart
index b0329a6..0d1882c 100644
--- a/utils/tests/pub/real_version_test.dart
+++ b/utils/tests/pub/real_version_test.dart
@@ -7,7 +7,7 @@
import 'dart:io';
import 'test_pub.dart';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../../../pkg/unittest/lib/unittest.dart';
main() {
diff --git a/utils/tests/pub/sdk_constraint_test.dart b/utils/tests/pub/sdk_constraint_test.dart
index 33d4686..7032c61 100644
--- a/utils/tests/pub/sdk_constraint_test.dart
+++ b/utils/tests/pub/sdk_constraint_test.dart
@@ -35,7 +35,7 @@
schedulePub(args: [command],
error:
"""
- Some packages are not compatible with your SDK version 0.1.2+3:
+ Some packages that were installed are not compatible with your SDK version 0.1.2+3 and may not work:
- 'myapp' requires >2.0.0
You may be able to resolve this by upgrading to the latest Dart SDK
@@ -72,7 +72,7 @@
schedulePub(args: [command],
error:
"""
- Some packages are not compatible with your SDK version 0.1.2+3:
+ Some packages that were installed are not compatible with your SDK version 0.1.2+3 and may not work:
- 'myapp' requires >2.0.0
- 'foo' requires >0.1.3
@@ -110,7 +110,7 @@
schedulePub(args: [command],
error:
"""
- Some packages are not compatible with your SDK version 0.1.2+3:
+ Some packages that were installed are not compatible with your SDK version 0.1.2+3 and may not work:
- 'bar' requires <0.1.1
You may be able to resolve this by upgrading to the latest Dart SDK
@@ -144,7 +144,7 @@
schedulePub(args: [command],
error:
"""
- Some packages are not compatible with your SDK version 0.1.2+3:
+ Some packages that were installed are not compatible with your SDK version 0.1.2+3 and may not work:
- 'myapp' requires >2.0.0
- 'foo' requires >3.0.0
diff --git a/utils/tests/pub/test_pub.dart b/utils/tests/pub/test_pub.dart
index 64ca423..3f56b3d 100644
--- a/utils/tests/pub/test_pub.dart
+++ b/utils/tests/pub/test_pub.dart
@@ -18,7 +18,7 @@
import '../../../pkg/http/lib/testing.dart';
import '../../../pkg/oauth2/lib/oauth2.dart' as oauth2;
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../../../pkg/unittest/lib/unittest.dart';
import '../../../pkg/yaml/lib/yaml.dart';
import '../../lib/file_system.dart' as fs;
@@ -430,7 +430,7 @@
case "git":
var url = description is String ? description : description['url'];
// TODO(rnystrom): Using path.basename on a URL is hacky. If we add URL
- // support to pkg/path, should use an explicit builder for that.
+ // support to pkg/pathos, should use an explicit builder for that.
return path.basename(url.replaceFirst(new RegExp(r"(\.git)?/?$"), ""));
case "hosted":
if (description is String) return description;
@@ -559,6 +559,16 @@
});
}
+
+/// Schedules creating a symlink at path [symlink] that points to [target],
+/// both of which are assumed to be relative to [sandboxDir].
+void scheduleSymlink(String target, String symlink) {
+ _schedule((sandboxDir) {
+ return createSymlink(path.join(sandboxDir, target),
+ path.join(sandboxDir, symlink));
+ });
+}
+
/// Schedules a call to the Pub command-line utility. Runs Pub with [args] and
/// validates that its results match [output], [error], and [exitCode].
void schedulePub({List args, Pattern output, Pattern error,
@@ -582,7 +592,7 @@
failures.addAll(result.stderr.map((line) => '| $line'));
}
- throw new ExpectException(failures.join('\n'));
+ throw new TestFailure(failures.join('\n'));
}
return null;
@@ -859,7 +869,7 @@
var entry = path.join(dir, name);
return defer(() {
if (!entryExists(entry)) {
- throw new ExpectException('Entry $entry not found.');
+ throw new TestFailure('Entry $entry not found.');
}
return validate(entry);
});
@@ -876,7 +886,7 @@
return listDir(dir).then((files) {
var matches = files.where((file) => endsWithPattern(file, name)).toList();
if (matches.isEmpty) {
- throw new ExpectException('No files in $dir match pattern $name.');
+ throw new TestFailure('No files in $dir match pattern $name.');
}
if (matches.length == 1) return validate(matches[0]);
@@ -891,12 +901,12 @@
}
var error = new StringBuffer();
- error.add("No files named $name in $dir were valid:\n");
+ error.write("No files named $name in $dir were valid:\n");
for (var failure in failures) {
- error.add(" $failure\n");
+ error.write(" $failure\n");
}
completer.completeError(
- new ExpectException(error.toString()), stackTrace);
+ new TestFailure(error.toString()), stackTrace);
}
for (var match in matches) {
@@ -943,7 +953,7 @@
var text = readTextFile(file);
if (text == textContents) return null;
- throw new ExpectException(
+ throw new TestFailure(
'File $file should contain:\n\n$textContents\n\n'
'but contained:\n\n$text');
});
@@ -1173,7 +1183,7 @@
Future validate(String dir) {
return defer(() {
if (entryExists(path.join(dir, name))) {
- throw new ExpectException('File $name in $dir should not exist.');
+ throw new TestFailure('File $name in $dir should not exist.');
}
});
}
@@ -1305,10 +1315,9 @@
_process = p;
byteStreamToLines(stream) {
- var handledErrors = wrapStream(stream.handleError((e) {
+ return streamToLines(new ByteStream(stream.handleError((e) {
registerException(e.error, e.stackTrace);
- }));
- return streamToLines(new ByteStream(handledErrors).toStringStream());
+ })).toStringStream());
}
var stdoutTee = tee(byteStreamToLines(p.stdout));
@@ -1350,7 +1359,7 @@
return _printStreams();
}).then((_) {
- registerException(new ExpectException("Process $name ended "
+ registerException(new TestFailure("Process $name ended "
"earlier than scheduled with exit code $exitCode"));
});
}).catchError((e) => registerException(e.error, e.stackTrace));
@@ -1430,7 +1439,7 @@
/// Writes [line] to the process as stdin.
void writeLine(String line) {
_schedule((_) => _processFuture.then(
- (p) => p.stdin.add('$line\n'.charCodes)));
+ (p) => p.stdin.add('$line\n'.codeUnits)));
}
/// Kills the process, and waits until it's dead.
diff --git a/utils/tests/pub/validator_test.dart b/utils/tests/pub/validator_test.dart
index 4f59bba..c439633 100644
--- a/utils/tests/pub/validator_test.dart
+++ b/utils/tests/pub/validator_test.dart
@@ -11,7 +11,7 @@
import '../../../pkg/http/lib/http.dart' as http;
import '../../../pkg/http/lib/testing.dart';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
import '../../../pkg/unittest/lib/unittest.dart';
import 'test_pub.dart';
diff --git a/utils/tests/string_encoding/benchmark_runner.dart b/utils/tests/string_encoding/benchmark_runner.dart
index 3f8bf39..514e87e 100644
--- a/utils/tests/string_encoding/benchmark_runner.dart
+++ b/utils/tests/string_encoding/benchmark_runner.dart
@@ -89,7 +89,7 @@
*/
class TestReport {
TestReport(this.id, this.desc, this.warmup, this.results) {
- spaceChar = " ".charCodes[0];
+ spaceChar = " ".codeUnits[0];
}
int spaceChar;
@@ -168,7 +168,7 @@
String _leftAlign(String s, int width) {
List<int> outCodes = [];
outCodes.insertRange(0, width, spaceChar);
- outCodes.setRange(0, Math.min(width, s.length), s.charCodes);
+ outCodes.setRange(0, Math.min(width, s.length), s.codeUnits);
return new String.fromCharCodes(outCodes);
}
@@ -176,7 +176,7 @@
List<int> outCodes = [];
outCodes.insertRange(0, width, spaceChar);
outCodes.setRange(Math.max(0, width - s.length), Math.min(width, s.length),
- s.charCodes);
+ s.codeUnits);
return new String.fromCharCodes(outCodes);
}
diff --git a/utils/tests/string_encoding/dunit.dart b/utils/tests/string_encoding/dunit.dart
index 3c092b3..e2302e3 100644
--- a/utils/tests/string_encoding/dunit.dart
+++ b/utils/tests/string_encoding/dunit.dart
@@ -33,19 +33,19 @@
}
void reportResults(List<TestResult> results) {
- if(results.every(bool _(TestResult r) => r is PassedTest)) {
+ if(results.every((TestResult r) => r is PassedTest)) {
print("OK -- ALL TESTS PASS (${results.length} run)");
} else {
for(TestResult r in
- results.where(bool _(TestResult r) => !(r is PassedTest))) {
+ results.where((TestResult r) => !(r is PassedTest))) {
print(r);
}
int passedTests =
- results.where(bool _(TestResult r) => r is PassedTest).length;
+ results.where((TestResult r) => r is PassedTest).length;
int failures =
- results.where(bool _(TestResult r) => r is FailedTest).length;
+ results.where((TestResult r) => r is FailedTest).length;
int errors =
- results.where(bool _(TestResult r) => r is TestError).length;
+ results.where((TestResult r) => r is TestError).length;
print("FAIL -- TESTS RUN: ${results.length}");
print(" PASSED: ${passedTests}");
print(" FAILED: ${failures}");
@@ -97,7 +97,7 @@
class TestClass {
void register(String description, Function test, TestSuite suite) {
- suite._registerTest(TestResult _() {
+ suite._registerTest(() {
setUp();
try {
test();
@@ -113,7 +113,7 @@
});
}
- abstract void registerTests(TestSuite suite);
+ void registerTests(TestSuite suite);
void setUp() {}
void tearDown() {}
}
diff --git a/utils/tests/string_encoding/unicode_test.dart b/utils/tests/string_encoding/unicode_test.dart
index 054ff45..5b57377 100755
--- a/utils/tests/string_encoding/unicode_test.dart
+++ b/utils/tests/string_encoding/unicode_test.dart
@@ -5,7 +5,7 @@
library unicode_tests;
import 'dunit.dart';
-import '../../../lib/utf/utf.dart';
+import '../../../sdk/lib/utf/utf.dart';
void main() {
TestSuite suite = new TestSuite();
@@ -30,7 +30,7 @@
}
void testStringCharCodes() {
- Expect.listEquals(testCodepoints, testPhrase.charCodes());
+ Expect.listEquals(testCodepoints, testPhrase.codeUnits);
}
void testCodepointsToString() {
@@ -42,6 +42,6 @@
}
void testEmptyStringCharCodes() {
- Expect.listEquals([], "".charCodes());
+ Expect.listEquals([], "".codeUnits);
}
}
diff --git a/utils/tests/string_encoding/utf16_test.dart b/utils/tests/string_encoding/utf16_test.dart
index 004dcf0..7e58a6c 100755
--- a/utils/tests/string_encoding/utf16_test.dart
+++ b/utils/tests/string_encoding/utf16_test.dart
@@ -118,7 +118,7 @@
IterableUtf16Decoder koreanDecoder =
decodeUtf16AsIterable(testKoreanCharSubsetUtf16beBom);
// get the first character
- Expect.equals(testKoreanCharSubset.charCodes[0], koreanDecoder.first);
+ Expect.equals(testKoreanCharSubset.codeUnits[0], koreanDecoder.first);
// get the whole translation using the Iterable interface
Expect.stringEquals(testKoreanCharSubset,
new String.fromCharCodes(new List<int>.from(koreanDecoder)));
diff --git a/utils/tests/string_encoding/utf32_test.dart b/utils/tests/string_encoding/utf32_test.dart
index eb727bc..ed6ace8 100755
--- a/utils/tests/string_encoding/utf32_test.dart
+++ b/utils/tests/string_encoding/utf32_test.dart
@@ -170,7 +170,7 @@
IterableUtf32Decoder koreanDecoder =
decodeUtf32AsIterable(testKoreanCharSubsetUtf32beBom);
// get the first character
- Expect.equals(testKoreanCharSubset.charCodes[0],
+ Expect.equals(testKoreanCharSubset.codeUnits[0],
koreanDecoder.iterator.first);
// get the whole translation using the Iterable interface
Expect.stringEquals(testKoreanCharSubset,
diff --git a/utils/tests/string_encoding/utf8_test.dart b/utils/tests/string_encoding/utf8_test.dart
index 596626e..09fee3c 100755
--- a/utils/tests/string_encoding/utf8_test.dart
+++ b/utils/tests/string_encoding/utf8_test.dart
@@ -466,7 +466,7 @@
IterableUtf8Decoder kataDecoder = decodeUtf8AsIterable(testKatakanaUtf8);
// get the first character
- Expect.equals(testKatakanaPhrase.charCodes[0], kataDecoder.first);
+ Expect.equals(testKatakanaPhrase.codeUnits[0], kataDecoder.first);
// get the whole translation using the Iterable interface
Expect.stringEquals(testKatakanaPhrase,
new String.fromCharCodes(new List<int>.from(kataDecoder)));