mirror of
https://github.com/dart-lang/sdk
synced 2024-09-20 06:21:32 +00:00
Emit declarations for typedefs that are needed by reflection.
Typedefs are encoded like closure classes, but without a call-method and a superclass. For example, the typedef `typedef int Foo(String s);` is emitted as: Foo: {'^': ':15'}, where `15` is the index into `init.metadata` at which the function type is emitted. BUG= http://dartbug.com/16939 R=johnniwinther@google.com, floitsch@google.com, herhut@google.com Committed: https://code.google.com/p/dart/source/detail?r=37814 Reverted in https://code.google.com/p/dart/source/detail?r=37848 Committed: https://code.google.com/p/dart/source/detail?r=37939 Reverted in https://code.google.com/p/dart/source/detail?r=37940 Committed: https://code.google.com/p/dart/source/detail?r=37945 Review URL: https://codereview.chromium.org//360493002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@38891 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
ec6f1dfb64
commit
b203f95355
|
@ -314,11 +314,13 @@ abstract class Enqueuer {
|
|||
/// needed for reflection.
|
||||
void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) {
|
||||
if (shouldIncludeElementDueToMirrors(element,
|
||||
includedEnclosing: enclosingWasIncluded)
|
||||
// Do not enqueue typedefs.
|
||||
&& !element.impliesType) {
|
||||
includedEnclosing: enclosingWasIncluded)) {
|
||||
logEnqueueReflectiveAction(element);
|
||||
if (Elements.isStaticOrTopLevel(element)) {
|
||||
if (element.isTypedef) {
|
||||
TypedefElement typedef = element;
|
||||
typedef.ensureResolved(compiler);
|
||||
compiler.world.allTypedefs.add(element);
|
||||
} else if (Elements.isStaticOrTopLevel(element)) {
|
||||
registerStaticUse(element.declaration);
|
||||
} else if (element.isInstanceMember) {
|
||||
// We need to enqueue all members matching this one in subclasses, as
|
||||
|
|
|
@ -340,9 +340,6 @@ class JavaScriptBackend extends Backend {
|
|||
/// List of elements that the backend may use.
|
||||
final Set<Element> helpersUsed = new Set<Element>();
|
||||
|
||||
/// Set of typedefs that are used as type literals.
|
||||
final Set<TypedefElement> typedefTypeLiterals = new Set<TypedefElement>();
|
||||
|
||||
/// All the checked mode helpers.
|
||||
static const checkedModeHelpers = CheckedModeHelper.helpers;
|
||||
|
||||
|
@ -1937,11 +1934,13 @@ class JavaScriptBackend extends Backend {
|
|||
if (foundClosure) {
|
||||
reflectableMembers.add(closureClass);
|
||||
}
|
||||
// It would be nice to have a better means to select
|
||||
Set<Element> closurizedMembers = compiler.resolverWorld.closurizedMembers;
|
||||
if (closurizedMembers.any(reflectableMembers.contains)) {
|
||||
reflectableMembers.add(boundClosureClass);
|
||||
}
|
||||
// Add typedefs.
|
||||
reflectableMembers
|
||||
.addAll(compiler.world.allTypedefs.where(referencedFromMirrorSystem));
|
||||
// Register all symbols of reflectable elements
|
||||
for (Element element in reflectableMembers) {
|
||||
symbolsUsed.add(element.name);
|
||||
|
@ -2170,7 +2169,7 @@ class JavaScriptionResolutionCallbacks extends ResolutionCallbacks {
|
|||
// when reflection is used. However, as long as we disable tree-shaking
|
||||
// eagerly it doesn't matter.
|
||||
if (type.isTypedef) {
|
||||
backend.typedefTypeLiterals.add(type.element);
|
||||
backend.compiler.world.allTypedefs.add(type.element);
|
||||
}
|
||||
backend.customElementsAnalysis.registerTypeLiteral(type, registry);
|
||||
}
|
||||
|
|
|
@ -244,7 +244,7 @@ class NativeEmitter {
|
|||
emitter.classEmitter.emitClassBuilderWithReflectionData(
|
||||
backend.namer.getNameOfClass(classElement),
|
||||
classElement, builders[classElement],
|
||||
emitter.getElementDecriptor(classElement));
|
||||
emitter.getElementDescriptor(classElement));
|
||||
emitter.needsDefineClass = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,32 +80,10 @@ class ClassEmitter extends CodeEmitterHelper {
|
|||
// [ constructorName, fields,
|
||||
// fields.map(
|
||||
// (name) => js('this.# = #', [name, name]))]));
|
||||
task.precompiledFunction.add(
|
||||
new jsAst.FunctionDeclaration(
|
||||
new jsAst.VariableDeclaration(constructorName),
|
||||
js('function(#) { #; }',
|
||||
[fields,
|
||||
fields.map((name) => js('this.# = #', [name, name]))])));
|
||||
// TODO(floitsch): do we actually need the name field?
|
||||
// TODO(floitsch): these should all go through the namer.
|
||||
|
||||
task.precompiledFunction.add(
|
||||
js.statement(r'''{
|
||||
#.builtin$cls = #;
|
||||
if (!"name" in #)
|
||||
#.name = #;
|
||||
$desc=$collectedClasses.#;
|
||||
if ($desc instanceof Array) $desc = $desc[1];
|
||||
#.prototype = $desc;
|
||||
}''',
|
||||
[ constructorName, js.string(constructorName),
|
||||
constructorName,
|
||||
constructorName, js.string(constructorName),
|
||||
constructorName,
|
||||
constructorName
|
||||
]));
|
||||
|
||||
task.precompiledConstructorNames.add(js('#', constructorName));
|
||||
jsAst.Expression constructorAst = js('function(#) { #; }',
|
||||
[fields,
|
||||
fields.map((name) => js('this.# = #', [name, name]))]);
|
||||
task.emitPrecompiledConstructor(constructorName, constructorAst);
|
||||
}
|
||||
|
||||
/// Returns `true` if fields added.
|
||||
|
|
|
@ -55,6 +55,8 @@ class CodeEmitterTask extends CompilerTask {
|
|||
// TODO(ngeoffray): remove this field.
|
||||
Set<ClassElement> instantiatedClasses;
|
||||
|
||||
List<TypedefElement> typedefsNeededForReflection;
|
||||
|
||||
JavaScriptBackend get backend => compiler.backend;
|
||||
TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler;
|
||||
|
||||
|
@ -63,9 +65,12 @@ class CodeEmitterTask extends CompilerTask {
|
|||
String get n => compiler.enableMinification ? "" : "\n";
|
||||
String get N => compiler.enableMinification ? "\n" : ";\n";
|
||||
|
||||
CodeBuffer getBuffer(OutputUnit outputUnit) {
|
||||
return outputBuffers.putIfAbsent(outputUnit, () => new CodeBuffer());
|
||||
}
|
||||
|
||||
CodeBuffer get mainBuffer {
|
||||
return outputBuffers.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit,
|
||||
() => new CodeBuffer());
|
||||
return getBuffer(compiler.deferredLoadTask.mainOutputUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -752,6 +757,8 @@ class CodeEmitterTask extends CompilerTask {
|
|||
ClassElement cls = element;
|
||||
if (cls.isUnnamedMixinApplication) return null;
|
||||
return cls.name;
|
||||
} else if (element.isTypedef) {
|
||||
return element.name;
|
||||
}
|
||||
throw compiler.internalError(element,
|
||||
'Do not know how to reflect on this $element.');
|
||||
|
@ -861,7 +868,7 @@ class CodeEmitterTask extends CompilerTask {
|
|||
for (Element element in Elements.sortedByPosition(elements)) {
|
||||
ClassBuilder builder = new ClassBuilder(element, namer);
|
||||
containerBuilder.addMember(element, builder);
|
||||
getElementDecriptor(element).properties.addAll(builder.properties);
|
||||
getElementDescriptor(element).properties.addAll(builder.properties);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1149,10 +1156,15 @@ class CodeEmitterTask extends CompilerTask {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute all the classes that must be emitted.
|
||||
*/
|
||||
void computeNeededClasses() {
|
||||
/// Compute all the classes and typedefs that must be emitted.
|
||||
void computeNeededDeclarations() {
|
||||
// Compute needed typedefs.
|
||||
typedefsNeededForReflection = Elements.sortedByPosition(
|
||||
compiler.world.allTypedefs
|
||||
.where(backend.isAccessibleByReflection)
|
||||
.toList());
|
||||
|
||||
// Compute needed classes.
|
||||
instantiatedClasses =
|
||||
compiler.codegenWorld.instantiatedClasses.where(computeClassFilter())
|
||||
.toSet();
|
||||
|
@ -1311,26 +1323,21 @@ class CodeEmitterTask extends CompilerTask {
|
|||
uri = relativize(compiler.outputUri, library.canonicalUri, false);
|
||||
}
|
||||
}
|
||||
Map<OutputUnit, ClassBuilder> descriptors = elementDescriptors[library];
|
||||
String libraryName =
|
||||
(!compiler.enableMinification || backend.mustRetainLibraryNames) ?
|
||||
library.getLibraryName() :
|
||||
"";
|
||||
Map<OutputUnit, ClassBuilder> descriptors =
|
||||
elementDescriptors[library];
|
||||
|
||||
for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) {
|
||||
ClassBuilder descriptor =
|
||||
descriptors.putIfAbsent(outputUnit,
|
||||
() => new ClassBuilder(library, namer));
|
||||
if (descriptor.properties.isEmpty) continue;
|
||||
bool isDeferred =
|
||||
outputUnit != compiler.deferredLoadTask.mainOutputUnit;
|
||||
if (!descriptors.containsKey(outputUnit)) continue;
|
||||
|
||||
ClassBuilder descriptor = descriptors[outputUnit];
|
||||
jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library);
|
||||
|
||||
jsAst.ObjectInitializer initializers =
|
||||
descriptor.toObjectInitializer();
|
||||
CodeBuffer outputBuffer =
|
||||
outputBuffers.putIfAbsent(outputUnit, () => new CodeBuffer());
|
||||
jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer();
|
||||
CodeBuffer outputBuffer = getBuffer(outputUnit);
|
||||
|
||||
int sizeBefore = outputBuffer.length;
|
||||
compiler.dumpInfoTask.registerElementAst(library, metadata);
|
||||
compiler.dumpInfoTask.registerElementAst(library, initializers);
|
||||
|
@ -1352,6 +1359,30 @@ class CodeEmitterTask extends CompilerTask {
|
|||
}
|
||||
}
|
||||
|
||||
void emitPrecompiledConstructor(String constructorName,
|
||||
jsAst.Expression constructorAst) {
|
||||
precompiledFunction.add(
|
||||
new jsAst.FunctionDeclaration(
|
||||
new jsAst.VariableDeclaration(constructorName), constructorAst));
|
||||
precompiledFunction.add(
|
||||
js.statement(r'''{
|
||||
#.builtin$cls = #;
|
||||
if (!"name" in #)
|
||||
#.name = #;
|
||||
$desc=$collectedClasses.#;
|
||||
if ($desc instanceof Array) $desc = $desc[1];
|
||||
#.prototype = $desc;
|
||||
}''',
|
||||
[ constructorName, js.string(constructorName),
|
||||
constructorName,
|
||||
constructorName, js.string(constructorName),
|
||||
constructorName,
|
||||
constructorName
|
||||
]));
|
||||
|
||||
precompiledConstructorNames.add(js('#', constructorName));
|
||||
}
|
||||
|
||||
String assembleProgram() {
|
||||
measure(() {
|
||||
invalidateCaches();
|
||||
|
@ -1360,7 +1391,7 @@ class CodeEmitterTask extends CompilerTask {
|
|||
// 'is$' method.
|
||||
typeTestEmitter.computeRequiredTypeChecks();
|
||||
|
||||
computeNeededClasses();
|
||||
computeNeededDeclarations();
|
||||
|
||||
mainBuffer.add(buildGeneratedBy());
|
||||
addComment(HOOKS_API_USAGE, mainBuffer);
|
||||
|
@ -1395,7 +1426,8 @@ class CodeEmitterTask extends CompilerTask {
|
|||
// Only output the classesCollector if we actually have any classes.
|
||||
if (!(nativeClasses.isEmpty &&
|
||||
compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty &&
|
||||
outputClassLists.values.every((classList) => classList.isEmpty))) {
|
||||
outputClassLists.values.every((classList) => classList.isEmpty) &&
|
||||
typedefsNeededForReflection.isEmpty)) {
|
||||
// Shorten the code by using "$$" as temporary.
|
||||
classesCollector = r"$$";
|
||||
mainBuffer.add('var $classesCollector$_=$_{}$N$n');
|
||||
|
@ -1419,7 +1451,7 @@ class CodeEmitterTask extends CompilerTask {
|
|||
// Might create methodClosures.
|
||||
for (List<ClassElement> outputClassList in outputClassLists.values) {
|
||||
for (ClassElement element in outputClassList) {
|
||||
generateClass(element, getElementDecriptor(element));
|
||||
generateClass(element, getElementDescriptor(element));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1439,6 +1471,8 @@ class CodeEmitterTask extends CompilerTask {
|
|||
mainBuffer.write(';');
|
||||
}
|
||||
|
||||
// TODO(karlklose): document what kinds of fields this loop adds to the
|
||||
// library class builder.
|
||||
for (Element element in elementDescriptors.keys) {
|
||||
// TODO(ahe): Should iterate over all libraries. Otherwise, we will
|
||||
// not see libraries that only have fields.
|
||||
|
@ -1458,6 +1492,32 @@ class CodeEmitterTask extends CompilerTask {
|
|||
}
|
||||
}
|
||||
|
||||
// Emit all required typedef declarations into the main output unit.
|
||||
// TODO(karlklose): unify required classes and typedefs to declarations
|
||||
// and have builders for each kind.
|
||||
for (TypedefElement typedef in typedefsNeededForReflection) {
|
||||
OutputUnit mainUnit = compiler.deferredLoadTask.mainOutputUnit;
|
||||
LibraryElement library = typedef.library;
|
||||
// TODO(karlklose): add a TypedefBuilder and move this code there.
|
||||
DartType type = typedef.alias;
|
||||
int typeIndex = metadataEmitter.reifyType(type);
|
||||
String typeReference =
|
||||
encoding.encodeTypedefFieldDescriptor(typeIndex);
|
||||
jsAst.Property descriptor = new jsAst.Property(
|
||||
js.string(namer.classDescriptorProperty),
|
||||
js.string(typeReference));
|
||||
jsAst.Node declaration = new jsAst.ObjectInitializer([descriptor]);
|
||||
String mangledName = namer.getNameX(typedef);
|
||||
String reflectionName = getReflectionName(typedef, mangledName);
|
||||
getElementDescriptorForOutputUnit(library, mainUnit)
|
||||
..addProperty(mangledName, declaration)
|
||||
..addProperty("+$reflectionName", js.string(''));
|
||||
// Also emit a trivial constructor for CSP mode.
|
||||
String constructorName = mangledName;
|
||||
jsAst.Expression constructorAst = js('function() {}');
|
||||
emitPrecompiledConstructor(constructorName, constructorAst);
|
||||
}
|
||||
|
||||
if (!mangledFieldNames.isEmpty) {
|
||||
var keys = mangledFieldNames.keys.toList();
|
||||
keys.sort();
|
||||
|
@ -1714,7 +1774,7 @@ class CodeEmitterTask extends CompilerTask {
|
|||
() => new ClassBuilder(element, namer));
|
||||
}
|
||||
|
||||
ClassBuilder getElementDecriptor(Element element) {
|
||||
ClassBuilder getElementDescriptor(Element element) {
|
||||
Element owner = element.library;
|
||||
if (!element.isTopLevel && !element.isNative) {
|
||||
// For static (not top level) elements, record their code in a buffer
|
||||
|
|
|
@ -69,6 +69,8 @@ import '../util/util.dart' show
|
|||
import '../deferred_load.dart' show
|
||||
OutputUnit;
|
||||
|
||||
import '../runtime_data.dart' as encoding;
|
||||
|
||||
part 'class_builder.dart';
|
||||
part 'class_emitter.dart';
|
||||
part 'code_emitter_helper.dart';
|
||||
|
|
|
@ -90,20 +90,8 @@ class MetadataEmitter extends CodeEmitterHelper {
|
|||
}
|
||||
|
||||
void emitMetadata(CodeBuffer buffer) {
|
||||
var literals = backend.typedefTypeLiterals.toList();
|
||||
Elements.sortedByPosition(literals);
|
||||
var properties = [];
|
||||
for (TypedefElement literal in literals) {
|
||||
var key = namer.getNameX(literal);
|
||||
var value = js.number(reifyType(literal.rawType));
|
||||
properties.add(new jsAst.Property(js.string(key), value));
|
||||
}
|
||||
var map = new jsAst.ObjectInitializer(properties);
|
||||
buffer.write(
|
||||
jsAst.prettyPrint(
|
||||
js.statement('init.functionAliases = #', map), compiler));
|
||||
buffer.write('${N}init.metadata$_=$_[');
|
||||
for (var metadata in globalMetadata) {
|
||||
buffer.write('init.metadata$_=$_[');
|
||||
for (String metadata in globalMetadata) {
|
||||
if (metadata is String) {
|
||||
if (metadata != 'null') {
|
||||
buffer.write(metadata);
|
||||
|
|
|
@ -1301,6 +1301,7 @@ class ResolverTask extends CompilerTask {
|
|||
|
||||
TreeElements resolveTypedef(TypedefElementX element) {
|
||||
if (element.isResolved) return element.treeElements;
|
||||
compiler.world.allTypedefs.add(element);
|
||||
return _resolveTypeDeclaration(element, () {
|
||||
ResolutionRegistry registry = new ResolutionRegistry(compiler, element);
|
||||
return compiler.withCurrentElement(element, () {
|
||||
|
|
22
sdk/lib/_internal/compiler/implementation/runtime_data.dart
Normal file
22
sdk/lib/_internal/compiler/implementation/runtime_data.dart
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/// Contains encoding, decoding and detection functionality for the
|
||||
/// representation of program data at runtime.
|
||||
///
|
||||
/// This library is shared between the compiler and the runtime system.
|
||||
library dart2js.runtime_data;
|
||||
|
||||
|
||||
String encodeTypedefFieldDescriptor(int typeIndex) {
|
||||
return ":$typeIndex;";
|
||||
}
|
||||
|
||||
bool isTypedefDescriptor(String descriptor) {
|
||||
return descriptor.startsWith(':');
|
||||
}
|
||||
|
||||
int getTypeFromTypedef(String descriptor) {
|
||||
return int.parse(descriptor.substring(1, descriptor.length - 1));
|
||||
}
|
|
@ -10,6 +10,8 @@ class World {
|
|||
final Set<Element> functionsCalledInLoop = new Set<Element>();
|
||||
final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>();
|
||||
|
||||
final Set<TypedefElement> allTypedefs = new Set<TypedefElement>();
|
||||
|
||||
final Map<ClassElement, Set<MixinApplicationElement>> mixinUses =
|
||||
new Map<ClassElement, Set<MixinApplicationElement>>();
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
library dart._js_mirrors;
|
||||
|
||||
import 'dart:async';
|
||||
import '../compiler/implementation/runtime_data.dart' as encoding;
|
||||
|
||||
import 'dart:collection' show
|
||||
UnmodifiableListView,
|
||||
|
@ -334,10 +334,12 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
|
|||
var cls = reflectClassByMangledName(className);
|
||||
if (cls is ClassMirror) {
|
||||
cls = cls.originalDeclaration;
|
||||
if (cls is JsClassMirror) {
|
||||
result[cls.simpleName] = cls;
|
||||
cls._owner = this;
|
||||
}
|
||||
}
|
||||
if (cls is JsClassMirror) {
|
||||
result[cls.simpleName] = cls;
|
||||
cls._owner = this;
|
||||
} else if (cls is JsTypedefMirror) {
|
||||
result[cls.simpleName] = cls;
|
||||
}
|
||||
}
|
||||
return _cachedClasses =
|
||||
|
@ -572,12 +574,6 @@ TypeMirror reflectClassByName(Symbol symbol, String mangledName) {
|
|||
}
|
||||
var constructor = JS('var', 'init.allClasses[#]', mangledName);
|
||||
if (constructor == null) {
|
||||
int index = JS('int|Null', 'init.functionAliases[#]', mangledName);
|
||||
if (index != null) {
|
||||
mirror = new JsTypedefMirror(symbol, mangledName, getMetadata(index));
|
||||
JsCache.update(classMirrors, mangledName, mirror);
|
||||
return mirror;
|
||||
}
|
||||
// Probably an intercepted class.
|
||||
// TODO(ahe): How to handle intercepted classes?
|
||||
throw new UnsupportedError('Cannot find class for: ${n(symbol)}');
|
||||
|
@ -602,23 +598,28 @@ TypeMirror reflectClassByName(Symbol symbol, String mangledName) {
|
|||
}
|
||||
}
|
||||
|
||||
var superclassName = fields.split(';')[0];
|
||||
var mixins = superclassName.split('+');
|
||||
if (mixins.length > 1 && mangledGlobalNames[mangledName] == null) {
|
||||
mirror = reflectMixinApplication(mixins, mangledName);
|
||||
if (encoding.isTypedefDescriptor(fields)) {
|
||||
int index = encoding.getTypeFromTypedef(fields);
|
||||
mirror = new JsTypedefMirror(symbol, mangledName, getMetadata(index));
|
||||
} else {
|
||||
ClassMirror classMirror = new JsClassMirror(
|
||||
symbol, mangledName, constructor, fields, fieldsMetadata);
|
||||
List typeVariables =
|
||||
JS('JSExtendableArray|Null', '#.prototype["<>"]', constructor);
|
||||
if (typeVariables == null || typeVariables.length == 0) {
|
||||
mirror = classMirror;
|
||||
var superclassName = fields.split(';')[0];
|
||||
var mixins = superclassName.split('+');
|
||||
if (mixins.length > 1 && mangledGlobalNames[mangledName] == null) {
|
||||
mirror = reflectMixinApplication(mixins, mangledName);
|
||||
} else {
|
||||
String typeArguments = 'dynamic';
|
||||
for (int i = 1; i < typeVariables.length; i++) {
|
||||
typeArguments += ',dynamic';
|
||||
ClassMirror classMirror = new JsClassMirror(
|
||||
symbol, mangledName, constructor, fields, fieldsMetadata);
|
||||
List typeVariables =
|
||||
JS('JSExtendableArray|Null', '#.prototype["<>"]', constructor);
|
||||
if (typeVariables == null || typeVariables.length == 0) {
|
||||
mirror = classMirror;
|
||||
} else {
|
||||
String typeArguments = 'dynamic';
|
||||
for (int i = 1; i < typeVariables.length; i++) {
|
||||
typeArguments += ',dynamic';
|
||||
}
|
||||
mirror = new JsTypeBoundClassMirror(classMirror, typeArguments);
|
||||
}
|
||||
mirror = new JsTypeBoundClassMirror(classMirror, typeArguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@ const Map<String, List<String>> WHITE_LIST = const {
|
|||
// Some things in dart_printer are not yet used
|
||||
"implementation/dart_backend/backend_ast_nodes.dart" : const [" is never "],
|
||||
|
||||
// dart2js uses only the encoding functions, the decoding functions are used
|
||||
// from the generated code.
|
||||
"implementation/runtime_data.dart": const [" is never "],
|
||||
|
||||
// Setlet implements the Set interface: Issue 18959.
|
||||
"implementation/util/setlet.dart": const [" is never "],
|
||||
};
|
||||
|
|
|
@ -204,7 +204,6 @@ async/schedule_microtask6_test: Fail # Issue 10957 - may be related
|
|||
convert/json_lib_test: Fail # Issue 10961
|
||||
|
||||
[ $compiler == dart2js && $minified ]
|
||||
mirrors/typedef_test/01: Fail # http://dartbug.com/6490
|
||||
mirrors/mirrors_used_get_name_test: RuntimeError
|
||||
mirrors/mirrors_used_get_name2_test: RuntimeError
|
||||
|
||||
|
@ -253,6 +252,8 @@ mirrors/mirrors_used_inheritance_test: RuntimeError # Issue 16048
|
|||
|
||||
async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
|
||||
|
||||
mirrors/typedef_declaration_test/01: Fail # dartbug.com/16048. Remove multitest marker when it passes.
|
||||
|
||||
[ $compiler == none && ( $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
|
||||
async/schedule_microtask6_test: Fail # Issue 10910
|
||||
async/timer_test: Fail, Pass # Issue 15487
|
||||
|
|
|
@ -57,13 +57,12 @@ test(MirrorSystem mirrors) {
|
|||
Expect.isFalse(Obj.isSubclassOf(Func));
|
||||
|
||||
// Function typedef.
|
||||
// TODO(16939): retrieve via declaration when dart2js supports it.
|
||||
var NumPred = reflectType(NumberPredicate);
|
||||
var IntPred = reflectType(IntegerPredicate);
|
||||
var DubPred = reflectType(DoublePredicate);
|
||||
var NumGen = reflectType(NumberGenerator);
|
||||
var IntGen = reflectType(IntegerGenerator);
|
||||
var DubGen = reflectType(DoubleGenerator);
|
||||
var NumPred = thisLibrary.declarations[#NumberPredicate];
|
||||
var IntPred = thisLibrary.declarations[#IntegerPredicate];
|
||||
var DubPred = thisLibrary.declarations[#DoublePredicate];
|
||||
var NumGen = thisLibrary.declarations[#NumberGenerator];
|
||||
var IntGen = thisLibrary.declarations[#IntegerGenerator];
|
||||
var DubGen = thisLibrary.declarations[#DoubleGenerator];
|
||||
|
||||
isArgumentOrTypeError(e) => e is ArgumentError || e is TypeError;
|
||||
Expect.throws(() => Func.isSubclassOf(NumPred), isArgumentOrTypeError);
|
||||
|
|
29
tests/lib/mirrors/typedef_declaration_test.dart
Normal file
29
tests/lib/mirrors/typedef_declaration_test.dart
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
library test;
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
@MirrorsUsed(targets: "Foo")
|
||||
import 'dart:mirrors';
|
||||
|
||||
typedef int Foo(String x);
|
||||
typedef int Bar();
|
||||
|
||||
main() {
|
||||
LibraryMirror thisLibrary = currentMirrorSystem().findLibrary(#test);
|
||||
|
||||
Mirror fooMirror = thisLibrary.declarations[#Foo];
|
||||
|
||||
Expect.isTrue(fooMirror != null, 'Foo not found.');
|
||||
Expect.isTrue(thisLibrary.declarations[#Foo] is TypedefMirror,
|
||||
'TypedefMirror expected, found $fooMirror');
|
||||
|
||||
// The following code does not currenty work on the VM, because it does not
|
||||
// support MirrorsUsed (see dartbug.com/16048).
|
||||
Mirror barMirror = thisLibrary.declarations[#Bar]; /// 01: ok
|
||||
Expect.isTrue(barMirror == null, /// 01: continued
|
||||
'Bar should not be emitted due to MirrorsUsed.'); /// 01: continued
|
||||
}
|
Loading…
Reference in a new issue