mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:19:47 +00:00
[VM] [CFE]: Make VM send over type information for expression compilation
Missing: * Function types. * Type variables in bounds, like "method<T, S extends T>() {}" and "method<T extends Foo<T>>() {}" This is in many ways a follow-up to https://dart-review.googlesource.com/c/sdk/+/212286 TEST=service and (cfe) expression suite tests added. Change-Id: I20472b59ed73e9845f073e176d73b2c213f9407a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215760 Reviewed-by: Johnni Winther <johnniwinther@google.com> Reviewed-by: Ben Konyi <bkonyi@google.com> Commit-Queue: Jens Johansen <jensj@google.com>
This commit is contained in:
parent
c49ccf09f1
commit
adb1dc9380
|
@ -0,0 +1,213 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
|
||||
show isLegalIdentifier;
|
||||
|
||||
import 'package:front_end/src/api_prototype/lowering_predicates.dart'
|
||||
show isExtensionThisName;
|
||||
|
||||
import 'package:kernel/ast.dart'
|
||||
show
|
||||
Class,
|
||||
DartType,
|
||||
DynamicType,
|
||||
InterfaceType,
|
||||
Library,
|
||||
Nullability,
|
||||
TypeParameter;
|
||||
|
||||
import 'package:kernel/library_index.dart' show LibraryIndex;
|
||||
|
||||
Map<String, DartType>? createDefinitionsWithTypes(
|
||||
Iterable<Library>? knownLibraries,
|
||||
List<String> definitionTypes,
|
||||
List<String> definitions) {
|
||||
if (knownLibraries == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ParsedType> definitionTypesParsed =
|
||||
parseDefinitionTypes(definitionTypes);
|
||||
if (definitionTypesParsed.length != definitions.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<String> libraryUris = collectParsedTypeUris(definitionTypesParsed);
|
||||
LibraryIndex libraryIndex =
|
||||
new LibraryIndex.fromLibraries(knownLibraries, libraryUris);
|
||||
|
||||
Map<String, DartType> completeDefinitions = {};
|
||||
for (int i = 0; i < definitions.length; i++) {
|
||||
String name = definitions[i];
|
||||
if (isLegalIdentifier(name) || (i == 0 && isExtensionThisName(name))) {
|
||||
ParsedType type = definitionTypesParsed[i];
|
||||
DartType dartType = type.createDartType(libraryIndex);
|
||||
completeDefinitions[name] = dartType;
|
||||
}
|
||||
}
|
||||
return completeDefinitions;
|
||||
}
|
||||
|
||||
List<TypeParameter>? createTypeParametersWithBounds(
|
||||
Iterable<Library>? knownLibraries,
|
||||
List<String> typeBounds,
|
||||
List<String> typeDefaults,
|
||||
List<String> typeDefinitions) {
|
||||
if (knownLibraries == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ParsedType> typeBoundsParsed = parseDefinitionTypes(typeBounds);
|
||||
if (typeBoundsParsed.length != typeDefinitions.length) {
|
||||
return null;
|
||||
}
|
||||
List<ParsedType> typeDefaultsParsed = parseDefinitionTypes(typeDefaults);
|
||||
if (typeDefaultsParsed.length != typeDefinitions.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<String> libraryUris = collectParsedTypeUris(typeBoundsParsed)
|
||||
..addAll(collectParsedTypeUris(typeDefaultsParsed));
|
||||
LibraryIndex libraryIndex =
|
||||
new LibraryIndex.fromLibraries(knownLibraries, libraryUris);
|
||||
|
||||
List<TypeParameter> typeParameters = [];
|
||||
for (int i = 0; i < typeDefinitions.length; i++) {
|
||||
String name = typeDefinitions[i];
|
||||
if (!isLegalIdentifier(name)) continue;
|
||||
ParsedType bound = typeBoundsParsed[i];
|
||||
DartType dartTypeBound = bound.createDartType(libraryIndex);
|
||||
ParsedType defaultType = typeDefaultsParsed[i];
|
||||
DartType dartTypeDefaultType = defaultType.createDartType(libraryIndex);
|
||||
typeParameters
|
||||
.add(new TypeParameter(name, dartTypeBound, dartTypeDefaultType));
|
||||
}
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
List<ParsedType> parseDefinitionTypes(List<String> definitionTypes) {
|
||||
List<ParsedType> result = [];
|
||||
int i = 0;
|
||||
List<ParsedType> argumentReceivers = [];
|
||||
while (i < definitionTypes.length) {
|
||||
String uriOrNullString = definitionTypes[i];
|
||||
if (uriOrNullString == "null") {
|
||||
if (argumentReceivers.isEmpty) {
|
||||
result.add(new ParsedType.nullType());
|
||||
} else {
|
||||
argumentReceivers
|
||||
.removeLast()
|
||||
.arguments!
|
||||
.add(new ParsedType.nullType());
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
} else {
|
||||
// We expect at least 4 elements: Uri, class name, nullability,
|
||||
// number of type arguments.
|
||||
if (i + 4 > definitionTypes.length) throw "invalid input";
|
||||
String className = definitionTypes[i + 1];
|
||||
int nullability = int.parse(definitionTypes[i + 2]);
|
||||
int typeArgumentsCount = int.parse(definitionTypes[i + 3]);
|
||||
ParsedType type = new ParsedType(uriOrNullString, className, nullability);
|
||||
if (argumentReceivers.isEmpty) {
|
||||
result.add(type);
|
||||
} else {
|
||||
argumentReceivers.removeLast().arguments!.add(type);
|
||||
}
|
||||
for (int j = 0; j < typeArgumentsCount; j++) {
|
||||
argumentReceivers.add(type);
|
||||
}
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
if (argumentReceivers.isNotEmpty) {
|
||||
throw "Nesting error on input $definitionTypes";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class ParsedType {
|
||||
final String? uri;
|
||||
final String? className;
|
||||
final int? nullability;
|
||||
final List<ParsedType>? arguments;
|
||||
|
||||
bool get isNullType => uri == null;
|
||||
|
||||
ParsedType(this.uri, this.className, this.nullability) : arguments = [];
|
||||
|
||||
ParsedType.nullType()
|
||||
: uri = null,
|
||||
className = null,
|
||||
nullability = null,
|
||||
arguments = null;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other is! ParsedType) return false;
|
||||
if (uri != other.uri) return false;
|
||||
if (className != other.className) return false;
|
||||
if (nullability != other.nullability) return false;
|
||||
if (arguments?.length != other.arguments?.length) return false;
|
||||
if (arguments != null) {
|
||||
for (int i = 0; i < arguments!.length; i++) {
|
||||
if (arguments![i] != other.arguments![i]) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
if (isNullType) return 0;
|
||||
int hash = 0x3fffffff & uri.hashCode;
|
||||
hash = 0x3fffffff & (hash * 31 + (hash ^ className.hashCode));
|
||||
hash = 0x3fffffff & (hash * 31 + (hash ^ nullability.hashCode));
|
||||
for (ParsedType argument in arguments!) {
|
||||
hash = 0x3fffffff & (hash * 31 + (hash ^ argument.hashCode));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
if (isNullType) return "null-type";
|
||||
return "$uri[$className] ($nullability) <$arguments>";
|
||||
}
|
||||
|
||||
DartType createDartType(LibraryIndex libraryIndex) {
|
||||
if (isNullType) return new DynamicType();
|
||||
Class? classNode = libraryIndex.tryGetClass(uri!, className!);
|
||||
if (classNode == null) return new DynamicType();
|
||||
|
||||
return new InterfaceType(
|
||||
classNode,
|
||||
_getDartNullability(),
|
||||
arguments
|
||||
?.map((e) => e.createDartType(libraryIndex))
|
||||
.toList(growable: false));
|
||||
}
|
||||
|
||||
Nullability _getDartNullability() {
|
||||
if (isNullType) throw "No nullability on the null type";
|
||||
if (nullability == 0) return Nullability.nullable;
|
||||
if (nullability == 1) return Nullability.nonNullable;
|
||||
if (nullability == 2) return Nullability.legacy;
|
||||
throw "Unknown nullability";
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> collectParsedTypeUris(List<ParsedType> parsedTypes) {
|
||||
Set<String> result = {};
|
||||
List<ParsedType> workList = new List.from(parsedTypes);
|
||||
while (workList.isNotEmpty) {
|
||||
ParsedType type = workList.removeLast();
|
||||
if (type.isNullType) continue;
|
||||
result.add(type.uri!);
|
||||
workList.addAll(type.arguments!);
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -18,6 +18,9 @@ export '../api_prototype/compiler_options.dart'
|
|||
export '../api_prototype/experimental_flags.dart'
|
||||
show defaultExperimentalFlags, ExperimentalFlag;
|
||||
|
||||
export '../api_prototype/expression_compilation_tools.dart'
|
||||
show createDefinitionsWithTypes, createTypeParametersWithBounds;
|
||||
|
||||
export '../api_prototype/file_system.dart'
|
||||
show FileSystem, FileSystemEntity, FileSystemException;
|
||||
|
||||
|
|
135
pkg/front_end/test/expression_compilation_tools_test.dart
Normal file
135
pkg/front_end/test/expression_compilation_tools_test.dart
Normal file
|
@ -0,0 +1,135 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:expect/minitest.dart';
|
||||
|
||||
import 'package:front_end/src/api_prototype/expression_compilation_tools.dart';
|
||||
|
||||
void main() {
|
||||
// null value.
|
||||
expect(parseDefinitionTypes(["null"]), [new ParsedType.nullType()]);
|
||||
|
||||
// String, kNonNullable
|
||||
expect(
|
||||
parseDefinitionTypes([
|
||||
"dart:core",
|
||||
"_OneByteString",
|
||||
"1",
|
||||
"0",
|
||||
]),
|
||||
[new ParsedType("dart:core", "_OneByteString", 1)]);
|
||||
|
||||
// List<something it can't represent which thus becomes an explicit
|
||||
// dynamic/null>, kNonNullable.
|
||||
expect(parseDefinitionTypes(["dart:core", "List", "1", "1", "null"]), [
|
||||
new ParsedType("dart:core", "List", 1)
|
||||
..arguments!.add(new ParsedType.nullType())
|
||||
]);
|
||||
|
||||
// List<int>, kNonNullable
|
||||
expect(
|
||||
parseDefinitionTypes([
|
||||
"dart:core",
|
||||
"_GrowableList",
|
||||
"1",
|
||||
"1",
|
||||
"dart:core",
|
||||
"int",
|
||||
"1",
|
||||
"0",
|
||||
]),
|
||||
[
|
||||
new ParsedType("dart:core", "_GrowableList", 1)
|
||||
..arguments!.add(new ParsedType("dart:core", "int", 1))
|
||||
]);
|
||||
|
||||
// Map<int, int>, kNonNullable
|
||||
expect(
|
||||
parseDefinitionTypes([
|
||||
"dart:core",
|
||||
"Map",
|
||||
"1",
|
||||
"2",
|
||||
"dart:core",
|
||||
"int",
|
||||
"1",
|
||||
"0",
|
||||
"dart:core",
|
||||
"int",
|
||||
"1",
|
||||
"0",
|
||||
]),
|
||||
[
|
||||
new ParsedType("dart:core", "Map", 1)
|
||||
..arguments!.add(new ParsedType("dart:core", "int", 1))
|
||||
..arguments!.add(new ParsedType("dart:core", "int", 1))
|
||||
]);
|
||||
|
||||
// [0] = String
|
||||
// [1] = int
|
||||
// [2] = List<String>
|
||||
// [3] = Bar
|
||||
// [4] = null
|
||||
// [5] = HashMap<Map<int, List<int>>, List<String>>
|
||||
expect(
|
||||
parseDefinitionTypes([
|
||||
// String, kNonNullable, no arguments
|
||||
"dart:core", "_OneByteString", "1", "0",
|
||||
// Int, kNonNullable, no arguments
|
||||
"dart:core", "_Smi", "1", "0",
|
||||
// List, kNonNullable, 1 argument
|
||||
"dart:core", "_GrowableList", "1", "1",
|
||||
// -> String, kNonNullable (i.e. the above is List<String>)
|
||||
/**/ "dart:core", "String", "1", "0",
|
||||
// "Bar", kNonNullable, no arguments
|
||||
"file://wherever/t.dart", "Bar", "1", "0",
|
||||
// null value
|
||||
"null",
|
||||
// HashMap, kNonNullable, 2 arguments
|
||||
"dart:collection", "_InternalLinkedHashMap", "1", "2",
|
||||
// -> Map, kNonNullable, 2 arguments
|
||||
/**/ "dart:core", "Map", "1", "2",
|
||||
// -> -> int, kNonNullable, no arguments
|
||||
/*/**/*/ "dart:core", "int", "1", "0",
|
||||
// -> -> List, kNonNullable, 1 argument
|
||||
/*/**/*/ "dart:core", "List", "1", "1",
|
||||
// -> -> -> int, kNonNullable, no arguments
|
||||
/*/*/**/*/*/ "dart:core", "int", "1", "0",
|
||||
// -> List, kNonNullable, 1 argument
|
||||
"dart:core", "List", "1", "1",
|
||||
// -> -> String, kNonNullable, no arguments
|
||||
"dart:core", "String", "1", "0"
|
||||
]),
|
||||
<ParsedType>[
|
||||
// String
|
||||
new ParsedType("dart:core", "_OneByteString", 1),
|
||||
// int
|
||||
new ParsedType("dart:core", "_Smi", 1),
|
||||
// List<String>
|
||||
new ParsedType("dart:core", "_GrowableList", 1)
|
||||
..arguments!.addAll([
|
||||
new ParsedType("dart:core", "String", 1),
|
||||
]),
|
||||
// Bar
|
||||
new ParsedType("file://wherever/t.dart", "Bar", 1),
|
||||
// null value
|
||||
new ParsedType.nullType(),
|
||||
// HashMap<Map<int, List<int>>, List<String>>
|
||||
new ParsedType("dart:collection", "_InternalLinkedHashMap", 1)
|
||||
..arguments!.addAll([
|
||||
new ParsedType("dart:core", "Map", 1)
|
||||
..arguments!.addAll([
|
||||
new ParsedType("dart:core", "int", 1),
|
||||
new ParsedType("dart:core", "List", 1)
|
||||
..arguments!.addAll([
|
||||
new ParsedType("dart:core", "int", 1),
|
||||
]),
|
||||
]),
|
||||
new ParsedType("dart:core", "List", 1)
|
||||
..arguments!.addAll([
|
||||
new ParsedType("dart:core", "String", 1),
|
||||
]),
|
||||
]),
|
||||
]);
|
||||
}
|
|
@ -16,6 +16,12 @@ import "package:front_end/src/api_prototype/compiler_options.dart"
|
|||
show CompilerOptions, DiagnosticMessage;
|
||||
import 'package:front_end/src/api_prototype/experimental_flags.dart';
|
||||
|
||||
import 'package:front_end/src/api_prototype/expression_compilation_tools.dart'
|
||||
show createDefinitionsWithTypes, createTypeParametersWithBounds;
|
||||
|
||||
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
|
||||
show IncrementalCompilerResult;
|
||||
|
||||
import "package:front_end/src/api_prototype/memory_file_system.dart"
|
||||
show MemoryFileSystem;
|
||||
|
||||
|
@ -34,7 +40,7 @@ import 'package:front_end/src/fasta/incremental_compiler.dart'
|
|||
show IncrementalCompiler;
|
||||
|
||||
import "package:kernel/ast.dart"
|
||||
show Procedure, Component, DynamicType, DartType, TypeParameter;
|
||||
show Component, DartType, DynamicType, Procedure, TypeParameter;
|
||||
|
||||
import 'package:kernel/target/targets.dart' show TargetFlags;
|
||||
|
||||
|
@ -132,8 +138,14 @@ class TestCase {
|
|||
|
||||
final List<String> definitions;
|
||||
|
||||
final List<String> definitionTypes;
|
||||
|
||||
final List<String> typeDefinitions;
|
||||
|
||||
final List<String> typeBounds;
|
||||
|
||||
final List<String> typeDefaults;
|
||||
|
||||
final bool isStaticMethod;
|
||||
|
||||
final Uri? library;
|
||||
|
@ -151,7 +163,10 @@ class TestCase {
|
|||
this.entryPoint,
|
||||
this.import,
|
||||
this.definitions,
|
||||
this.definitionTypes,
|
||||
this.typeDefinitions,
|
||||
this.typeBounds,
|
||||
this.typeDefaults,
|
||||
this.isStaticMethod,
|
||||
this.library,
|
||||
this.className,
|
||||
|
@ -164,7 +179,10 @@ class TestCase {
|
|||
"$entryPoint, "
|
||||
"$import, "
|
||||
"$definitions, "
|
||||
"$definitionTypes, "
|
||||
"$typeDefinitions,"
|
||||
"$typeBounds,"
|
||||
"$typeDefaults,"
|
||||
"$library, "
|
||||
"$className, "
|
||||
"static = $isStaticMethod)";
|
||||
|
@ -259,7 +277,10 @@ class ReadTest extends Step<TestDescription, List<TestCase>, Context> {
|
|||
Uri? entryPoint;
|
||||
Uri? import;
|
||||
List<String> definitions = <String>[];
|
||||
List<String> definitionTypes = <String>[];
|
||||
List<String> typeDefinitions = <String>[];
|
||||
List<String> typeBounds = <String>[];
|
||||
List<String> typeDefaults = <String>[];
|
||||
bool isStaticMethod = false;
|
||||
Uri? library;
|
||||
String? className;
|
||||
|
@ -289,9 +310,16 @@ class ReadTest extends Step<TestDescription, List<TestCase>, Context> {
|
|||
methodName = value as String;
|
||||
} else if (key == "definitions") {
|
||||
definitions = (value as YamlList).map((x) => x as String).toList();
|
||||
} else if (key == "definition_types") {
|
||||
definitionTypes =
|
||||
(value as YamlList).map((x) => x as String).toList();
|
||||
} else if (key == "type_definitions") {
|
||||
typeDefinitions =
|
||||
(value as YamlList).map((x) => x as String).toList();
|
||||
} else if (key == "type_bounds") {
|
||||
typeBounds = (value as YamlList).map((x) => x as String).toList();
|
||||
} else if (key == "type_defaults") {
|
||||
typeDefaults = (value as YamlList).map((x) => x as String).toList();
|
||||
} else if (key == "static") {
|
||||
isStaticMethod = value;
|
||||
} else if (key == "expression") {
|
||||
|
@ -303,7 +331,10 @@ class ReadTest extends Step<TestDescription, List<TestCase>, Context> {
|
|||
entryPoint,
|
||||
import,
|
||||
definitions,
|
||||
definitionTypes,
|
||||
typeDefinitions,
|
||||
typeBounds,
|
||||
typeDefaults,
|
||||
isStaticMethod,
|
||||
library,
|
||||
className,
|
||||
|
@ -328,15 +359,29 @@ class CompileExpression extends Step<List<TestCase>, List<TestCase>, Context> {
|
|||
// Compile [test.expression], update [test.errors] with results.
|
||||
// As a side effect - verify that generated procedure can be serialized.
|
||||
Future<void> compileExpression(TestCase test, IncrementalCompiler compiler,
|
||||
Component component, Context context) async {
|
||||
Map<String, DartType> definitions = {};
|
||||
for (String name in test.definitions) {
|
||||
definitions[name] = new DynamicType();
|
||||
IncrementalCompilerResult sourceCompilerResult, Context context) async {
|
||||
Map<String, DartType>? definitions = createDefinitionsWithTypes(
|
||||
sourceCompilerResult.classHierarchy?.knownLibraries,
|
||||
test.definitionTypes,
|
||||
test.definitions);
|
||||
|
||||
if (definitions == null) {
|
||||
definitions = {};
|
||||
for (String name in test.definitions) {
|
||||
definitions[name] = new DynamicType();
|
||||
}
|
||||
}
|
||||
List<TypeParameter> typeParams = [];
|
||||
for (String name in test.typeDefinitions) {
|
||||
typeParams
|
||||
.add(new TypeParameter(name, new DynamicType(), new DynamicType()));
|
||||
List<TypeParameter>? typeParams = createTypeParametersWithBounds(
|
||||
sourceCompilerResult.classHierarchy?.knownLibraries,
|
||||
test.typeBounds,
|
||||
test.typeDefaults,
|
||||
test.typeDefinitions);
|
||||
if (typeParams == null) {
|
||||
typeParams = [];
|
||||
for (String name in test.typeDefinitions) {
|
||||
typeParams
|
||||
.add(new TypeParameter(name, new DynamicType(), new DynamicType()));
|
||||
}
|
||||
}
|
||||
|
||||
Procedure? compiledProcedure = await compiler.compileExpression(
|
||||
|
@ -353,7 +398,7 @@ class CompileExpression extends Step<List<TestCase>, List<TestCase>, Context> {
|
|||
test.results.add(new CompilationResult(compiledProcedure, errors));
|
||||
if (compiledProcedure != null) {
|
||||
// Confirm we can serialize generated procedure.
|
||||
component.computeCanonicalNames();
|
||||
sourceCompilerResult.component.computeCanonicalNames();
|
||||
List<int> list = serializeProcedure(compiledProcedure);
|
||||
assert(list.length > 0);
|
||||
}
|
||||
|
@ -371,8 +416,9 @@ class CompileExpression extends Step<List<TestCase>, List<TestCase>, Context> {
|
|||
await new File.fromUri(test.import!).readAsBytes());
|
||||
}
|
||||
|
||||
var sourceCompiler = new IncrementalCompiler(context.compilerContext);
|
||||
var sourceCompilerResult =
|
||||
IncrementalCompiler sourceCompiler =
|
||||
new IncrementalCompiler(context.compilerContext);
|
||||
IncrementalCompilerResult sourceCompilerResult =
|
||||
await sourceCompiler.computeDelta(entryPoints: [test.entryPoint!]);
|
||||
Component component = sourceCompilerResult.component;
|
||||
var errors = context.takeErrors();
|
||||
|
@ -387,11 +433,12 @@ class CompileExpression extends Step<List<TestCase>, List<TestCase>, Context> {
|
|||
path: test.entryPoint!.path + ".dill");
|
||||
Uint8List dillData = await serializeComponent(component);
|
||||
context.fileSystem.entityForUri(dillFileUri).writeAsBytesSync(dillData);
|
||||
await compileExpression(test, sourceCompiler, component, context);
|
||||
await compileExpression(
|
||||
test, sourceCompiler, sourceCompilerResult, context);
|
||||
|
||||
var dillCompiler =
|
||||
IncrementalCompiler dillCompiler =
|
||||
new IncrementalCompiler(context.compilerContext, dillFileUri);
|
||||
var dillCompilerResult =
|
||||
IncrementalCompilerResult dillCompilerResult =
|
||||
await dillCompiler.computeDelta(entryPoints: [test.entryPoint!]);
|
||||
component = dillCompilerResult.component;
|
||||
component.computeCanonicalNames();
|
||||
|
@ -400,7 +447,7 @@ class CompileExpression extends Step<List<TestCase>, List<TestCase>, Context> {
|
|||
// Since it compiled successfully from source, the bootstrap-from-Dill
|
||||
// should also succeed without errors.
|
||||
assert(errors.isEmpty);
|
||||
await compileExpression(test, dillCompiler, component, context);
|
||||
await compileExpression(test, dillCompiler, dillCompilerResult, context);
|
||||
}
|
||||
return new Result.pass(tests);
|
||||
}
|
||||
|
|
|
@ -398,6 +398,7 @@ micro
|
|||
minimize
|
||||
minimizer
|
||||
minimizing
|
||||
minitest
|
||||
minst
|
||||
mintty
|
||||
minutes
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
entry_point: "main.dart"
|
||||
definitions: ["x"]
|
||||
# List<String>
|
||||
definition_types: ["dart:core", "List", "1", "1", "dart:core", "String", "1", "0"]
|
||||
type_definitions: [""]
|
||||
type_bounds: []
|
||||
type_defaults: []
|
||||
position: "main.dart"
|
||||
method: "hasList"
|
||||
# x is List<String> with entries, so x.first is String, String has extension
|
||||
# with method getFortyTwo.
|
||||
expression: |
|
||||
x.first.getFortyTwo()
|
|
@ -0,0 +1,4 @@
|
|||
Errors: {
|
||||
}
|
||||
method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr< extends dynamic>(dart.core::List<dart.core::String> x) → dynamic
|
||||
return main::Foo|getFortyTwo(x.{dart.core::Iterable::first}{dart.core::String*});
|
|
@ -0,0 +1,16 @@
|
|||
# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
entry_point: "main.dart"
|
||||
definitions: ["x", "y"]
|
||||
# List<String>, int
|
||||
definition_types: ["dart:core", "List", "1", "1", "dart:core", "String", "1", "0", "dart:core", "int", "1", "0"]
|
||||
type_definitions: []
|
||||
type_bounds: []
|
||||
type_defaults: []
|
||||
position: "main.dart"
|
||||
method: "hasList"
|
||||
# Because x has a type (List<String>) x.fold knows that element is a String.
|
||||
expression: |
|
||||
x.fold<int>(0, (previousValue, element) => previousValue + element.length)
|
|
@ -0,0 +1,4 @@
|
|||
Errors: {
|
||||
}
|
||||
method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr(dart.core::List<dart.core::String> x, dart.core::int y) → dynamic
|
||||
return x.{dart.core::Iterable::fold}<dart.core::int*>(0, (dart.core::int* previousValue, dart.core::String* element) → dart.core::int* => previousValue.{dart.core::num::+}(element.{dart.core::String::length}{dart.core::int*}){(dart.core::num*) →* dart.core::int*}){(dart.core::int*, (dart.core::int*, dart.core::String*) →* dart.core::int*) →* dart.core::int*};
|
|
@ -100,3 +100,30 @@ class E<T> {
|
|||
T _t;
|
||||
T get t => _t;
|
||||
}
|
||||
|
||||
void withBound<E extends String>(List<E> x) {
|
||||
List<E> y = [];
|
||||
List<String> z = [];
|
||||
z.addAll(y);
|
||||
}
|
||||
|
||||
void withBound2<E>() {
|
||||
print(E);
|
||||
}
|
||||
|
||||
void hasList() {
|
||||
List<String> x = ["a", "b", "c"];
|
||||
int xCombinedLength = x.fold<int>(
|
||||
0, (previousValue, element) => previousValue + element.length);
|
||||
print("xCombinedLength = $xCombinedLength");
|
||||
}
|
||||
|
||||
void hasClosure() {
|
||||
List<String> x() {
|
||||
return ["hello"];
|
||||
}
|
||||
|
||||
int xCombinedLength = x()
|
||||
.fold<int>(0, (previousValue, element) => previousValue + element.length);
|
||||
print("xCombinedLength = $xCombinedLength");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
entry_point: "main.dart"
|
||||
definitions: ["x"]
|
||||
# _Closure --- note that this is not what the VM sends (anymore).
|
||||
definition_types: ["dart:core", "_Closure", "1", "0"]
|
||||
type_definitions: []
|
||||
type_bounds: []
|
||||
type_defaults: []
|
||||
position: "main.dart"
|
||||
method: "hasClosure"
|
||||
expression: |
|
||||
x().fold<int>(0, (previousValue, element) => previousValue + element.length)
|
|
@ -0,0 +1,9 @@
|
|||
Errors: {
|
||||
org-dartlang-debug:synthetic_debug_expression:1:2: Error: Cannot invoke an instance of '_Closure' because it declares 'call' to be something other than a method.
|
||||
- '_Closure' is from 'dart:core'.
|
||||
Try changing 'call' to a method or explicitly invoke 'call'.
|
||||
x().fold<int>(0, (previousValue, element) => previousValue + element.length)
|
||||
^
|
||||
}
|
||||
method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr(dart.core::_Closure x) → dynamic
|
||||
return invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:2: Error: Cannot invoke an instance of '_Closure' because it declares 'call' to be something other than a method.\n - '_Closure' is from 'dart:core'.\nTry changing 'call' to a method or explicitly invoke 'call'.\nx().fold<int>(0, (previousValue, element) => previousValue + element.length)\n ^"{dynamic}.fold<dart.core::int*>(0, (dynamic previousValue, dynamic element) → dynamic => previousValue{dynamic}.+(element{dynamic}.length));
|
|
@ -0,0 +1,15 @@
|
|||
# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
entry_point: "main.dart"
|
||||
definitions: ["x"]
|
||||
# _Closure is send as null aka dynamic.
|
||||
definition_types: ["null"]
|
||||
type_definitions: []
|
||||
type_bounds: []
|
||||
type_defaults: []
|
||||
position: "main.dart"
|
||||
method: "hasClosure"
|
||||
expression: |
|
||||
x().fold<int>(0, (previousValue, element) => previousValue + element.length)
|
|
@ -0,0 +1,4 @@
|
|||
Errors: {
|
||||
}
|
||||
method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr(dynamic x) → dynamic
|
||||
return x{dynamic}.call(){dynamic}.fold<dart.core::int*>(0, (dynamic previousValue, dynamic element) → dynamic => previousValue{dynamic}.+(element{dynamic}.length));
|
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
entry_point: "main.dart"
|
||||
definitions: ["x"]
|
||||
# List<String>
|
||||
definition_types: ["dart:core", "List", "1", "1", "dart:core", "String", "1", "0"]
|
||||
type_definitions: ["E"]
|
||||
# String
|
||||
type_bounds: ["dart:core", "String", "1", "0"]
|
||||
# String
|
||||
type_defaults: ["dart:core", "String", "1", "0"]
|
||||
position: "main.dart"
|
||||
method: "withBound"
|
||||
# Can add List<E> to List<String> as E extends String.
|
||||
expression: |
|
||||
() { List<E> y = []; x.addAll(y); }()
|
|
@ -0,0 +1,7 @@
|
|||
Errors: {
|
||||
}
|
||||
method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr<E extends dart.core::String>(dart.core::List<dart.core::String> x) → dynamic
|
||||
return (() → Null {
|
||||
dart.core::List<#lib1::debugExpr::E*>* y = dart.core::_GrowableList::•<#lib1::debugExpr::E*>(0);
|
||||
x.{dart.core::List::addAll}(y){(dart.core::Iterable<dart.core::String*>*) →* void};
|
||||
})(){() →* Null};
|
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
entry_point: "main.dart"
|
||||
definitions: ["x"]
|
||||
# List<String>
|
||||
definition_types: ["dart:core", "List", "1", "1", "dart:core", "String", "1", "0"]
|
||||
type_definitions: ["E"]
|
||||
# String
|
||||
type_bounds: ["dart:core", "String", "1", "0"]
|
||||
# String
|
||||
type_defaults: ["dart:core", "String", "1", "0"]
|
||||
position: "main.dart"
|
||||
method: "withBound"
|
||||
# Can't add List<String> to List<E> :(
|
||||
expression: |
|
||||
() { List<E> y = []; y.addAll(x); }
|
|
@ -0,0 +1,12 @@
|
|||
Errors: {
|
||||
org-dartlang-debug:synthetic_debug_expression:1:31: Error: The argument type 'List<String>' can't be assigned to the parameter type 'Iterable<E>'.
|
||||
- 'List' is from 'dart:core'.
|
||||
- 'Iterable' is from 'dart:core'.
|
||||
() { List<E> y = []; y.addAll(x); }
|
||||
^
|
||||
}
|
||||
method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr<E extends dart.core::String>(dart.core::List<dart.core::String> x) → dynamic
|
||||
return () → Null {
|
||||
dart.core::List<#lib1::debugExpr::E*>* y = dart.core::_GrowableList::•<#lib1::debugExpr::E*>(0);
|
||||
y.{dart.core::List::addAll}(invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:31: Error: The argument type 'List<String>' can't be assigned to the parameter type 'Iterable<E>'.\n - 'List' is from 'dart:core'.\n - 'Iterable' is from 'dart:core'.\n() { List<E> y = []; y.addAll(x); }\n ^" in x as{TypeError} Never){(dart.core::Iterable<#lib1::debugExpr::E*>*) →* void};
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
entry_point: "main.dart"
|
||||
definitions: []
|
||||
definition_types: []
|
||||
type_definitions: ["E"]
|
||||
# Object?
|
||||
type_bounds: ["dart:core", "Object", "0", "0"]
|
||||
# null (because dynamic).
|
||||
type_defaults: ["null"]
|
||||
position: "main.dart"
|
||||
method: "withBound2"
|
||||
expression: |
|
||||
print(E)
|
|
@ -0,0 +1,4 @@
|
|||
Errors: {
|
||||
}
|
||||
method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr<E extends dart.core::Object? = dynamic>() → dynamic
|
||||
return dart.core::print(#lib1::debugExpr::E*);
|
|
@ -285,7 +285,10 @@ abstract class CompilerInterface {
|
|||
Future<Null> compileExpression(
|
||||
String expression,
|
||||
List<String> definitions,
|
||||
List<String> definitionTypes,
|
||||
List<String> typeDefinitions,
|
||||
List<String> typeBounds,
|
||||
List<String> typeDefaults,
|
||||
String libraryUri,
|
||||
String klass,
|
||||
String method,
|
||||
|
@ -840,15 +843,27 @@ class FrontendCompiler implements CompilerInterface {
|
|||
Future<Null> compileExpression(
|
||||
String expression,
|
||||
List<String> definitions,
|
||||
List<String> definitionTypes,
|
||||
List<String> typeDefinitions,
|
||||
List<String> typeBounds,
|
||||
List<String> typeDefaults,
|
||||
String libraryUri,
|
||||
String klass,
|
||||
String method,
|
||||
bool isStatic) async {
|
||||
final String boundaryKey = Uuid().generateV4();
|
||||
_outputStream.writeln('result $boundaryKey');
|
||||
Procedure procedure = await _generator.compileExpression(expression,
|
||||
definitions, typeDefinitions, libraryUri, klass, method, isStatic);
|
||||
Procedure procedure = await _generator.compileExpression(
|
||||
expression,
|
||||
definitions,
|
||||
definitionTypes,
|
||||
typeDefinitions,
|
||||
typeBounds,
|
||||
typeDefaults,
|
||||
libraryUri,
|
||||
klass,
|
||||
method,
|
||||
isStatic);
|
||||
if (procedure != null) {
|
||||
Component component = createExpressionEvaluationComponent(procedure);
|
||||
final IOSink sink = File(_kernelBinaryFilename).openWrite();
|
||||
|
@ -1127,7 +1142,10 @@ class _CompileExpressionRequest {
|
|||
// Note that FE will reject a compileExpression command by returning a null
|
||||
// procedure when defs or typeDefs include an illegal identifier.
|
||||
List<String> defs = <String>[];
|
||||
List<String> defTypes = <String>[];
|
||||
List<String> typeDefs = <String>[];
|
||||
List<String> typeBounds = <String>[];
|
||||
List<String> typeDefaults = <String>[];
|
||||
String library;
|
||||
String klass;
|
||||
String method;
|
||||
|
@ -1268,7 +1286,10 @@ StreamSubscription<String> listenAndCompile(CompilerInterface compiler,
|
|||
compiler.compileExpression(
|
||||
compileExpressionRequest.expression,
|
||||
compileExpressionRequest.defs,
|
||||
compileExpressionRequest.defTypes,
|
||||
compileExpressionRequest.typeDefs,
|
||||
compileExpressionRequest.typeBounds,
|
||||
compileExpressionRequest.typeDefaults,
|
||||
compileExpressionRequest.library,
|
||||
compileExpressionRequest.klass,
|
||||
compileExpressionRequest.method,
|
||||
|
|
|
@ -22,9 +22,14 @@ class LibraryIndex {
|
|||
final Map<String, _ClassTable> _libraries = <String, _ClassTable>{};
|
||||
|
||||
/// Indexes the libraries with the URIs given in [libraryUris].
|
||||
LibraryIndex(Component component, Iterable<String> libraryUris) {
|
||||
LibraryIndex(Component component, Iterable<String> libraryUris)
|
||||
: this.fromLibraries(component.libraries, libraryUris);
|
||||
|
||||
/// Indexes the libraries with the URIs given in [libraryUris].
|
||||
LibraryIndex.fromLibraries(
|
||||
Iterable<Library> libraries, Iterable<String> libraryUris) {
|
||||
Set<String> libraryUriSet = libraryUris.toSet();
|
||||
for (Library library in component.libraries) {
|
||||
for (Library library in libraries) {
|
||||
String uri = '${library.importUri}';
|
||||
if (libraryUriSet.contains(uri)) {
|
||||
_libraries[uri] = new _ClassTable(library);
|
||||
|
|
|
@ -500,16 +500,19 @@ Future _processExpressionCompilationRequest(request) async {
|
|||
final dynamic dart_platform_kernel = request[3];
|
||||
final String expression = request[4];
|
||||
final List<String> definitions = request[5].cast<String>();
|
||||
final List<String> typeDefinitions = request[6].cast<String>();
|
||||
final String libraryUri = request[7];
|
||||
final String? klass = request[8];
|
||||
final String? method = request[9];
|
||||
final bool isStatic = request[10];
|
||||
final List<List<int>> dillData = request[11].cast<List<int>>();
|
||||
final int blobLoadCount = request[12];
|
||||
final bool enableAsserts = request[13];
|
||||
final List<String> definitionTypes = request[6].cast<String>();
|
||||
final List<String> typeDefinitions = request[7].cast<String>();
|
||||
final List<String> typeBounds = request[8].cast<String>();
|
||||
final List<String> typeDefaults = request[9].cast<String>();
|
||||
final String libraryUri = request[10];
|
||||
final String? klass = request[11];
|
||||
final String? method = request[12];
|
||||
final bool isStatic = request[13];
|
||||
final List<List<int>> dillData = request[14].cast<List<int>>();
|
||||
final int blobLoadCount = request[15];
|
||||
final bool enableAsserts = request[16];
|
||||
final List<String>? experimentalFlags =
|
||||
request[14] != null ? request[14].cast<String>() : null;
|
||||
request[17] != null ? request[17].cast<String>() : null;
|
||||
|
||||
IncrementalCompilerWrapper? compiler = isolateCompilers[isolateGroupId];
|
||||
|
||||
|
@ -623,7 +626,10 @@ Future _processExpressionCompilationRequest(request) async {
|
|||
Procedure? procedure = await compiler.generator!.compileExpression(
|
||||
expression,
|
||||
definitions,
|
||||
definitionTypes,
|
||||
typeDefinitions,
|
||||
typeBounds,
|
||||
typeDefaults,
|
||||
libraryUri,
|
||||
klass,
|
||||
method,
|
||||
|
|
|
@ -194,23 +194,43 @@ class IncrementalCompiler {
|
|||
Future<Procedure?> compileExpression(
|
||||
String expression,
|
||||
List<String> definitions,
|
||||
List<String> definitionTypes,
|
||||
List<String> typeDefinitions,
|
||||
List<String> typeBounds,
|
||||
List<String> typeDefaults,
|
||||
String libraryUri,
|
||||
String? klass,
|
||||
String? method,
|
||||
bool isStatic) {
|
||||
Map<String, DartType> completeDefinitions = {};
|
||||
for (int i = 0; i < definitions.length; i++) {
|
||||
String name = definitions[i];
|
||||
if (isLegalIdentifier(name) || (i == 0 && isExtensionThisName(name))) {
|
||||
completeDefinitions[name] = new DynamicType();
|
||||
ClassHierarchy? classHierarchy =
|
||||
(_lastKnownGood ?? _combinePendingDeltas(false)).classHierarchy;
|
||||
Map<String, DartType>? completeDefinitions = createDefinitionsWithTypes(
|
||||
classHierarchy?.knownLibraries, definitionTypes, definitions);
|
||||
if (completeDefinitions == null) {
|
||||
completeDefinitions = {};
|
||||
// No class hierarchy or wasn't provided correct types.
|
||||
// Revert to old behaviour of setting everything to dynamic.
|
||||
for (int i = 0; i < definitions.length; i++) {
|
||||
String name = definitions[i];
|
||||
if (isLegalIdentifier(name) || (i == 0 && isExtensionThisName(name))) {
|
||||
completeDefinitions[name] = new DynamicType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<TypeParameter> typeParameters = [];
|
||||
for (String name in typeDefinitions) {
|
||||
if (!isLegalIdentifier(name)) continue;
|
||||
typeParameters.add(new TypeParameter(name, new DynamicType()));
|
||||
List<TypeParameter>? typeParameters = createTypeParametersWithBounds(
|
||||
classHierarchy?.knownLibraries,
|
||||
typeBounds,
|
||||
typeDefaults,
|
||||
typeDefinitions);
|
||||
if (typeParameters == null) {
|
||||
// No class hierarchy or wasn't provided correct types.
|
||||
// Revert to old behaviour of setting everything to dynamic.
|
||||
typeParameters = [];
|
||||
for (String name in typeDefinitions) {
|
||||
if (!isLegalIdentifier(name)) continue;
|
||||
typeParameters.add(new TypeParameter(name, new DynamicType()));
|
||||
}
|
||||
}
|
||||
|
||||
Uri library = Uri.parse(libraryUri);
|
||||
|
|
|
@ -115,14 +115,32 @@ main() {
|
|||
await compiler.compile();
|
||||
compiler.accept();
|
||||
{
|
||||
Procedure? procedure = await compiler.compileExpression('main',
|
||||
<String>[], <String>[], main.uri.toString(), null, null, true);
|
||||
Procedure? procedure = await compiler.compileExpression(
|
||||
'main',
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
main.uri.toString(),
|
||||
null,
|
||||
null,
|
||||
true);
|
||||
expect(procedure, isNotNull);
|
||||
expect(errorsReported, equals(0));
|
||||
}
|
||||
{
|
||||
Procedure? procedure = await compiler.compileExpression('main1',
|
||||
<String>[], <String>[], main.uri.toString(), null, null, true);
|
||||
Procedure? procedure = await compiler.compileExpression(
|
||||
'main1',
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
main.uri.toString(),
|
||||
null,
|
||||
null,
|
||||
true);
|
||||
expect(procedure, isNotNull);
|
||||
expect(errorsReported, equals(1));
|
||||
errorsReported = 0;
|
||||
|
@ -1038,8 +1056,17 @@ main() {
|
|||
}
|
||||
compiler.accept();
|
||||
{
|
||||
Procedure? procedure = await compiler.compileExpression('a', <String>[],
|
||||
<String>[], 'package:foo/bar.dart', 'A', null, true);
|
||||
Procedure? procedure = await compiler.compileExpression(
|
||||
'a',
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
'package:foo/bar.dart',
|
||||
'A',
|
||||
null,
|
||||
true);
|
||||
expect(procedure, isNotNull);
|
||||
}
|
||||
|
||||
|
@ -1055,8 +1082,17 @@ main() {
|
|||
}
|
||||
await compiler.reject();
|
||||
{
|
||||
Procedure? procedure = await compiler.compileExpression('a', <String>[],
|
||||
<String>[], 'package:foo/bar.dart', 'A', null, true);
|
||||
Procedure? procedure = await compiler.compileExpression(
|
||||
'a',
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
'package:foo/bar.dart',
|
||||
'A',
|
||||
null,
|
||||
true);
|
||||
expect(procedure, isNotNull);
|
||||
}
|
||||
});
|
||||
|
@ -1106,7 +1142,16 @@ main() {
|
|||
compiler.accept();
|
||||
{
|
||||
final Procedure procedure = (await compiler.compileExpression(
|
||||
'a', <String>[], <String>[], barUri.toString(), 'A', null, true))!;
|
||||
'a',
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
barUri.toString(),
|
||||
'A',
|
||||
null,
|
||||
true))!;
|
||||
// Verify that the expression only has links to the only bar we know
|
||||
// about.
|
||||
final LibraryReferenceCollector lrc = new LibraryReferenceCollector();
|
||||
|
@ -1153,7 +1198,16 @@ main() {
|
|||
}
|
||||
{
|
||||
final Procedure procedure = (await compiler.compileExpression(
|
||||
'a', <String>[], <String>[], barUri.toString(), 'A', null, true))!;
|
||||
'a',
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
<String>[],
|
||||
barUri.toString(),
|
||||
'A',
|
||||
null,
|
||||
true))!;
|
||||
// Verify that the expression only has links to the original bar.
|
||||
final LibraryReferenceCollector lrc = new LibraryReferenceCollector();
|
||||
procedure.accept(lrc);
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:developer';
|
||||
import 'package:observatory/models.dart' show InstanceKind;
|
||||
import 'package:observatory/service_io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'service_test_common.dart';
|
||||
import 'test_helper.dart';
|
||||
|
||||
void testFunction() {
|
||||
List<String> x = ["a", "b", "c"];
|
||||
int xCombinedLength = x.fold<int>(
|
||||
0, (previousValue, element) => previousValue + element.length);
|
||||
debugger();
|
||||
print("xCombinedLength = $xCombinedLength");
|
||||
}
|
||||
|
||||
var tests = <IsolateTest>[
|
||||
hasStoppedAtBreakpoint,
|
||||
(Isolate isolate) async {
|
||||
Instance result = await isolate.evalFrame(0, '''x.fold<int>(
|
||||
0, (previousValue, element) => previousValue + element.length)''')
|
||||
as Instance;
|
||||
expect(result.valueAsString, equals('3'));
|
||||
expect(result.kind, equals(InstanceKind.int));
|
||||
},
|
||||
];
|
||||
|
||||
main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:developer';
|
||||
import 'package:observatory/models.dart' show InstanceKind;
|
||||
import 'package:observatory/service_io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'service_test_common.dart';
|
||||
import 'test_helper.dart';
|
||||
|
||||
class A {}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
class C extends Object with ListMixin<C> implements List<C> {
|
||||
int length = 0;
|
||||
C operator [](int index) => throw UnimplementedError();
|
||||
void operator []=(int index, C value) {}
|
||||
}
|
||||
|
||||
void testFunction4<T4 extends List<T4>>() {
|
||||
debugger();
|
||||
print("T4 = $T4");
|
||||
}
|
||||
|
||||
void testFunction3<T3, S3 extends T3>() {
|
||||
debugger();
|
||||
print("T3 = $T3");
|
||||
print("S3 = $S3");
|
||||
}
|
||||
|
||||
void testFunction2<E extends String>(List<E> x) {
|
||||
debugger();
|
||||
print("x = $x");
|
||||
}
|
||||
|
||||
void testFunction() {
|
||||
testFunction2<String>(<String>["a", "b", "c"]);
|
||||
testFunction3<A, B>();
|
||||
testFunction4<C>();
|
||||
}
|
||||
|
||||
void fooxx<E extends String>(List<E> y) {
|
||||
List<E> x = new List<E>.from(["hello"]);
|
||||
}
|
||||
|
||||
var tests = <IsolateTest>[
|
||||
hasStoppedAtBreakpoint,
|
||||
(Isolate isolate) async {
|
||||
{
|
||||
// Can add List<E extends String> to List<String> directly.
|
||||
Instance result = await isolate.evalFrame(0, '''() {
|
||||
List<E> y = new List<E>.from(["hello"]);
|
||||
x.addAll(y);
|
||||
return x.last;
|
||||
}()''') as Instance;
|
||||
expect(result.valueAsString, equals("hello"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
}
|
||||
{
|
||||
// Can't add List<String> to List<E extends String> directly.
|
||||
DartError result = await isolate.evalFrame(0, '''() {
|
||||
List<E> y = [];
|
||||
y.addAll(x);
|
||||
return y.last;
|
||||
}()''') as DartError;
|
||||
expect(
|
||||
result.message,
|
||||
contains(
|
||||
"The argument type '_GrowableList<String>' can't be assigned "
|
||||
"to the parameter type 'Iterable<E>'"));
|
||||
}
|
||||
{
|
||||
// Can add List<String> to List<E extends String> via cast.
|
||||
Instance result = await isolate.evalFrame(0, '''() {
|
||||
List<E> y = [];
|
||||
y.addAll(x.cast());
|
||||
return y.toString();
|
||||
}()''') as Instance;
|
||||
// Notice how "hello" was added a few evaluations back.
|
||||
expect(result.valueAsString, equals("[a, b, c, hello]"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
}
|
||||
{
|
||||
// Can create List<String> from List<E extends String>.
|
||||
Instance result = await isolate.evalFrame(0, '''() {
|
||||
List<E> y = new List<E>.from(x);
|
||||
return y.toString();
|
||||
}()''') as Instance;
|
||||
// Notice how "hello" was added a few evaluations back.
|
||||
expect(result.valueAsString, equals("[a, b, c, hello]"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
}
|
||||
},
|
||||
resumeIsolate,
|
||||
(Isolate isolate) async {
|
||||
// This is just to make sure the VM doesn't crash.
|
||||
Instance result =
|
||||
await isolate.evalFrame(0, '''S3.toString()''') as Instance;
|
||||
expect(result.valueAsString, equals("B"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
},
|
||||
resumeIsolate,
|
||||
(Isolate isolate) async {
|
||||
// This is just to make sure the VM doesn't crash.
|
||||
Instance result =
|
||||
await isolate.evalFrame(0, '''T4.toString()''') as Instance;
|
||||
expect(result.valueAsString, equals("C"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
},
|
||||
];
|
||||
|
||||
main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:developer';
|
||||
import 'package:observatory/models.dart' show InstanceKind;
|
||||
import 'package:observatory/service_io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'service_test_common.dart';
|
||||
import 'test_helper.dart';
|
||||
|
||||
extension on String {
|
||||
String printAndReturnHello() {
|
||||
String response = "Hello from String '$this'";
|
||||
print(response);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
void testFunction() {
|
||||
String x = "hello";
|
||||
String value = x.printAndReturnHello();
|
||||
debugger();
|
||||
print("value = $value");
|
||||
}
|
||||
|
||||
var tests = <IsolateTest>[
|
||||
hasStoppedAtBreakpoint,
|
||||
(Isolate isolate) async {
|
||||
Instance result =
|
||||
await isolate.evalFrame(0, 'x.printAndReturnHello()') as Instance;
|
||||
expect(result.valueAsString, equals("Hello from String 'hello'"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
},
|
||||
];
|
||||
|
||||
main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
|
|
@ -95,6 +95,7 @@ evaluate_activation_in_method_class_test: SkipByDesign # Debugger is disabled in
|
|||
evaluate_activation_test: SkipByDesign
|
||||
evaluate_async_closure_test: SkipByDesign
|
||||
evaluate_class_type_parameters_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_fold_on_list_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_function_type_parameters_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_in_async_activation_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_in_async_star_activation_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
|
@ -102,6 +103,8 @@ evaluate_in_extension_method_test: SkipByDesign # Debugger is disabled in AOT mo
|
|||
evaluate_in_frame_rpc_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_in_frame_with_scope_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_in_sync_star_activation_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_type_arguments_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_type_with_extension_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_with_escaping_closure_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_with_scope_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
field_script_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:developer';
|
||||
import 'package:observatory_2/models.dart' show InstanceKind;
|
||||
import 'package:observatory_2/service_io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'service_test_common.dart';
|
||||
import 'test_helper.dart';
|
||||
|
||||
void testFunction() {
|
||||
List<String> x = ["a", "b", "c"];
|
||||
int xCombinedLength = x.fold<int>(
|
||||
0, (previousValue, element) => previousValue + element.length);
|
||||
debugger();
|
||||
print("xCombinedLength = $xCombinedLength");
|
||||
}
|
||||
|
||||
var tests = <IsolateTest>[
|
||||
hasStoppedAtBreakpoint,
|
||||
(Isolate isolate) async {
|
||||
Instance result = await isolate.evalFrame(0, '''x.fold<int>(
|
||||
0, (previousValue, element) => previousValue + element.length)''')
|
||||
as Instance;
|
||||
expect(result.valueAsString, equals('3'));
|
||||
expect(result.kind, equals(InstanceKind.int));
|
||||
},
|
||||
];
|
||||
|
||||
main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:developer';
|
||||
import 'package:observatory_2/models.dart' show InstanceKind;
|
||||
import 'package:observatory_2/service_io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'service_test_common.dart';
|
||||
import 'test_helper.dart';
|
||||
|
||||
class A {}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
class C extends Object with ListMixin<C> implements List<C> {
|
||||
int length = 0;
|
||||
C operator [](int index) => throw UnimplementedError();
|
||||
void operator []=(int index, C value) {}
|
||||
}
|
||||
|
||||
void testFunction4<T4 extends List<T4>>() {
|
||||
debugger();
|
||||
print("T4 = $T4");
|
||||
}
|
||||
|
||||
void testFunction3<T3, S3 extends T3>() {
|
||||
debugger();
|
||||
print("T3 = $T3");
|
||||
print("S3 = $S3");
|
||||
}
|
||||
|
||||
void testFunction2<E extends String>(List<E> x) {
|
||||
debugger();
|
||||
print("x = $x");
|
||||
}
|
||||
|
||||
void testFunction() {
|
||||
testFunction2<String>(<String>["a", "b", "c"]);
|
||||
testFunction3<A, B>();
|
||||
testFunction4<C>();
|
||||
}
|
||||
|
||||
void fooxx<E extends String>(List<E> y) {
|
||||
List<E> x = new List<E>.from(["hello"]);
|
||||
}
|
||||
|
||||
var tests = <IsolateTest>[
|
||||
hasStoppedAtBreakpoint,
|
||||
(Isolate isolate) async {
|
||||
{
|
||||
// Can add List<E extends String> to List<String> directly.
|
||||
Instance result = await isolate.evalFrame(0, '''() {
|
||||
List<E> y = new List<E>.from(["hello"]);
|
||||
x.addAll(y);
|
||||
return x.last;
|
||||
}()''') as Instance;
|
||||
expect(result.valueAsString, equals("hello"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
}
|
||||
{
|
||||
// Can't add List<String> to List<E extends String> directly.
|
||||
DartError result = await isolate.evalFrame(0, '''() {
|
||||
List<E> y = [];
|
||||
y.addAll(x);
|
||||
return y.last;
|
||||
}()''') as DartError;
|
||||
expect(
|
||||
result.message,
|
||||
contains(
|
||||
"The argument type '_GrowableList<String>' can't be assigned "
|
||||
"to the parameter type 'Iterable<E>'"));
|
||||
}
|
||||
{
|
||||
// Can add List<String> to List<E extends String> via cast.
|
||||
Instance result = await isolate.evalFrame(0, '''() {
|
||||
List<E> y = [];
|
||||
y.addAll(x.cast());
|
||||
return y.toString();
|
||||
}()''') as Instance;
|
||||
// Notice how "hello" was added a few evaluations back.
|
||||
expect(result.valueAsString, equals("[a, b, c, hello]"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
}
|
||||
{
|
||||
// Can create List<String> from List<E extends String>.
|
||||
Instance result = await isolate.evalFrame(0, '''() {
|
||||
List<E> y = new List<E>.from(x);
|
||||
return y.toString();
|
||||
}()''') as Instance;
|
||||
// Notice how "hello" was added a few evaluations back.
|
||||
expect(result.valueAsString, equals("[a, b, c, hello]"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
}
|
||||
},
|
||||
resumeIsolate,
|
||||
(Isolate isolate) async {
|
||||
// This is just to make sure the VM doesn't crash.
|
||||
Instance result =
|
||||
await isolate.evalFrame(0, '''S3.toString()''') as Instance;
|
||||
expect(result.valueAsString, equals("B"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
},
|
||||
resumeIsolate,
|
||||
(Isolate isolate) async {
|
||||
// This is just to make sure the VM doesn't crash.
|
||||
Instance result =
|
||||
await isolate.evalFrame(0, '''T4.toString()''') as Instance;
|
||||
expect(result.valueAsString, equals("C"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
},
|
||||
];
|
||||
|
||||
main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:developer';
|
||||
import 'package:observatory_2/models.dart' show InstanceKind;
|
||||
import 'package:observatory_2/service_io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'service_test_common.dart';
|
||||
import 'test_helper.dart';
|
||||
|
||||
extension on String {
|
||||
String printAndReturnHello() {
|
||||
String response = "Hello from String '$this'";
|
||||
print(response);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
void testFunction() {
|
||||
String x = "hello";
|
||||
String value = x.printAndReturnHello();
|
||||
debugger();
|
||||
print("value = $value");
|
||||
}
|
||||
|
||||
var tests = <IsolateTest>[
|
||||
hasStoppedAtBreakpoint,
|
||||
(Isolate isolate) async {
|
||||
Instance result =
|
||||
await isolate.evalFrame(0, 'x.printAndReturnHello()') as Instance;
|
||||
expect(result.valueAsString, equals("Hello from String 'hello'"));
|
||||
expect(result.kind, equals(InstanceKind.string));
|
||||
},
|
||||
];
|
||||
|
||||
main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
|
|
@ -95,6 +95,7 @@ evaluate_activation_in_method_class_test: SkipByDesign # Debugger is disabled in
|
|||
evaluate_activation_test: SkipByDesign
|
||||
evaluate_async_closure_test: SkipByDesign
|
||||
evaluate_class_type_parameters_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_fold_on_list_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_function_type_parameters_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_in_async_activation_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_in_async_star_activation_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
|
@ -102,6 +103,8 @@ evaluate_in_extension_method_test: SkipByDesign # Debugger is disabled in AOT mo
|
|||
evaluate_in_frame_rpc_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_in_frame_with_scope_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_in_sync_star_activation_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_type_arguments_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_type_with_extension_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_with_escaping_closure_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
evaluate_with_scope_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
field_script_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
|
|
|
@ -208,6 +208,7 @@ TEST_CASE(EvalExpression) {
|
|||
KernelIsolate::CompileExpressionToKernel(
|
||||
/*platform_kernel=*/nullptr, /*platform_kernel_size=*/0,
|
||||
expr_text.ToCString(), Array::empty_array(), Array::empty_array(),
|
||||
Array::empty_array(), Array::empty_array(), Array::empty_array(),
|
||||
String::Handle(lib_handle.url()).ToCString(), "A",
|
||||
/* method= */ nullptr,
|
||||
/* is_static= */ false);
|
||||
|
|
|
@ -1287,7 +1287,9 @@ ObjectPtr ActivationFrame::EvaluateCompiledExpression(
|
|||
TypeArgumentsPtr ActivationFrame::BuildParameters(
|
||||
const GrowableObjectArray& param_names,
|
||||
const GrowableObjectArray& param_values,
|
||||
const GrowableObjectArray& type_params_names) {
|
||||
const GrowableObjectArray& type_params_names,
|
||||
const GrowableObjectArray& type_params_bounds,
|
||||
const GrowableObjectArray& type_params_defaults) {
|
||||
GetDescIndices();
|
||||
bool type_arguments_available = false;
|
||||
String& name = String::Handle();
|
||||
|
@ -1329,6 +1331,12 @@ TypeArgumentsPtr ActivationFrame::BuildParameters(
|
|||
intptr_t num_vars = function().NumTypeArguments();
|
||||
type_params_names.Grow(num_vars);
|
||||
type_params_names.SetLength(num_vars);
|
||||
type_params_bounds.Grow(num_vars);
|
||||
type_params_bounds.SetLength(num_vars);
|
||||
type_params_defaults.Grow(num_vars);
|
||||
type_params_defaults.SetLength(num_vars);
|
||||
AbstractType& bound = AbstractType::Handle();
|
||||
AbstractType& defaultType = AbstractType::Handle();
|
||||
TypeParameters& type_params = TypeParameters::Handle();
|
||||
Function& current = Function::Handle(function().ptr());
|
||||
intptr_t mapping_offset = num_vars;
|
||||
|
@ -1341,12 +1349,16 @@ TypeArgumentsPtr ActivationFrame::BuildParameters(
|
|||
mapping_offset -= size;
|
||||
for (intptr_t j = 0; j < size; ++j) {
|
||||
name = type_params.NameAt(j);
|
||||
bound = type_params.BoundAt(j);
|
||||
defaultType = type_params.DefaultAt(j);
|
||||
// Write the names in backwards in terms of chain of functions.
|
||||
// But keep the order of names within the same function. so they
|
||||
// match up with the order of the types in 'type_arguments'.
|
||||
// Index:0 1 2 3 ...
|
||||
// |Names in Grandparent| |Names in Parent| ..|Names in Child|
|
||||
type_params_names.SetAt(mapping_offset + j, name);
|
||||
type_params_bounds.SetAt(mapping_offset + j, bound);
|
||||
type_params_defaults.SetAt(mapping_offset + j, defaultType);
|
||||
}
|
||||
}
|
||||
if (!type_arguments.IsNull()) {
|
||||
|
|
|
@ -392,7 +392,9 @@ class ActivationFrame : public ZoneAllocated {
|
|||
TypeArgumentsPtr BuildParameters(
|
||||
const GrowableObjectArray& param_names,
|
||||
const GrowableObjectArray& param_values,
|
||||
const GrowableObjectArray& type_params_names);
|
||||
const GrowableObjectArray& type_params_names,
|
||||
const GrowableObjectArray& type_params_bounds,
|
||||
const GrowableObjectArray& type_params_defaults);
|
||||
|
||||
ObjectPtr EvaluateCompiledExpression(const ExternalTypedData& kernel_data,
|
||||
const Array& arguments,
|
||||
|
|
|
@ -181,7 +181,10 @@ DART_EXPORT Dart_Handle Dart_EvaluateStaticExpr(Dart_Handle lib_handle,
|
|||
/* platform_kernel= */ nullptr, /* platform_kernel_size= */ 0,
|
||||
expr.ToCString(),
|
||||
/* definitions= */ Array::empty_array(),
|
||||
/* definition_types= */ Array::empty_array(),
|
||||
/* type_defintions= */ Array::empty_array(),
|
||||
/* type_bounds= */ Array::empty_array(),
|
||||
/* type_defaults= */ Array::empty_array(),
|
||||
String::Handle(lib.url()).ToCString(),
|
||||
/* klass= */ nullptr,
|
||||
/* method= */ nullptr,
|
||||
|
|
|
@ -476,7 +476,10 @@ class KernelCompilationRequest : public ValueObject {
|
|||
intptr_t platform_kernel_size,
|
||||
const char* expression,
|
||||
const Array& definitions,
|
||||
const Array& definition_types,
|
||||
const Array& type_definitions,
|
||||
const Array& type_bounds,
|
||||
const Array& type_defaults,
|
||||
char const* library_uri,
|
||||
char const* klass,
|
||||
char const* method,
|
||||
|
@ -537,6 +540,22 @@ class KernelCompilationRequest : public ValueObject {
|
|||
}
|
||||
definitions_object.value.as_array.values = definitions_array;
|
||||
|
||||
Dart_CObject definition_types_object;
|
||||
intptr_t num_definition_types = definition_types.Length();
|
||||
definition_types_object.type = Dart_CObject_kArray;
|
||||
definition_types_object.value.as_array.length = num_definition_types;
|
||||
|
||||
Dart_CObject** definition_types_array =
|
||||
new Dart_CObject*[num_definition_types];
|
||||
for (intptr_t i = 0; i < num_definition_types; ++i) {
|
||||
definition_types_array[i] = new Dart_CObject;
|
||||
definition_types_array[i]->type = Dart_CObject_kString;
|
||||
definition_types_array[i]->value.as_string = const_cast<char*>(
|
||||
String::CheckedHandle(thread->zone(), definition_types.At(i))
|
||||
.ToCString());
|
||||
}
|
||||
definition_types_object.value.as_array.values = definition_types_array;
|
||||
|
||||
Dart_CObject type_definitions_object;
|
||||
intptr_t num_type_definitions = type_definitions.Length();
|
||||
type_definitions_object.type = Dart_CObject_kArray;
|
||||
|
@ -553,6 +572,35 @@ class KernelCompilationRequest : public ValueObject {
|
|||
}
|
||||
type_definitions_object.value.as_array.values = type_definitions_array;
|
||||
|
||||
Dart_CObject type_bounds_object;
|
||||
intptr_t num_type_bounds = type_bounds.Length();
|
||||
type_bounds_object.type = Dart_CObject_kArray;
|
||||
type_bounds_object.value.as_array.length = num_type_bounds;
|
||||
|
||||
Dart_CObject** type_bounds_array = new Dart_CObject*[num_type_bounds];
|
||||
for (intptr_t i = 0; i < num_type_bounds; ++i) {
|
||||
type_bounds_array[i] = new Dart_CObject;
|
||||
type_bounds_array[i]->type = Dart_CObject_kString;
|
||||
type_bounds_array[i]->value.as_string = const_cast<char*>(
|
||||
String::CheckedHandle(thread->zone(), type_bounds.At(i)).ToCString());
|
||||
}
|
||||
type_bounds_object.value.as_array.values = type_bounds_array;
|
||||
|
||||
Dart_CObject type_defaults_object;
|
||||
intptr_t num_type_defaults = type_defaults.Length();
|
||||
type_defaults_object.type = Dart_CObject_kArray;
|
||||
type_defaults_object.value.as_array.length = num_type_defaults;
|
||||
|
||||
Dart_CObject** type_defaults_array = new Dart_CObject*[num_type_defaults];
|
||||
for (intptr_t i = 0; i < num_type_defaults; ++i) {
|
||||
type_defaults_array[i] = new Dart_CObject;
|
||||
type_defaults_array[i]->type = Dart_CObject_kString;
|
||||
type_defaults_array[i]->value.as_string = const_cast<char*>(
|
||||
String::CheckedHandle(thread->zone(), type_defaults.At(i))
|
||||
.ToCString());
|
||||
}
|
||||
type_defaults_object.value.as_array.values = type_defaults_array;
|
||||
|
||||
Dart_CObject library_uri_object;
|
||||
library_uri_object.type = Dart_CObject_kString;
|
||||
library_uri_object.value.as_string = const_cast<char*>(library_uri);
|
||||
|
@ -659,7 +707,10 @@ class KernelCompilationRequest : public ValueObject {
|
|||
&dart_platform_kernel,
|
||||
&expression_object,
|
||||
&definitions_object,
|
||||
&definition_types_object,
|
||||
&type_definitions_object,
|
||||
&type_bounds_object,
|
||||
&type_defaults_object,
|
||||
&library_uri_object,
|
||||
&class_object,
|
||||
&method_object,
|
||||
|
@ -690,11 +741,26 @@ class KernelCompilationRequest : public ValueObject {
|
|||
}
|
||||
delete[] definitions_array;
|
||||
|
||||
for (intptr_t i = 0; i < num_definition_types; ++i) {
|
||||
delete definition_types_array[i];
|
||||
}
|
||||
delete[] definition_types_array;
|
||||
|
||||
for (intptr_t i = 0; i < num_type_definitions; ++i) {
|
||||
delete type_definitions_array[i];
|
||||
}
|
||||
delete[] type_definitions_array;
|
||||
|
||||
for (intptr_t i = 0; i < num_type_bounds; ++i) {
|
||||
delete type_bounds_array[i];
|
||||
}
|
||||
delete[] type_bounds_array;
|
||||
|
||||
for (intptr_t i = 0; i < num_type_defaults; ++i) {
|
||||
delete type_defaults_array[i];
|
||||
}
|
||||
delete[] type_defaults_array;
|
||||
|
||||
for (intptr_t i = 0; i < num_dills; ++i) {
|
||||
delete dills_array[i];
|
||||
}
|
||||
|
@ -1142,7 +1208,10 @@ Dart_KernelCompilationResult KernelIsolate::CompileExpressionToKernel(
|
|||
intptr_t platform_kernel_size,
|
||||
const char* expression,
|
||||
const Array& definitions,
|
||||
const Array& definition_types,
|
||||
const Array& type_definitions,
|
||||
const Array& type_bounds,
|
||||
const Array& type_defaults,
|
||||
const char* library_url,
|
||||
const char* klass,
|
||||
const char* method,
|
||||
|
@ -1160,7 +1229,8 @@ Dart_KernelCompilationResult KernelIsolate::CompileExpressionToKernel(
|
|||
ASSERT(is_static || (klass != nullptr));
|
||||
return request.SendAndWaitForResponse(
|
||||
kernel_port, platform_kernel, platform_kernel_size, expression,
|
||||
definitions, type_definitions, library_url, klass, method, is_static,
|
||||
definitions, definition_types, type_definitions, type_bounds,
|
||||
type_defaults, library_url, klass, method, is_static,
|
||||
experimental_flags_);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,10 @@ class KernelIsolate : public AllStatic {
|
|||
intptr_t platform_kernel_size,
|
||||
const char* expression,
|
||||
const Array& definitions,
|
||||
const Array& definition_types,
|
||||
const Array& type_definitions,
|
||||
const Array& type_bounds,
|
||||
const Array& type_defaults,
|
||||
const char* library_url,
|
||||
const char* klass,
|
||||
const char* method,
|
||||
|
|
|
@ -2857,6 +2857,51 @@ static const MethodParameter* const build_expression_evaluation_scope_params[] =
|
|||
NULL,
|
||||
};
|
||||
|
||||
static void CollectStringifiedType(Zone* zone,
|
||||
const AbstractType& type,
|
||||
const GrowableObjectArray& output) {
|
||||
Instance& instance = Instance::Handle(zone);
|
||||
if (type.IsFunctionType()) {
|
||||
// The closure class
|
||||
// (IsolateGroup::Current()->object_store()->closure_class())
|
||||
// is statically typed weird (the call method redirects to itself)
|
||||
// and the type is therefore not useful for the CFE. We use null instead.
|
||||
output.Add(instance);
|
||||
return;
|
||||
}
|
||||
if (type.IsDynamicType()) {
|
||||
// Dynamic is weird in that it seems to have a class with no name and a
|
||||
// library called something like '7189777121420'. We use null instead.
|
||||
output.Add(instance);
|
||||
return;
|
||||
}
|
||||
if (type.IsTypeParameter() && type.IsAbstractType()) {
|
||||
// Calling type_class on an abstract type parameter will crash the VM.
|
||||
// We use null instead.
|
||||
output.Add(instance);
|
||||
return;
|
||||
}
|
||||
const Class& cls = Class::Handle(type.type_class());
|
||||
const Library& lib = Library::Handle(zone, cls.library());
|
||||
|
||||
instance ^= lib.url();
|
||||
output.Add(instance);
|
||||
|
||||
instance ^= cls.ScrubbedName();
|
||||
output.Add(instance);
|
||||
|
||||
instance ^= Smi::New((intptr_t)type.nullability());
|
||||
output.Add(instance);
|
||||
|
||||
const TypeArguments& srcArguments = TypeArguments::Handle(type.arguments());
|
||||
instance ^= Smi::New(srcArguments.Length());
|
||||
output.Add(instance);
|
||||
for (int i = 0; i < srcArguments.Length(); i++) {
|
||||
const AbstractType& src_type = AbstractType::Handle(srcArguments.TypeAt(i));
|
||||
CollectStringifiedType(zone, src_type, output);
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildExpressionEvaluationScope(Thread* thread, JSONStream* js) {
|
||||
if (CheckDebuggerDisabled(thread, js)) {
|
||||
return;
|
||||
|
@ -2877,6 +2922,10 @@ static void BuildExpressionEvaluationScope(Thread* thread, JSONStream* js) {
|
|||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
const GrowableObjectArray& type_params_names =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
const GrowableObjectArray& type_params_bounds =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
const GrowableObjectArray& type_params_defaults =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
String& klass_name = String::Handle(zone);
|
||||
String& method_name = String::Handle(zone);
|
||||
String& library_uri = String::Handle(zone);
|
||||
|
@ -2896,7 +2945,8 @@ static void BuildExpressionEvaluationScope(Thread* thread, JSONStream* js) {
|
|||
}
|
||||
|
||||
ActivationFrame* frame = stack->FrameAt(framePos);
|
||||
frame->BuildParameters(param_names, param_values, type_params_names);
|
||||
frame->BuildParameters(param_names, param_values, type_params_names,
|
||||
type_params_bounds, type_params_defaults);
|
||||
|
||||
if (frame->function().is_static()) {
|
||||
const Class& cls = Class::Handle(zone, frame->function().Owner());
|
||||
|
@ -2976,6 +3026,28 @@ static void BuildExpressionEvaluationScope(Thread* thread, JSONStream* js) {
|
|||
jsonParamNames.AddValue(param_name.ToCString());
|
||||
}
|
||||
}
|
||||
{
|
||||
const JSONArray jsonParamTypes(&report, "param_types");
|
||||
Object& obj = Object::Handle();
|
||||
Instance& instance = Instance::Handle();
|
||||
const GrowableObjectArray& param_types =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
AbstractType& type = AbstractType::Handle();
|
||||
for (intptr_t i = 0; i < param_names.Length(); i++) {
|
||||
obj = param_values.At(i);
|
||||
if (obj.IsNull()) {
|
||||
param_types.Add(obj);
|
||||
} else if (obj.IsInstance()) {
|
||||
instance ^= param_values.At(i);
|
||||
type = instance.GetType(Heap::kNew);
|
||||
CollectStringifiedType(zone, type, param_types);
|
||||
}
|
||||
}
|
||||
for (intptr_t i = 0; i < param_types.Length(); i++) {
|
||||
instance ^= param_types.At(i);
|
||||
jsonParamTypes.AddValue(instance.ToCString());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
JSONArray jsonTypeParamsNames(&report, "type_params_names");
|
||||
|
@ -2985,6 +3057,36 @@ static void BuildExpressionEvaluationScope(Thread* thread, JSONStream* js) {
|
|||
jsonTypeParamsNames.AddValue(type_param_name.ToCString());
|
||||
}
|
||||
}
|
||||
{
|
||||
const JSONArray jsonParamTypes(&report, "type_params_bounds");
|
||||
const GrowableObjectArray& type_params_bounds_strings =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
AbstractType& type = AbstractType::Handle();
|
||||
for (intptr_t i = 0; i < type_params_bounds.Length(); i++) {
|
||||
type ^= type_params_bounds.At(i);
|
||||
CollectStringifiedType(zone, type, type_params_bounds_strings);
|
||||
}
|
||||
Instance& instance = Instance::Handle();
|
||||
for (intptr_t i = 0; i < type_params_bounds_strings.Length(); i++) {
|
||||
instance ^= type_params_bounds_strings.At(i);
|
||||
jsonParamTypes.AddValue(instance.ToCString());
|
||||
}
|
||||
}
|
||||
{
|
||||
const JSONArray jsonParamTypes(&report, "type_params_defaults");
|
||||
const GrowableObjectArray& type_params_defaults_strings =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
AbstractType& type = AbstractType::Handle();
|
||||
for (intptr_t i = 0; i < type_params_defaults.Length(); i++) {
|
||||
type ^= type_params_defaults.At(i);
|
||||
CollectStringifiedType(zone, type, type_params_defaults_strings);
|
||||
}
|
||||
Instance& instance = Instance::Handle();
|
||||
for (intptr_t i = 0; i < type_params_defaults_strings.Length(); i++) {
|
||||
instance ^= type_params_defaults_strings.At(i);
|
||||
jsonParamTypes.AddValue(instance.ToCString());
|
||||
}
|
||||
}
|
||||
report.AddProperty("libraryUri", library_uri.ToCString());
|
||||
if (!klass_name.IsNull()) {
|
||||
report.AddProperty("klass", klass_name.ToCString());
|
||||
|
@ -3036,7 +3138,10 @@ static const MethodParameter* const compile_expression_params[] = {
|
|||
RUNNABLE_ISOLATE_PARAMETER,
|
||||
new StringParameter("expression", true),
|
||||
new StringParameter("definitions", false),
|
||||
new StringParameter("definitionTypes", false),
|
||||
new StringParameter("typeDefinitions", false),
|
||||
new StringParameter("typeBounds", false),
|
||||
new StringParameter("typeDefaults", false),
|
||||
new StringParameter("libraryUri", true),
|
||||
new StringParameter("klass", false),
|
||||
new BoolParameter("isStatic", false),
|
||||
|
@ -3070,6 +3175,12 @@ static void CompileExpression(Thread* thread, JSONStream* js) {
|
|||
PrintInvalidParamError(js, "definitions");
|
||||
return;
|
||||
}
|
||||
const GrowableObjectArray& param_types =
|
||||
GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New());
|
||||
if (!ParseCSVList(js->LookupParam("definitionTypes"), param_types)) {
|
||||
PrintInvalidParamError(js, "definitionTypes");
|
||||
return;
|
||||
}
|
||||
|
||||
const GrowableObjectArray& type_params =
|
||||
GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New());
|
||||
|
@ -3077,6 +3188,18 @@ static void CompileExpression(Thread* thread, JSONStream* js) {
|
|||
PrintInvalidParamError(js, "typedDefinitions");
|
||||
return;
|
||||
}
|
||||
const GrowableObjectArray& type_bounds =
|
||||
GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New());
|
||||
if (!ParseCSVList(js->LookupParam("typeBounds"), type_bounds)) {
|
||||
PrintInvalidParamError(js, "typeBounds");
|
||||
return;
|
||||
}
|
||||
const GrowableObjectArray& type_defaults =
|
||||
GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New());
|
||||
if (!ParseCSVList(js->LookupParam("typeDefaults"), type_defaults)) {
|
||||
PrintInvalidParamError(js, "typeDefaults");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t* kernel_buffer = Service::dart_library_kernel();
|
||||
const intptr_t kernel_buffer_len = Service::dart_library_kernel_length();
|
||||
|
@ -3085,7 +3208,10 @@ static void CompileExpression(Thread* thread, JSONStream* js) {
|
|||
KernelIsolate::CompileExpressionToKernel(
|
||||
kernel_buffer, kernel_buffer_len, js->LookupParam("expression"),
|
||||
Array::Handle(Array::MakeFixedLength(params)),
|
||||
Array::Handle(Array::MakeFixedLength(param_types)),
|
||||
Array::Handle(Array::MakeFixedLength(type_params)),
|
||||
Array::Handle(Array::MakeFixedLength(type_bounds)),
|
||||
Array::Handle(Array::MakeFixedLength(type_defaults)),
|
||||
js->LookupParam("libraryUri"), js->LookupParam("klass"),
|
||||
js->LookupParam("method"), is_static);
|
||||
|
||||
|
@ -3145,6 +3271,10 @@ static void EvaluateCompiledExpression(Thread* thread, JSONStream* js) {
|
|||
}
|
||||
const GrowableObjectArray& type_params_names =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
const GrowableObjectArray& type_params_bounds =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
const GrowableObjectArray& type_params_defaults =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
|
||||
|
||||
const ExternalTypedData& kernel_data = ExternalTypedData::Handle(
|
||||
zone, DecodeKernelBuffer(js->LookupParam("kernelBytes")));
|
||||
|
@ -3160,7 +3290,8 @@ static void EvaluateCompiledExpression(Thread* thread, JSONStream* js) {
|
|||
ActivationFrame* frame = stack->FrameAt(frame_pos);
|
||||
TypeArguments& type_arguments = TypeArguments::Handle(
|
||||
zone,
|
||||
frame->BuildParameters(param_names, param_values, type_params_names));
|
||||
frame->BuildParameters(param_names, param_values, type_params_names,
|
||||
type_params_bounds, type_params_defaults));
|
||||
|
||||
const Object& result = Object::Handle(
|
||||
zone,
|
||||
|
|
|
@ -648,7 +648,9 @@ Dart_Handle TestCase::EvaluateExpression(const Library& lib,
|
|||
KernelIsolate::CompileExpressionToKernel(
|
||||
/* platform_kernel= */ nullptr, /* platform_kernel_size= */ 0,
|
||||
expr.ToCString(), param_names, Array::empty_array(),
|
||||
String::Handle(lib.url()).ToCString(), /* klass= */ nullptr,
|
||||
Array::empty_array(), Array::empty_array(), Array::empty_array(),
|
||||
String::Handle(lib.url()).ToCString(),
|
||||
/* klass= */ nullptr,
|
||||
/* method= */ nullptr,
|
||||
/* is_static= */ true);
|
||||
if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
|
||||
|
|
|
@ -124,7 +124,10 @@ class _Evaluator {
|
|||
'isolateId': _message.params['isolateId']!,
|
||||
'expression': _message.params['expression']!,
|
||||
'definitions': buildScopeResponseResult['param_names']!,
|
||||
'definitionTypes': buildScopeResponseResult['param_types']!,
|
||||
'typeDefinitions': buildScopeResponseResult['type_params_names']!,
|
||||
'typeBounds': buildScopeResponseResult['type_params_bounds']!,
|
||||
'typeDefaults': buildScopeResponseResult['type_params_defaults']!,
|
||||
'libraryUri': buildScopeResponseResult['libraryUri']!,
|
||||
'isStatic': buildScopeResponseResult['isStatic']!,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue