Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Unified Diff: lib/src/codegen/js_codegen.dart

Issue 1117793002: add checks needed for covariant generics, and List<E> (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/src/codegen/js_codegen.dart
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
index c533eb4e0fa548cd439354c802d7383e160b3a68..f11569eb29c27dade60b2acc5ed7fb38f10cc129 100644
--- a/lib/src/codegen/js_codegen.dart
+++ b/lib/src/codegen/js_codegen.dart
@@ -332,32 +332,34 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
var classExpr = new JS.ClassExpression(new JS.Identifier(type.name),
_classHeritage(node), _emitClassMethods(node, ctors, fields));
- var body =
- _finishClassMembers(classElem, classExpr, ctors, fields, staticFields);
+ String jsPeerName;
+ var jsPeer = getAnnotationValue(node, _isJsPeerInterface);
+ if (jsPeer != null) {
+ jsPeerName = getConstantField(jsPeer, 'name', types.stringType);
+ }
+
+ var body = _finishClassMembers(
+ classElem, classExpr, ctors, fields, staticFields, jsPeerName);
var result = _finishClassDef(type, body);
- var jsPeer = getAnnotationValue(node, _isJsPeerInterface);
- if (jsPeer != null) {
- var jsPeerName = getConstantField(jsPeer, 'name', types.stringType);
- if (jsPeerName != null) {
- // This class isn't allowed to be lazy, because we need to set up
- // the native JS type eagerly at this point.
- // If we wanted to support laziness, we could defer the hookup until
- // the end of the Dart library cycle load.
- assert(!_lazyClass(type));
-
- // TODO(jmesserly): this copies the dynamic members.
- // Probably fine for objects coming from JS, but not if we actually
- // want to support construction of instances with generic types other
- // than dynamic. See issue #154 for Array and List<E> related bug.
- var copyMembers = js.statement(
- 'dart.registerExtension(dart.global.#, #);', [
- _propertyName(jsPeerName),
- classElem.name
- ]);
- return _statement([result, copyMembers]);
- }
+ if (jsPeerName != null) {
+ // This class isn't allowed to be lazy, because we need to set up
+ // the native JS type eagerly at this point.
+ // If we wanted to support laziness, we could defer the hookup until
+ // the end of the Dart library cycle load.
+ assert(!_lazyClass(type));
+
+ // TODO(jmesserly): this copies the dynamic members.
+ // Probably fine for objects coming from JS, but not if we actually
+ // want to support construction of instances with generic types other
+ // than dynamic. See issue #154 for Array and List<E> related bug.
+ var copyMembers = js.statement(
+ 'dart.registerExtension(dart.global.#, #);', [
+ _propertyName(jsPeerName),
+ classElem.name
+ ]);
+ return _statement([result, copyMembers]);
}
return result;
}
@@ -602,11 +604,20 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
/// inside the ES6 `class { ... }` node.
JS.Statement _finishClassMembers(ClassElement classElem,
JS.ClassExpression cls, List<ConstructorDeclaration> ctors,
- List<FieldDeclaration> fields, List<FieldDeclaration> staticFields) {
+ List<FieldDeclaration> fields, List<FieldDeclaration> staticFields,
+ String jsPeerName) {
var name = classElem.name;
var body = <JS.Statement>[];
body.add(new JS.ClassDeclaration(cls));
+ // TODO(jmesserly): we should really just extend native Array.
+ if (jsPeerName != null && classElem.typeParameters.isNotEmpty) {
+ body.add(js.statement('dart.setBaseClass(#, dart.global.#);', [
+ classElem.name,
+ _propertyName(jsPeerName)
+ ]));
+ }
+
// Interfaces
if (classElem.interfaces.isNotEmpty) {
body.add(js.statement('#[dart.implements] = () => #;', [
@@ -902,9 +913,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
bool _hasArgumentInitializers(FormalParameterList parameters) {
if (parameters == null) return false;
- return parameters.parameters.any((p) => p.kind != ParameterKind.REQUIRED);
+ return parameters.parameters.any((p) => p.kind != ParameterKind.REQUIRED ||
+ p.element.type is TypeParameterType);
}
+ /// Emits argument initializers, which handles optional/named args, as well
+ /// as generic type checks needed due to our covariance.
JS.Statement _emitArgumentInitializers(FormalParameterList parameters) {
if (parameters == null || !_hasArgumentInitializers(parameters)) {
return null;
@@ -934,10 +948,20 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
_defaultParamValue(param)
]));
}
+
+ // TODO(jmesserly): we could merge this with the named/optional code.
+ var paramType = param.element.type;
+ if (_hasTypeParameter(paramType)) {
+ body.add(js.statement(
+ 'dart.as(#, #);', [jsParam, _emitTypeName(paramType)]));
vsm 2015/04/30 14:00:51 At some point, it'd be cleaner to hoist this befor
Jennifer Messerly 2015/05/01 20:43:04 agreed, discussed offline, filed https://github.co
+ }
}
return _statement(body);
}
+ bool _hasTypeParameter(DartType t) => t is TypeParameterType ||
+ t is ParameterizedType && t.typeArguments.any(_hasTypeParameter);
+
JS.Expression _defaultParamValue(FormalParameter param) {
if (param is DefaultFormalParameter && param.defaultValue != null) {
return _visit(param.defaultValue);
@@ -1557,6 +1581,11 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
if (expr is Conversion) {
return _isNonNullableExpression(expr.expression);
}
+ if (expr is SimpleIdentifier) {
+ // Type literals are not null.
+ Element e = expr.staticElement;
+ if (e is ClassElement || e is FunctionTypeAliasElement) return true;
+ }
DartType type = null;
if (expr is BinaryExpression) {
type = getStaticType(expr.leftOperand);

Powered by Google App Engine
This is Rietveld 408576698