Version 1.19.0-dev.2.0
Merge 2966185560acfb10b97326b613eae1ac66d1a528 into dev
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index cea1817..7a9db13 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -461,6 +461,34 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_ImportElement_withPrefix_forMultipleImports() async {
+ _indexTestUnit('''
+import 'dart:async' as p;
+import 'dart:math' as p;
+main() {
+ p.Random;
+ p.Future;
+}
+''');
+ Element mainElement = findElement('main');
+ var kind = MatchKind.REFERENCE;
+ var length = 'p.'.length;
+ {
+ ImportElement element = testLibraryElement.imports[0];
+ var expected = [
+ _expectId(mainElement, kind, 'p.Future;', length: length),
+ ];
+ await _verifyReferences(element, expected);
+ }
+ {
+ ImportElement element = testLibraryElement.imports[1];
+ var expected = [
+ _expectId(mainElement, kind, 'p.Random', length: length),
+ ];
+ await _verifyReferences(element, expected);
+ }
+ }
+
test_searchReferences_LabelElement() async {
_indexTestUnit('''
main() {
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 53f9109..59a51e9 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -72,7 +72,7 @@
* [nodes].
*/
List<AstNode/*=E*/ > cloneNodeList/*<E extends AstNode>*/(
- NodeList/*<E>*/ nodes) {
+ List/*<E>*/ nodes) {
int count = nodes.length;
List/*<E>*/ clonedNodes = new List/*<E>*/();
for (int i = 0; i < count; i++) {
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 57eee89..8c48f49 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -75,6 +75,9 @@
*/
final ConstantEvaluationValidator validator;
+ /** Whether we are running in strong mode. */
+ final bool strongMode;
+
/**
* Initialize a newly created [ConstantEvaluationEngine]. The [typeProvider]
* is used to access known types. [_declaredVariables] is the set of
@@ -82,9 +85,12 @@
* given, is used to verify correct dependency analysis when running unit
* tests.
*/
- ConstantEvaluationEngine(this.typeProvider, this._declaredVariables,
+ ConstantEvaluationEngine(TypeProvider typeProvider, this._declaredVariables,
{ConstantEvaluationValidator validator, TypeSystem typeSystem})
- : validator =
+ : typeProvider = typeProvider,
+ strongMode =
+ typeProvider.objectType.element.context.analysisOptions.strongMode,
+ validator =
validator ?? new ConstantEvaluationValidator_ForProduction(),
typeSystem = typeSystem ?? new TypeSystemImpl();
@@ -409,7 +415,7 @@
DartObjectImpl evaluateConstructorCall(
AstNode node,
- NodeList<Expression> arguments,
+ List<Expression> arguments,
ConstructorElement constructor,
ConstantVisitor constantVisitor,
ErrorReporter errorReporter) {
@@ -515,25 +521,49 @@
// so consider it an unknown value to suppress further errors.
return new DartObjectImpl.validWithUnknownValue(definingClass);
}
- HashMap<String, DartObjectImpl> fieldMap =
- new HashMap<String, DartObjectImpl>();
+
+ // In strong mode, we allow constants to have type arguments.
+ //
+ // They will be added to the lexical environment when evaluating
+ // subexpressions.
+ HashMap<String, DartObjectImpl> typeArgumentMap;
+ if (strongMode) {
+ // Instantiate the constructor with the in-scope type arguments.
+ definingClass = constantVisitor.evaluateType(definingClass);
+ constructor = ConstructorMember.from(constructorBase, definingClass);
+
+ typeArgumentMap = new HashMap<String, DartObjectImpl>.fromIterables(
+ definingClass.typeParameters.map((t) => t.name),
+ definingClass.typeArguments.map(constantVisitor.typeConstant));
+ }
+
+ var fieldMap = new HashMap<String, DartObjectImpl>();
+ var fieldInitVisitor = new ConstantVisitor(this, errorReporter,
+ lexicalEnvironment: typeArgumentMap);
// Start with final fields that are initialized at their declaration site.
- for (FieldElement field in constructor.enclosingElement.fields) {
+ List<FieldElement> fields = constructor.enclosingElement.fields;
+ for (int i = 0; i < fields.length; i++) {
+ FieldElement field = fields[i];
if ((field.isFinal || field.isConst) &&
!field.isStatic &&
field is ConstFieldElementImpl) {
validator.beforeGetFieldEvaluationResult(field);
- EvaluationResultImpl evaluationResult = field.evaluationResult;
+
+ DartObjectImpl fieldValue;
+ if (strongMode) {
+ fieldValue = field.constantInitializer.accept(fieldInitVisitor);
+ } else {
+ fieldValue = field.evaluationResult?.value;
+ }
// It is possible that the evaluation result is null.
// This happens for example when we have duplicate fields.
// class Test {final x = 1; final x = 2; const Test();}
- if (evaluationResult == null) {
+ if (fieldValue == null) {
continue;
}
// Match the value and the type.
DartType fieldType =
FieldMember.from(field, constructor.returnType).type;
- DartObjectImpl fieldValue = evaluationResult.value;
if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) {
errorReporter.reportErrorForNode(
CheckedModeCompileTimeErrorCode
@@ -549,6 +579,7 @@
new HashMap<String, DartObjectImpl>();
List<ParameterElement> parameters = constructor.parameters;
int parameterCount = parameters.length;
+
for (int i = 0; i < parameterCount; i++) {
ParameterElement parameter = parameters[i];
ParameterElement baseParameter = parameter;
@@ -574,12 +605,23 @@
// The parameter is an optional positional parameter for which no value
// was provided, so use the default value.
validator.beforeGetParameterDefault(baseParameter);
- EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
- if (evaluationResult == null) {
- // No default was provided, so the default value is null.
- argumentValue = typeProvider.nullObject;
- } else if (evaluationResult.value != null) {
- argumentValue = evaluationResult.value;
+ if (strongMode && baseParameter is ConstVariableElement) {
+ var defaultValue =
+ (baseParameter as ConstVariableElement).constantInitializer;
+ if (defaultValue == null) {
+ argumentValue = typeProvider.nullObject;
+ } else {
+ argumentValue = defaultValue.accept(fieldInitVisitor);
+ }
+ } else {
+ EvaluationResultImpl evaluationResult =
+ baseParameter.evaluationResult;
+ if (evaluationResult == null) {
+ // No default was provided, so the default value is null.
+ argumentValue = typeProvider.nullObject;
+ } else if (evaluationResult.value != null) {
+ argumentValue = evaluationResult.value;
+ }
}
}
if (argumentValue != null) {
@@ -677,6 +719,7 @@
if (superArguments == null) {
superArguments = new NodeList<Expression>(null);
}
+
evaluateSuperConstructorCall(node, fieldMap, superConstructor,
superArguments, initializerVisitor, errorReporter);
}
@@ -688,7 +731,7 @@
AstNode node,
HashMap<String, DartObjectImpl> fieldMap,
ConstructorElement superConstructor,
- NodeList<Expression> superArguments,
+ List<Expression> superArguments,
ConstantVisitor initializerVisitor,
ErrorReporter errorReporter) {
if (superConstructor != null && superConstructor.isConst) {
@@ -1231,6 +1274,7 @@
// problem - the error has already been reported.
return null;
}
+
return evaluationEngine.evaluateConstructorCall(
node, node.argumentList.arguments, constructor, this, _errorReporter);
}
@@ -1274,9 +1318,9 @@
return null;
}
DartType elementType = _typeProvider.dynamicType;
- if (node.typeArguments != null &&
- node.typeArguments.arguments.length == 1) {
- DartType type = node.typeArguments.arguments[0].type;
+ NodeList<TypeName> typeArgs = node.typeArguments?.arguments;
+ if (typeArgs?.length == 1) {
+ DartType type = visitTypeName(typeArgs[0])?.toTypeValue();
if (type != null) {
elementType = type;
}
@@ -1309,13 +1353,13 @@
}
DartType keyType = _typeProvider.dynamicType;
DartType valueType = _typeProvider.dynamicType;
- if (node.typeArguments != null &&
- node.typeArguments.arguments.length == 2) {
- DartType keyTypeCandidate = node.typeArguments.arguments[0].type;
+ NodeList<TypeName> typeArgs = node.typeArguments?.arguments;
+ if (typeArgs?.length == 2) {
+ DartType keyTypeCandidate = visitTypeName(typeArgs[0])?.toTypeValue();
if (keyTypeCandidate != null) {
keyType = keyTypeCandidate;
}
- DartType valueTypeCandidate = node.typeArguments.arguments[1].type;
+ DartType valueTypeCandidate = visitTypeName(typeArgs[1])?.toTypeValue();
if (valueTypeCandidate != null) {
valueType = valueTypeCandidate;
}
@@ -1465,6 +1509,57 @@
_typeProvider.symbolType, new SymbolState(buffer.toString()));
}
+ @override
+ DartObjectImpl visitTypeName(TypeName node) {
+ DartType type = evaluateType(node.type);
+ if (type == null) {
+ return super.visitTypeName(node);
+ }
+ return typeConstant(type);
+ }
+
+ /**
+ * Given a [type], returns the constant value that contains that type value.
+ */
+ DartObjectImpl typeConstant(DartType type) {
+ return new DartObjectImpl(_typeProvider.typeType, new TypeState(type));
+ }
+
+ /**
+ * Given a [type] that may contain free type variables, evaluate them against
+ * the current lexical environment and return the substituted type.
+ */
+ DartType evaluateType(DartType type) {
+ if (type is TypeParameterType) {
+ // Constants may only refer to type parameters in strong mode.
+ if (!evaluationEngine.strongMode) {
+ return null;
+ }
+
+ String name = type.name;
+ if (_lexicalEnvironment != null) {
+ return _lexicalEnvironment[name]?.toTypeValue() ?? type;
+ }
+ return type;
+ }
+ if (type is ParameterizedType) {
+ List<DartType> typeArguments;
+ for (int i = 0; i < type.typeArguments.length; i++) {
+ DartType ta = type.typeArguments[i];
+ DartType t = evaluateType(ta);
+ if (!identical(t, ta)) {
+ if (typeArguments == null) {
+ typeArguments = type.typeArguments.toList(growable: false);
+ }
+ typeArguments[i] = t;
+ }
+ }
+ if (typeArguments == null) return type;
+ return type.substitute2(typeArguments, type.typeArguments);
+ }
+ return type;
+ }
+
/**
* Create an error associated with the given [node]. The error will have the
* given error [code].
@@ -1497,10 +1592,13 @@
}
return new DartObjectImpl(functionType, new FunctionState(function));
}
- } else if (variableElement is ClassElement ||
- variableElement is FunctionTypeAliasElement ||
- variableElement is DynamicElementImpl) {
- return new DartObjectImpl(_typeProvider.typeType, new TypeState(element));
+ } else if (variableElement is TypeDefiningElement) {
+ // Constants may only refer to type parameters in strong mode.
+ if (evaluationEngine.strongMode ||
+ variableElement is! TypeParameterElement) {
+ return new DartObjectImpl(
+ _typeProvider.typeType, new TypeState(variableElement.type));
+ }
}
// TODO(brianwilkerson) Figure out which error to report.
_error(node, null);
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index a269925..a0d1162 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -720,10 +720,7 @@
DartType toTypeValue() {
InstanceState state = _state;
if (state is TypeState) {
- Element element = state._element;
- if (element is TypeDefiningElement) {
- return element.type;
- }
+ return state._type;
}
return null;
}
@@ -2771,29 +2768,29 @@
/**
* The element representing the type being modeled.
*/
- final Element _element;
+ final DartType _type;
/**
* Initialize a newly created state to represent the given [value].
*/
- TypeState(this._element);
+ TypeState(this._type);
@override
- int get hashCode => _element == null ? 0 : _element.hashCode;
+ int get hashCode => _type?.hashCode ?? 0;
@override
String get typeName => "Type";
@override
bool operator ==(Object object) =>
- object is TypeState && (_element == object._element);
+ object is TypeState && (_type == object._type);
@override
StringState convertToString() {
- if (_element == null) {
+ if (_type == null) {
return StringState.UNKNOWN_VALUE;
}
- return new StringState(_element.name);
+ return new StringState(_type.displayName);
}
@override
@@ -2804,15 +2801,15 @@
@override
BoolState isIdentical(InstanceState rightOperand) {
- if (_element == null) {
+ if (_type == null) {
return BoolState.UNKNOWN_VALUE;
}
if (rightOperand is TypeState) {
- Element rightElement = rightOperand._element;
- if (rightElement == null) {
+ DartType rightType = rightOperand._type;
+ if (rightType == null) {
return BoolState.UNKNOWN_VALUE;
}
- return BoolState.from(_element == rightElement);
+ return BoolState.from(_type == rightType);
} else if (rightOperand is DynamicState) {
return BoolState.UNKNOWN_VALUE;
}
@@ -2820,5 +2817,5 @@
}
@override
- String toString() => _element == null ? "-unknown-" : _element.name;
+ String toString() => _type?.toString() ?? "-unknown-";
}
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 0a54caa..4a7cef1 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -868,7 +868,9 @@
_checkForConstWithNonConst(node);
_checkForConstWithUndefinedConstructor(
node, constructorName, typeName);
- _checkForConstWithTypeParameters(typeName);
+ if (!_options.strongMode) {
+ _checkForConstWithTypeParameters(typeName);
+ }
_checkForConstDeferredClass(node, constructorName, typeName);
} else {
_checkForNewWithUndefinedConstructor(node, constructorName, typeName);
@@ -891,9 +893,9 @@
Object visitListLiteral(ListLiteral node) {
TypeArgumentList typeArguments = node.typeArguments;
if (typeArguments != null) {
- if (node.constKeyword != null) {
+ if (!_options.strongMode && node.constKeyword != null) {
NodeList<TypeName> arguments = typeArguments.arguments;
- if (arguments.length != 0) {
+ if (arguments.isNotEmpty) {
_checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST);
}
@@ -910,7 +912,7 @@
TypeArgumentList typeArguments = node.typeArguments;
if (typeArguments != null) {
NodeList<TypeName> arguments = typeArguments.arguments;
- if (arguments.length != 0) {
+ if (!_options.strongMode && arguments.isNotEmpty) {
if (node.constKeyword != null) {
_checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP);
@@ -4393,10 +4395,9 @@
void _checkForMissingJSLibAnnotation(Annotation node) {
if (node.elementAnnotation?.isJS ?? false) {
- Element element = ElementLocator.locate(node.parent);
- if (element?.library?.isJS != true) {
+ if (_currentLibrary.isJS != true) {
_errorReporter.reportErrorForNode(
- HintCode.MISSING_JS_LIB_ANNOTATION, node, [element.name]);
+ HintCode.MISSING_JS_LIB_ANNOTATION, node);
}
}
}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 0705295..b111583 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -7193,7 +7193,12 @@
// return.
DartType staticClosureType = closure.element?.type;
if (staticClosureType != null &&
- !expectedClosureType.isMoreSpecificThan(staticClosureType)) {
+ !FunctionTypeImpl.relate(
+ expectedClosureType,
+ staticClosureType,
+ (DartType t, DartType s) => (t as TypeImpl).isMoreSpecificThan(s),
+ new TypeSystemImpl().instantiateToBounds,
+ returnRelation: (s, t) => true)) {
return;
}
// set propagated type for the closure
@@ -10090,20 +10095,6 @@
}
@override
- Object visitFunctionExpression(FunctionExpression node) {
- // Clear the static element return type of closures.
- // We need this to restore the state when closure parameter types can
- // be propagated from invocation parameter types.
- if (node is! FunctionDeclaration) {
- ExecutableElement element = node.element;
- if (element is FunctionElementImpl) {
- element.returnType = null;
- }
- }
- return super.visitFunctionExpression(node);
- }
-
- @override
Object visitFunctionTypeAlias(FunctionTypeAlias node) {
FunctionTypeAliasElementImpl element =
node.element as FunctionTypeAliasElementImpl;
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index f3247b6..5d8496d 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -655,6 +655,10 @@
Token token = getBeginTokenNotComment(node);
Token endToken = node.endToken;
while (true) {
+ // stop if past the end token
+ if (token.offset > endToken.end) {
+ break;
+ }
// append comment tokens
for (Token commentToken = token.precedingComments;
commentToken != null;
@@ -694,8 +698,12 @@
// Some synthetic elements have new offsets, e.g. synthetic accessors
// of property inducing elements. But some are purely synthetic, e.g.
// synthetic enum fields and their accessors.
+ // PrefixElement(s) can be shared between import directives, so
+ // their name offsets are outside of the second and subsequent import
+ // directives. But we update the name offsets while visiting the first
+ // import directive.
if (newOffset == null) {
- assert(element.isSynthetic);
+ assert(element.isSynthetic || element is PrefixElement);
return;
}
element.nameOffset = newOffset;
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index e5563a5..3ff98f7 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:unittest/unittest.dart';
@@ -21,54 +22,6 @@
@reflectiveTest
class HintCodeTest extends ResolverTestCase {
- void fail_isInt() {
- Source source = addSource("var v = 1 is int;");
- computeLibrarySourceErrors(source);
- assertErrors(source, [HintCode.IS_INT]);
- verify([source]);
- }
-
- void fail_isNotInt() {
- Source source = addSource("var v = 1 is! int;");
- computeLibrarySourceErrors(source);
- assertErrors(source, [HintCode.IS_NOT_INT]);
- verify([source]);
- }
-
- void fail_overrideEqualsButNotHashCode() {
- Source source = addSource(r'''
-class A {
- bool operator ==(x) {}
-}''');
- computeLibrarySourceErrors(source);
- assertErrors(source, [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]);
- verify([source]);
- }
-
- void fail_unusedImport_as_equalPrefixes() {
- // See todo at ImportsVerifier.prefixElementMap.
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' as one;
-import 'lib2.dart' as one;
-one.A a;''');
- Source source2 = addNamedSource(
- "/lib1.dart",
- r'''
-library lib1;
-class A {}''');
- Source source3 = addNamedSource(
- "/lib2.dart",
- r'''
-library lib2;
-class B {}''');
- computeLibrarySourceErrors(source);
- assertErrors(source, [HintCode.UNUSED_IMPORT]);
- assertNoErrors(source2);
- assertNoErrors(source3);
- verify([source, source2, source3]);
- }
-
@override
void reset() {
analysisContext2 = AnalysisContextFactory.contextWithCoreAndPackages({
@@ -1726,6 +1679,14 @@
verify([source]);
}
+ @failingTest
+ void test_isInt() {
+ Source source = addSource("var v = 1 is int;");
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [HintCode.IS_INT]);
+ verify([source]);
+ }
+
void test_isNotDouble() {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
options.dart2jsHint = true;
@@ -1736,6 +1697,14 @@
verify([source]);
}
+ @failingTest
+ void test_isNotInt() {
+ Source source = addSource("var v = 1 is! int;");
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [HintCode.IS_NOT_INT]);
+ verify([source]);
+ }
+
void test_js_lib_OK() {
Source source = addSource(r'''
@JS()
@@ -1751,7 +1720,7 @@
verify([source]);
}
- void test_missing_js_lib_on_class_decl() {
+ void test_missingJsLibAnnotation_class() {
Source source = addSource(r'''
library foo;
@@ -1765,7 +1734,21 @@
verify([source]);
}
- void test_missing_js_lib_on_function() {
+ void test_missingJsLibAnnotation_externalField() {
+ // https://github.com/dart-lang/sdk/issues/26987
+ Source source = addSource(r'''
+import 'package:js/js.dart';
+
+@JS()
+external dynamic exports;
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source,
+ [ParserErrorCode.EXTERNAL_FIELD, HintCode.MISSING_JS_LIB_ANNOTATION]);
+ verify([source]);
+ }
+
+ void test_missingJsLibAnnotation_function() {
Source source = addSource(r'''
library foo;
@@ -1779,7 +1762,7 @@
verify([source]);
}
- void test_missing_js_lib_on_member() {
+ void test_missingJsLibAnnotation_method() {
Source source = addSource(r'''
library foo;
@@ -1795,6 +1778,18 @@
verify([source]);
}
+ void test_missingJsLibAnnotation_variable() {
+ Source source = addSource(r'''
+import 'package:js/js.dart';
+
+@JS()
+dynamic variable;
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [HintCode.MISSING_JS_LIB_ANNOTATION]);
+ verify([source]);
+ }
+
void test_missingReturn_async() {
Source source = addSource('''
import 'dart:async';
@@ -2047,6 +2042,17 @@
verify([source]);
}
+ @failingTest
+ void test_overrideEqualsButNotHashCode() {
+ Source source = addSource(r'''
+class A {
+ bool operator ==(x) {}
+}''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]);
+ verify([source]);
+ }
+
void test_overrideOnNonOverridingField_invalid() {
Source source = addSource(r'''
library dart.core;
@@ -3511,6 +3517,31 @@
verify([source, source2]);
}
+ @failingTest
+ void test_unusedImport_as_equalPrefixes() {
+ // See todo at ImportsVerifier.prefixElementMap.
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' as one;
+import 'lib2.dart' as one;
+one.A a;''');
+ Source source2 = addNamedSource(
+ "/lib1.dart",
+ r'''
+library lib1;
+class A {}''');
+ Source source3 = addNamedSource(
+ "/lib2.dart",
+ r'''
+library lib2;
+class B {}''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [HintCode.UNUSED_IMPORT]);
+ assertNoErrors(source2);
+ assertNoErrors(source3);
+ verify([source, source2, source3]);
+ }
+
void test_unusedImport_hide() {
Source source = addSource(r'''
library L;
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 0030f98..8c13cf5 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -3660,6 +3660,64 @@
expect(parameterName.propagatedType, context.typeProvider.intType);
}
+ void test_sequence_closureParameterTypesPropagation2() {
+ var code = r'''
+import 'b.dart';
+main(x) {
+ x.toMap();
+ f((p) => 'z');
+}
+f(double c(int p)) {}
+''';
+ Source a = addSource('/a.dart', code);
+ Source b = addSource(
+ '/b.dart',
+ r'''
+import 'c.dart';
+''');
+ addSource(
+ '/c.dart',
+ r'''
+import 'd.dart';
+''');
+ Source d = addSource(
+ '/d.dart',
+ r'''
+class D {}
+''');
+ _performPendingAnalysisTasks();
+ LibrarySpecificUnit targetA = new LibrarySpecificUnit(a, a);
+ // Update b.dart, resolution in a.dart is not affected.
+ context.setContents(
+ b,
+ r'''
+import 'c.dart';
+class B {}
+''');
+ _assertValidAllResolution(a);
+ _performPendingAnalysisTasks();
+ // Update d.dart, this should invalidate a.dart and type propagation
+ // performed for the closure parameter.
+ context.setContents(
+ d,
+ r'''
+class D {
+ toMap() {}
+}
+''');
+ _assertValidUnits(a, RESOLVED_UNIT6);
+ _assertInvalidUnits(a, RESOLVED_UNIT7);
+ _performPendingAnalysisTasks();
+ // Validate "(p) =>" types.
+ {
+ CompilationUnit unit = context.getResult(targetA, RESOLVED_UNIT2);
+ SimpleIdentifier parameterName =
+ EngineTestCase.findSimpleIdentifier(unit, code, 'p) =>');
+ expect(parameterName.staticType, context.typeProvider.dynamicType);
+ expect(parameterName.propagatedType, context.typeProvider.intType);
+ }
+ }
+
void test_sequence_compoundingResults_exportNamespace() {
Source a = addSource(
'/a.dart',
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index cf6d9cd..dd3c4f3 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -30,6 +30,7 @@
initializeTestEnvironment();
runReflectiveTests(ConstantValueComputerTest);
runReflectiveTests(ConstantVisitorTest);
+ runReflectiveTests(StrongConstantValueComputerTest);
}
/**
@@ -1600,3 +1601,11 @@
return result;
}
}
+
+@reflectiveTest
+class StrongConstantValueComputerTest extends ConstantValueComputerTest {
+ void setUp() {
+ super.setUp();
+ resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
+ }
+}
diff --git a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
index cdca3b4..27427dc 100644
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
@@ -1158,6 +1158,35 @@
expect(unitDelta.hasDirectiveChange, isFalse);
}
+ test_directives_sameImportPrefix_sameOrder() {
+ _buildOldUnit(r'''
+import 'test1.dart' as m;
+import 'test2.dart' as m;
+''');
+ List<Directive> oldDirectives = oldUnit.directives.toList();
+ ImportDirective import1 = oldDirectives[0];
+ ImportDirective import2 = oldDirectives[1];
+ ImportElementImpl importElement1 = new ImportElementImpl(import1.offset);
+ ImportElementImpl importElement2 = new ImportElementImpl(import2.offset);
+ PrefixElement prefixElement = new PrefixElementImpl.forNode(import1.prefix);
+ importElement1.prefix = prefixElement;
+ importElement2.prefix = prefixElement;
+ import1.element = importElement1;
+ import2.element = importElement2;
+ import1.prefix.staticElement = prefixElement;
+ import2.prefix.staticElement = prefixElement;
+ _buildNewUnit(r'''
+import 'test1.dart' as m;
+import 'test2.dart' as m;
+class A {}
+''');
+ int expectedPrefixOffset = 23;
+ expect(import1.prefix.staticElement.nameOffset, expectedPrefixOffset);
+ expect(import2.prefix.staticElement.nameOffset, expectedPrefixOffset);
+ expect(importElement1.prefix.nameOffset, expectedPrefixOffset);
+ expect(importElement2.prefix.nameOffset, expectedPrefixOffset);
+ }
+
test_directives_sameOrder_insertSpaces() {
_buildOldUnit(r'''
library test;
@@ -1832,6 +1861,21 @@
''');
}
+ test_update_parseError_diffPlus_removeOne() {
+ _buildOldUnit(r'''
+class C {
+ + /// comment
+ + String field;
+}
+''');
+ _buildNewUnit(r'''
+class C {
+ + /// comment
+ String field;
+}
+''');
+ }
+
test_update_rewrittenConstructorName() {
_buildOldUnit(r'''
class A {
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 343a2ae..8bdd4ce 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2164,6 +2164,58 @@
check(implicitDynamic: false);
}
+ void test_constantGenericTypeArg_infer() {
+ // Regression test for https://github.com/dart-lang/sdk/issues/26141
+ checkFile('''
+abstract class Equality<Q> {}
+abstract class EqualityBase<R> implements Equality<R> {
+ final C<R> c = /*info:INFERRED_TYPE_ALLOCATION*/const C();
+ const EqualityBase();
+}
+class DefaultEquality<S> extends EqualityBase<S> {
+ const DefaultEquality();
+}
+class SetEquality<T> implements Equality<T> {
+ final Equality<T> field = const DefaultEquality();
+ const SetEquality([Equality<T> inner = const DefaultEquality()]);
+}
+class C<Q> {
+ final List<Q> list = /*info:INFERRED_TYPE_LITERAL*/const [];
+ final Map<Q, Iterable<Q>> m = /*info:INFERRED_TYPE_LITERAL*/const {};
+ const C();
+}
+main() {
+ const SetEquality<String>();
+}
+ ''');
+ }
+
+ void test_constantGenericTypeArg_explict() {
+ // Regression test for https://github.com/dart-lang/sdk/issues/26141
+ checkFile('''
+abstract class Equality<R> {}
+abstract class EqualityBase<R> implements Equality<R> {
+ final C<R> c = const C<R>();
+ const EqualityBase();
+}
+class DefaultEquality<S> extends EqualityBase<S> {
+ const DefaultEquality();
+}
+class SetEquality<T> implements Equality<T> {
+ final Equality<T> field = const DefaultEquality<T>();
+ const SetEquality([Equality<T> inner = const DefaultEquality<T>()]);
+}
+class C<Q> {
+ final List<Q> list = const <Q>[];
+ final Map<Q, Iterable<Q>> m = const <Q, Iterable<Q>>{};
+ const C();
+}
+main() {
+ const SetEquality<String>();
+}
+ ''');
+ }
+
void test_invalidOverrides_baseClassOverrideToChildInterface() {
checkFile('''
class A {}
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index fb91ab7..2e92fe3 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -587,5 +587,6 @@
sources = [
"run_vm_tests_fuchsia.cc"
]
+ libs = [ "launchpad" ]
}
} # defined(is_fuchsia) && is_fuchsia
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc
index 04fb060..2c303a1 100644
--- a/runtime/bin/builtin.cc
+++ b/runtime/bin/builtin.cc
@@ -119,7 +119,7 @@
ASSERT(static_cast<int>(id) >= 0);
ASSERT(static_cast<int>(id) < num_libs_);
- Dart_Handle library = Dart_LoadLibrary(url, Source(id), 0, 0);
+ Dart_Handle library = Dart_LoadLibrary(url, Dart_Null(), Source(id), 0, 0);
if (!Dart_IsError(library) && (builtin_libraries_[id].has_natives_)) {
// Setup the native resolver for built in library functions.
DART_CHECK_VALID(
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 7780208..d4aa012 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -346,11 +346,11 @@
// Handling of Resource class by dispatching to the load port.
Future<List<int>> _resourceReadAsBytes(Uri uri) async {
List response = await _makeLoaderRequest(_Dart_kResourceLoad, uri.toString());
- if (response[3] is String) {
+ if (response[4] is String) {
// Throw the error.
- throw response[3];
+ throw response[4];
} else {
- return response[3];
+ return response[4];
}
}
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 1b1f42f..e723764 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -434,7 +434,7 @@
Dart_Handle part_uri_obj = DartUtils::NewString(part_uri);
free(part_uri);
return Dart_LoadSource(library,
- part_uri_obj,
+ part_uri_obj, Dart_Null(),
Builtin::PartSource(id, url_string), 0, 0);
}
// All cases should have been handled above.
@@ -570,7 +570,8 @@
result = DartUtils::NewError("%s is not a valid UTF-8 script",
resolved_script_uri);
} else {
- result = Dart_LoadScript(resolved_script_uri, source, 0, 0);
+ result = Dart_LoadScript(resolved_script_uri, Dart_Null(),
+ source, 0, 0);
}
}
} else {
@@ -582,14 +583,16 @@
resolved_script_uri);
} else {
if (tag == Dart_kImportTag) {
- result = Dart_LoadLibrary(resolved_script_uri, source, 0, 0);
+ result = Dart_LoadLibrary(resolved_script_uri, Dart_Null(),
+ source, 0, 0);
} else {
ASSERT(tag == Dart_kSourceTag);
Dart_Handle library = Dart_LookupLibrary(library_uri);
if (Dart_IsError(library)) {
Dart_PropagateError(library);
}
- result = Dart_LoadSource(library, resolved_script_uri, source, 0, 0);
+ result = Dart_LoadSource(library, resolved_script_uri, Dart_Null(),
+ source, 0, 0);
}
}
}
diff --git a/runtime/bin/fuchsia_test.cc b/runtime/bin/fuchsia_test.cc
index d063612..341f9c7 100644
--- a/runtime/bin/fuchsia_test.cc
+++ b/runtime/bin/fuchsia_test.cc
@@ -72,7 +72,8 @@
DART_CHECK_VALID(builtin_script);
Log::Print("Loading builtin library\n");
- Dart_Handle status = Dart_LoadLibrary(builtin_uri, builtin_script, 0, 0);
+ Dart_Handle status =
+ Dart_LoadLibrary(builtin_uri, Dart_Null(), builtin_script, 0, 0);
DART_CHECK_VALID(status);
Log::Print("Looking up builtin library\n");
@@ -96,7 +97,8 @@
DART_CHECK_VALID(script_string);
Log::Print("Loading script into new library\n");
- Dart_Handle status = Dart_LoadLibrary(script_uri, script_string, 0, 0);
+ Dart_Handle status =
+ Dart_LoadLibrary(script_uri, Dart_Null(), script_string, 0, 0);
DART_CHECK_VALID(status);
Log::Print("Looking up script library\n");
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index d75a347..8654e28 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -491,9 +491,9 @@
return source;
}
if (IsSnapshottingForPrecompilation()) {
- return Dart_LoadScript(resolved_uri, source, 0, 0);
+ return Dart_LoadScript(resolved_uri, Dart_Null(), source, 0, 0);
} else {
- return Dart_LoadLibrary(resolved_uri, source, 0, 0);
+ return Dart_LoadLibrary(resolved_uri, Dart_Null(), source, 0, 0);
}
}
@@ -558,7 +558,7 @@
if (libraryBuiltinId != Builtin::kInvalidLibrary) {
// Special case for parting sources of a builtin library.
if (tag == Dart_kSourceTag) {
- return Dart_LoadSource(library, url,
+ return Dart_LoadSource(library, url, Dart_Null(),
Builtin::PartSource(libraryBuiltinId, url_string), 0, 0);
}
ASSERT(tag == Dart_kImportTag);
@@ -579,10 +579,10 @@
return source;
}
if (tag == Dart_kImportTag) {
- return Dart_LoadLibrary(url, source, 0, 0);
+ return Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
} else {
ASSERT(tag == Dart_kSourceTag);
- return Dart_LoadSource(library, url, source, 0, 0);
+ return Dart_LoadSource(library, url, Dart_Null(), source, 0, 0);
}
}
@@ -721,7 +721,8 @@
lib_index);
Dart_Handle script_url = Dart_NewStringFromCString(load_buffer);
free(load_buffer);
- Dart_Handle loaded = Dart_LoadLibrary(script_url, script_handle, 0, 0);
+ Dart_Handle loaded = Dart_LoadLibrary(script_url, Dart_Null(),
+ script_handle, 0, 0);
DART_CHECK_VALID(loaded);
// Do a fresh lookup
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index cf6f4ec..2220478 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -66,14 +66,16 @@
// Copy the contents of |message| into an |IOResult|.
void Loader::IOResult::Setup(Dart_CObject* message) {
ASSERT(message->type == Dart_CObject_kArray);
- ASSERT(message->value.as_array.length == 4);
+ ASSERT(message->value.as_array.length == 5);
Dart_CObject* tag_message = message->value.as_array.values[0];
ASSERT(tag_message != NULL);
Dart_CObject* uri_message = message->value.as_array.values[1];
ASSERT(uri_message != NULL);
- Dart_CObject* library_uri_message = message->value.as_array.values[2];
+ Dart_CObject* resolved_uri_message = message->value.as_array.values[2];
+ ASSERT(resolved_uri_message != NULL);
+ Dart_CObject* library_uri_message = message->value.as_array.values[3];
ASSERT(library_uri_message != NULL);
- Dart_CObject* payload_message = message->value.as_array.values[3];
+ Dart_CObject* payload_message = message->value.as_array.values[4];
ASSERT(payload_message != NULL);
// Grab the tag.
@@ -84,6 +86,10 @@
ASSERT(uri_message->type == Dart_CObject_kString);
uri = strdup(uri_message->value.as_string);
+ // Grab the resolved uri.
+ ASSERT(resolved_uri_message->type == Dart_CObject_kString);
+ resolved_uri = strdup(resolved_uri_message->value.as_string);
+
// Grab the library uri if one is present.
if (library_uri_message->type != Dart_CObject_kNull) {
ASSERT(library_uri_message->type == Dart_CObject_kString);
@@ -113,6 +119,7 @@
void Loader::IOResult::Cleanup() {
free(uri);
+ free(resolved_uri);
free(library_uri);
free(payload);
}
@@ -268,6 +275,8 @@
// dropping the lock below |result| may no longer valid.
Dart_Handle uri =
Dart_NewStringFromCString(reinterpret_cast<char*>(result->uri));
+ Dart_Handle resolved_uri =
+ Dart_NewStringFromCString(reinterpret_cast<char*>(result->resolved_uri));
Dart_Handle library_uri = Dart_Null();
if (result->library_uri != NULL) {
library_uri =
@@ -360,20 +369,20 @@
switch (tag) {
case Dart_kImportTag:
- dart_result = Dart_LoadLibrary(uri, source, 0, 0);
+ dart_result = Dart_LoadLibrary(uri, resolved_uri, source, 0, 0);
break;
case Dart_kSourceTag: {
ASSERT(library_uri != Dart_Null());
Dart_Handle library = Dart_LookupLibrary(library_uri);
ASSERT(!Dart_IsError(library));
- dart_result = Dart_LoadSource(library, uri, source, 0, 0);
+ dart_result = Dart_LoadSource(library, uri, resolved_uri, source, 0, 0);
}
break;
case Dart_kScriptTag:
if (is_snapshot) {
dart_result = Dart_LoadScriptFromSnapshot(payload, payload_length);
} else {
- dart_result = Dart_LoadScript(uri, source, 0, 0);
+ dart_result = Dart_LoadScript(uri, resolved_uri, source, 0, 0);
}
break;
default:
@@ -653,7 +662,7 @@
Dart_Handle part_uri_obj = DartUtils::NewString(part_uri);
free(part_uri);
return Dart_LoadSource(library,
- part_uri_obj,
+ part_uri_obj, Dart_Null(),
Builtin::PartSource(id, url_string), 0, 0);
}
// All cases should have been handled above.
diff --git a/runtime/bin/loader.h b/runtime/bin/loader.h
index 97e87a4..4fe6ac0 100644
--- a/runtime/bin/loader.h
+++ b/runtime/bin/loader.h
@@ -61,6 +61,7 @@
intptr_t payload_length;
char* library_uri;
char* uri;
+ char* resolved_uri;
int8_t tag;
void Setup(Dart_CObject* message);
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 89c752b..0c6b8b7 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -1043,6 +1043,22 @@
}
+static bool FileModifiedCallback(const char* url, int64_t since) {
+ if (strncmp(url, "file:///", 8) == 0) {
+ // If it isn't a file on local disk, we don't know if it has been
+ // modified.
+ return true;
+ }
+ int64_t data[File::kStatSize];
+ File::Stat(url + 7, data);
+ if (data[File::kType] == File::kDoesNotExist) {
+ return true;
+ }
+ bool modified = data[File::kModifiedTime] > since;
+ return modified;
+}
+
+
static void WriteSnapshotFile(const char* snapshot_directory,
const char* filename,
bool write_magic_number,
@@ -1060,7 +1076,11 @@
}
File* file = File::Open(qualified_filename, File::kWriteTruncate);
- ASSERT(file != NULL);
+ if (file == NULL) {
+ ErrorExit(kErrorExitCode,
+ "Unable to open file %s for writing snapshot\n",
+ qualified_filename);
+ }
if (write_magic_number) {
// Write the magic number to indicate file is a script snapshot.
@@ -1069,7 +1089,7 @@
if (!file->WriteFully(buffer, size)) {
ErrorExit(kErrorExitCode,
- "Unable to open file %s for writing snapshot\n",
+ "Unable to write file %s for writing snapshot\n",
qualified_filename);
}
file->Release();
@@ -1708,6 +1728,7 @@
"getIO", &ServiceGetIOHandler, NULL);
Dart_SetServiceStreamCallbacks(&ServiceStreamListenCallback,
&ServiceStreamCancelCallback);
+ Dart_SetFileModifiedCallback(&FileModifiedCallback);
// Run the main isolate until we aren't told to restart.
while (RunMainIsolate(script_name, &dart_options)) {
diff --git a/runtime/bin/run_vm_tests_fuchsia.cc b/runtime/bin/run_vm_tests_fuchsia.cc
index 3e7430a..431b162 100644
--- a/runtime/bin/run_vm_tests_fuchsia.cc
+++ b/runtime/bin/run_vm_tests_fuchsia.cc
@@ -3,8 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
#include <fcntl.h>
+#include <launchpad/launchpad.h>
#include <magenta/syscalls.h>
#include <mxio/util.h>
+#include <pthread.h>
+#include <runtime/sysinfo.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -29,11 +32,8 @@
// Hangs.
"ArrayLengthMaxElements",
"Int8ListLengthMaxElements",
- "ThreadPool_WorkerShutdown",
"LargeMap",
"CompileFunctionOnHelperThread",
- // Kernel panic.
- "ThreadBarrier",
// The profiler is turned off.
"Profiler_AllocationSampleTest",
"Profiler_ArrayAllocation",
@@ -84,13 +84,9 @@
// Bugs to fix, or things that are not yet impelemnted.
const char* kBugs[] = {
- // pthreads not using specified stack size.
+ // pthreads not using specified stack size?
"StackOverflowStacktraceInfo",
// Needs OS::GetCurrentThreadCPUMicros.
- "Timeline_Dart_TimelineDuration",
- "Timeline_Dart_TimelineInstant"
- "Timeline_Dart_TimelineAsyncDisabled",
- "Timeline_Dart_TimelineAsync",
"Timeline_Dart_TimelineGetTrace",
"Timeline_Dart_TimelineGetTraceOnlyDartEvents",
"Timeline_Dart_TimelineGetTraceWithDartEvents",
@@ -101,34 +97,17 @@
"TimelineEventDurationPrintJSON",
"TimelineEventArguments",
"TimelineEventArgumentsPrintJSON",
- "TimelineEventBufferPrintJSON",
"TimelineEventCallbackRecorderBasic",
"TimelineAnalysis_ThreadBlockCount",
"TimelineRingRecorderJSONOrder",
"TimelinePauses_BeginEnd",
- // Crash.
- "FindCodeObject",
- // Needs OS::Sleep.
- "MessageHandler_Run",
- "Sleep",
- // Calls VirtualMemory::FreeSubSegment.
- "GrowableObjectArray",
- "PrintJSON",
- "GenerateSource",
- "FreeVirtualMemory",
- // Several missing calls.
- "OsFuncs",
- // OS::AlignedAllocate.
- "OSAlignedAllocate",
// Needs NativeSymbolResolver
"Service_PersistentHandles",
// Need to investigate:
- "ThreadPool_RunOne",
- "ThreadPool_WorkerTimeout",
- "Monitor",
+ "FindCodeObject",
"ThreadIterator_AddFindRemove",
- // Needs Utils::HostToBigEndian16
- "Endianity",
+ "PrintJSON",
+ "SourceReport_Coverage_AllFunctions_ForceCompile",
};
@@ -165,9 +144,9 @@
argv[0] = kRunVmTestsPath;
argv[1] = test_name;
- mx_handle_t p = mxio_start_process(argv[0], kArgc, argv);
+ mx_handle_t p = launchpad_launch(argv[0], kArgc, argv);
if (p < 0) {
- printf("process failed to start\n");
+ fprintf(stderr, "process failed to start\n");
return -1;
}
@@ -175,7 +154,7 @@
mx_status_t r = mx_handle_wait_one(
p, MX_SIGNAL_SIGNALED, MX_TIME_INFINITE, &state);
if (r != NO_ERROR) {
- printf("[process(%x): wait failed? %d]\n", p, r);
+ fprintf(stderr, "[process(%x): wait failed? %d]\n", p, r);
return -1;
}
@@ -183,7 +162,7 @@
mx_ssize_t ret = mx_handle_get_info(
p, MX_INFO_PROCESS, &proc_info, sizeof(proc_info));
if (ret != sizeof(proc_info)) {
- printf("[process(%x): handle_get_info failed? %ld]\n", p, ret);
+ fprintf(stderr, "[process(%x): handle_get_info failed? %ld]\n", p, ret);
return -1;
}
@@ -192,19 +171,6 @@
}
-static void trim(char* line) {
- const intptr_t line_len = strlen(line);
- if (line[line_len - 1] == '\n') {
- line[line_len - 1] = '\0';
- }
-}
-
-
-static bool should_run(const char* test) {
- return !(test[0] == '#') && !isSkip(test);
-}
-
-
static void handle_result(intptr_t result, const char* test) {
if (result != 0) {
if (!isExpectFail(test) && !isBug(test)) {
@@ -221,6 +187,84 @@
}
+typedef struct {
+ pthread_mutex_t* test_list_lock;
+ char** test_list;
+ intptr_t test_list_length;
+ intptr_t* test_list_index;
+} runner_args_t;
+
+
+static void* test_runner_thread(void* arg) {
+ runner_args_t* args = reinterpret_cast<runner_args_t*>(arg);
+
+ pthread_mutex_lock(args->test_list_lock);
+ while (*args->test_list_index < args->test_list_length) {
+ const intptr_t index = *args->test_list_index;
+ *args->test_list_index = index + 1;
+ pthread_mutex_unlock(args->test_list_lock);
+ const char* test = args->test_list[index];
+ handle_result(run_test(test), test);
+ pthread_mutex_lock(args->test_list_lock);
+ }
+ pthread_mutex_unlock(args->test_list_lock);
+
+ return NULL;
+}
+
+
+static void trim(char* line) {
+ const intptr_t line_len = strlen(line);
+ if (line[line_len - 1] == '\n') {
+ line[line_len - 1] = '\0';
+ }
+}
+
+
+static bool should_run(const char* test) {
+ return !(test[0] == '#') && !isSkip(test);
+}
+
+
+static intptr_t count_lines(FILE* fp) {
+ intptr_t lines = 0;
+
+ // Make sure we're at the beginning of the file.
+ rewind(fp);
+
+ intptr_t ch;
+ while ((ch = fgetc(fp)) != EOF) {
+ if (ch == '\n') {
+ lines++;
+ }
+ }
+
+ rewind(fp);
+ return lines;
+}
+
+
+static intptr_t read_lines(FILE* fp, char** lines, intptr_t lines_length) {
+ char* test = NULL;
+ size_t len = 0;
+ ssize_t read;
+ intptr_t i = 0;
+ while (((read = getline(&test, &len, fp)) != -1) && (i < lines_length)) {
+ trim(test);
+ if (!should_run(test)) {
+ continue;
+ }
+ lines[i] = strdup(test);
+ i++;
+ }
+
+ if (test != NULL) {
+ free(test);
+ }
+ return i;
+}
+
+
int main(int argc, char** argv) {
if (argc <= 1) {
fprintf(stderr, "Pass the path to a file containing the list of tests\n");
@@ -234,22 +278,43 @@
return -1;
}
- char* test = NULL;
- size_t len = 0;
- ssize_t read;
- while ((read = getline(&test, &len, fp)) != -1) {
- trim(test);
- if (!should_run(test)) {
- continue;
- }
- intptr_t result = run_test(test);
- handle_result(result, test);
+ intptr_t lines_count = count_lines(fp);
+ char** test_list =
+ reinterpret_cast<char**>(malloc(sizeof(*test_list) * lines_count));
+ lines_count = read_lines(fp, test_list, lines_count);
+ fclose(fp);
+
+ pthread_mutex_t args_mutex;
+ pthread_mutex_init(&args_mutex, NULL);
+ intptr_t test_list_index = 0;
+ runner_args_t args;
+ args.test_list_lock = &args_mutex;
+ args.test_list = test_list;
+ args.test_list_length = lines_count;
+ args.test_list_index = &test_list_index;
+
+ const intptr_t num_cpus = mxr_get_nprocs_conf();
+ pthread_t* threads =
+ reinterpret_cast<pthread_t*>(malloc(num_cpus * sizeof(pthread_t)));
+ for (int i = 0; i < num_cpus; i++) {
+ pthread_create(&threads[i], NULL, test_runner_thread, &args);
}
- fclose(fp);
- if (test != NULL) {
- free(test);
+ for (int i = 0; i < num_cpus; i++) {
+ pthread_join(threads[i], NULL);
}
+
+ free(threads);
+ for (int i = 0; i < lines_count; i++) {
+ free(test_list[i]);
+ }
+ free(test_list);
+ pthread_mutex_destroy(&args_mutex);
+
+ if (test_list_index != lines_count) {
+ fprintf(stderr, "Failed to attempt all the tests!\n");
+ return -1;
+ }
+
return 0;
}
-
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index 7686f1c..bf5af11 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.dart
@@ -319,10 +319,11 @@
void _sendResourceResponse(SendPort sp,
int tag,
Uri uri,
+ Uri resolvedUri,
String libraryUrl,
dynamic data) {
assert((data is List<int>) || (data is String));
- var msg = new List(4);
+ var msg = new List(5);
if (data is String) {
// We encountered an error, flip the sign of the tag to indicate that.
tag = -tag;
@@ -334,8 +335,9 @@
}
msg[0] = tag;
msg[1] = uri.toString();
- msg[2] = libraryUrl;
- msg[3] = data;
+ msg[2] = resolvedUri.toString();
+ msg[3] = libraryUrl;
+ msg[4] = data;
sp.send(msg);
}
@@ -344,7 +346,7 @@
Uri uri,
String libraryUrl,
String resolvedUri) {
- var msg = new List(4);
+ var msg = new List(5);
int tag = _Dart_kImportExtension;
if (resolvedUri == null) {
// We could not resolve the dart-ext: uri.
@@ -353,8 +355,9 @@
}
msg[0] = tag;
msg[1] = uri.toString();
- msg[2] = libraryUrl;
- msg[3] = resolvedUri;
+ msg[2] = resolvedUri;
+ msg[3] = libraryUrl;
+ msg[4] = resolvedUri;
sp.send(msg);
}
@@ -376,18 +379,20 @@
if (response.statusCode != 200) {
var msg = "Failure getting $resolvedUri:\n"
" ${response.statusCode} ${response.reasonPhrase}";
- _sendResourceResponse(sp, tag, uri, libraryUrl, msg);
+ _sendResourceResponse(sp, tag, uri, resolvedUri, libraryUrl, msg);
} else {
- _sendResourceResponse(sp, tag, uri, libraryUrl,
+ _sendResourceResponse(sp, tag, uri, resolvedUri, libraryUrl,
builder.takeBytes());
}
},
onError: (e) {
- _sendResourceResponse(sp, tag, uri, libraryUrl, e.toString());
+ _sendResourceResponse(
+ sp, tag, uri, resolvedUri, libraryUrl, e.toString());
});
})
.catchError((e) {
- _sendResourceResponse(sp, tag, uri, libraryUrl, e.toString());
+ _sendResourceResponse(
+ sp, tag, uri, resolvedUri, libraryUrl, e.toString());
});
// It's just here to push an event on the event loop so that we invoke the
// scheduled microtasks.
@@ -402,10 +407,10 @@
var path = resolvedUri.toFilePath();
var sourceFile = new File(path);
sourceFile.readAsBytes().then((data) {
- _sendResourceResponse(sp, tag, uri, libraryUrl, data);
+ _sendResourceResponse(sp, tag, uri, resolvedUri, libraryUrl, data);
},
onError: (e) {
- _sendResourceResponse(sp, tag, uri, libraryUrl, e.toString());
+ _sendResourceResponse(sp, tag, uri, resolvedUri, libraryUrl, e.toString());
});
}
@@ -426,9 +431,10 @@
// The C++ portion of the embedder assumes UTF-8.
throw "Only utf-8 or US-ASCII encodings are supported: $charset given.";
}
- _sendResourceResponse(sp, tag, uri, libraryUrl, uri.data.contentAsBytes());
+ _sendResourceResponse(
+ sp, tag, uri, resolvedUri, libraryUrl, uri.data.contentAsBytes());
} catch (e) {
- _sendResourceResponse(sp, tag, uri, libraryUrl,
+ _sendResourceResponse(sp, tag, uri, resolvedUri, libraryUrl,
"Invalid data uri ($uri):\n $e");
}
}
@@ -454,6 +460,7 @@
_sendResourceResponse(sp,
tag,
uri,
+ resolvedUri,
libraryUrl,
e.toString());
return;
@@ -517,6 +524,7 @@
} else {
_sendResourceResponse(sp, tag,
uri,
+ resolvedUri,
libraryUrl,
'Unknown scheme (${resolvedUri.scheme}) for '
'$resolvedUri');
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index d851863..871a91c 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -317,21 +317,21 @@
Dart_Handle VmService::LoadScript(const char* name) {
Dart_Handle uri = Dart_NewStringFromCString(kVMServiceIOLibraryUri);
Dart_Handle source = GetSource(name);
- return Dart_LoadScript(uri, source, 0, 0);
+ return Dart_LoadScript(uri, Dart_Null(), source, 0, 0);
}
Dart_Handle VmService::LoadLibrary(const char* name) {
Dart_Handle uri = Dart_NewStringFromCString(kVMServiceIOLibraryUri);
Dart_Handle source = GetSource(name);
- return Dart_LoadLibrary(uri, source, 0, 0);
+ return Dart_LoadLibrary(uri, Dart_Null(), source, 0, 0);
}
Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) {
Dart_Handle uri = Dart_NewStringFromCString(name);
Dart_Handle source = GetSource(name);
- return Dart_LoadSource(library, uri, source, 0, 0);
+ return Dart_LoadSource(library, uri, Dart_Null(), source, 0, 0);
}
@@ -368,7 +368,7 @@
if (Dart_IsError(source)) {
return source;
}
- return Dart_LoadSource(library, url, source, 0, 0);
+ return Dart_LoadSource(library, url, Dart_Null(), source, 0, 0);
}
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 123064c..627e80f 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -2653,7 +2653,6 @@
* Scripts and Libraries
* =====================
*/
-/* TODO(turnidge): Finish documenting this section. */
typedef enum {
Dart_kCanonicalizeUrl = 0,
@@ -2662,7 +2661,43 @@
Dart_kImportTag,
} Dart_LibraryTag;
-/* TODO(turnidge): Document. */
+/**
+ * The library tag handler is a multi-purpose callback provided by the
+ * embedder to the Dart VM. The embedder implements the tag handler to
+ * provide the ability to load Dart scripts and imports.
+ *
+ * -- TAGS --
+ *
+ * Dart_kCanonicalizeUrl
+ *
+ * This tag indicates that the embedder should canonicalize 'url' with
+ * respect to 'library'. For most embedders, the
+ * Dart_DefaultCanonicalizeUrl function is a sufficient implementation
+ * of this tag. The return value should be a string holding the
+ * canonicalized url.
+ *
+ * Dart_kScriptTag
+ *
+ * This tag indicates that the root script should be loaded from
+ * 'url'. The 'library' parameter will always be null. Once the root
+ * script is loaded, the embedder should call Dart_LoadScript to
+ * install the root script in the VM. The return value should be an
+ * error or null.
+ *
+ * Dart_kSourceTag
+ *
+ * This tag is used to load a file referenced by Dart language "part
+ * of" directive. Once the file's source is loaded, the embedder
+ * should call Dart_LoadSource to provide the file contents to the VM.
+ * The return value should be an error or null.
+ *
+ * Dart_kImportTag
+ *
+ * This tag is used to load a script referenced by Dart language
+ * "import" directive. Once the script is loaded, the embedder should
+ * call Dart_LoadLibrary to provide the script source to the VM. The
+ * return value should be an error or null.
+ */
typedef Dart_Handle (*Dart_LibraryTagHandler)(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle url);
@@ -2704,18 +2739,30 @@
Dart_Handle url);
/**
- * Loads the root script for the current isolate. The script can be
- * embedded in another file, for example in an html file.
+ * Called by the embedder to provide the source for the root script to
+ * the VM. This function should be called in response to a
+ * Dart_kScriptTag tag handler request (See Dart_LibraryTagHandler,
+ * above).
*
- * TODO(turnidge): Document.
+ * \param url The original url requested for the script.
+ *
+ * \param resolved_url The actual url which was loaded. This parameter
+ * is optionally provided to support isolate reloading. A value of
+ * Dart_Null() indicates that the resolved url was the same as the
+ * requested url.
+ *
+ * \param source The contents of the url.
*
* \param line_offset is the number of text lines before the
* first line of the Dart script in the containing file.
*
* \param col_offset is the number of characters before the first character
* in the first line of the Dart script.
+ *
+ * \return A valid handle if no error occurs during the operation.
*/
DART_EXPORT Dart_Handle Dart_LoadScript(Dart_Handle url,
+ Dart_Handle resolved_url,
Dart_Handle source,
intptr_t line_offset,
intptr_t col_offset);
@@ -2808,7 +2855,33 @@
Dart_Handle error);
+/**
+ * Called by the embedder to provide the source for an "import"
+ * directive. This function should be called in response to a
+ * Dart_kImportTag tag handler request (See Dart_LibraryTagHandler,
+ * above).
+ *
+ * \param library The library where the "import" directive occurs.
+ *
+ * \param url The original url requested for the import.
+ *
+ * \param resolved_url The actual url which was loaded. This parameter
+ * is optionally provided to support isolate reloading. A value of
+ * Dart_Null() indicates that the resolved url was the same as the
+ * requested url.
+ *
+ * \param source The contents of the url.
+ *
+ * \param line_offset is the number of text lines before the
+ * first line of the Dart script in the containing file.
+ *
+ * \param col_offset is the number of characters before the first character
+ * in the first line of the Dart script.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
DART_EXPORT Dart_Handle Dart_LoadLibrary(Dart_Handle url,
+ Dart_Handle resolved_url,
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset);
@@ -2829,16 +2902,33 @@
Dart_Handle prefix);
/**
- * Loads a source string into a library.
+ * Called by the embedder to provide the source for a "part of"
+ * directive. This function should be called in response to a
+ * Dart_kSourceTag tag handler request (See Dart_LibraryTagHandler,
+ * above).
*
- * \param library A library
- * \param url A url identifying the origin of the source
- * \param source A string of Dart source
+ * \param library The library where the "part of" directive occurs.
+ *
+ * \param url The original url requested for the part.
+ *
+ * \param resolved_url The actual url which was loaded. This parameter
+ * is optionally provided to support isolate reloading. A value of
+ * Dart_Null() indicates that the resolved url was the same as the
+ * requested url.
+ *
+ * \param source The contents of the url.
+ *
+ * \param line_offset is the number of text lines before the
+ * first line of the Dart script in the containing file.
+ *
+ * \param col_offset is the number of characters before the first character
+ * in the first line of the Dart script.
*
* \return A valid handle if no error occurs during the operation.
*/
DART_EXPORT Dart_Handle Dart_LoadSource(Dart_Handle library,
Dart_Handle url,
+ Dart_Handle resolved_url,
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset);
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 961c444..edf8918 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -898,6 +898,26 @@
/*
* ========
+ * Reload support
+ * ========
+ *
+ * These functions are used to implement reloading in the Dart VM.
+ * This is an experimental feature, so embedders should be prepared
+ * for these functions to change.
+ */
+
+/**
+ * A callback which determines whether the file at some url has been
+ * modified since some time. If the file cannot be found, true should
+ * be returned.
+ */
+typedef bool (*Dart_FileModifiedCallback)(const char* url, int64_t since);
+
+DART_EXPORT Dart_Handle Dart_SetFileModifiedCallback(
+ Dart_FileModifiedCallback file_modified_callback);
+
+/*
+ * ========
* Timeline
* ========
*/
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 1233d18..0e627a0 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -54,9 +54,6 @@
get_allocation_samples_test: RuntimeError # Profiling unimplemented.
get_cpu_profile_timeline_rpc_test: RuntimeError # Profiling unimplemented.
implicit_getter_setter_test: RuntimeError # Field guards unimplemented.
-get_stack_rpc_test: RuntimeError # Missing single stepping check at fast Smi op
-vm_restart_test: RuntimeError # Missing single stepping check at fast Smi op
-debugging_test: RuntimeError # Missing single stepping check at fast Smi op
[ $hot_reload ]
# Skip all service tests because random reloads interfere.
diff --git a/runtime/platform/assert.cc b/runtime/platform/assert.cc
index ff71e3f..921a564 100644
--- a/runtime/platform/assert.cc
+++ b/runtime/platform/assert.cc
@@ -6,6 +6,7 @@
#include "platform/globals.h"
#include "vm/os.h"
+#include "vm/profiler.h"
namespace dart {
@@ -40,9 +41,8 @@
// In case of failed assertions, abort right away. Otherwise, wait
// until the program is exiting before producing a non-zero exit
// code through abort.
- // TODO(5411324): replace std::abort with OS::Abort so that we can handle
- // restoring of signal handlers before aborting.
if (kind_ == ASSERT) {
+ NOT_IN_PRODUCT(Profiler::DumpStackTrace(true /* native_stack_trace */));
OS::Abort();
}
static bool failed = false;
diff --git a/runtime/platform/utils_fuchsia.h b/runtime/platform/utils_fuchsia.h
index 0129bfe..4e8c4e9 100644
--- a/runtime/platform/utils_fuchsia.h
+++ b/runtime/platform/utils_fuchsia.h
@@ -5,7 +5,7 @@
#ifndef PLATFORM_UTILS_FUCHSIA_H_
#define PLATFORM_UTILS_FUCHSIA_H_
-#include "platform/assert.h"
+#include <endian.h>
namespace dart {
@@ -32,38 +32,32 @@
inline uint16_t Utils::HostToBigEndian16(uint16_t value) {
- UNIMPLEMENTED();
- return 0;
+ return htobe16(value);
}
inline uint32_t Utils::HostToBigEndian32(uint32_t value) {
- UNIMPLEMENTED();
- return 0;
+ return htobe32(value);
}
inline uint64_t Utils::HostToBigEndian64(uint64_t value) {
- UNIMPLEMENTED();
- return 0;
+ return htobe64(value);
}
inline uint16_t Utils::HostToLittleEndian16(uint16_t value) {
- UNIMPLEMENTED();
- return 0;
+ return htole16(value);
}
inline uint32_t Utils::HostToLittleEndian32(uint32_t value) {
- UNIMPLEMENTED();
- return 0;
+ return htole32(value);
}
inline uint64_t Utils::HostToLittleEndian64(uint64_t value) {
- UNIMPLEMENTED();
- return 0;
+ return htole64(value);
}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index f91c0bc..364613f 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -154,8 +154,6 @@
cc/GuardFieldFinalVariableLengthListTest: Skip
cc/GuardFieldSimpleTest: Skip
-cc/Debug_StepInto: Fail # Missing single stepping check at fast Smi op
-
# This test is meaningless for DBC as allocation stubs are not used.
cc/RegenerateAllocStubs: Skip
diff --git a/runtime/vm/bit_vector.cc b/runtime/vm/bit_vector.cc
index bf18147..cc38df3 100644
--- a/runtime/vm/bit_vector.cc
+++ b/runtime/vm/bit_vector.cc
@@ -100,6 +100,16 @@
}
+bool BitVector::IsEmpty() const {
+ for (intptr_t i = 0; i < data_length_; i++) {
+ if (data_[i] != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
void BitVector::Print() const {
OS::Print("[");
for (intptr_t i = 0; i < length_; i++) {
diff --git a/runtime/vm/bit_vector.h b/runtime/vm/bit_vector.h
index af5122d..9afa05f 100644
--- a/runtime/vm/bit_vector.h
+++ b/runtime/vm/bit_vector.h
@@ -84,6 +84,8 @@
void Intersect(const BitVector* other);
+ bool IsEmpty() const;
+
bool Contains(intptr_t i) const {
ASSERT(i >= 0 && i < length());
uword block = data_[i / kBitsPerWord];
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index ea33dae..b0b3a9c1 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1360,7 +1360,7 @@
// Maybe adjust the rate of future reloads.
isolate->MaybeIncreaseReloadEveryNStackOverflowChecks();
// Issue a reload.
- isolate->ReloadSources();
+ isolate->ReloadSources(true /* force_reload */);
const Error& error = Error::Handle(isolate->sticky_reload_error());
if (!error.IsNull()) {
FATAL1("*** Isolate reload failed: %s\n", error.ToErrorCString());
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 66894b5..aff9955 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -21,6 +21,7 @@
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/lockers.h"
+#include "vm/isolate_reload.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/native_entry.h"
@@ -5220,6 +5221,7 @@
DART_EXPORT Dart_Handle Dart_LoadScript(Dart_Handle url,
+ Dart_Handle resolved_url,
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset) {
@@ -5230,6 +5232,13 @@
if (url_str.IsNull()) {
RETURN_TYPE_ERROR(Z, url, String);
}
+ if (::Dart_IsNull(resolved_url)) {
+ resolved_url = url;
+ }
+ const String& resolved_url_str = Api::UnwrapStringHandle(Z, resolved_url);
+ if (resolved_url_str.IsNull()) {
+ RETURN_TYPE_ERROR(Z, resolved_url, String);
+ }
const String& source_str = Api::UnwrapStringHandle(Z, source);
if (source_str.IsNull()) {
RETURN_TYPE_ERROR(Z, source, String);
@@ -5258,8 +5267,9 @@
library.Register(T);
I->object_store()->set_root_library(library);
- const Script& script = Script::Handle(Z,
- Script::New(url_str, source_str, RawScript::kScriptTag));
+ const Script& script =
+ Script::Handle(Z, Script::New(url_str, resolved_url_str, source_str,
+ RawScript::kScriptTag));
script.SetLocationOffset(line_offset, column_offset);
Dart_Handle result;
CompileSource(T, library, script, &result);
@@ -5497,6 +5507,7 @@
DART_EXPORT Dart_Handle Dart_LoadLibrary(Dart_Handle url,
+ Dart_Handle resolved_url,
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset) {
@@ -5507,6 +5518,13 @@
if (url_str.IsNull()) {
RETURN_TYPE_ERROR(Z, url, String);
}
+ if (::Dart_IsNull(resolved_url)) {
+ resolved_url = url;
+ }
+ const String& resolved_url_str = Api::UnwrapStringHandle(Z, resolved_url);
+ if (resolved_url_str.IsNull()) {
+ RETURN_TYPE_ERROR(Z, resolved_url, String);
+ }
const String& source_str = Api::UnwrapStringHandle(Z, source);
if (source_str.IsNull()) {
RETURN_TYPE_ERROR(Z, source, String);
@@ -5536,8 +5554,9 @@
return Api::NewError("%s: library '%s' has already been loaded.",
CURRENT_FUNC, url_str.ToCString());
}
- const Script& script = Script::Handle(Z,
- Script::New(url_str, source_str, RawScript::kLibraryTag));
+ const Script& script =
+ Script::Handle(Z, Script::New(url_str, resolved_url_str, source_str,
+ RawScript::kLibraryTag));
script.SetLocationOffset(line_offset, column_offset);
Dart_Handle result;
CompileSource(T, library, script, &result);
@@ -5603,6 +5622,7 @@
DART_EXPORT Dart_Handle Dart_LoadSource(Dart_Handle library,
Dart_Handle url,
+ Dart_Handle resolved_url,
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset) {
@@ -5617,6 +5637,13 @@
if (url_str.IsNull()) {
RETURN_TYPE_ERROR(Z, url, String);
}
+ if (::Dart_IsNull(resolved_url)) {
+ resolved_url = url;
+ }
+ const String& resolved_url_str = Api::UnwrapStringHandle(Z, resolved_url);
+ if (resolved_url_str.IsNull()) {
+ RETURN_TYPE_ERROR(Z, resolved_url, String);
+ }
const String& source_str = Api::UnwrapStringHandle(Z, source);
if (source_str.IsNull()) {
RETURN_TYPE_ERROR(Z, source, String);
@@ -5634,8 +5661,9 @@
NoHeapGrowthControlScope no_growth_control;
- const Script& script = Script::Handle(Z,
- Script::New(url_str, source_str, RawScript::kSourceTag));
+ const Script& script =
+ Script::Handle(Z, Script::New(url_str, resolved_url_str, source_str,
+ RawScript::kSourceTag));
script.SetLocationOffset(line_offset, column_offset);
Dart_Handle result;
CompileSource(T, lib, script, &result);
@@ -5666,8 +5694,9 @@
NoHeapGrowthControlScope no_growth_control;
- const Script& script = Script::Handle(Z,
- Script::New(url_str, source_str, RawScript::kPatchTag));
+ const Script& script =
+ Script::Handle(Z, Script::New(url_str, url_str, source_str,
+ RawScript::kPatchTag));
Dart_Handle result;
CompileSource(T, lib, script, &result);
return result;
@@ -5843,6 +5872,12 @@
}
+DART_EXPORT Dart_Handle Dart_SetFileModifiedCallback(
+ Dart_FileModifiedCallback file_mod_callback) {
+ return Api::Success();
+}
+
+
DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
return;
}
@@ -5955,6 +5990,30 @@
}
+DART_EXPORT Dart_Handle Dart_SetFileModifiedCallback(
+ Dart_FileModifiedCallback file_modified_callback) {
+ if (!FLAG_support_service) {
+ return Api::Success();
+ }
+ if (file_modified_callback != NULL) {
+ if (IsolateReloadContext::file_modified_callback() != NULL) {
+ return Api::NewError(
+ "%s permits only one callback to be registered, please "
+ "remove the existing callback and then add this callback",
+ CURRENT_FUNC);
+ }
+ } else {
+ if (IsolateReloadContext::file_modified_callback() == NULL) {
+ return Api::NewError(
+ "%s expects 'file_modified_callback' to be set before it is cleared.",
+ CURRENT_FUNC);
+ }
+ }
+ IsolateReloadContext::SetFileModifiedCallback(file_modified_callback);
+ return Api::Success();
+}
+
+
DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
if (!FLAG_support_timeline) {
return;
@@ -6236,6 +6295,8 @@
bool reset_fields) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("Precompilation is not supported on IA32.");
+#elif defined(TARGET_ARCH_DBC)
+ return Api::NewError("Precompilation is not supported on DBC.");
#else
API_TIMELINE_BEGIN_END;
DARTSCOPE(Thread::Current());
@@ -6265,7 +6326,9 @@
uint8_t** assembly_buffer,
intptr_t* assembly_size) {
#if defined(TARGET_ARCH_IA32)
- return Api::NewError("Snapshots with code are not supported on IA32.");
+ return Api::NewError("Precompilation is not supported on IA32.");
+#elif defined(TARGET_ARCH_DBC)
+ return Api::NewError("Precompilation is not supported on DBC.");
#else
API_TIMELINE_DURATION;
DARTSCOPE(Thread::Current());
@@ -6325,7 +6388,9 @@
uint8_t** rodata_blob_buffer,
intptr_t* rodata_blob_size) {
#if defined(TARGET_ARCH_IA32)
- return Api::NewError("Snapshots with code are not supported on IA32.");
+ return Api::NewError("Precompilation is not supported on IA32.");
+#elif defined(TARGET_ARCH_DBC)
+ return Api::NewError("Precompilation is not supported on DBC.");
#else
API_TIMELINE_DURATION;
DARTSCOPE(Thread::Current());
@@ -6427,6 +6492,8 @@
intptr_t* rodata_blob_size) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("Snapshots with code are not supported on IA32.");
+#elif defined(TARGET_ARCH_DBC)
+ return Api::NewError("Snapshots with code are not supported on DBC.");
#else
API_TIMELINE_DURATION;
DARTSCOPE(Thread::Current());
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 53d7755..3dbf3f6 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3578,7 +3578,7 @@
Dart_Handle source = NewString(kScriptChars);
Dart_Handle result = Dart_SetLibraryTagHandler(TestCase::library_handler);
EXPECT_VALID(result);
- Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -3961,7 +3961,7 @@
// Load imported lib.
Dart_Handle url = NewString("library_url");
Dart_Handle source = NewString(kImportedScriptChars);
- Dart_Handle imported_lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle imported_lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
Dart_Handle prefix = Dart_EmptyString();
EXPECT_VALID(imported_lib);
Dart_Handle result = Dart_LibraryImportLibrary(lib, imported_lib, prefix);
@@ -5356,13 +5356,13 @@
// Load lib1
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib1 = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib1 = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib1);
// Load lib2
url = NewString("library2_url");
source = NewString(kLibrary2Chars);
- Dart_Handle lib2 = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib2 = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib2);
// Import lib2 from lib1
@@ -5883,37 +5883,47 @@
result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
- result = Dart_LoadScript(Dart_Null(), source, 0, 0);
+ result = Dart_LoadScript(Dart_Null(), Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadScript expects argument 'url' to be non-null.",
Dart_GetError(result));
- result = Dart_LoadScript(Dart_True(), source, 0, 0);
+ result = Dart_LoadScript(Dart_True(), Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadScript expects argument 'url' to be of type String.",
Dart_GetError(result));
- result = Dart_LoadScript(error, source, 0, 0);
+ result = Dart_LoadScript(error, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("incoming error", Dart_GetError(result));
- result = Dart_LoadScript(url, Dart_Null(), 0, 0);
+ result = Dart_LoadScript(url, Dart_True(), source, 0, 0);
+ EXPECT(Dart_IsError(result));
+ EXPECT_STREQ(
+ "Dart_LoadScript expects argument 'resolved_url' to be of type String.",
+ Dart_GetError(result));
+
+ result = Dart_LoadScript(url, error, source, 0, 0);
+ EXPECT(Dart_IsError(result));
+ EXPECT_STREQ("incoming error", Dart_GetError(result));
+
+ result = Dart_LoadScript(url, Dart_Null(), Dart_Null(), 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadScript expects argument 'source' to be non-null.",
Dart_GetError(result));
- result = Dart_LoadScript(url, Dart_True(), 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), Dart_True(), 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ(
"Dart_LoadScript expects argument 'source' to be of type String.",
Dart_GetError(result));
- result = Dart_LoadScript(url, error, 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), error, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("incoming error", Dart_GetError(result));
// Load a script successfully.
- result = Dart_LoadScript(url, source, 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
Dart_FinalizeLoading(false);
@@ -5925,7 +5935,7 @@
EXPECT_EQ(12345, value);
// Further calls to LoadScript are errors.
- result = Dart_LoadScript(url, source, 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadScript: "
"A script has already been loaded from 'test-lib'.",
@@ -5947,7 +5957,7 @@
// Load a script.
Dart_Handle url = NewString(TestCase::url());
Dart_Handle source = NewString(kScriptChars);
- EXPECT_VALID(Dart_LoadScript(url, source, 0, 0));
+ EXPECT_VALID(Dart_LoadScript(url, Dart_Null(), source, 0, 0));
root_lib = Dart_RootLibrary();
Dart_Handle lib_name = Dart_LibraryName(root_lib);
@@ -6035,7 +6045,7 @@
Dart_Handle source = NewString(kScriptChars);
Dart_Handle result = Dart_SetLibraryTagHandler(import_library_handler);
EXPECT_VALID(result);
- result = Dart_LoadScript(url, source, 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT(strstr(Dart_GetError(result), "unexpected token ')'"));
}
@@ -6054,12 +6064,12 @@
Dart_Handle source = NewString(kScriptChars);
Dart_Handle result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
- result = Dart_LoadScript(url, source, 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
url = NewString("library1_dart");
source = NewString(kLibrary1Chars);
- result = Dart_LoadLibrary(url, source, 0, 0);
+ result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
result = Dart_LookupLibrary(url);
@@ -6093,7 +6103,7 @@
"library library1_name;";
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
Dart_Handle error = Dart_NewApiError("incoming error");
EXPECT_VALID(lib);
@@ -6129,7 +6139,7 @@
"library library1_name;";
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
Dart_Handle error = Dart_NewApiError("incoming error");
EXPECT_VALID(lib);
intptr_t libraryId = -1;
@@ -6169,7 +6179,7 @@
"library library1_name;";
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
Dart_Handle error = Dart_NewApiError("incoming error");
EXPECT_VALID(lib);
@@ -6213,7 +6223,7 @@
Dart_Handle url = NewString("library_url");
Dart_Handle source = NewString(kLibraryChars);
- Dart_Handle lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
Dart_Handle result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -6266,7 +6276,7 @@
// Get the functions from a library.
Dart_Handle url = NewString("library_url");
Dart_Handle source = NewString(kLibraryChars);
- Dart_Handle lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
Dart_Handle result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -6318,12 +6328,12 @@
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib1 = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib1 = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib1);
url = NewString("library2_url");
source = NewString(kLibrary2Chars);
- Dart_Handle lib2 = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib2 = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib2);
result = Dart_LibraryImportLibrary(Dart_Null(), lib2, Dart_Null());
@@ -6369,7 +6379,7 @@
"int bar() => 42;";
Dart_Handle url1 = NewString("library1_url");
Dart_Handle source1 = NewString(kLibrary1Chars);
- Dart_Handle lib1 = Dart_LoadLibrary(url1, source1, 0, 0);
+ Dart_Handle lib1 = Dart_LoadLibrary(url1, Dart_Null(), source1, 0, 0);
EXPECT_VALID(lib1);
EXPECT(Dart_IsLibrary(lib1));
@@ -6378,7 +6388,7 @@
"int foobar() => foo.bar();";
Dart_Handle url2 = NewString("library2_url");
Dart_Handle source2 = NewString(kLibrary2Chars);
- Dart_Handle lib2 = Dart_LoadLibrary(url2, source2, 0, 0);
+ Dart_Handle lib2 = Dart_LoadLibrary(url2, Dart_Null(), source2, 0, 0);
EXPECT_VALID(lib2);
EXPECT(Dart_IsLibrary(lib2));
@@ -6415,42 +6425,52 @@
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- result = Dart_LoadLibrary(Dart_Null(), source, 0, 0);
+ result = Dart_LoadLibrary(Dart_Null(), Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadLibrary expects argument 'url' to be non-null.",
Dart_GetError(result));
- result = Dart_LoadLibrary(Dart_True(), source, 0, 0);
+ result = Dart_LoadLibrary(Dart_True(), Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadLibrary expects argument 'url' to be of type String.",
Dart_GetError(result));
- result = Dart_LoadLibrary(error, source, 0, 0);
+ result = Dart_LoadLibrary(error, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("incoming error", Dart_GetError(result));
- result = Dart_LoadLibrary(url, Dart_Null(), 0, 0);
+ result = Dart_LoadLibrary(url, Dart_True(), source, 0, 0);
+ EXPECT(Dart_IsError(result));
+ EXPECT_STREQ(
+ "Dart_LoadLibrary expects argument 'resolved_url' to be of type String.",
+ Dart_GetError(result));
+
+ result = Dart_LoadLibrary(url, error, source, 0, 0);
+ EXPECT(Dart_IsError(result));
+ EXPECT_STREQ("incoming error", Dart_GetError(result));
+
+ result = Dart_LoadLibrary(url, Dart_Null(), Dart_Null(), 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadLibrary expects argument 'source' to be non-null.",
Dart_GetError(result));
- result = Dart_LoadLibrary(url, Dart_True(), 0, 0);
+ result = Dart_LoadLibrary(url, Dart_Null(), Dart_True(), 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ(
"Dart_LoadLibrary expects argument 'source' to be of type String.",
Dart_GetError(result));
- result = Dart_LoadLibrary(url, error, 0, 0);
+ result = Dart_LoadLibrary(url, Dart_Null(), error, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("incoming error", Dart_GetError(result));
// Success.
- result = Dart_LoadLibrary(url, source, 0, 0);
+ result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
EXPECT(Dart_IsLibrary(result));
// Duplicate library load fails.
- result = Dart_LoadLibrary(url, source, 0, 0);
+ result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ(
"Dart_LoadLibrary: library 'library1_url' has already been loaded.",
@@ -6464,7 +6484,7 @@
")";
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle result = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT(strstr(Dart_GetError(result), "unexpected token ')'"));
}
@@ -6483,72 +6503,82 @@
// Load up a library.
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
EXPECT(Dart_IsLibrary(lib));
url = NewString("source_url");
source = NewString(kSourceChars);
- result = Dart_LoadSource(Dart_Null(), url, source, 0, 0);
+ result = Dart_LoadSource(Dart_Null(), url, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadSource expects argument 'library' to be non-null.",
Dart_GetError(result));
- result = Dart_LoadSource(Dart_True(), url, source, 0, 0);
+ result = Dart_LoadSource(Dart_True(), url, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ(
"Dart_LoadSource expects argument 'library' to be of type Library.",
Dart_GetError(result));
- result = Dart_LoadSource(error, url, source, 0, 0);
+ result = Dart_LoadSource(error, url, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("incoming error", Dart_GetError(result));
- result = Dart_LoadSource(lib, Dart_Null(), source, 0, 0);
+ result = Dart_LoadSource(lib, Dart_Null(), Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadSource expects argument 'url' to be non-null.",
Dart_GetError(result));
- result = Dart_LoadSource(lib, Dart_True(), source, 0, 0);
+ result = Dart_LoadSource(lib, Dart_True(), Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadSource expects argument 'url' to be of type String.",
Dart_GetError(result));
- result = Dart_LoadSource(lib, error, source, 0, 0);
+ result = Dart_LoadSource(lib, error, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("incoming error", Dart_GetError(result));
- result = Dart_LoadSource(lib, url, Dart_Null(), 0, 0);
+ result = Dart_LoadSource(lib, url, Dart_True(), source, 0, 0);
+ EXPECT(Dart_IsError(result));
+ EXPECT_STREQ(
+ "Dart_LoadSource expects argument 'resolved_url' to be of type String.",
+ Dart_GetError(result));
+
+ result = Dart_LoadSource(lib, url, error, source, 0, 0);
+ EXPECT(Dart_IsError(result));
+ EXPECT_STREQ("incoming error", Dart_GetError(result));
+
+ result = Dart_LoadSource(lib, url, Dart_Null(), Dart_Null(), 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("Dart_LoadSource expects argument 'source' to be non-null.",
Dart_GetError(result));
- result = Dart_LoadSource(lib, url, Dart_True(), 0, 0);
+ result = Dart_LoadSource(lib, url, Dart_Null(), Dart_True(), 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ(
"Dart_LoadSource expects argument 'source' to be of type String.",
Dart_GetError(result));
- result = Dart_LoadSource(lib, error, source, 0, 0);
+ result = Dart_LoadSource(lib, error, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
EXPECT_STREQ("incoming error", Dart_GetError(result));
// Success.
- result = Dart_LoadSource(lib, url, source, 0, 0);
+ result = Dart_LoadSource(lib, url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
EXPECT(Dart_IsLibrary(result));
EXPECT(Dart_IdentityEquals(lib, result));
// Duplicate calls are okay.
- result = Dart_LoadSource(lib, url, source, 0, 0);
+ result = Dart_LoadSource(lib, url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
EXPECT(Dart_IsLibrary(result));
EXPECT(Dart_IdentityEquals(lib, result));
// Language errors are detected.
source = NewString(kBadSourceChars);
- result = Dart_LoadSource(lib, url, source, 0, 0);
+ result = Dart_LoadSource(lib, url, Dart_Null(), source, 0, 0);
EXPECT(Dart_IsError(result));
}
@@ -6566,7 +6596,7 @@
"}\n";
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
EXPECT(Dart_IsLibrary(lib));
Dart_Handle result = Dart_FinalizeLoading(false);
@@ -6586,7 +6616,7 @@
// Load a source file late.
url = NewString("source_url");
source = NewString(kSourceChars);
- EXPECT_VALID(Dart_LoadSource(lib, url, source, 0, 0));
+ EXPECT_VALID(Dart_LoadSource(lib, url, Dart_Null(), source, 0, 0));
result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -6615,14 +6645,14 @@
// Load up a library.
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
EXPECT(Dart_IsLibrary(lib));
url = NewString("source_url");
source = NewString(kSourceChars);
- Dart_Handle result = Dart_LoadSource(lib, url, source, 0, 0);
+ Dart_Handle result = Dart_LoadSource(lib, url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
url = NewString("patch_url");
@@ -6670,14 +6700,14 @@
// Load up a library.
Dart_Handle url = NewString("library1_url");
Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib = Dart_LoadLibrary(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
EXPECT(Dart_IsLibrary(lib));
url = NewString("source_url");
source = NewString(kSourceChars);
- Dart_Handle result = Dart_LoadSource(lib, url, source, 0, 0);
+ Dart_Handle result = Dart_LoadSource(lib, url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
url = NewString("patch_url");
@@ -6862,7 +6892,7 @@
Dart_Handle url = NewString("theLibrary");
Dart_Handle source = NewString(kLibraryChars);
- result = Dart_LoadLibrary(url, source, 0, 0);
+ result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
const char* patchNames[] = { "main library patch",
@@ -6892,7 +6922,8 @@
Dart_Handle script_url = NewString("theScript");
source = NewString(kScriptChars);
- Dart_Handle test_script = Dart_LoadScript(script_url, source, 0, 0);
+ Dart_Handle test_script =
+ Dart_LoadScript(script_url, Dart_Null(), source, 0, 0);
EXPECT_VALID(test_script);
result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -6996,7 +7027,7 @@
Dart_Handle source = NewString(kScriptChars);
result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
- Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -7082,15 +7113,15 @@
Dart_Handle source = NewString(kScriptChars);
result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
- result = Dart_LoadScript(url, source, 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
url = NewString("library1_dart");
source = NewString(kLibrary1Chars);
- Dart_LoadLibrary(url, source, 0, 0);
+ Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
url = NewString("library2_dart");
source = NewString(kLibrary2Chars);
- Dart_LoadLibrary(url, source, 0, 0);
+ Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
Dart_FinalizeLoading(false);
@@ -7120,16 +7151,16 @@
Dart_Handle source = NewString(kScriptChars);
result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
- result = Dart_LoadScript(url, source, 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
url = NewString("library2_dart");
source = NewString(kLibrary2Chars);
- Dart_LoadLibrary(url, source, 0, 0);
+ Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
url = NewString("library1_dart");
source = NewString(kLibrary1Chars);
- Dart_LoadLibrary(url, source, 0, 0);
+ Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -7159,16 +7190,16 @@
Dart_Handle source = NewString(kScriptChars);
result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
- result = Dart_LoadScript(url, source, 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(result);
url = NewString("library2_dart");
source = NewString(kLibrary2Chars);
- Dart_LoadLibrary(url, source, 0, 0);
+ Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
url = NewString("library1_dart");
source = NewString(kLibrary1Chars);
- Dart_LoadLibrary(url, source, 0, 0);
+ Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
Dart_FinalizeLoading(false);
result = Dart_Invoke(result, NewString("main"), 0, NULL);
@@ -7195,11 +7226,11 @@
Dart_Handle source = NewString(kScriptChars);
result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
- result = Dart_LoadScript(url, source, 0, 0);
+ result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
url = NewString("lib.dart");
source = NewString(kLibraryChars);
- Dart_LoadLibrary(url, source, 0, 0);
+ Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
Dart_FinalizeLoading(false);
result = Dart_Invoke(result, NewString("main"), 0, NULL);
@@ -7538,7 +7569,7 @@
Dart_Handle source = NewString(kScriptChars);
Dart_Handle result = Dart_SetLibraryTagHandler(TestCase::library_handler);
EXPECT_VALID(result);
- Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -7645,7 +7676,7 @@
Dart_Handle source = NewString(kScriptChars);
Dart_Handle result = Dart_SetLibraryTagHandler(TestCase::library_handler);
EXPECT_VALID(result);
- lib = Dart_LoadScript(url, source, 0, 0);
+ lib = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -7758,7 +7789,7 @@
Dart_Handle source = NewString(kScriptChars);
Dart_Handle result = Dart_SetLibraryTagHandler(TestCase::library_handler);
EXPECT_VALID(result);
- Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
@@ -7937,7 +7968,7 @@
Dart_Handle source = NewString(kScriptChars);
result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
- Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
EXPECT(Dart_IsLibrary(lib));
result = Dart_SetNativeResolver(lib, &MyNativeClosureResolver, NULL);
@@ -8086,7 +8117,7 @@
Dart_Handle source = NewString(kScriptChars);
result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
- Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
EXPECT_VALID(lib);
EXPECT(Dart_IsLibrary(lib));
result = Dart_SetNativeResolver(lib, &MyStaticNativeClosureResolver, NULL);
@@ -8855,7 +8886,7 @@
Dart_Handle source = NewString(kLoadSecond);
Dart_Handle url = NewString(TestCase::url());
- Dart_LoadSource(TestCase::lib(), url, source, 0, 0);
+ Dart_LoadSource(TestCase::lib(), url, Dart_Null(), source, 0, 0);
result = Dart_FinalizeLoading(false);
EXPECT_VALID(result);
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index 319716e..7ea64d6 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -610,8 +610,13 @@
} while (true);
// Wait for all markers to stop.
barrier_->Sync();
+#if defined(DEBUG)
ASSERT(AtomicOperations::LoadRelaxed(num_busy_) == 0);
-
+ // Caveat: must not allow any marker to continue past the barrier
+ // before we checked num_busy, otherwise one of them might rush
+ // ahead and increment it.
+ barrier_->Sync();
+#endif
// Check if we have any pending properties with marked keys.
// Those might have been marked by another marker.
more_to_mark = visitor.ProcessPendingWeakProperties();
@@ -626,7 +631,7 @@
// between all markers and the main thread.
barrier_->Sync();
if (!more_to_mark && (AtomicOperations::LoadRelaxed(num_busy_) > 0)) {
- // All markers continue to marker as long as any single marker has
+ // All markers continue to mark as long as any single marker has
// some work to do.
AtomicOperations::FetchAndIncrement(num_busy_);
more_to_mark = true;
@@ -747,6 +752,13 @@
do {
// Wait for all markers to stop.
barrier.Sync();
+#if defined(DEBUG)
+ ASSERT(AtomicOperations::LoadRelaxed(&num_busy) == 0);
+ // Caveat: must not allow any marker to continue past the barrier
+ // before we checked num_busy, otherwise one of them might rush
+ // ahead and increment it.
+ barrier.Sync();
+#endif
// Wait for all markers to go through weak properties and verify
// that there are no more objects to mark.
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
index f1be32d..02d095e 100644
--- a/runtime/vm/intermediate_language_dbc.cc
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -786,7 +786,7 @@
ASSERT(!link_lazily());
const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
const intptr_t target_kidx =
- __ object_pool_wrapper().FindImmediate(label.address());
+ __ object_pool_wrapper().FindNativeEntry(&label, kNotPatchable);
const intptr_t argc_tag_kidx =
__ object_pool_wrapper().FindImmediate(static_cast<uword>(argc_tag));
__ PushConstant(target_kidx);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 15091b5..27a3529 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -846,7 +846,8 @@
has_attempted_reload_(false),
no_reload_scope_depth_(0),
reload_every_n_stack_overflow_checks_(FLAG_reload_every),
- reload_context_(NULL) {
+ reload_context_(NULL),
+ last_reload_timestamp_(OS::GetCurrentTimeMillis()) {
NOT_IN_PRODUCT(FlagsCopyFrom(api_flags));
// TODO(asiva): A Thread is not available here, need to figure out
// how the vm_tag (kEmbedderTagId) can be set, these tags need to
@@ -1095,12 +1096,13 @@
}
-void Isolate::ReloadSources(bool dont_delete_reload_context) {
+void Isolate::ReloadSources(bool force_reload,
+ bool dont_delete_reload_context) {
// TODO(asiva): Add verification of canonical objects.
ASSERT(!IsReloading());
has_attempted_reload_ = true;
reload_context_ = new IsolateReloadContext(this);
- reload_context_->StartReload();
+ reload_context_->StartReload(force_reload);
// TODO(asiva): Add verification of canonical objects.
if (dont_delete_reload_context) {
// Unit tests use the reload context later. Caller is responsible
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 9761071..9c55cf3 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -249,7 +249,8 @@
// By default the reload context is deleted. This parameter allows
// the caller to delete is separately if it is still needed.
- void ReloadSources(bool dont_delete_reload_context = false);
+ void ReloadSources(bool force_reload,
+ bool dont_delete_reload_context = false);
bool MakeRunnable();
void Run();
@@ -483,6 +484,13 @@
void ReportReloadError(const Error& error);
+ void set_last_reload_timestamp(int64_t value) {
+ last_reload_timestamp_ = value;
+ }
+ int64_t last_reload_timestamp() const {
+ return last_reload_timestamp_;
+ }
+
uword user_tag() const {
return user_tag_;
}
@@ -822,6 +830,7 @@
// Per-isolate copy of FLAG_reload_every.
intptr_t reload_every_n_stack_overflow_checks_;
IsolateReloadContext* reload_context_;
+ int64_t last_reload_timestamp_;
#define ISOLATE_METRIC_VARIABLE(type, variable, name, unit) \
type metric_##variable##_;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index b23dd3b..f174406 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -5,6 +5,7 @@
#include "vm/isolate_reload.h"
#include "vm/become.h"
+#include "vm/bit_vector.h"
#include "vm/code_generator.h"
#include "vm/compiler.h"
#include "vm/dart_api_impl.h"
@@ -356,13 +357,16 @@
IsolateReloadContext::IsolateReloadContext(Isolate* isolate)
: start_time_micros_(OS::GetCurrentMonotonicMicros()),
+ reload_timestamp_(OS::GetCurrentTimeMillis()),
isolate_(isolate),
+ reload_skipped_(false),
saved_num_cids_(-1),
saved_class_table_(NULL),
num_saved_libs_(-1),
instance_morphers_(),
reasons_to_cancel_reload_(),
cid_mapper_(),
+ modified_libs_(NULL),
script_uri_(String::null()),
error_(Error::null()),
old_classes_set_storage_(Array::null()),
@@ -414,7 +418,7 @@
};
-void IsolateReloadContext::StartReload() {
+void IsolateReloadContext::StartReload(bool force_reload) {
TIMELINE_SCOPE(Reload);
Thread* thread = Thread::Current();
ASSERT(isolate() == thread->isolate());
@@ -424,6 +428,15 @@
ASSERT(!root_lib.IsNull());
const String& root_lib_url = String::Handle(root_lib.url());
+ // Check to see which libraries have been modified.
+ modified_libs_ = FindModifiedLibraries(force_reload);
+ if (!modified_libs_->Contains(root_lib.index())) {
+ ASSERT(modified_libs_->IsEmpty());
+ reload_skipped_ = true;
+ TIR_Print("Skipping reload. No libraries were modified\n");
+ return;
+ }
+
// Preallocate storage for maps.
old_classes_set_storage_ =
HashTables::New<UnorderedHashSet<ClassMapTraits> >(4);
@@ -501,11 +514,15 @@
void IsolateReloadContext::FinishReload() {
+ if (reload_skipped_) {
+ return;
+ }
BuildLibraryMapping();
TIR_Print("---- DONE FINALIZING\n");
if (ValidateReload()) {
Commit();
PostCommit();
+ isolate()->set_last_reload_timestamp(reload_timestamp_);
} else {
ReportReasonsForCancelling();
Rollback();
@@ -516,7 +533,7 @@
RebuildDirectSubclasses();
if (FLAG_write_protect_code) {
- // Disable code page write protection while we are reloading.
+ // Re-enable code page write protection.
I->heap()->WriteProtectCode(true);
}
@@ -649,8 +666,119 @@
}
-bool IsolateReloadContext::IsCleanLibrary(const Library& lib) {
- return lib.is_dart_scheme();
+Dart_FileModifiedCallback IsolateReloadContext::file_modified_callback_ = NULL;
+
+
+bool IsolateReloadContext::ScriptModifiedSince(const Script& script,
+ int64_t since) {
+ if (file_modified_callback_ == NULL) {
+ return true;
+ }
+ // We use the resolved url to determine if the script has been modified.
+ const String& url = String::Handle(script.resolved_url());
+ const char* url_chars = url.ToCString();
+ return (*file_modified_callback_)(url_chars, since);
+}
+
+
+static void PropagateLibraryModified(
+ const ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >* imported_by,
+ intptr_t lib_index,
+ BitVector* modified_libs) {
+ ZoneGrowableArray<intptr_t>* dep_libs = (*imported_by)[lib_index];
+ for (intptr_t i = 0; i < dep_libs->length(); i++) {
+ intptr_t dep_lib_index = (*dep_libs)[i];
+ if (!modified_libs->Contains(dep_lib_index)) {
+ modified_libs->Add(dep_lib_index);
+ PropagateLibraryModified(imported_by, dep_lib_index, modified_libs);
+ }
+ }
+}
+
+
+BitVector* IsolateReloadContext::FindModifiedLibraries(bool force_reload) {
+ Thread* thread = Thread::Current();
+ int64_t last_reload = I->last_reload_timestamp();
+
+ const GrowableObjectArray& libs =
+ GrowableObjectArray::Handle(object_store()->libraries());
+ Library& lib = Library::Handle();
+ Array& scripts = Array::Handle();
+ Script& script = Script::Handle();
+ intptr_t num_libs = libs.Length();
+
+ // Construct the imported-by graph.
+ ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >* imported_by =
+ new ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >(num_libs);
+ imported_by->SetLength(num_libs);
+ for (intptr_t i = 0; i < num_libs; i++) {
+ (*imported_by)[i] = new ZoneGrowableArray<intptr_t>();
+ }
+ Array& imports = Array::Handle();
+ Namespace& ns = Namespace::Handle();
+ Library& target = Library::Handle();
+
+ for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) {
+ lib ^= libs.At(lib_idx);
+ ASSERT(lib_idx == lib.index());
+ if (lib.is_dart_scheme()) {
+ // We don't care about imports among dart scheme libraries.
+ continue;
+ }
+
+ // Add imports to the import-by graph.
+ imports = lib.imports();
+ for (intptr_t import_idx = 0; import_idx < imports.Length(); import_idx++) {
+ ns ^= imports.At(import_idx);
+ if (!ns.IsNull()) {
+ target = ns.library();
+ (*imported_by)[target.index()]->Add(lib.index());
+ }
+ }
+
+ // Add prefixed imports to the import-by graph.
+ DictionaryIterator entries(lib);
+ Object& entry = Object::Handle();
+ LibraryPrefix& prefix = LibraryPrefix::Handle();
+ while (entries.HasNext()) {
+ entry = entries.GetNext();
+ if (entry.IsLibraryPrefix()) {
+ prefix ^= entry.raw();
+ imports = prefix.imports();
+ for (intptr_t import_idx = 0; import_idx < imports.Length();
+ import_idx++) {
+ ns ^= imports.At(import_idx);
+ if (!ns.IsNull()) {
+ target = ns.library();
+ (*imported_by)[target.index()]->Add(lib.index());
+ }
+ }
+ }
+ }
+ }
+
+ BitVector* modified_libs = new(Z) BitVector(Z, num_libs);
+
+ for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) {
+ lib ^= libs.At(lib_idx);
+ if (lib.is_dart_scheme() || modified_libs->Contains(lib_idx)) {
+ // We don't consider dart scheme libraries during reload. If
+ // the modified libs set already contains this library, then we
+ // have already visited it.
+ continue;
+ }
+ scripts = lib.LoadedScripts();
+ for (intptr_t script_idx = 0; script_idx < scripts.Length(); script_idx++) {
+ script ^= scripts.At(script_idx);
+ if (force_reload || ScriptModifiedSince(script, last_reload)) {
+ modified_libs->Add(lib_idx);
+ PropagateLibraryModified(imported_by, lib_idx, modified_libs);
+ break;
+ }
+ }
+ }
+
+ return modified_libs;
}
@@ -677,19 +805,20 @@
num_saved_libs_ = 0;
for (intptr_t i = 0; i < libs.Length(); i++) {
lib ^= libs.At(i);
- if (IsCleanLibrary(lib)) {
+ if (modified_libs_->Contains(i)) {
+ // We are going to reload this library. Clear the index.
+ lib.set_index(-1);
+ } else {
// We are preserving this library across the reload, assign its new index
lib.set_index(new_libs.Length());
new_libs.Add(lib, Heap::kOld);
num_saved_libs_++;
- } else {
- // We are going to reload this library. Clear the index.
- lib.set_index(-1);
}
// Add old library to old libraries set.
bool already_present = old_libraries_set.Insert(lib);
ASSERT(!already_present);
}
+ modified_libs_ = NULL; // Renumbering the libraries has invalidated this.
old_libraries_set_storage_ = old_libraries_set.Release().raw();
// Reset the registered libraries to the filtered array.
@@ -1342,11 +1471,8 @@
Library& replacement_or_new = Library::Handle();
Library& old = Library::Handle();
- for (intptr_t i = 0; i < libs.Length(); i++) {
+ for (intptr_t i = num_saved_libs_; i < libs.Length(); i++) {
replacement_or_new = Library::RawCast(libs.At(i));
- if (IsCleanLibrary(replacement_or_new)) {
- continue;
- }
old ^= OldLibraryOrNull(replacement_or_new);
if (old.IsNull()) {
if (FLAG_identity_reload) {
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index 0a3b591..a479aae 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -5,6 +5,8 @@
#ifndef VM_ISOLATE_RELOAD_H_
#define VM_ISOLATE_RELOAD_H_
+#include "include/dart_tools_api.h"
+
#include "vm/hash_map.h"
#include "vm/globals.h"
#include "vm/growable_array.h"
@@ -33,16 +35,18 @@
namespace dart {
+class BitVector;
class GrowableObjectArray;
class Isolate;
class Library;
+class ObjectPointerVisitor;
+class ObjectStore;
class RawError;
class RawGrowableObjectArray;
class RawLibrary;
class RawObject;
class RawString;
-class ObjectPointerVisitor;
-class ObjectStore;
+class Script;
class UpdateClassesVisitor;
@@ -129,7 +133,7 @@
explicit IsolateReloadContext(Isolate* isolate);
~IsolateReloadContext();
- void StartReload();
+ void StartReload(bool force_reload);
void FinishReload();
void AbortReload(const Error& error);
@@ -141,9 +145,13 @@
void ReportError(const Error& error);
void ReportSuccess();
+ bool reload_skipped() const { return reload_skipped_; }
+
bool has_error() const { return HasReasonsForCancelling(); }
RawError* error() const;
+ int64_t reload_timestamp() const { return reload_timestamp_; }
+
static bool IsSameField(const Field& a, const Field& b);
static bool IsSameLibrary(const Library& a_lib, const Library& b_lib);
static bool IsSameClass(const Class& a, const Class& b);
@@ -185,6 +193,13 @@
return !instance_morphers_.is_empty();
}
+ static Dart_FileModifiedCallback file_modified_callback() {
+ return file_modified_callback_;
+ }
+ static void SetFileModifiedCallback(Dart_FileModifiedCallback callback) {
+ file_modified_callback_ = callback;
+ }
+
private:
void set_saved_root_library(const Library& value);
@@ -202,8 +217,9 @@
void CheckpointClasses();
- // Is |lib| a library whose sources have not changed?
- bool IsCleanLibrary(const Library& lib);
+ bool ScriptModifiedSince(const Script& script, int64_t since);
+ BitVector* FindModifiedLibraries(bool force_reload);
+
void CheckpointLibraries();
// Transforms the heap based on instance_morphers_.
@@ -233,7 +249,9 @@
void InvalidateWorld();
int64_t start_time_micros_;
+ int64_t reload_timestamp_;
Isolate* isolate_;
+ bool reload_skipped_;
intptr_t saved_num_cids_;
RawClass** saved_class_table_;
@@ -265,6 +283,9 @@
};
MallocGrowableArray<LibraryInfo> library_infos_;
+ // A bit vector indicating which of the original libraries were modified.
+ BitVector* modified_libs_;
+
RawClass* OldClassOrNull(const Class& replacement_or_new);
RawLibrary* OldLibraryOrNull(const Library& replacement_or_new);
@@ -302,6 +323,8 @@
friend class Isolate;
friend class Class; // AddStaticFieldMapping, AddEnumBecomeMapping.
friend class ObjectLocator;
+
+ static Dart_FileModifiedCallback file_modified_callback_;
};
} // namespace dart
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 49672f6..46774c7 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -2223,6 +2223,168 @@
EXPECT_VALID(lib);
}
+static bool NothingModifiedCallback(const char* url, int64_t since) {
+ return false;
+}
+
+
+TEST_CASE(IsolateReload_NoLibsModified) {
+ const char* kImportScript =
+ "importedFunc() => 'fancy';";
+ TestCase::SetImportableTestLibScript(kImportScript);
+
+ const char* kScript =
+ "import 'test:importable_lib';\n"
+ "main() {\n"
+ " return importedFunc() + ' feast';\n"
+ "}\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("fancy feast", SimpleInvokeStr(lib, "main"));
+
+ const char* kReloadImportScript =
+ "importedFunc() => 'bossy';";
+ TestCase::SetImportableTestLibScript(kReloadImportScript);
+
+ const char* kReloadScript =
+ "import 'test:importable_lib';\n"
+ "main() {\n"
+ " return importedFunc() + ' pants';\n"
+ "}\n";
+
+ Dart_SetFileModifiedCallback(&NothingModifiedCallback);
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ Dart_SetFileModifiedCallback(NULL);
+
+ // No reload occurred because no files were "modified".
+ EXPECT_STREQ("fancy feast", SimpleInvokeStr(lib, "main"));
+}
+
+
+static bool MainModifiedCallback(const char* url, int64_t since) {
+ if (strcmp(url, "test-lib") == 0) {
+ return true;
+ }
+ return false;
+}
+
+
+TEST_CASE(IsolateReload_MainLibModified) {
+ const char* kImportScript =
+ "importedFunc() => 'fancy';";
+ TestCase::SetImportableTestLibScript(kImportScript);
+
+ const char* kScript =
+ "import 'test:importable_lib';\n"
+ "main() {\n"
+ " return importedFunc() + ' feast';\n"
+ "}\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("fancy feast", SimpleInvokeStr(lib, "main"));
+
+ const char* kReloadImportScript =
+ "importedFunc() => 'bossy';";
+ TestCase::SetImportableTestLibScript(kReloadImportScript);
+
+ const char* kReloadScript =
+ "import 'test:importable_lib';\n"
+ "main() {\n"
+ " return importedFunc() + ' pants';\n"
+ "}\n";
+
+ Dart_SetFileModifiedCallback(&MainModifiedCallback);
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ Dart_SetFileModifiedCallback(NULL);
+
+ // Imported library is not reloaded.
+ EXPECT_STREQ("fancy pants", SimpleInvokeStr(lib, "main"));
+}
+
+
+static bool ImportModifiedCallback(const char* url, int64_t since) {
+ if (strcmp(url, "test:importable_lib") == 0) {
+ return true;
+ }
+ return false;
+}
+
+
+TEST_CASE(IsolateReload_ImportedLibModified) {
+ const char* kImportScript =
+ "importedFunc() => 'fancy';";
+ TestCase::SetImportableTestLibScript(kImportScript);
+
+ const char* kScript =
+ "import 'test:importable_lib';\n"
+ "main() {\n"
+ " return importedFunc() + ' feast';\n"
+ "}\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("fancy feast", SimpleInvokeStr(lib, "main"));
+
+ const char* kReloadImportScript =
+ "importedFunc() => 'bossy';";
+ TestCase::SetImportableTestLibScript(kReloadImportScript);
+
+ const char* kReloadScript =
+ "import 'test:importable_lib';\n"
+ "main() {\n"
+ " return importedFunc() + ' pants';\n"
+ "}\n";
+
+ Dart_SetFileModifiedCallback(&ImportModifiedCallback);
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ Dart_SetFileModifiedCallback(NULL);
+
+ // Modification of an imported library propagates to the importing library.
+ EXPECT_STREQ("bossy pants", SimpleInvokeStr(lib, "main"));
+}
+
+
+TEST_CASE(IsolateReload_PrefixImportedLibModified) {
+ const char* kImportScript =
+ "importedFunc() => 'fancy';";
+ TestCase::SetImportableTestLibScript(kImportScript);
+
+ const char* kScript =
+ "import 'test:importable_lib' as cobra;\n"
+ "main() {\n"
+ " return cobra.importedFunc() + ' feast';\n"
+ "}\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("fancy feast", SimpleInvokeStr(lib, "main"));
+
+ const char* kReloadImportScript =
+ "importedFunc() => 'bossy';";
+ TestCase::SetImportableTestLibScript(kReloadImportScript);
+
+ const char* kReloadScript =
+ "import 'test:importable_lib' as cobra;\n"
+ "main() {\n"
+ " return cobra.importedFunc() + ' pants';\n"
+ "}\n";
+
+ Dart_SetFileModifiedCallback(&ImportModifiedCallback);
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ Dart_SetFileModifiedCallback(NULL);
+
+ // Modification of an prefix-imported library propagates to the
+ // importing library.
+ EXPECT_STREQ("bossy pants", SimpleInvokeStr(lib, "main"));
+}
+
+
#endif // !PRODUCT
} // namespace dart
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 71cd044..2f062f1 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -8816,6 +8816,11 @@
}
+void Script::set_resolved_url(const String& value) const {
+ StorePointer(&raw_ptr()->resolved_url_, value.raw());
+}
+
+
void Script::set_source(const String& value) const {
StorePointer(&raw_ptr()->source_, value.raw());
}
@@ -9078,10 +9083,20 @@
RawScript* Script::New(const String& url,
const String& source,
RawScript::Kind kind) {
+ return Script::New(url, url, source, kind);
+}
+
+
+RawScript* Script::New(const String& url,
+ const String& resolved_url,
+ const String& source,
+ RawScript::Kind kind) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
const Script& result = Script::Handle(zone, Script::New());
result.set_url(String::Handle(zone, Symbols::New(thread, url)));
+ result.set_resolved_url(
+ String::Handle(zone, Symbols::New(thread, resolved_url)));
result.set_source(source);
result.set_kind(kind);
result.set_load_timestamp(FLAG_remove_script_timestamps_for_test
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 82f01cb..802bf513 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3396,6 +3396,9 @@
class Script : public Object {
public:
RawString* url() const { return raw_ptr()->url_; }
+
+ // The actual url which was loaded from disk, if provided by the embedder.
+ RawString* resolved_url() const { return raw_ptr()->resolved_url_; }
bool HasSource() const;
RawString* Source() const;
RawString* GenerateSource() const; // Generates source code from Tokenstream.
@@ -3451,8 +3454,14 @@
const String& source,
RawScript::Kind kind);
+ static RawScript* New(const String& url,
+ const String& resolved_url,
+ const String& source,
+ RawScript::Kind kind);
+
private:
void set_url(const String& value) const;
+ void set_resolved_url(const String& value) const;
void set_source(const String& value) const;
void set_kind(RawScript::Kind value) const;
void set_load_timestamp(int64_t value) const;
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index b634352..e28ef54 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -10,6 +10,7 @@
#include <errno.h>
#include <magenta/syscalls.h>
#include <magenta/types.h>
+#include <runtime/sysinfo.h>
#include "platform/assert.h"
#include "vm/zone.h"
@@ -29,8 +30,7 @@
intptr_t OS::ProcessId() {
- UNIMPLEMENTED();
- return 0;
+ return static_cast<intptr_t>(getpid());
}
@@ -86,13 +86,19 @@
void* OS::AlignedAllocate(intptr_t size, intptr_t alignment) {
- UNIMPLEMENTED();
- return NULL;
+ const int kMinimumAlignment = 16;
+ ASSERT(Utils::IsPowerOfTwo(alignment));
+ ASSERT(alignment >= kMinimumAlignment);
+ void* p = memalign(alignment, size);
+ if (p == NULL) {
+ UNREACHABLE();
+ }
+ return p;
}
void OS::AlignedFree(void* ptr) {
- UNIMPLEMENTED();
+ free(ptr);
}
@@ -146,18 +152,19 @@
int OS::NumberOfAvailableProcessors() {
- UNIMPLEMENTED();
- return 0;
+ return mxr_get_nprocs_conf();
}
void OS::Sleep(int64_t millis) {
- UNIMPLEMENTED();
+ mx_nanosleep(
+ millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond);
}
void OS::SleepMicros(int64_t micros) {
- UNIMPLEMENTED();
+ mx_nanosleep(
+ micros * kNanosecondsPerMicrosecond);
}
diff --git a/runtime/vm/os_thread_fuchsia.cc b/runtime/vm/os_thread_fuchsia.cc
index cca791c..536f11f 100644
--- a/runtime/vm/os_thread_fuchsia.cc
+++ b/runtime/vm/os_thread_fuchsia.cc
@@ -52,12 +52,8 @@
int64_t secs = target / kNanosecondsPerSecond;
int64_t nanos = target - (secs * kNanosecondsPerSecond);
- ts->tv_sec += secs;
- ts->tv_nsec += nanos;
- if (ts->tv_nsec >= kNanosecondsPerSecond) {
- ts->tv_sec += 1;
- ts->tv_nsec -= kNanosecondsPerSecond;
- }
+ ts->tv_sec = secs;
+ ts->tv_nsec = nanos;
}
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 1b7cec3..d11536b 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -2419,19 +2419,6 @@
AstNode* receiver) {
Function& implicit_closure_function =
Function::ZoneHandle(Z, func.ImplicitClosureFunction());
- if (receiver != NULL) {
- // If we create an implicit instance closure from inside a closure of a
- // parameterized class, make sure that the receiver is captured as
- // instantiator.
- if (FunctionLevel() > 0) {
- const Type& signature_type = Type::Handle(Z,
- implicit_closure_function.SignatureType());
- const Class& scope_class = Class::Handle(Z, signature_type.type_class());
- if (scope_class.IsGeneric()) {
- CaptureInstantiator();
- }
- }
- }
return new ClosureNode(token_pos, implicit_closure_function, receiver, NULL);
}
@@ -9028,13 +9015,18 @@
loop_var_name = ExpectIdentifier("variable name expected");
}
ExpectToken(Token::kIN);
+
+ // Ensure that the block token range contains the call to moveNext and it
+ // also starts the block at a different token position than the following
+ // loop block. Both blocks can allocate contexts and if they have a matching
+ // token position range, it can be an issue (cf. bug 26941).
+ OpenBlock(); // Implicit block around while loop.
+
const TokenPosition collection_pos = TokenPos();
AstNode* collection_expr =
ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
ExpectToken(Token::kRPAREN);
- OpenBlock(); // Implicit block around while loop.
-
// Generate implicit iterator variable and add to scope.
// We could set the type of the implicit iterator variable to Iterator<T>
// where T is the type of the for loop variable. However, the type error
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 6e3527a..165822e 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -340,7 +340,7 @@
} else {
OS::Print("Frame[%" Pd "] = `%s` [0x%" Px "]\n",
frame_index, native_symbol_name, pc);
- free(native_symbol_name);
+ NativeSymbolResolver::FreeSymbolName(native_symbol_name);
}
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index fb1f06e..52c424c 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -998,6 +998,7 @@
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->url_); }
RawString* url_;
+ RawString* resolved_url_;
RawArray* compile_time_constants_;
RawTokenStream* tokens_;
RawString* source_;
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index ccc5309..8ef6e89 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2457,6 +2457,7 @@
static const MethodParameter* reload_sources_params[] = {
RUNNABLE_ISOLATE_PARAMETER,
+ new BoolParameter("force", false),
NULL,
};
@@ -2489,8 +2490,10 @@
"This isolate cannot reload sources right now.");
return true;
}
+ const bool force_reload =
+ BoolParameter::Parse(js->LookupParam("force"), false);
- isolate->ReloadSources();
+ isolate->ReloadSources(force_reload);
const Error& error = Error::Handle(isolate->sticky_reload_error());
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index de12ec7..226222c 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -798,7 +798,9 @@
const intptr_t lhs = reinterpret_cast<intptr_t>(SP[-1]); \
const intptr_t rhs = reinterpret_cast<intptr_t>(SP[-0]); \
ResultT* slot = reinterpret_cast<ResultT*>(SP - 1); \
- if (LIKELY(AreBothSmis(lhs, rhs) && !Func(lhs, rhs, slot))) { \
+ if (LIKELY(!thread->isolate()->single_step()) && \
+ LIKELY(AreBothSmis(lhs, rhs) && \
+ !Func(lhs, rhs, slot))) { \
SMI_FASTPATH_ICDATA_INC; \
/* Fast path succeeded. Skip the generic call that follows. */ \
pc++; \
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index bcd69f7..915358a 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -1373,6 +1373,7 @@
// Load the library.
Dart_Handle import_lib = Dart_LoadLibrary(NewString("dart_import_lib"),
+ Dart_Null(),
NewString(kLibScriptChars),
0, 0);
EXPECT_VALID(import_lib);
@@ -1435,6 +1436,7 @@
// Load the library.
Dart_Handle lib = Dart_LoadLibrary(NewString("dart_lib"),
+ Dart_Null(),
NewString(kScriptChars),
0, 0);
EXPECT_VALID(lib);
@@ -1610,6 +1612,7 @@
// Load the library.
Dart_Handle import_lib = Dart_LoadLibrary(NewString("dart_import_lib"),
+ Dart_Null(),
NewString(kLibScriptChars),
0, 0);
EXPECT_VALID(import_lib);
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 522974e..9c89d9c 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -81,14 +81,27 @@
}
+const char* kDefaultImportableTestLibScript =
+ "importedFunc() => 'a';\n"
+ "importedIntFunc() => 4;\n"
+ "class ImportedMixin {\n"
+ " mixinFunc() => 'mixin';\n"
+ "}\n";
+const char* importable_test_lib_script = kDefaultImportableTestLibScript;
+
+
+void TestCase::SetImportableTestLibScript(const char* source) {
+ importable_test_lib_script = source;
+}
+
+
+void TestCase::RestoreImportableTestLibScript() {
+ importable_test_lib_script = kDefaultImportableTestLibScript;
+}
+
+
static Dart_Handle ImportableTestLibSource() {
- const char* kScript =
- "importedFunc() => 'a';\n"
- "importedIntFunc() => 4;\n"
- "class ImportedMixin {\n"
- " mixinFunc() => 'mixin';\n"
- "}\n";
- return DartUtils::NewString(kScript);
+ return DartUtils::NewString(importable_test_lib_script);
}
@@ -155,6 +168,7 @@
ASSERT(script_source != NULL);
OSThread::SetThreadLocal(script_reload_key, 0);
return Dart_LoadScript(url,
+ Dart_Null(),
NewString(script_source),
0,
0);
@@ -191,12 +205,12 @@
}
}
if (IsImportableTestLib(url_chars)) {
- return Dart_LoadLibrary(url, ImportableTestLibSource(), 0, 0);
+ return Dart_LoadLibrary(url, Dart_Null(), ImportableTestLibSource(), 0, 0);
}
NOT_IN_PRODUCT(
if (IsIsolateReloadTestLib(url_chars)) {
Dart_Handle library =
- Dart_LoadLibrary(url, IsolateReloadTestLibSource(), 0, 0);
+ Dart_LoadLibrary(url, Dart_Null(), IsolateReloadTestLibSource(), 0, 0);
DART_CHECK_VALID(library);
Dart_SetNativeResolver(library, IsolateReloadTestNativeResolver, 0);
return library;
@@ -204,28 +218,28 @@
if (is_io_library) {
ASSERT(tag == Dart_kSourceTag);
return Dart_LoadSource(library,
- url,
+ url, Dart_Null(),
Builtin::PartSource(Builtin::kIOLibrary,
url_chars),
0, 0);
}
+ Dart_Handle resolved_url = url;
+ const char* resolved_url_chars = url_chars;
if (IsPackageSchemeURL(url_chars)) {
- Dart_Handle resolved_uri = ResolvePackageUri(url_chars);
- DART_CHECK_VALID(resolved_uri);
- url_chars = NULL;
- Dart_Handle result = Dart_StringToCString(resolved_uri, &url_chars);
- if (Dart_IsError(result)) {
- return Dart_NewApiError("accessing url characters failed");
+ resolved_url = ResolvePackageUri(url_chars);
+ DART_CHECK_VALID(resolved_url);
+ if (Dart_IsError(Dart_StringToCString(resolved_url, &resolved_url_chars))) {
+ return Dart_NewApiError("unable to convert resolved uri to string");
}
}
// Do sync loading since unit_test doesn't support async.
- Dart_Handle source = DartUtils::ReadStringFromFile(url_chars);
+ Dart_Handle source = DartUtils::ReadStringFromFile(resolved_url_chars);
EXPECT_VALID(source);
if (tag == Dart_kImportTag) {
- return Dart_LoadLibrary(url, source, 0, 0);
+ return Dart_LoadLibrary(url, resolved_url, source, 0, 0);
} else {
ASSERT(tag == Dart_kSourceTag);
- return Dart_LoadSource(library, url, source, 0, 0);
+ return Dart_LoadSource(library, url, resolved_url, source, 0, 0);
}
}
@@ -238,7 +252,7 @@
Dart_Handle source = NewString(script);
Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler);
EXPECT_VALID(result);
- Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
+ Dart_Handle lib = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
DART_CHECK_VALID(lib);
result = Dart_SetNativeResolver(lib, resolver, NULL);
DART_CHECK_VALID(result);
@@ -269,7 +283,8 @@
{
TransitionNativeToVM transition(Thread::Current());
- isolate->ReloadSources(/* dont_delete_reload_context = */ true);
+ isolate->ReloadSources(false, // force_reload
+ true); // dont_delete_reload_context
}
return Dart_FinalizeLoading(false);
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index ac7645a..5a72dbb 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -314,6 +314,10 @@
// Helper function which reloads the current isolate using |script|.
static Dart_Handle ReloadTestScript(const char* script);
+ // Changes the default importable test lib script.
+ static void SetImportableTestLibScript(const char* source);
+ static void RestoreImportableTestLibScript();
+
private:
static Dart_Isolate CreateIsolate(const uint8_t* buffer, const char* name);
diff --git a/runtime/vm/virtual_memory_fuchsia.cc b/runtime/vm/virtual_memory_fuchsia.cc
index 933f494..6e7d439 100644
--- a/runtime/vm/virtual_memory_fuchsia.cc
+++ b/runtime/vm/virtual_memory_fuchsia.cc
@@ -68,7 +68,8 @@
bool VirtualMemory::FreeSubSegment(void* address, intptr_t size) {
- UNIMPLEMENTED();
+ // TODO(zra): It should be possible to free a subsegment after
+ // Issue MG-162 is addressed.
return false;
}
diff --git a/tools/VERSION b/tools/VERSION
index 2092cfe..59e58d0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 1
MINOR 19
PATCH 0
-PRERELEASE 1
+PRERELEASE 2
PRERELEASE_PATCH 0
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 19f4e04..b73f612 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -9,7 +9,7 @@
vars.update({
"dartium_chromium_commit": "67a7ba9669f7bb0300ef35085d4e6bb98b1966cc",
- "dartium_webkit_commit": "241a4a90dd2aa42490243c2efcc8732ff8aa0a59",
+ "dartium_webkit_commit": "bfb8649f69c7b02100aa6fd5a9c77d7858106d1b",
"chromium_base_revision": "338390",
# We use mirrors of all github repos to guarantee reproducibility and