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

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
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | test/browser/runtime_tests.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/codegen/js_codegen.dart
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
index 0c9199c7f46c6969dd6918f2c7b413ca89946466..a0c750b5519a024c9da84f430df81edab25777b9 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] = () => #;', [
@@ -744,7 +755,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
// Generate optional/named argument value assignment. These can not have
// side effects, and may be used by the constructor's initializers, so it's
// nice to do them first.
- var init = _emitArgumentInitializers(node.parameters);
+ var init = _emitArgumentInitializers(node, constructor: true);
if (init != null) body.add(init);
// Redirecting constructors: these are not allowed to have initializers,
@@ -890,26 +901,24 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
}
FormalParameterList _parametersOf(node) {
- // Note: ConstructorDeclaration is intentionally skipped here so we can
- // emit the argument initializers in a different place.
// TODO(jmesserly): clean this up. If we can model ES6 spread/rest args, we
// could handle argument initializers more consistently in a separate
// lowering pass.
+ if (node is ConstructorDeclaration) return node.parameters;
if (node is MethodDeclaration) return node.parameters;
if (node is FunctionDeclaration) node = node.functionExpression;
- if (node is FunctionExpression) return node.parameters;
- return null;
+ return (node as FunctionExpression).parameters;
}
- bool _hasArgumentInitializers(FormalParameterList parameters) {
- if (parameters == null) return false;
- return parameters.parameters.any((p) => p.kind != ParameterKind.REQUIRED);
- }
+ /// Emits argument initializers, which handles optional/named args, as well
+ /// as generic type checks needed due to our covariance.
+ JS.Statement _emitArgumentInitializers(node, {bool constructor: false}) {
+ // Constructor argument initializers are emitted earlier in the code, rather
+ // than always when we visit the function body, so we control it explicitly.
+ if (node is ConstructorDeclaration != constructor) return null;
- JS.Statement _emitArgumentInitializers(FormalParameterList parameters) {
- if (parameters == null || !_hasArgumentInitializers(parameters)) {
- return null;
- }
+ var parameters = _parametersOf(node);
+ if (parameters == null) return null;
var body = [];
for (var param in parameters.parameters) {
@@ -935,10 +944,21 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
_defaultParamValue(param)
]));
}
+
+ // TODO(jmesserly): various problems here, see:
+ // https://github.com/dart-lang/dev_compiler/issues/161
+ var paramType = param.element.type;
+ if (!constructor && _hasTypeParameter(paramType)) {
+ body.add(js.statement(
+ 'dart.as(#, #);', [jsParam, _emitTypeName(paramType)]));
+ }
}
- return _statement(body);
+ return body.isEmpty ? null : _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);
@@ -1239,7 +1259,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
@override
JS.Block visitExpressionFunctionBody(ExpressionFunctionBody node) {
- var initArgs = _emitArgumentInitializers(_parametersOf(node.parent));
+ var initArgs = _emitArgumentInitializers(node.parent);
var ret = new JS.Return(_visit(node.expression));
return new JS.Block(initArgs != null ? [initArgs, ret] : [ret]);
}
@@ -1249,7 +1269,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
@override
JS.Block visitBlockFunctionBody(BlockFunctionBody node) {
- var initArgs = _emitArgumentInitializers(_parametersOf(node.parent));
+ var initArgs = _emitArgumentInitializers(node.parent);
var block = visitBlock(node.block);
if (initArgs != null) return new JS.Block([initArgs, block]);
return block;
@@ -1558,6 +1578,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);
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | test/browser/runtime_tests.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698