Handle generic jsinterop classes as type arguments.

Change-Id: I89d8a77d632cf6d4f8adffa84f042a1c03a79f26
Reviewed-on: https://dart-review.googlesource.com/56665
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2018-05-31 07:50:52 +00:00 committed by commit-bot@chromium.org
parent c6129f768e
commit 39b0efd613
3 changed files with 75 additions and 9 deletions

View file

@ -2146,12 +2146,21 @@ class TypeRepresentationGenerator
jsAst.Expression visitInterfaceType(InterfaceType type, Emitter emitter) {
jsAst.Expression name = getJavaScriptClassName(type.element, emitter);
if (_nativeData.isJsInteropClass(type.element)) {
return getJsInteropTypeArguments(type.typeArguments.length, name: name);
jsAst.Expression result;
if (type.treatAsRaw) {
result = name;
} else {
// Visit all type arguments. This is done even for jsinterop classes to
// enforce the invariant that [onVariable] is called for each type
// variable in the type.
result = visitList(type.typeArguments, emitter, head: name);
if (_nativeData.isJsInteropClass(type.element)) {
// Replace type arguments of generic jsinterop classes with 'any' type.
result =
getJsInteropTypeArguments(type.typeArguments.length, name: name);
}
}
return type.treatAsRaw
? name
: visitList(type.typeArguments, emitter, head: name);
return result;
}
jsAst.Expression visitList(List<DartType> types, Emitter emitter,

View file

@ -3092,6 +3092,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
}
void visitTypeInfoExpression(HTypeInfoExpression node) {
DartType type = node.dartType;
List<js.Expression> arguments = <js.Expression>[];
for (HInstruction input in node.inputs) {
use(input);
@ -3103,19 +3104,19 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
int index = 0;
js.Expression result = _rtiEncoder.getTypeRepresentation(
_emitter.emitter,
node.dartType,
type,
(TypeVariableType variable) => arguments[index++]);
assert(
index == node.inputs.length,
"Not all input is read for type ${node.dartType}: "
"Not all input is read for type ${type}: "
"$index of ${node.inputs}.");
push(result);
return;
case TypeInfoExpressionKind.INSTANCE:
// We expect only flat types for the INSTANCE representation.
assert((node.dartType as InterfaceType).typeArguments.length ==
arguments.length);
assert(
(type as InterfaceType).typeArguments.length == arguments.length);
_registry.registerInstantiatedClass(_commonElements.listClass);
push(new js.ArrayInitializer(arguments)
.withSourceInformation(node.sourceInformation));

View file

@ -0,0 +1,56 @@
// Copyright (c) 2018, 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.
// dart2jsOptions=--strong
@JS()
library foo;
/*class: global#JavaScriptObject:checks=[$asA,$isA]*/
import 'package:expect/expect.dart';
import 'package:js/js.dart';
/*kernel.class: A:checkedTypeArgument,checks=[],typeArgument*/
/*strong.class: A:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
@JS()
@anonymous
class A<T> {
external factory A();
}
/*class: Class1:checks=[],instance*/
class Class1<T> {
method() {
// This caused and assertion failure in codegen.
test1(new List<A<T>>.from([]));
}
}
/*class: Class2:checks=[],instance*/
class Class2<T> {
method() {
// This caused and assertion failure in codegen.
test2(new List<A<T> Function()>.from([]));
}
}
main() {
new Class1<int>().method();
new Class1<String>().method();
new Class2<int>().method();
new Class2<String>().method();
}
test1(o) {
Expect.isTrue(o is List<A<int>>, "Expected $o to be List<A<int>>");
Expect.isTrue(o is List<A<String>>, "Expected $o to be List<A<String>>");
}
test2(o) {
Expect.isTrue(o is List<A<int> Function()>,
"Expected $o to be List<A<int> Function()>");
Expect.isTrue(o is List<A<String> Function()>,
"Expected $o to be List<A<String> Function()>");
}