Chromium Code Reviews| Index: pkg/dev_compiler/lib/src/compiler/code_generator.dart |
| diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
| index 9deaaa4fa053320d93a13df21a5d4f3fb4bdeee7..31b30abeed87b429e427b5061b08dbed5a715a20 100644 |
| --- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
| +++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
| @@ -44,7 +44,7 @@ import 'js_interop.dart'; |
| import 'js_metalet.dart' as JS; |
| import 'js_names.dart' as JS; |
| import 'js_typeref_codegen.dart' show JsTypeRefCodegen; |
| -import 'js_typerep.dart' show JSTypeRep; |
| +import 'js_typerep.dart' show JSTypeRep, JSType; |
| import 'module_builder.dart' show pathToJSIdentifier; |
| import 'nullable_type_inference.dart' show NullableTypeInference; |
| import 'property_model.dart'; |
| @@ -135,8 +135,11 @@ class CodeGenerator extends Object |
| /// The dart:core `identical` element. |
| final FunctionElement _coreIdentical; |
| - /// The dart:_interceptors JSArray element. |
| + /// The dart:_interceptors implementation elements. |
| final ClassElement _jsArray; |
| + final ClassElement _jsBool; |
| + final ClassElement _jsNumber; |
| + final ClassElement _jsString; |
| final ClassElement boolClass; |
| final ClassElement intClass; |
| @@ -205,6 +208,9 @@ class CodeGenerator extends Object |
| _coreIdentical = |
| _getLibrary(c, 'dart:core').publicNamespace.get('identical'), |
| _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), |
| + _jsBool = _getLibrary(c, 'dart:_interceptors').getType('JSBool'), |
| + _jsString = _getLibrary(c, 'dart:_interceptors').getType('JSString'), |
| + _jsNumber = _getLibrary(c, 'dart:_interceptors').getType('JSNumber'), |
| interceptorClass = |
| _getLibrary(c, 'dart:_interceptors').getType('Interceptor'), |
| dartCoreLibrary = _getLibrary(c, 'dart:core'), |
| @@ -2432,6 +2438,9 @@ class CodeGenerator extends Object |
| var castType = _emitType(paramElement.type); |
| body.add(js.statement('#._check(#);', [castType, jsParam])); |
| } |
| + if (_annotatedNullCheck(paramElement)) { |
| + body.add(nullParameterCheck(jsParam)); |
| + } |
| } |
| return body.isEmpty ? null : _statement(body); |
| } |
| @@ -3267,6 +3276,9 @@ class CodeGenerator extends Object |
| // (for example, x is IndexExpression) we evaluate those once. |
| var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| var lhs = _bindLeftHandSide(vars, left, context: context); |
| + // TODO(leafp): The element for lhs here will be the setter element |
| + // instead of the getter element if lhs is a property access. This |
| + // interferes with nullability analysis. |
|
Jennifer Messerly
2017/08/22 21:54:41
FYI ... I think it would be safe to fix _bindLeftH
Leaf
2017/08/23 17:26:14
Not super high priority, but good to fix at some p
|
| Expression inc = AstBuilder.binaryExpression(lhs, op, right) |
| ..staticElement = element |
| ..staticType = getStaticType(lhs); |
| @@ -4050,7 +4062,10 @@ class CodeGenerator extends Object |
| var v = variables[0]; |
| if (v.initializer != null) { |
| var name = new JS.Identifier(v.name.name); |
| - return _visit<JS.Expression>(v.initializer).toVariableDeclaration(name); |
| + var value = _annotatedNullCheck(v.element) |
| + ? notNull(v.initializer) |
| + : _visit<JS.Expression>(v.initializer); |
| + return value.toVariableDeclaration(name); |
| } |
| } |
| return _visit<JS.Expression>(node.variables).toStatement(); |
| @@ -4093,7 +4108,9 @@ class CodeGenerator extends Object |
| } |
| JS.Expression _visitInitializer(VariableDeclaration node) { |
| - var value = _visit(node.initializer); |
| + var value = _annotatedNullCheck(node.element) |
| + ? notNull(node.initializer) |
| + : _visit(node.initializer); |
| // explicitly initialize to null, to avoid getting `undefined`. |
| // TODO(jmesserly): do this only for vars that aren't definitely assigned. |
| return value ?? new JS.LiteralNull(); |
| @@ -4254,6 +4271,20 @@ class CodeGenerator extends Object |
| bool isPrimitiveType(DartType t) => typeRep.isPrimitive(t); |
| + InterfaceType getImplementationType(DartType t) { |
|
Jennifer Messerly
2017/08/22 21:54:41
add a doc comment?
/// Given a Dart type for `boo
Leaf
2017/08/23 17:26:14
Done.
|
| + JSType rep = typeRep.typeFor(t); |
| + // Number, String, and Bool are final |
| + if (rep == JSType.jsNumber) return _jsNumber.type; |
| + if (rep == JSType.jsBoolean) return _jsBool.type; |
| + if (rep == JSType.jsString) return _jsString.type; |
| + return null; |
| + } |
| + |
| + JS.Statement nullParameterCheck(JS.Expression param) { |
| + var call = _callHelper('throwArgumentErrorValue((#))', [param]); |
|
Jennifer Messerly
2017/08/22 21:54:41
if these are really common, consider a shorter nam
Leaf
2017/08/23 17:26:13
Done.
|
| + return js.statement('if (# == null) #;', [param, call]); |
| + } |
| + |
| JS.Expression notNull(Expression expr) { |
| if (expr == null) return null; |
| var jsExpr = _visit(expr); |
| @@ -5116,10 +5147,17 @@ class CodeGenerator extends Object |
| } |
| var init = _visit(node.identifier); |
| + var iterable = _visit(node.iterable); |
| + var body = _visitScope(node.body); |
| if (init == null) { |
| - init = js.call('let #', node.loopVariable.identifier.name); |
| + var name = node.loopVariable.identifier.name; |
| + init = js.call('let #', name); |
| + if (_annotatedNullCheck(node.loopVariable.element)) { |
| + body = |
| + new JS.Block([nullParameterCheck(new JS.Identifier(name)), body]); |
| + } |
| } |
| - return new JS.ForOf(init, _visit(node.iterable), _visitScope(node.body)); |
| + return new JS.ForOf(init, iterable, body); |
| } |
| JS.Statement _emitAwaitFor(ForEachStatement node) { |
| @@ -5999,3 +6037,6 @@ bool _isDeferredLoadLibrary(Expression target, SimpleIdentifier name) { |
| var imports = containingLibrary.getImportsWithPrefix(prefix); |
| return imports.length == 1 && imports[0].isDeferred; |
| } |
| + |
| +bool _annotatedNullCheck(Element e) => |
| + (e != null) && (findAnnotation(e, isNullCheckAnnotation) != null); |
|
Jennifer Messerly
2017/08/22 21:54:41
fyi, parens not necessary
Leaf
2017/08/23 17:26:14
Done.
|