| 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 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 if (hide != null) { | 286 if (hide != null) { |
| 287 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); | 287 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); |
| 288 } | 288 } |
| 289 args.add(new JS.ArrayInitializer(shownNames)); | 289 args.add(new JS.ArrayInitializer(shownNames)); |
| 290 args.add(new JS.ArrayInitializer(hiddenNames)); | 290 args.add(new JS.ArrayInitializer(hiddenNames)); |
| 291 } | 291 } |
| 292 _moduleItems.add(js.statement('dart.export(#);', [args])); | 292 _moduleItems.add(js.statement('dart.export(#);', [args])); |
| 293 } | 293 } |
| 294 | 294 |
| 295 JS.Identifier _initSymbol(JS.Identifier id) { | 295 JS.Identifier _initSymbol(JS.Identifier id) { |
| 296 var s = js.statement('let # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); | 296 var s = js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]
); |
| 297 _moduleItems.add(s); | 297 _moduleItems.add(s); |
| 298 return id; | 298 return id; |
| 299 } | 299 } |
| 300 | 300 |
| 301 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, | 301 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, |
| 302 // until we have better name tracking. | 302 // until we have better name tracking. |
| 303 String get _SYMBOL { | 303 String get _SYMBOL { |
| 304 var name = currentLibrary.name; | 304 var name = currentLibrary.name; |
| 305 if (name == 'dart.core' || name == 'dart._internal') return 'dart.JsSymbol'; | 305 if (name == 'dart.core' || name == 'dart._internal') return 'dart.JsSymbol'; |
| 306 return 'Symbol'; | 306 return 'Symbol'; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 return null; | 359 return null; |
| 360 } | 360 } |
| 361 | 361 |
| 362 @override | 362 @override |
| 363 visitFunctionTypeAlias(FunctionTypeAlias node) { | 363 visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 364 var element = node.element; | 364 var element = node.element; |
| 365 var type = element.type; | 365 var type = element.type; |
| 366 var name = element.name; | 366 var name = element.name; |
| 367 | 367 |
| 368 var fnType = annotateTypeDef( | 368 var fnType = annotateTypeDef( |
| 369 js.statement('let # = dart.typedef(#, () => #);', [ | 369 js.statement('const # = dart.typedef(#, () => #);', [ |
| 370 name, | 370 name, |
| 371 js.string(name, "'"), | 371 js.string(name, "'"), |
| 372 _emitTypeName(type, lowerTypedef: true) | 372 _emitTypeName(type, lowerTypedef: true) |
| 373 ]), | 373 ]), |
| 374 node.element); | 374 node.element); |
| 375 | 375 |
| 376 return _finishClassDef(type, fnType); | 376 return _finishClassDef(type, fnType); |
| 377 } | 377 } |
| 378 | 378 |
| 379 @override | 379 @override |
| (...skipping 25 matching lines...) Expand all Loading... |
| 405 JS.Statement _emitJsType(String dartClassName, DartObject jsName) { | 405 JS.Statement _emitJsType(String dartClassName, DartObject jsName) { |
| 406 var jsTypeName = | 406 var jsTypeName = |
| 407 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); | 407 getConstantField(jsName, 'name', types.stringType)?.toStringValue(); |
| 408 | 408 |
| 409 if (jsTypeName != null && jsTypeName != dartClassName) { | 409 if (jsTypeName != null && jsTypeName != dartClassName) { |
| 410 // We export the JS type as if it was a Dart type. For example this allows | 410 // We export the JS type as if it was a Dart type. For example this allows |
| 411 // `dom.InputElement` to actually be HTMLInputElement. | 411 // `dom.InputElement` to actually be HTMLInputElement. |
| 412 // TODO(jmesserly): if we had the JS name on the Element, we could just | 412 // TODO(jmesserly): if we had the JS name on the Element, we could just |
| 413 // generate it correctly when we refer to it. | 413 // generate it correctly when we refer to it. |
| 414 if (isPublic(dartClassName)) _addExport(dartClassName); | 414 if (isPublic(dartClassName)) _addExport(dartClassName); |
| 415 return js.statement('let # = #;', [dartClassName, jsTypeName]); | 415 return js.statement('const # = #;', [dartClassName, jsTypeName]); |
| 416 } | 416 } |
| 417 return null; | 417 return null; |
| 418 } | 418 } |
| 419 | 419 |
| 420 @override | 420 @override |
| 421 JS.Statement visitClassDeclaration(ClassDeclaration node) { | 421 JS.Statement visitClassDeclaration(ClassDeclaration node) { |
| 422 var classElem = node.element; | 422 var classElem = node.element; |
| 423 var type = classElem.type; | 423 var type = classElem.type; |
| 424 var jsName = findAnnotation(classElem, isJSAnnotation); | 424 var jsName = findAnnotation(classElem, isJSAnnotation); |
| 425 | 425 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); | 555 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); |
| 556 } | 556 } |
| 557 return body; | 557 return body; |
| 558 } | 558 } |
| 559 | 559 |
| 560 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { | 560 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { |
| 561 var name = type.name; | 561 var name = type.name; |
| 562 var genericName = '$name\$'; | 562 var genericName = '$name\$'; |
| 563 var typeParams = type.typeParameters.map((p) => p.name); | 563 var typeParams = type.typeParameters.map((p) => p.name); |
| 564 if (isPublic(name)) _exports.add(genericName); | 564 if (isPublic(name)) _exports.add(genericName); |
| 565 return js.statement('let # = dart.generic(function(#) { #; return #; });', | 565 return js.statement('const # = dart.generic(function(#) { #; return #; });', |
| 566 [genericName, typeParams, body, name]); | 566 [genericName, typeParams, body, name]); |
| 567 } | 567 } |
| 568 | 568 |
| 569 final _hasDeferredSupertype = new HashSet<ClassElement>(); | 569 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
| 570 | 570 |
| 571 bool _deferIfNeeded(DartType type, ClassElement current) { | 571 bool _deferIfNeeded(DartType type, ClassElement current) { |
| 572 if (type is ParameterizedType) { | 572 if (type is ParameterizedType) { |
| 573 var typeArguments = type.typeArguments; | 573 var typeArguments = type.typeArguments; |
| 574 for (var typeArg in typeArguments) { | 574 for (var typeArg in typeArguments) { |
| 575 var typeElement = typeArg.element; | 575 var typeElement = typeArg.element; |
| (...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 var func = node.functionDeclaration; | 1453 var func = node.functionDeclaration; |
| 1454 if (func.isGetter || func.isSetter) { | 1454 if (func.isGetter || func.isSetter) { |
| 1455 return js.comment('Unimplemented function get/set statement: $node'); | 1455 return js.comment('Unimplemented function get/set statement: $node'); |
| 1456 } | 1456 } |
| 1457 | 1457 |
| 1458 var fn = _visit(func.functionExpression); | 1458 var fn = _visit(func.functionExpression); |
| 1459 | 1459 |
| 1460 var name = new JS.Identifier(func.name.name); | 1460 var name = new JS.Identifier(func.name.name); |
| 1461 JS.Statement declareFn; | 1461 JS.Statement declareFn; |
| 1462 if (JS.This.foundIn(fn)) { | 1462 if (JS.This.foundIn(fn)) { |
| 1463 declareFn = js.statement('let # = #.bind(this);', [name, fn]); | 1463 declareFn = js.statement('const # = #.bind(this);', [name, fn]); |
| 1464 } else { | 1464 } else { |
| 1465 declareFn = new JS.FunctionDeclaration(name, fn); | 1465 declareFn = new JS.FunctionDeclaration(name, fn); |
| 1466 } | 1466 } |
| 1467 declareFn = annotate(declareFn, node.functionDeclaration.element); | 1467 declareFn = annotate(declareFn, node.functionDeclaration.element); |
| 1468 | 1468 |
| 1469 return new JS.Block([ | 1469 return new JS.Block([ |
| 1470 declareFn, | 1470 declareFn, |
| 1471 _emitFunctionTagged(name, func.element.type).toStatement() | 1471 _emitFunctionTagged(name, func.element.type).toStatement() |
| 1472 ]); | 1472 ]); |
| 1473 } | 1473 } |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2040 eagerInit = false; | 2040 eagerInit = false; |
| 2041 } | 2041 } |
| 2042 | 2042 |
| 2043 var fieldName = field.name.name; | 2043 var fieldName = field.name.name; |
| 2044 if (field.isConst && eagerInit && element is TopLevelVariableElement) { | 2044 if (field.isConst && eagerInit && element is TopLevelVariableElement) { |
| 2045 // constant fields don't change, so we can generate them as `let` | 2045 // constant fields don't change, so we can generate them as `let` |
| 2046 // but add them to the module's exports. However, make sure we generate | 2046 // but add them to the module's exports. However, make sure we generate |
| 2047 // anything they depend on first. | 2047 // anything they depend on first. |
| 2048 | 2048 |
| 2049 if (isPublic(fieldName)) _addExport(fieldName); | 2049 if (isPublic(fieldName)) _addExport(fieldName); |
| 2050 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; |
| 2050 return annotateVariable( | 2051 return annotateVariable( |
| 2051 js.statement('let # = #;', [new JS.Identifier(fieldName), jsInit]), | 2052 js.statement('$declKeyword # = #;', |
| 2053 [new JS.Identifier(fieldName), jsInit]), |
| 2052 field.element); | 2054 field.element); |
| 2053 } | 2055 } |
| 2054 | 2056 |
| 2055 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { | 2057 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { |
| 2056 return annotateVariable( | 2058 return annotateVariable( |
| 2057 js.statement('# = #;', [_visit(field.name), jsInit]), field.element); | 2059 js.statement('# = #;', [_visit(field.name), jsInit]), field.element); |
| 2058 } | 2060 } |
| 2059 | 2061 |
| 2060 var body = <JS.Statement>[]; | 2062 var body = <JS.Statement>[]; |
| 2061 if (_lazyFields.isNotEmpty) { | 2063 if (_lazyFields.isNotEmpty) { |
| (...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3347 | 3349 |
| 3348 /// A special kind of element created by the compiler, signifying a temporary | 3350 /// A special kind of element created by the compiler, signifying a temporary |
| 3349 /// variable. These objects use instance equality, and should be shared | 3351 /// variable. These objects use instance equality, and should be shared |
| 3350 /// everywhere in the tree where they are treated as the same variable. | 3352 /// everywhere in the tree where they are treated as the same variable. |
| 3351 class TemporaryVariableElement extends LocalVariableElementImpl { | 3353 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3352 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3354 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3353 | 3355 |
| 3354 int get hashCode => identityHashCode(this); | 3356 int get hashCode => identityHashCode(this); |
| 3355 bool operator ==(Object other) => identical(this, other); | 3357 bool operator ==(Object other) => identical(this, other); |
| 3356 } | 3358 } |
| OLD | NEW |