| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dev_compiler.src.codegen.js_codegen; | 5 library dev_compiler.src.codegen.js_codegen; |
| 6 | 6 |
| 7 import 'dart:collection' show HashSet, HashMap; | 7 import 'dart:collection' show HashSet, HashMap; |
| 8 import 'dart:io' show Directory, File; | 8 import 'dart:io' show Directory, File; |
| 9 | 9 |
| 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 @override | 252 @override |
| 253 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { | 253 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { |
| 254 // If we've already emitted this class, skip it. | 254 // If we've already emitted this class, skip it. |
| 255 var classElem = node.element; | 255 var classElem = node.element; |
| 256 if (_pendingClasses.remove(classElem) == null) return null; | 256 if (_pendingClasses.remove(classElem) == null) return null; |
| 257 | 257 |
| 258 var name = node.name.name; | 258 var name = node.name.name; |
| 259 var heritage = | 259 var heritage = |
| 260 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]); | 260 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]); |
| 261 var classDecl = new JS.ClassDeclaration( | 261 var classDecl = new JS.ClassDeclaration( |
| 262 new JS.ClassExpression(new JS.VariableDeclaration(name), heritage, [])); | 262 new JS.ClassExpression(new JS.Identifier(name), heritage, [])); |
| 263 | 263 |
| 264 return _finishClassDef(classElem, classDecl); | 264 return _finishClassDef(classElem, classDecl); |
| 265 } | 265 } |
| 266 | 266 |
| 267 @override | 267 @override |
| 268 JS.Statement visitClassDeclaration(ClassDeclaration node) { | 268 JS.Statement visitClassDeclaration(ClassDeclaration node) { |
| 269 // If we've already emitted this class, skip it. | 269 // If we've already emitted this class, skip it. |
| 270 var classElem = node.element; | 270 var classElem = node.element; |
| 271 if (_pendingClasses.remove(classElem) == null) return null; | 271 if (_pendingClasses.remove(classElem) == null) return null; |
| 272 if (_getJsNameAnnotation(node) != null) return null; | 272 if (_getJsNameAnnotation(node) != null) return null; |
| 273 | 273 |
| 274 currentClass = node; | 274 currentClass = node; |
| 275 | 275 |
| 276 var name = classElem.name; | 276 var name = classElem.name; |
| 277 | 277 |
| 278 var ctors = <ConstructorDeclaration>[]; | 278 var ctors = <ConstructorDeclaration>[]; |
| 279 var fields = <FieldDeclaration>[]; | 279 var fields = <FieldDeclaration>[]; |
| 280 var staticFields = <FieldDeclaration>[]; | 280 var staticFields = <FieldDeclaration>[]; |
| 281 for (var member in node.members) { | 281 for (var member in node.members) { |
| 282 if (member is ConstructorDeclaration) { | 282 if (member is ConstructorDeclaration) { |
| 283 ctors.add(member); | 283 ctors.add(member); |
| 284 } else if (member is FieldDeclaration) { | 284 } else if (member is FieldDeclaration) { |
| 285 (member.isStatic ? staticFields : fields).add(member); | 285 (member.isStatic ? staticFields : fields).add(member); |
| 286 } | 286 } |
| 287 } | 287 } |
| 288 | 288 |
| 289 var classExpr = new JS.ClassExpression(new JS.VariableDeclaration(name), | 289 var classExpr = new JS.ClassExpression(new JS.Identifier(name), |
| 290 _classHeritage(node), _emitClassMethods(node, ctors, fields)); | 290 _classHeritage(node), _emitClassMethods(node, ctors, fields)); |
| 291 | 291 |
| 292 var body = _finishClassMembers(name, classExpr, ctors, staticFields); | 292 var body = _finishClassMembers(name, classExpr, ctors, staticFields); |
| 293 currentClass = null; | 293 currentClass = null; |
| 294 | 294 |
| 295 return _finishClassDef(classElem, body); | 295 return _finishClassDef(classElem, body); |
| 296 } | 296 } |
| 297 | 297 |
| 298 @override | 298 @override |
| 299 JS.Statement visitEnumDeclaration(EnumDeclaration node) => | 299 JS.Statement visitEnumDeclaration(EnumDeclaration node) => |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 for (var e in library.exports) { | 455 for (var e in library.exports) { |
| 456 if (result) break; | 456 if (result) break; |
| 457 result = _inLibraryCycle(e.exportedLibrary); | 457 result = _inLibraryCycle(e.exportedLibrary); |
| 458 } | 458 } |
| 459 return _libraryCycleMemo[library] = result; | 459 return _libraryCycleMemo[library] = result; |
| 460 } | 460 } |
| 461 | 461 |
| 462 JS.Statement _emitGenericClassDef(ClassElement cls, JS.Statement body) { | 462 JS.Statement _emitGenericClassDef(ClassElement cls, JS.Statement body) { |
| 463 var name = cls.name; | 463 var name = cls.name; |
| 464 var genericName = '$name\$'; | 464 var genericName = '$name\$'; |
| 465 var typeParams = cls.typeParameters.map((p) => new JS.Parameter(p.name)); | 465 var typeParams = cls.typeParameters.map((p) => p.name); |
| 466 return js.statement('let # = dart.generic(function(#) { #; return #; });', [ | 466 return js.statement('let # = dart.generic(function(#) { #; return #; });', [ |
| 467 genericName, | 467 genericName, |
| 468 typeParams, | 468 typeParams, |
| 469 body, | 469 body, |
| 470 name | 470 name |
| 471 ]); | 471 ]); |
| 472 } | 472 } |
| 473 | 473 |
| 474 JS.Expression _classHeritage(ClassDeclaration node) { | 474 JS.Expression _classHeritage(ClassDeclaration node) { |
| 475 if (node.element.type.isObject) return null; | 475 if (node.element.type.isObject) return null; |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 return null; | 854 return null; |
| 855 } | 855 } |
| 856 | 856 |
| 857 var body = <JS.Statement>[]; | 857 var body = <JS.Statement>[]; |
| 858 _flushLibraryProperties(body); | 858 _flushLibraryProperties(body); |
| 859 | 859 |
| 860 var name = node.name.name; | 860 var name = node.name.name; |
| 861 body.add(js.comment('Function $name: ${node.element.type}')); | 861 body.add(js.comment('Function $name: ${node.element.type}')); |
| 862 | 862 |
| 863 body.add(new JS.FunctionDeclaration( | 863 body.add(new JS.FunctionDeclaration( |
| 864 new JS.VariableDeclaration(name), _visit(node.functionExpression))); | 864 new JS.Identifier(name), _visit(node.functionExpression))); |
| 865 | 865 |
| 866 if (isPublic(name)) _exports.add(name); | 866 if (isPublic(name)) _exports.add(name); |
| 867 return _statement(body); | 867 return _statement(body); |
| 868 } | 868 } |
| 869 | 869 |
| 870 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { | 870 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { |
| 871 var name = node.name.name; | 871 var name = node.name.name; |
| 872 return new JS.Method(_propertyName(name), _visit(node.functionExpression), | 872 return new JS.Method(_propertyName(name), _visit(node.functionExpression), |
| 873 isGetter: node.isGetter, isSetter: node.isSetter); | 873 isGetter: node.isGetter, isSetter: node.isSetter); |
| 874 } | 874 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 898 } | 898 } |
| 899 | 899 |
| 900 @override | 900 @override |
| 901 JS.Statement visitFunctionDeclarationStatement( | 901 JS.Statement visitFunctionDeclarationStatement( |
| 902 FunctionDeclarationStatement node) { | 902 FunctionDeclarationStatement node) { |
| 903 var func = node.functionDeclaration; | 903 var func = node.functionDeclaration; |
| 904 if (func.isGetter || func.isSetter) { | 904 if (func.isGetter || func.isSetter) { |
| 905 return js.comment('Unimplemented function get/set statement: $node'); | 905 return js.comment('Unimplemented function get/set statement: $node'); |
| 906 } | 906 } |
| 907 | 907 |
| 908 var name = new JS.VariableDeclaration(func.name.name); | 908 var name = new JS.Identifier(func.name.name); |
| 909 return new JS.Block([ | 909 return new JS.Block([ |
| 910 js.comment("// Function ${func.name.name}: ${func.element.type}\n"), | 910 js.comment("// Function ${func.name.name}: ${func.element.type}\n"), |
| 911 new JS.FunctionDeclaration(name, _visit(func.functionExpression)) | 911 new JS.FunctionDeclaration(name, _visit(func.functionExpression)) |
| 912 ]); | 912 ]); |
| 913 } | 913 } |
| 914 | 914 |
| 915 /// Writes a simple identifier. This can handle implicit `this` as well as | 915 /// Writes a simple identifier. This can handle implicit `this` as well as |
| 916 /// going through the qualified library name if necessary. | 916 /// going through the qualified library name if necessary. |
| 917 @override | 917 @override |
| 918 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { | 918 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { |
| 919 var e = node.staticElement; | 919 var e = node.staticElement; |
| 920 if (e == null) { | 920 if (e == null) { |
| 921 return js.commentExpression( | 921 return js.commentExpression( |
| 922 'Unimplemented unknown name', new JS.VariableUse(node.name)); | 922 'Unimplemented unknown name', new JS.Identifier(node.name)); |
| 923 } | 923 } |
| 924 | 924 |
| 925 var name = node.name; | 925 var name = node.name; |
| 926 var variable = e is PropertyAccessorElement ? e.variable : e; | 926 var variable = e is PropertyAccessorElement ? e.variable : e; |
| 927 | 927 |
| 928 if (e.enclosingElement is CompilationUnitElement && | 928 if (e.enclosingElement is CompilationUnitElement && |
| 929 (e.library != libraryInfo.library || | 929 (e.library != libraryInfo.library || |
| 930 variable is TopLevelVariableElement && !variable.isConst)) { | 930 variable is TopLevelVariableElement && !variable.isConst)) { |
| 931 return js.call('#.#', [_libraryName(e.library), name]); | 931 return js.call('#.#', [_libraryName(e.library), name]); |
| 932 } else if (currentClass != null && _needsImplicitThis(e)) { | 932 } else if (currentClass != null && _needsImplicitThis(e)) { |
| 933 return js.call('this.#', _jsMemberName(name)); | 933 return js.call('this.#', _jsMemberName(name)); |
| 934 } else if (variable is ConstFieldElementImpl) { | 934 } else if (variable is ConstFieldElementImpl) { |
| 935 var className = (variable.enclosingElement as ClassElement).name; | 935 var className = (variable.enclosingElement as ClassElement).name; |
| 936 return js.call('#.#', [className, name]); | 936 return js.call('#.#', [className, name]); |
| 937 } else if (e is ParameterElement && e.isInitializingFormal) { | 937 } else if (e is ParameterElement && e.isInitializingFormal) { |
| 938 name = _fieldParameterName(name); | 938 name = _fieldParameterName(name); |
| 939 } | 939 } |
| 940 return new JS.VariableUse(name); | 940 return new JS.Identifier(name); |
| 941 } | 941 } |
| 942 | 942 |
| 943 JS.Expression _emitTypeName(DartType type) { | 943 JS.Expression _emitTypeName(DartType type) { |
| 944 var name = type.name; | 944 var name = type.name; |
| 945 var element = type.element; | 945 var element = type.element; |
| 946 if (name == '') { | 946 if (name == '') { |
| 947 // TODO(jmesserly): remove when we're using coercion reifier. | 947 // TODO(jmesserly): remove when we're using coercion reifier. |
| 948 return _unimplementedCall('Unimplemented type $type'); | 948 return _unimplementedCall('Unimplemented type $type'); |
| 949 } | 949 } |
| 950 | 950 |
| 951 var typeArgs = null; | 951 var typeArgs = null; |
| 952 if (type is ParameterizedType) { | 952 if (type is ParameterizedType) { |
| 953 // TODO(jmesserly): this is a workaround for an analyzer bug, see: | 953 // TODO(jmesserly): this is a workaround for an analyzer bug, see: |
| 954 // https://github.com/dart-lang/dev_compiler/commit/a212d59ad046085a626dd8
d16881cdb8e8b9c3fa | 954 // https://github.com/dart-lang/dev_compiler/commit/a212d59ad046085a626dd8
d16881cdb8e8b9c3fa |
| 955 if (type is! FunctionType || element is FunctionTypeAlias) { | 955 if (type is! FunctionType || element is FunctionTypeAlias) { |
| 956 var args = type.typeArguments; | 956 var args = type.typeArguments; |
| 957 if (args.any((a) => a != rules.provider.dynamicType)) { | 957 if (args.any((a) => a != rules.provider.dynamicType)) { |
| 958 name = '$name\$'; | 958 name = '$name\$'; |
| 959 typeArgs = args.map(_emitTypeName); | 959 typeArgs = args.map(_emitTypeName); |
| 960 } | 960 } |
| 961 } | 961 } |
| 962 } | 962 } |
| 963 | 963 |
| 964 JS.Expression result; | 964 JS.Expression result; |
| 965 if (_needQualifiedName(element)) { | 965 if (_needQualifiedName(element)) { |
| 966 result = js.call('#.#', [_libraryName(element.library), name]); | 966 result = js.call('#.#', [_libraryName(element.library), name]); |
| 967 } else { | 967 } else { |
| 968 result = new JS.VariableUse(name); | 968 result = new JS.Identifier(name); |
| 969 } | 969 } |
| 970 | 970 |
| 971 if (typeArgs != null) { | 971 if (typeArgs != null) { |
| 972 result = js.call('#(#)', [result, typeArgs]); | 972 result = js.call('#(#)', [result, typeArgs]); |
| 973 } | 973 } |
| 974 return result; | 974 return result; |
| 975 } | 975 } |
| 976 | 976 |
| 977 bool _needQualifiedName(Element element) { | 977 bool _needQualifiedName(Element element) { |
| 978 var lib = element.library; | 978 var lib = element.library; |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1151 } | 1151 } |
| 1152 | 1152 |
| 1153 @override | 1153 @override |
| 1154 JS.Property visitNamedExpression(NamedExpression node) { | 1154 JS.Property visitNamedExpression(NamedExpression node) { |
| 1155 assert(node.parent is ArgumentList); | 1155 assert(node.parent is ArgumentList); |
| 1156 return new JS.Property( | 1156 return new JS.Property( |
| 1157 _propertyName(node.name.label.name), _visit(node.expression)); | 1157 _propertyName(node.name.label.name), _visit(node.expression)); |
| 1158 } | 1158 } |
| 1159 | 1159 |
| 1160 @override | 1160 @override |
| 1161 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) { | 1161 List<JS.Identifier> visitFormalParameterList(FormalParameterList node) { |
| 1162 var result = <JS.Parameter>[]; | 1162 var result = <JS.Identifier>[]; |
| 1163 for (FormalParameter param in node.parameters) { | 1163 for (FormalParameter param in node.parameters) { |
| 1164 if (param.kind == ParameterKind.NAMED) { | 1164 if (param.kind == ParameterKind.NAMED) { |
| 1165 result.add(new JS.Parameter(r'opt$')); | 1165 result.add(new JS.Identifier(r'opt$')); |
| 1166 break; | 1166 break; |
| 1167 } | 1167 } |
| 1168 result.add(_visit(param)); | 1168 result.add(_visit(param)); |
| 1169 } | 1169 } |
| 1170 return result; | 1170 return result; |
| 1171 } | 1171 } |
| 1172 | 1172 |
| 1173 @override | 1173 @override |
| 1174 JS.Statement visitExpressionStatement(ExpressionStatement node) => | 1174 JS.Statement visitExpressionStatement(ExpressionStatement node) => |
| 1175 _expressionStatement(_visit(node.expression)); | 1175 _expressionStatement(_visit(node.expression)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1197 @override | 1197 @override |
| 1198 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { | 1198 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
| 1199 var body = <JS.Statement>[]; | 1199 var body = <JS.Statement>[]; |
| 1200 | 1200 |
| 1201 for (var field in node.variables.variables) { | 1201 for (var field in node.variables.variables) { |
| 1202 if (field.isConst) { | 1202 if (field.isConst) { |
| 1203 // constant fields don't change, so we can generate them as `let` | 1203 // constant fields don't change, so we can generate them as `let` |
| 1204 // but add them to the module's exports | 1204 // but add them to the module's exports |
| 1205 var name = field.name.name; | 1205 var name = field.name.name; |
| 1206 body.add(js.statement('let # = #;', [ | 1206 body.add(js.statement('let # = #;', [ |
| 1207 new JS.VariableDeclaration(name), | 1207 new JS.Identifier(name), |
| 1208 _visitInitializer(field) | 1208 _visitInitializer(field) |
| 1209 ])); | 1209 ])); |
| 1210 if (isPublic(name)) _exports.add(name); | 1210 if (isPublic(name)) _exports.add(name); |
| 1211 } else if (_isFieldInitConstant(field)) { | 1211 } else if (_isFieldInitConstant(field)) { |
| 1212 body.add(js.statement( | 1212 body.add(js.statement( |
| 1213 '# = #;', [_visit(field.name), _visitInitializer(field)])); | 1213 '# = #;', [_visit(field.name), _visitInitializer(field)])); |
| 1214 } else { | 1214 } else { |
| 1215 _lazyFields.add(field); | 1215 _lazyFields.add(field); |
| 1216 } | 1216 } |
| 1217 } | 1217 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1232 // We can reuse the variable to desugar it: | 1232 // We can reuse the variable to desugar it: |
| 1233 // var result = []..length = length; | 1233 // var result = []..length = length; |
| 1234 // becomes: | 1234 // becomes: |
| 1235 // var result = []; | 1235 // var result = []; |
| 1236 // result.length = length; | 1236 // result.length = length; |
| 1237 var savedCascadeTemp = _cascadeTarget; | 1237 var savedCascadeTemp = _cascadeTarget; |
| 1238 _cascadeTarget = last.name; | 1238 _cascadeTarget = last.name; |
| 1239 | 1239 |
| 1240 variables = _visitList(node.variables.take(node.variables.length - 1)); | 1240 variables = _visitList(node.variables.take(node.variables.length - 1)); |
| 1241 variables.add(new JS.VariableInitialization( | 1241 variables.add(new JS.VariableInitialization( |
| 1242 new JS.VariableDeclaration(last.name.name), | 1242 new JS.Identifier(last.name.name), |
| 1243 _visit(lastInitializer.target))); | 1243 _visit(lastInitializer.target))); |
| 1244 | 1244 |
| 1245 var result = | 1245 var result = |
| 1246 <JS.Expression>[new JS.VariableDeclarationList('let', variables)]; | 1246 <JS.Expression>[new JS.VariableDeclarationList('let', variables)]; |
| 1247 result.addAll(_visitList(lastInitializer.cascadeSections)); | 1247 result.addAll(_visitList(lastInitializer.cascadeSections)); |
| 1248 _cascadeTarget = savedCascadeTemp; | 1248 _cascadeTarget = savedCascadeTemp; |
| 1249 return _statement(result.map((e) => new JS.ExpressionStatement(e))); | 1249 return _statement(result.map((e) => new JS.ExpressionStatement(e))); |
| 1250 } else { | 1250 } else { |
| 1251 variables = _visitList(node.variables); | 1251 variables = _visitList(node.variables); |
| 1252 } | 1252 } |
| 1253 | 1253 |
| 1254 return new JS.VariableDeclarationList('let', variables); | 1254 return new JS.VariableDeclarationList('let', variables); |
| 1255 } | 1255 } |
| 1256 | 1256 |
| 1257 @override | 1257 @override |
| 1258 JS.VariableInitialization visitVariableDeclaration(VariableDeclaration node) { | 1258 JS.VariableInitialization visitVariableDeclaration(VariableDeclaration node) { |
| 1259 var name = new JS.VariableDeclaration(node.name.name); | 1259 var name = new JS.Identifier(node.name.name); |
| 1260 return new JS.VariableInitialization(name, _visitInitializer(node)); | 1260 return new JS.VariableInitialization(name, _visitInitializer(node)); |
| 1261 } | 1261 } |
| 1262 | 1262 |
| 1263 JS.Expression _visitInitializer(VariableDeclaration node) { | 1263 JS.Expression _visitInitializer(VariableDeclaration node) { |
| 1264 var value = _visit(node.initializer); | 1264 var value = _visit(node.initializer); |
| 1265 // explicitly initialize to null, to avoid getting `undefined`. | 1265 // explicitly initialize to null, to avoid getting `undefined`. |
| 1266 // TODO(jmesserly): do this only for vars that aren't definitely assigned. | 1266 // TODO(jmesserly): do this only for vars that aren't definitely assigned. |
| 1267 return value != null ? value : new JS.LiteralNull(); | 1267 return value != null ? value : new JS.LiteralNull(); |
| 1268 } | 1268 } |
| 1269 | 1269 |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1634 return false; | 1634 return false; |
| 1635 } | 1635 } |
| 1636 | 1636 |
| 1637 @override | 1637 @override |
| 1638 visitParenthesizedExpression(ParenthesizedExpression node) => | 1638 visitParenthesizedExpression(ParenthesizedExpression node) => |
| 1639 // The printer handles precedence so we don't need to. | 1639 // The printer handles precedence so we don't need to. |
| 1640 _visit(node.expression); | 1640 _visit(node.expression); |
| 1641 | 1641 |
| 1642 @override | 1642 @override |
| 1643 visitFormalParameter(FormalParameter node) => | 1643 visitFormalParameter(FormalParameter node) => |
| 1644 new JS.Parameter(node.identifier.name); | 1644 new JS.Identifier(node.identifier.name); |
| 1645 | 1645 |
| 1646 @override | 1646 @override |
| 1647 visitFieldFormalParameter(FieldFormalParameter node) => | 1647 visitFieldFormalParameter(FieldFormalParameter node) => |
| 1648 new JS.Parameter(_fieldParameterName(node.identifier.name)); | 1648 new JS.Identifier(_fieldParameterName(node.identifier.name)); |
| 1649 | 1649 |
| 1650 /// Rename private names so they don't shadow the private field symbol. | 1650 /// Rename private names so they don't shadow the private field symbol. |
| 1651 // TODO(jmesserly): replace this ad-hoc rename with a general strategy. | 1651 // TODO(jmesserly): replace this ad-hoc rename with a general strategy. |
| 1652 _fieldParameterName(name) => name.startsWith('_') ? '\$$name' : name; | 1652 _fieldParameterName(name) => name.startsWith('_') ? '\$$name' : name; |
| 1653 | 1653 |
| 1654 @override | 1654 @override |
| 1655 JS.This visitThisExpression(ThisExpression node) => new JS.This(); | 1655 JS.This visitThisExpression(ThisExpression node) => new JS.This(); |
| 1656 | 1656 |
| 1657 @override | 1657 @override |
| 1658 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); | 1658 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1788 _catchParameter = '\$e'; | 1788 _catchParameter = '\$e'; |
| 1789 | 1789 |
| 1790 if (clauses.length == 1) { | 1790 if (clauses.length == 1) { |
| 1791 // Special case for a single catch. | 1791 // Special case for a single catch. |
| 1792 var clause = clauses.single; | 1792 var clause = clauses.single; |
| 1793 if (clause.exceptionParameter != null) { | 1793 if (clause.exceptionParameter != null) { |
| 1794 _catchParameter = clause.exceptionParameter.name; | 1794 _catchParameter = clause.exceptionParameter.name; |
| 1795 } | 1795 } |
| 1796 } | 1796 } |
| 1797 | 1797 |
| 1798 var catchVarDecl = new JS.VariableDeclaration(_catchParameter); | 1798 var catchVarDecl = new JS.Identifier(_catchParameter); |
| 1799 var catchBody = new JS.Block(_visitList(clauses)); | 1799 var catchBody = new JS.Block(_visitList(clauses)); |
| 1800 _catchParameter = savedCatch; | 1800 _catchParameter = savedCatch; |
| 1801 | 1801 |
| 1802 return new JS.Catch(catchVarDecl, catchBody); | 1802 return new JS.Catch(catchVarDecl, catchBody); |
| 1803 } | 1803 } |
| 1804 | 1804 |
| 1805 JS.Statement _statement(Iterable stmts) { | 1805 JS.Statement _statement(Iterable stmts) { |
| 1806 var s = stmts is List ? stmts : new List<JS.Statement>.from(stmts); | 1806 var s = stmts is List ? stmts : new List<JS.Statement>.from(stmts); |
| 1807 // TODO(jmesserly): empty block singleton? | 1807 // TODO(jmesserly): empty block singleton? |
| 1808 if (s.length == 0) return new JS.Block([]); | 1808 if (s.length == 0) return new JS.Block([]); |
| 1809 if (s.length == 1) return s[0]; | 1809 if (s.length == 1) return s[0]; |
| 1810 return new JS.Block(s); | 1810 return new JS.Block(s); |
| 1811 } | 1811 } |
| 1812 | 1812 |
| 1813 @override | 1813 @override |
| 1814 JS.Statement visitCatchClause(CatchClause node) { | 1814 JS.Statement visitCatchClause(CatchClause node) { |
| 1815 var body = []; | 1815 var body = []; |
| 1816 | 1816 |
| 1817 var savedCatch = _catchParameter; | 1817 var savedCatch = _catchParameter; |
| 1818 if (node.catchKeyword != null) { | 1818 if (node.catchKeyword != null) { |
| 1819 var name = node.exceptionParameter; | 1819 var name = node.exceptionParameter; |
| 1820 if (name != null && name.name != _catchParameter) { | 1820 if (name != null && name.name != _catchParameter) { |
| 1821 var decl = new JS.VariableDeclaration(name.name); | 1821 var decl = new JS.Identifier(name.name); |
| 1822 decl.sourceInformation = name; | 1822 decl.sourceInformation = name; |
| 1823 body.add(js.statement('let # = #;', [decl, _catchParameter])); | 1823 body.add(js.statement('let # = #;', [decl, _catchParameter])); |
| 1824 _catchParameter = name.name; | 1824 _catchParameter = name.name; |
| 1825 } | 1825 } |
| 1826 if (node.stackTraceParameter != null) { | 1826 if (node.stackTraceParameter != null) { |
| 1827 var stackVar = node.stackTraceParameter.name; | 1827 var stackVar = node.stackTraceParameter.name; |
| 1828 body.add(js.statement( | 1828 body.add(js.statement( |
| 1829 'let # = dart.stackTrace(#);', [stackVar, _visit(name)])); | 1829 'let # = dart.stackTrace(#);', [stackVar, _visit(name)])); |
| 1830 } | 1830 } |
| 1831 } | 1831 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2067 /// | 2067 /// |
| 2068 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed | 2068 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed |
| 2069 /// for this transformation to happen, otherwise binary minus is assumed. | 2069 /// for this transformation to happen, otherwise binary minus is assumed. |
| 2070 /// | 2070 /// |
| 2071 /// Equality is a bit special, it is generated via the Dart `equals` runtime | 2071 /// Equality is a bit special, it is generated via the Dart `equals` runtime |
| 2072 /// helper, that checks for null. The user defined method is called '=='. | 2072 /// helper, that checks for null. The user defined method is called '=='. |
| 2073 /// | 2073 /// |
| 2074 JS.Expression _jsMemberName(String name, {bool unary: false}) { | 2074 JS.Expression _jsMemberName(String name, {bool unary: false}) { |
| 2075 if (name.startsWith('_')) { | 2075 if (name.startsWith('_')) { |
| 2076 if (_privateNames.add(name)) _pendingPrivateNames.add(name); | 2076 if (_privateNames.add(name)) _pendingPrivateNames.add(name); |
| 2077 return new JS.VariableUse(name); | 2077 return new JS.Identifier(name); |
| 2078 } | 2078 } |
| 2079 if (name == '[]') { | 2079 if (name == '[]') { |
| 2080 name = 'get'; | 2080 name = 'get'; |
| 2081 } else if (name == '[]=') { | 2081 } else if (name == '[]=') { |
| 2082 name = 'set'; | 2082 name = 'set'; |
| 2083 } else if (unary && name == '-') { | 2083 } else if (unary && name == '-') { |
| 2084 name = 'unary-'; | 2084 name = 'unary-'; |
| 2085 } | 2085 } |
| 2086 return _propertyName(name); | 2086 return _propertyName(name); |
| 2087 } | 2087 } |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2312 | 2312 |
| 2313 // TODO(jmesserly): in many cases marking the end will be unncessary. | 2313 // TODO(jmesserly): in many cases marking the end will be unncessary. |
| 2314 printer.mark(_location(node.end)); | 2314 printer.mark(_location(node.end)); |
| 2315 } | 2315 } |
| 2316 | 2316 |
| 2317 String _getIdentifier(AstNode node) { | 2317 String _getIdentifier(AstNode node) { |
| 2318 if (node is SimpleIdentifier) return node.name; | 2318 if (node is SimpleIdentifier) return node.name; |
| 2319 return null; | 2319 return null; |
| 2320 } | 2320 } |
| 2321 } | 2321 } |
| OLD | NEW |