| 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, SplayTreeSet; | 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
| 11 import 'package:analyzer/src/generated/constant.dart'; | 11 import 'package:analyzer/src/generated/constant.dart'; |
| 12 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
| 13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| 14 import 'package:analyzer/src/generated/scanner.dart' | 14 import 'package:analyzer/src/generated/scanner.dart' |
| 15 show StringToken, Token, TokenType; | 15 show StringToken, Token, TokenType; |
| 16 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder; | 16 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder; |
| 17 | 17 |
| 18 import 'package:dev_compiler/src/codegen/ast_builder.dart' show AstBuilder; | 18 import 'package:dev_compiler/src/codegen/ast_builder.dart' show AstBuilder; |
| 19 import 'package:dev_compiler/src/codegen/reify_coercions.dart' | 19 import 'package:dev_compiler/src/codegen/reify_coercions.dart' |
| 20 show CoercionReifier; | 20 show CoercionReifier; |
| 21 | 21 |
| 22 // TODO(jmesserly): import from its own package | 22 // TODO(jmesserly): import from its own package |
| 23 import 'package:dev_compiler/src/js/js_ast.dart' as JS; | 23 import 'package:dev_compiler/src/js/js_ast.dart' as JS; |
| 24 import 'package:dev_compiler/src/js/js_ast.dart' show js; | 24 import 'package:dev_compiler/src/js/js_ast.dart' show js; |
| 25 | 25 |
| 26 import 'package:dev_compiler/src/closure/closure_annotator.dart' show ClosureAnn
otator; | 26 import 'package:dev_compiler/src/closure/closure_annotator.dart' |
| 27 show ClosureAnnotator; |
| 27 import 'package:dev_compiler/src/compiler.dart' show AbstractCompiler; | 28 import 'package:dev_compiler/src/compiler.dart' show AbstractCompiler; |
| 28 import 'package:dev_compiler/src/checker/rules.dart'; | 29 import 'package:dev_compiler/src/checker/rules.dart'; |
| 29 import 'package:dev_compiler/src/info.dart'; | 30 import 'package:dev_compiler/src/info.dart'; |
| 30 import 'package:dev_compiler/src/options.dart' show CodegenOptions; | 31 import 'package:dev_compiler/src/options.dart' show CodegenOptions; |
| 31 import 'package:dev_compiler/src/utils.dart'; | 32 import 'package:dev_compiler/src/utils.dart'; |
| 32 | 33 |
| 33 import 'code_generator.dart'; | 34 import 'code_generator.dart'; |
| 34 import 'js_field_storage.dart'; | 35 import 'js_field_storage.dart'; |
| 35 import 'js_names.dart' as JS; | 36 import 'js_names.dart' as JS; |
| 36 import 'js_metalet.dart' as JS; | 37 import 'js_metalet.dart' as JS; |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 if (rules.isBoolType(t)) return 'boolean'; | 361 if (rules.isBoolType(t)) return 'boolean'; |
| 361 return null; | 362 return null; |
| 362 } | 363 } |
| 363 | 364 |
| 364 @override | 365 @override |
| 365 visitFunctionTypeAlias(FunctionTypeAlias node) { | 366 visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 366 var element = node.element; | 367 var element = node.element; |
| 367 var type = element.type; | 368 var type = element.type; |
| 368 var name = element.name; | 369 var name = element.name; |
| 369 | 370 |
| 370 var fnType = annotateTypeDef(js.statement('let # = dart.typedef(#, () => #);
', | 371 var fnType = annotateTypeDef( |
| 371 [name, js.string(name, "'"), _emitTypeName(type, lowerTypedef: true)]), | 372 js.statement('let # = dart.typedef(#, () => #);', [ |
| 373 name, |
| 374 js.string(name, "'"), |
| 375 _emitTypeName(type, lowerTypedef: true) |
| 376 ]), |
| 372 node.element); | 377 node.element); |
| 373 | 378 |
| 374 return _finishClassDef(type, fnType); | 379 return _finishClassDef(type, fnType); |
| 375 } | 380 } |
| 376 | 381 |
| 377 @override | 382 @override |
| 378 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type); | 383 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type); |
| 379 | 384 |
| 380 @override | 385 @override |
| 381 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { | 386 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { |
| (...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 return result === void 0 ? this : result; | 943 return result === void 0 ? this : result; |
| 939 }''') as JS.Block; | 944 }''') as JS.Block; |
| 940 } else { | 945 } else { |
| 941 body = _emitConstructorBody(node, fields); | 946 body = _emitConstructorBody(node, fields); |
| 942 } | 947 } |
| 943 | 948 |
| 944 // We generate constructors as initializer methods in the class; | 949 // We generate constructors as initializer methods in the class; |
| 945 // this allows use of `super` for instance methods/properties. | 950 // this allows use of `super` for instance methods/properties. |
| 946 // It also avoids V8 restrictions on `super` in default constructors. | 951 // It also avoids V8 restrictions on `super` in default constructors. |
| 947 return annotate( | 952 return annotate( |
| 948 new JS.Method( | 953 new JS.Method(name, |
| 949 name, new JS.Fun(_visit(node.parameters) as List<JS.Parameter>, body
)) | 954 new JS.Fun(_visit(node.parameters) as List<JS.Parameter>, body)) |
| 950 ..sourceInformation = node, | 955 ..sourceInformation = node, |
| 951 node.element); | 956 node.element); |
| 952 } | 957 } |
| 953 | 958 |
| 954 JS.Expression _constructorName(ConstructorElement ctor) { | 959 JS.Expression _constructorName(ConstructorElement ctor) { |
| 955 var name = ctor.name; | 960 var name = ctor.name; |
| 956 if (name != '') { | 961 if (name != '') { |
| 957 return _emitMemberName(name, isStatic: true); | 962 return _emitMemberName(name, isStatic: true); |
| 958 } | 963 } |
| 959 | 964 |
| 960 // Factory default constructors use `new` as their name, for readability | 965 // Factory default constructors use `new` as their name, for readability |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 if (parameters == null) return null; | 1159 if (parameters == null) return null; |
| 1155 | 1160 |
| 1156 var body = <JS.Statement>[]; | 1161 var body = <JS.Statement>[]; |
| 1157 for (var param in parameters.parameters) { | 1162 for (var param in parameters.parameters) { |
| 1158 var jsParam = _visit(param.identifier); | 1163 var jsParam = _visit(param.identifier); |
| 1159 | 1164 |
| 1160 if (param.kind == ParameterKind.NAMED) { | 1165 if (param.kind == ParameterKind.NAMED) { |
| 1161 // Parameters will be passed using their real names, not the (possibly | 1166 // Parameters will be passed using their real names, not the (possibly |
| 1162 // renamed) local variable. | 1167 // renamed) local variable. |
| 1163 var paramName = js.string(param.identifier.name, "'"); | 1168 var paramName = js.string(param.identifier.name, "'"); |
| 1164 | 1169 |
| 1165 // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming | 1170 // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming |
| 1166 // (either test if `obj.prop !== void 0`, or use JSCompiler_renameProper
ty). | 1171 // (either test if `obj.prop !== void 0`, or use JSCompiler_renameProper
ty). |
| 1167 body.add(js.statement('let # = # && # in # ? #.# : #;', [ | 1172 body.add(js.statement('let # = # && # in # ? #.# : #;', [ |
| 1168 jsParam, | 1173 jsParam, |
| 1169 _namedArgTemp, | 1174 _namedArgTemp, |
| 1170 paramName, | 1175 paramName, |
| 1171 _namedArgTemp, | 1176 _namedArgTemp, |
| 1172 _namedArgTemp, | 1177 _namedArgTemp, |
| 1173 paramName, | 1178 paramName, |
| 1174 _defaultParamValue(param), | 1179 _defaultParamValue(param), |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1226 // Rewrite the function to include the return. | 1231 // Rewrite the function to include the return. |
| 1227 fn = new JS.Fun(fn.params, new JS.Block([body, returnValue])) | 1232 fn = new JS.Fun(fn.params, new JS.Block([body, returnValue])) |
| 1228 ..sourceInformation = fn.sourceInformation; | 1233 ..sourceInformation = fn.sourceInformation; |
| 1229 } | 1234 } |
| 1230 | 1235 |
| 1231 return annotate( | 1236 return annotate( |
| 1232 new JS.Method(_elementMemberName(node.element), fn, | 1237 new JS.Method(_elementMemberName(node.element), fn, |
| 1233 isGetter: node.isGetter, | 1238 isGetter: node.isGetter, |
| 1234 isSetter: node.isSetter, | 1239 isSetter: node.isSetter, |
| 1235 isStatic: node.isStatic), | 1240 isStatic: node.isStatic), |
| 1236 node.element); | 1241 node.element); |
| 1237 } | 1242 } |
| 1238 | 1243 |
| 1239 @override | 1244 @override |
| 1240 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { | 1245 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { |
| 1241 assert(node.parent is CompilationUnit); | 1246 assert(node.parent is CompilationUnit); |
| 1242 | 1247 |
| 1243 if (_externalOrNative(node)) return null; | 1248 if (_externalOrNative(node)) return null; |
| 1244 | 1249 |
| 1245 if (node.isGetter || node.isSetter) { | 1250 if (node.isGetter || node.isSetter) { |
| 1246 // Add these later so we can use getter/setter syntax. | 1251 // Add these later so we can use getter/setter syntax. |
| (...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2010 // anything they depend on first. | 2015 // anything they depend on first. |
| 2011 | 2016 |
| 2012 if (isPublic(fieldName)) _addExport(fieldName); | 2017 if (isPublic(fieldName)) _addExport(fieldName); |
| 2013 return annotateVariable( | 2018 return annotateVariable( |
| 2014 js.statement('let # = #;', [new JS.Identifier(fieldName), jsInit]), | 2019 js.statement('let # = #;', [new JS.Identifier(fieldName), jsInit]), |
| 2015 field.element); | 2020 field.element); |
| 2016 } | 2021 } |
| 2017 | 2022 |
| 2018 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { | 2023 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { |
| 2019 return annotateVariable( | 2024 return annotateVariable( |
| 2020 js.statement('# = #;', [_visit(field.name), jsInit]), | 2025 js.statement('# = #;', [_visit(field.name), jsInit]), field.element); |
| 2021 field.element); | |
| 2022 } | 2026 } |
| 2023 | 2027 |
| 2024 var body = <JS.Statement>[]; | 2028 var body = <JS.Statement>[]; |
| 2025 if (_lazyFields.isNotEmpty) { | 2029 if (_lazyFields.isNotEmpty) { |
| 2026 var existingTarget = _lazyFields[0].element.enclosingElement; | 2030 var existingTarget = _lazyFields[0].element.enclosingElement; |
| 2027 if (existingTarget != element.enclosingElement) { | 2031 if (existingTarget != element.enclosingElement) { |
| 2028 _flushLazyFields(body); | 2032 _flushLazyFields(body); |
| 2029 } | 2033 } |
| 2030 } | 2034 } |
| 2031 | 2035 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2073 JS.Expression objExpr = _exportsVar; | 2077 JS.Expression objExpr = _exportsVar; |
| 2074 var target = _lazyFields[0].element.enclosingElement; | 2078 var target = _lazyFields[0].element.enclosingElement; |
| 2075 if (target is ClassElement) { | 2079 if (target is ClassElement) { |
| 2076 objExpr = new JS.Identifier(target.type.name); | 2080 objExpr = new JS.Identifier(target.type.name); |
| 2077 } | 2081 } |
| 2078 | 2082 |
| 2079 return js.statement( | 2083 return js.statement( |
| 2080 'dart.defineLazyProperties(#, { # });', [objExpr, methods]); | 2084 'dart.defineLazyProperties(#, { # });', [objExpr, methods]); |
| 2081 } | 2085 } |
| 2082 | 2086 |
| 2083 PropertyAccessorElement _findAccessor(VariableElement element, {bool getter})
{ | 2087 PropertyAccessorElement _findAccessor(VariableElement element, |
| 2084 var parent = element.enclosingElement; | 2088 {bool getter}) { |
| 2089 var parent = element.enclosingElement; |
| 2085 if (parent is ClassElement) { | 2090 if (parent is ClassElement) { |
| 2086 return getter ? parent.getGetter(element.name) : parent.getSetter(element.
name); | 2091 return getter |
| 2092 ? parent.getGetter(element.name) |
| 2093 : parent.getSetter(element.name); |
| 2087 } | 2094 } |
| 2088 return null; | 2095 return null; |
| 2089 } | 2096 } |
| 2090 | 2097 |
| 2091 void _flushLibraryProperties(List<JS.Statement> body) { | 2098 void _flushLibraryProperties(List<JS.Statement> body) { |
| 2092 if (_properties.isEmpty) return; | 2099 if (_properties.isEmpty) return; |
| 2093 body.add(js.statement('dart.copyProperties(#, { # });', | 2100 body.add(js.statement('dart.copyProperties(#, { # });', |
| 2094 [_exportsVar, _properties.map(_emitTopLevelProperty)])); | 2101 [_exportsVar, _properties.map(_emitTopLevelProperty)])); |
| 2095 _properties.clear(); | 2102 _properties.clear(); |
| 2096 } | 2103 } |
| (...skipping 1095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3192 DartType getStaticType(Expression e) => rules.getStaticType(e); | 3199 DartType getStaticType(Expression e) => rules.getStaticType(e); |
| 3193 | 3200 |
| 3194 @override | 3201 @override |
| 3195 String getQualifiedName(TypeDefiningElement type) { | 3202 String getQualifiedName(TypeDefiningElement type) { |
| 3196 JS.TemporaryId id = _imports[type.library]; | 3203 JS.TemporaryId id = _imports[type.library]; |
| 3197 return id == null ? type.name : '${id.name}.${type.name}'; | 3204 return id == null ? type.name : '${id.name}.${type.name}'; |
| 3198 } | 3205 } |
| 3199 | 3206 |
| 3200 JS.Node annotate(JS.Node method, ExecutableElement e) => | 3207 JS.Node annotate(JS.Node method, ExecutableElement e) => |
| 3201 options.closure && e != null | 3208 options.closure && e != null |
| 3202 ? method.withClosureAnnotation(closureAnnotationFor(e, _namedArgTemp.n
ame)) | 3209 ? method.withClosureAnnotation( |
| 3210 closureAnnotationFor(e, _namedArgTemp.name)) |
| 3203 : method; | 3211 : method; |
| 3204 | 3212 |
| 3205 JS.Node annotateDefaultConstructor(JS.Node method, ClassElement e) => | 3213 JS.Node annotateDefaultConstructor(JS.Node method, ClassElement e) => |
| 3206 options.closure && e != null | 3214 options.closure && e != null |
| 3207 ? method.withClosureAnnotation(closureAnnotationForDefaultConstructor(
e)) | 3215 ? method |
| 3216 .withClosureAnnotation(closureAnnotationForDefaultConstructor(e)) |
| 3208 : method; | 3217 : method; |
| 3209 | 3218 |
| 3210 JS.Node annotateVariable(JS.Node node, VariableElement e) => | 3219 JS.Node annotateVariable(JS.Node node, VariableElement e) => |
| 3211 options.closure && e != null | 3220 options.closure && e != null |
| 3212 ? node.withClosureAnnotation(closureAnnotationForVariable(e)) | 3221 ? node.withClosureAnnotation(closureAnnotationForVariable(e)) |
| 3213 : node; | 3222 : node; |
| 3214 | 3223 |
| 3215 JS.Node annotateTypeDef(JS.Node node, FunctionTypeAliasElement e) => | 3224 JS.Node annotateTypeDef(JS.Node node, FunctionTypeAliasElement e) => |
| 3216 options.closure && e != null | 3225 options.closure && e != null |
| 3217 ? node.withClosureAnnotation(closureAnnotationForTypeDef(e)) | 3226 ? node.withClosureAnnotation(closureAnnotationForTypeDef(e)) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3280 | 3289 |
| 3281 /// A special kind of element created by the compiler, signifying a temporary | 3290 /// A special kind of element created by the compiler, signifying a temporary |
| 3282 /// variable. These objects use instance equality, and should be shared | 3291 /// variable. These objects use instance equality, and should be shared |
| 3283 /// everywhere in the tree where they are treated as the same variable. | 3292 /// everywhere in the tree where they are treated as the same variable. |
| 3284 class TemporaryVariableElement extends LocalVariableElementImpl { | 3293 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3285 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3294 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3286 | 3295 |
| 3287 int get hashCode => identityHashCode(this); | 3296 int get hashCode => identityHashCode(this); |
| 3288 bool operator ==(Object other) => identical(this, other); | 3297 bool operator ==(Object other) => identical(this, other); |
| 3289 } | 3298 } |
| OLD | NEW |