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; |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 var code = _visit(node); | 242 var code = _visit(node); |
243 if (code != null) _moduleItems.add(code); | 243 if (code != null) _moduleItems.add(code); |
244 } | 244 } |
245 | 245 |
246 @override | 246 @override |
247 void visitLibraryDirective(LibraryDirective node) { | 247 void visitLibraryDirective(LibraryDirective node) { |
248 assert(_jsModuleValue == null); | 248 assert(_jsModuleValue == null); |
249 | 249 |
250 var jsName = findAnnotation(node.element, _isJsNameAnnotation); | 250 var jsName = findAnnotation(node.element, _isJsNameAnnotation); |
251 _jsModuleValue = | 251 _jsModuleValue = |
252 getConstantField(jsName, 'name', types.stringType) as String; | 252 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); |
253 } | 253 } |
254 | 254 |
255 @override | 255 @override |
256 void visitImportDirective(ImportDirective node) { | 256 void visitImportDirective(ImportDirective node) { |
257 // Nothing to do yet, but we'll want to convert this to an ES6 import once | 257 // Nothing to do yet, but we'll want to convert this to an ES6 import once |
258 // we have support for modules. | 258 // we have support for modules. |
259 } | 259 } |
260 | 260 |
261 @override void visitPartDirective(PartDirective node) {} | 261 @override void visitPartDirective(PartDirective node) {} |
262 @override void visitPartOfDirective(PartOfDirective node) {} | 262 @override void visitPartOfDirective(PartOfDirective node) {} |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 body.add(new JS.Method(_constructorName(ctor), fun)); | 394 body.add(new JS.Method(_constructorName(ctor), fun)); |
395 } | 395 } |
396 } | 396 } |
397 | 397 |
398 var classDecl = new JS.ClassDeclaration(new JS.ClassExpression( | 398 var classDecl = new JS.ClassDeclaration(new JS.ClassExpression( |
399 new JS.Identifier(element.name), _classHeritage(element), body)); | 399 new JS.Identifier(element.name), _classHeritage(element), body)); |
400 | 400 |
401 return _finishClassDef(element.type, classDecl); | 401 return _finishClassDef(element.type, classDecl); |
402 } | 402 } |
403 | 403 |
404 JS.Statement _emitJsType(String dartClassName, DartObjectImpl jsName) { | 404 JS.Statement _emitJsType(String dartClassName, DartObject jsName) { |
405 var jsTypeName = getConstantField(jsName, 'name', types.stringType); | 405 var jsTypeName = |
| 406 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); |
406 | 407 |
407 if (jsTypeName != null && jsTypeName != dartClassName) { | 408 if (jsTypeName != null && jsTypeName != dartClassName) { |
408 // We export the JS type as if it was a Dart type. For example this allows | 409 // We export the JS type as if it was a Dart type. For example this allows |
409 // `dom.InputElement` to actually be HTMLInputElement. | 410 // `dom.InputElement` to actually be HTMLInputElement. |
410 // TODO(jmesserly): if we had the JsName on the Element, we could just | 411 // TODO(jmesserly): if we had the JsName on the Element, we could just |
411 // generate it correctly when we refer to it. | 412 // generate it correctly when we refer to it. |
412 if (isPublic(dartClassName)) _addExport(dartClassName); | 413 if (isPublic(dartClassName)) _addExport(dartClassName); |
413 return js.statement('let # = #;', [dartClassName, jsTypeName]); | 414 return js.statement('let # = #;', [dartClassName, jsTypeName]); |
414 } | 415 } |
415 return null; | 416 return null; |
(...skipping 19 matching lines...) Expand all Loading... |
435 methods.add(member); | 436 methods.add(member); |
436 } | 437 } |
437 } | 438 } |
438 | 439 |
439 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), | 440 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), |
440 _classHeritage(classElem), _emitClassMethods(node, ctors, fields)); | 441 _classHeritage(classElem), _emitClassMethods(node, ctors, fields)); |
441 | 442 |
442 String jsPeerName; | 443 String jsPeerName; |
443 var jsPeer = findAnnotation(classElem, _isJsPeerInterface); | 444 var jsPeer = findAnnotation(classElem, _isJsPeerInterface); |
444 if (jsPeer != null) { | 445 if (jsPeer != null) { |
445 jsPeerName = getConstantField(jsPeer, 'name', types.stringType) as String; | 446 jsPeerName = |
| 447 getConstantField(jsPeer, 'name', types.stringType)?.toStringValue(); |
446 } | 448 } |
447 | 449 |
448 var body = _finishClassMembers(classElem, classExpr, ctors, fields, methods, | 450 var body = _finishClassMembers(classElem, classExpr, ctors, fields, methods, |
449 node.metadata, jsPeerName); | 451 node.metadata, jsPeerName); |
450 | 452 |
451 var result = _finishClassDef(type, body); | 453 var result = _finishClassDef(type, body); |
452 | 454 |
453 if (jsPeerName != null) { | 455 if (jsPeerName != null) { |
454 // This class isn't allowed to be lazy, because we need to set up | 456 // This class isn't allowed to be lazy, because we need to set up |
455 // the native JS type eagerly at this point. | 457 // the native JS type eagerly at this point. |
(...skipping 2837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3293 /// declaration) as it doesn't have any meaningful rules enforced. | 3295 /// declaration) as it doesn't have any meaningful rules enforced. |
3294 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); | 3296 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); |
3295 | 3297 |
3296 /// Shorthand for identifier-like property names. | 3298 /// Shorthand for identifier-like property names. |
3297 /// For now, we emit them as strings and the printer restores them to | 3299 /// For now, we emit them as strings and the printer restores them to |
3298 /// identifiers if it can. | 3300 /// identifiers if it can. |
3299 // TODO(jmesserly): avoid the round tripping through quoted form. | 3301 // TODO(jmesserly): avoid the round tripping through quoted form. |
3300 JS.LiteralString _propertyName(String name) => js.string(name, "'"); | 3302 JS.LiteralString _propertyName(String name) => js.string(name, "'"); |
3301 | 3303 |
3302 // TODO(jmesserly): validate the library. See issue #135. | 3304 // TODO(jmesserly): validate the library. See issue #135. |
3303 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; | 3305 bool _isJsNameAnnotation(DartObject value) => value.type.name == 'JsName'; |
3304 | 3306 |
3305 bool _isJsPeerInterface(DartObjectImpl value) => | 3307 bool _isJsPeerInterface(DartObject value) => |
3306 value.type.name == 'JsPeerInterface'; | 3308 value.type.name == 'JsPeerInterface'; |
3307 | 3309 |
3308 // TODO(jacobr): we would like to do something like the following | 3310 // TODO(jacobr): we would like to do something like the following |
3309 // but we don't have summary support yet. | 3311 // but we don't have summary support yet. |
3310 // bool _supportJsExtensionMethod(AnnotatedNode node) => | 3312 // bool _supportJsExtensionMethod(AnnotatedNode node) => |
3311 // _getAnnotation(node, "SupportJsExtensionMethod") != null; | 3313 // _getAnnotation(node, "SupportJsExtensionMethod") != null; |
3312 | 3314 |
3313 /// A special kind of element created by the compiler, signifying a temporary | 3315 /// A special kind of element created by the compiler, signifying a temporary |
3314 /// variable. These objects use instance equality, and should be shared | 3316 /// variable. These objects use instance equality, and should be shared |
3315 /// everywhere in the tree where they are treated as the same variable. | 3317 /// everywhere in the tree where they are treated as the same variable. |
3316 class TemporaryVariableElement extends LocalVariableElementImpl { | 3318 class TemporaryVariableElement extends LocalVariableElementImpl { |
3317 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3319 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
3318 | 3320 |
3319 int get hashCode => identityHashCode(this); | 3321 int get hashCode => identityHashCode(this); |
3320 bool operator ==(Object other) => identical(this, other); | 3322 bool operator ==(Object other) => identical(this, other); |
3321 } | 3323 } |
OLD | NEW |