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 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 | 303 |
304 String _jsTypeofName(DartType t) { | 304 String _jsTypeofName(DartType t) { |
305 if (rules.isIntType(t) || rules.isDoubleType(t)) return 'number'; | 305 if (rules.isIntType(t) || rules.isDoubleType(t)) return 'number'; |
306 if (rules.isStringType(t)) return 'string'; | 306 if (rules.isStringType(t)) return 'string'; |
307 if (rules.isBoolType(t)) return 'boolean'; | 307 if (rules.isBoolType(t)) return 'boolean'; |
308 return null; | 308 return null; |
309 } | 309 } |
310 | 310 |
311 @override | 311 @override |
312 visitFunctionTypeAlias(FunctionTypeAlias node) { | 312 visitFunctionTypeAlias(FunctionTypeAlias node) { |
313 // If we've already emitted this class, skip it. | |
314 var element = node.element; | 313 var element = node.element; |
315 var type = element.type; | 314 var type = element.type; |
316 var name = element.name; | 315 var name = element.name; |
317 | 316 |
318 var fnType = js.statement('let # = dart.typedef(#, () => #);', [ | 317 var fnType = js.statement('let # = dart.typedef(#, () => #);', [ |
319 name, | 318 name, |
320 js.string(name, "'"), | 319 js.string(name, "'"), |
321 _emitTypeName(type, lowerTypedef: true) | 320 _emitTypeName(type, lowerTypedef: true) |
322 ]); | 321 ]); |
323 | 322 |
324 return _finishClassDef(type, fnType); | 323 return _finishClassDef(type, fnType); |
325 } | 324 } |
326 | 325 |
327 @override | 326 @override |
328 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type); | 327 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type); |
329 | 328 |
330 @override | 329 @override |
331 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { | 330 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { |
332 // If we've already emitted this class, skip it. | |
333 var element = node.element; | 331 var element = node.element; |
334 | 332 |
| 333 // Forward all generative constructors from the base class. |
| 334 var body = []; |
| 335 |
| 336 var supertype = element.supertype; |
| 337 if (!supertype.isObject) { |
| 338 for (var ctor in element.constructors) { |
| 339 var parentCtor = supertype.lookUpConstructor(ctor.name, ctor.library); |
| 340 var fun = js.call('function() { super.#(...#); }', [ |
| 341 _constructorName(parentCtor), |
| 342 new JS.Identifier('arguments', allowRename: false) |
| 343 ]); |
| 344 body.add(new JS.Method(_constructorName(ctor), fun)); |
| 345 } |
| 346 } |
| 347 |
335 var classDecl = new JS.ClassDeclaration(new JS.ClassExpression( | 348 var classDecl = new JS.ClassDeclaration(new JS.ClassExpression( |
336 new JS.Identifier(element.name), _classHeritage(element), [])); | 349 new JS.Identifier(element.name), _classHeritage(element), body)); |
337 | 350 |
338 return _finishClassDef(element.type, classDecl); | 351 return _finishClassDef(element.type, classDecl); |
339 } | 352 } |
340 | 353 |
341 JS.Statement _emitJsType(String dartClassName, DartObjectImpl jsName) { | 354 JS.Statement _emitJsType(String dartClassName, DartObjectImpl jsName) { |
342 var jsTypeName = getConstantField(jsName, 'name', types.stringType); | 355 var jsTypeName = getConstantField(jsName, 'name', types.stringType); |
343 | 356 |
344 if (jsTypeName != null && jsTypeName != dartClassName) { | 357 if (jsTypeName != null && jsTypeName != dartClassName) { |
345 // We export the JS type as if it was a Dart type. For example this allows | 358 // We export the JS type as if it was a Dart type. For example this allows |
346 // `dom.InputElement` to actually be HTMLInputElement. | 359 // `dom.InputElement` to actually be HTMLInputElement. |
347 // TODO(jmesserly): if we had the JsName on the Element, we could just | 360 // TODO(jmesserly): if we had the JsName on the Element, we could just |
348 // generate it correctly when we refer to it. | 361 // generate it correctly when we refer to it. |
349 if (isPublic(dartClassName)) _addExport(dartClassName); | 362 if (isPublic(dartClassName)) _addExport(dartClassName); |
350 return js.statement('let # = #;', [dartClassName, jsTypeName]); | 363 return js.statement('let # = #;', [dartClassName, jsTypeName]); |
351 } | 364 } |
352 return null; | 365 return null; |
353 } | 366 } |
354 | 367 |
355 @override | 368 @override |
356 JS.Statement visitClassDeclaration(ClassDeclaration node) { | 369 JS.Statement visitClassDeclaration(ClassDeclaration node) { |
357 // If we've already emitted this class, skip it. | |
358 var classElem = node.element; | 370 var classElem = node.element; |
359 var type = classElem.type; | 371 var type = classElem.type; |
360 var jsName = findAnnotation(classElem, _isJsNameAnnotation); | 372 var jsName = findAnnotation(classElem, _isJsNameAnnotation); |
361 | 373 |
362 if (jsName != null) return _emitJsType(node.name.name, jsName); | 374 if (jsName != null) return _emitJsType(node.name.name, jsName); |
363 | 375 |
364 var ctors = <ConstructorDeclaration>[]; | 376 var ctors = <ConstructorDeclaration>[]; |
365 var fields = <FieldDeclaration>[]; | 377 var fields = <FieldDeclaration>[]; |
366 var methods = <MethodDeclaration>[]; | 378 var methods = <MethodDeclaration>[]; |
367 for (var member in node.members) { | 379 for (var member in node.members) { |
(...skipping 2422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2790 | 2802 |
2791 /// A special kind of element created by the compiler, signifying a temporary | 2803 /// A special kind of element created by the compiler, signifying a temporary |
2792 /// variable. These objects use instance equality, and should be shared | 2804 /// variable. These objects use instance equality, and should be shared |
2793 /// everywhere in the tree where they are treated as the same variable. | 2805 /// everywhere in the tree where they are treated as the same variable. |
2794 class TemporaryVariableElement extends LocalVariableElementImpl { | 2806 class TemporaryVariableElement extends LocalVariableElementImpl { |
2795 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2807 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
2796 | 2808 |
2797 int get hashCode => identityHashCode(this); | 2809 int get hashCode => identityHashCode(this); |
2798 bool operator ==(Object other) => identical(this, other); | 2810 bool operator ==(Object other) => identical(this, other); |
2799 } | 2811 } |
OLD | NEW |