| 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 | 2 |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 | 5 |
| 6 import 'dart:collection' show HashMap, HashSet; | 6 import 'dart:collection' show HashMap, HashSet; |
| 7 import 'dart:math' show min, max; | 7 import 'dart:math' show min, max; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 /// name scoping requirements. | 67 /// name scoping requirements. |
| 68 final _libraries = new Map<LibraryElement, JS.Identifier>(); | 68 final _libraries = new Map<LibraryElement, JS.Identifier>(); |
| 69 | 69 |
| 70 /// Imported libraries, and the temporaries used to refer to them. | 70 /// Imported libraries, and the temporaries used to refer to them. |
| 71 final _imports = new Map<LibraryElement, JS.TemporaryId>(); | 71 final _imports = new Map<LibraryElement, JS.TemporaryId>(); |
| 72 | 72 |
| 73 /// The list of output module items, in the order they need to be emitted in. | 73 /// The list of output module items, in the order they need to be emitted in. |
| 74 final _moduleItems = <JS.ModuleItem>[]; | 74 final _moduleItems = <JS.ModuleItem>[]; |
| 75 | 75 |
| 76 /// Table of named and possibly hoisted types. | 76 /// Table of named and possibly hoisted types. |
| 77 final _typeTable = new TypeTable(); | 77 TypeTable _typeTable; |
| 78 | 78 |
| 79 /// The global extension type table. | 79 /// The global extension type table. |
| 80 final ExtensionTypeSet _extensionTypes; | 80 final ExtensionTypeSet _extensionTypes; |
| 81 | 81 |
| 82 /// The variable for the target of the current `..` cascade expression. | 82 /// The variable for the target of the current `..` cascade expression. |
| 83 /// | 83 /// |
| 84 /// Usually a [SimpleIdentifier], but it can also be other expressions | 84 /// Usually a [SimpleIdentifier], but it can also be other expressions |
| 85 /// that are safe to evaluate multiple times, such as `this`. | 85 /// that are safe to evaluate multiple times, such as `this`. |
| 86 Expression _cascadeTarget; | 86 Expression _cascadeTarget; |
| 87 | 87 |
| 88 /// The variable for the current catch clause | 88 /// The variable for the current catch clause |
| 89 SimpleIdentifier _catchParameter; | 89 SimpleIdentifier _catchParameter; |
| 90 | 90 |
| 91 /// In an async* function, this represents the stream controller parameter. | 91 /// In an async* function, this represents the stream controller parameter. |
| 92 JS.TemporaryId _asyncStarController; | 92 JS.TemporaryId _asyncStarController; |
| 93 | 93 |
| 94 // TODO(jmesserly): fuse this with notNull check. | 94 // TODO(jmesserly): fuse this with notNull check. |
| 95 final _privateNames = | 95 final _privateNames = |
| 96 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); | 96 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); |
| 97 final _initializingFormalTemps = | 97 final _initializingFormalTemps = |
| 98 new HashMap<ParameterElement, JS.TemporaryId>(); | 98 new HashMap<ParameterElement, JS.TemporaryId>(); |
| 99 | 99 |
| 100 final _dartxVar = new JS.Identifier('dartx'); | 100 JS.Identifier _extensionSymbolsModule; |
| 101 final _runtimeLibVar = new JS.Identifier('dart'); | 101 JS.Identifier _runtimeModule; |
| 102 final namedArgumentTemp = new JS.TemporaryId('opts'); | 102 final namedArgumentTemp = new JS.TemporaryId('opts'); |
| 103 | 103 |
| 104 final _hasDeferredSupertype = new HashSet<ClassElement>(); | 104 final _hasDeferredSupertype = new HashSet<ClassElement>(); |
| 105 | 105 |
| 106 final _eagerTopLevelFields = new HashSet<Element>.identity(); | 106 final _eagerTopLevelFields = new HashSet<Element>.identity(); |
| 107 | 107 |
| 108 /// The type provider from the current Analysis [context]. | 108 /// The type provider from the current Analysis [context]. |
| 109 final TypeProvider types; | 109 final TypeProvider types; |
| 110 | 110 |
| 111 final LibraryElement dartCoreLibrary; | 111 final LibraryElement dartCoreLibrary; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 } | 224 } |
| 225 | 225 |
| 226 JS.Program _emitModule(List<CompilationUnit> compilationUnits) { | 226 JS.Program _emitModule(List<CompilationUnit> compilationUnits) { |
| 227 if (_moduleItems.isNotEmpty) { | 227 if (_moduleItems.isNotEmpty) { |
| 228 throw new StateError('Can only call emitModule once.'); | 228 throw new StateError('Can only call emitModule once.'); |
| 229 } | 229 } |
| 230 | 230 |
| 231 // Transform the AST to make coercions explicit. | 231 // Transform the AST to make coercions explicit. |
| 232 compilationUnits = CoercionReifier.reify(compilationUnits); | 232 compilationUnits = CoercionReifier.reify(compilationUnits); |
| 233 | 233 |
| 234 if (compilationUnits.any((u) => _isDartRuntime(u.element.library))) { |
| 235 // Don't allow these to be renamed when we're building the SDK. |
| 236 // There is JS code in dart:* that depends on their names. |
| 237 _runtimeModule = new JS.Identifier('dart'); |
| 238 _extensionSymbolsModule = new JS.Identifier('dartx'); |
| 239 } else { |
| 240 // Otherwise allow these to be renamed so users can write them. |
| 241 _runtimeModule = new JS.TemporaryId('dart'); |
| 242 _extensionSymbolsModule = new JS.TemporaryId('dartx'); |
| 243 } |
| 244 _typeTable = new TypeTable(_runtimeModule); |
| 245 |
| 234 // Initialize our library variables. | 246 // Initialize our library variables. |
| 235 var items = <JS.ModuleItem>[]; | 247 var items = <JS.ModuleItem>[]; |
| 236 for (var unit in compilationUnits) { | 248 for (var unit in compilationUnits) { |
| 237 var library = unit.element.library; | 249 var library = unit.element.library; |
| 238 if (unit.element != library.definingCompilationUnit) continue; | 250 if (unit.element != library.definingCompilationUnit) continue; |
| 239 | 251 |
| 240 var libraryTemp = _isDartRuntime(library) | 252 var libraryTemp = _isDartRuntime(library) |
| 241 ? _runtimeLibVar | 253 ? _runtimeModule |
| 242 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); | 254 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); |
| 243 _libraries[library] = libraryTemp; | 255 _libraries[library] = libraryTemp; |
| 244 items.add(new JS.ExportDeclaration( | 256 items.add(new JS.ExportDeclaration( |
| 245 js.call('const # = Object.create(null)', [libraryTemp]))); | 257 js.call('const # = Object.create(null)', [libraryTemp]))); |
| 246 | 258 |
| 247 // dart:_runtime has a magic module that holds extension method symbols. | 259 // dart:_runtime has a magic module that holds extension method symbols. |
| 248 // TODO(jmesserly): find a cleaner design for this. | 260 // TODO(jmesserly): find a cleaner design for this. |
| 249 if (_isDartRuntime(library)) { | 261 if (_isDartRuntime(library)) { |
| 250 items.add(new JS.ExportDeclaration( | 262 items.add(new JS.ExportDeclaration(js |
| 251 js.call('const # = Object.create(null)', [_dartxVar]))); | 263 .call('const # = Object.create(null)', [_extensionSymbolsModule]))); |
| 252 } | 264 } |
| 253 } | 265 } |
| 254 | 266 |
| 255 // Collect all Element -> Node mappings, in case we need to forward declare | 267 // Collect all Element -> Node mappings, in case we need to forward declare |
| 256 // any nodes. | 268 // any nodes. |
| 257 var nodes = new HashMap<Element, AstNode>.identity(); | 269 var nodes = new HashMap<Element, AstNode>.identity(); |
| 258 var sdkBootstrappingFns = new List<FunctionElement>(); | 270 var sdkBootstrappingFns = new List<FunctionElement>(); |
| 259 for (var unit in compilationUnits) { | 271 for (var unit in compilationUnits) { |
| 260 if (_isDartRuntime(unit.element.library)) { | 272 if (_isDartRuntime(unit.element.library)) { |
| 261 sdkBootstrappingFns.addAll(unit.element.functions); | 273 sdkBootstrappingFns.addAll(unit.element.functions); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 elementJSParts.add(e.name); | 337 elementJSParts.add(e.name); |
| 326 } | 338 } |
| 327 | 339 |
| 328 return libraryPrefix..addAll(elementJSParts); | 340 return libraryPrefix..addAll(elementJSParts); |
| 329 } | 341 } |
| 330 | 342 |
| 331 JS.Expression _emitJSInterop(Element e) { | 343 JS.Expression _emitJSInterop(Element e) { |
| 332 var jsName = _getJSName(e); | 344 var jsName = _getJSName(e); |
| 333 if (jsName == null) return null; | 345 if (jsName == null) return null; |
| 334 var fullName = ['global']..addAll(jsName); | 346 var fullName = ['global']..addAll(jsName); |
| 335 JS.Expression access = _runtimeLibVar; | 347 JS.Expression access = _runtimeModule; |
| 336 for (var part in fullName) { | 348 for (var part in fullName) { |
| 337 access = new JS.PropertyAccess(access, js.string(part)); | 349 access = new JS.PropertyAccess(access, js.string(part)); |
| 338 } | 350 } |
| 339 return access; | 351 return access; |
| 340 } | 352 } |
| 341 | 353 |
| 342 /// Flattens blocks in [items] to a single list. | 354 /// Flattens blocks in [items] to a single list. |
| 343 /// | 355 /// |
| 344 /// This will not flatten blocks that are marked as being scopes. | 356 /// This will not flatten blocks that are marked as being scopes. |
| 345 void _copyAndFlattenBlocks( | 357 void _copyAndFlattenBlocks( |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 // Our import variables are temps and can get renamed. Since our renaming | 396 // Our import variables are temps and can get renamed. Since our renaming |
| 385 // is integrated into js_ast, it is aware of this possibility and will | 397 // is integrated into js_ast, it is aware of this possibility and will |
| 386 // generate an "as" if needed. For example: | 398 // generate an "as" if needed. For example: |
| 387 // | 399 // |
| 388 // import {foo} from 'foo'; // if no rename needed | 400 // import {foo} from 'foo'; // if no rename needed |
| 389 // import {foo as foo$} from 'foo'; // if rename was needed | 401 // import {foo as foo$} from 'foo'; // if rename was needed |
| 390 // | 402 // |
| 391 var imports = | 403 var imports = |
| 392 libraries.map((l) => new JS.NameSpecifier(_imports[l])).toList(); | 404 libraries.map((l) => new JS.NameSpecifier(_imports[l])).toList(); |
| 393 if (module == coreModuleName) { | 405 if (module == coreModuleName) { |
| 394 imports.add(new JS.NameSpecifier(_runtimeLibVar)); | 406 imports.add(new JS.NameSpecifier(_runtimeModule)); |
| 395 imports.add(new JS.NameSpecifier(_dartxVar)); | 407 imports.add(new JS.NameSpecifier(_extensionSymbolsModule)); |
| 396 } | 408 } |
| 397 items.add(new JS.ImportDeclaration( | 409 items.add(new JS.ImportDeclaration( |
| 398 namedImports: imports, from: js.string(module, "'"))); | 410 namedImports: imports, from: js.string(module, "'"))); |
| 399 }); | 411 }); |
| 400 } | 412 } |
| 401 | 413 |
| 402 /// Collect toplevel elements and nodes we need to emit, and returns | 414 /// Collect toplevel elements and nodes we need to emit, and returns |
| 403 /// an ordered map of these. | 415 /// an ordered map of these. |
| 404 static void _collectElements( | 416 static void _collectElements( |
| 405 CompilationUnit unit, Map<Element, AstNode> map) { | 417 CompilationUnit unit, Map<Element, AstNode> map) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 _eagerTopLevelFields.contains(export)) { | 513 _eagerTopLevelFields.contains(export)) { |
| 502 // classes, typedefs, functions, and eager init fields can be assigned | 514 // classes, typedefs, functions, and eager init fields can be assigned |
| 503 // directly. | 515 // directly. |
| 504 // TODO(jmesserly): we don't know about eager init fields from other | 516 // TODO(jmesserly): we don't know about eager init fields from other |
| 505 // modules we import, so we will never go down this code path for them. | 517 // modules we import, so we will never go down this code path for them. |
| 506 _moduleItems | 518 _moduleItems |
| 507 .add(js.statement('#.# = #;', [libraryName, name.selector, name])); | 519 .add(js.statement('#.# = #;', [libraryName, name.selector, name])); |
| 508 } else { | 520 } else { |
| 509 // top-level fields, getters, setters need to copy the property | 521 // top-level fields, getters, setters need to copy the property |
| 510 // descriptor. | 522 // descriptor. |
| 511 _moduleItems.add(js.statement('dart.export(#, #, #);', | 523 _moduleItems.add(_callHelperStatement( |
| 512 [libraryName, name.receiver, name.selector])); | 524 'export(#, #, #);', [libraryName, name.receiver, name.selector])); |
| 513 } | 525 } |
| 514 } | 526 } |
| 515 | 527 |
| 516 for (var export in exportedNames.definedNames.values) { | 528 for (var export in exportedNames.definedNames.values) { |
| 517 if (export is PropertyAccessorElement) { | 529 if (export is PropertyAccessorElement) { |
| 518 export = (export as PropertyAccessorElement).variable; | 530 export = (export as PropertyAccessorElement).variable; |
| 519 } | 531 } |
| 520 | 532 |
| 521 // Don't allow redefining names from this library. | 533 // Don't allow redefining names from this library. |
| 522 if (currentNames.containsKey(export.name)) continue; | 534 if (currentNames.containsKey(export.name)) continue; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 546 if (_inWhitelistCode(node)) return jsFrom; | 558 if (_inWhitelistCode(node)) return jsFrom; |
| 547 | 559 |
| 548 // Skip the cast if it's not needed. | 560 // Skip the cast if it's not needed. |
| 549 if (rules.isSubtypeOf(from, to)) return jsFrom; | 561 if (rules.isSubtypeOf(from, to)) return jsFrom; |
| 550 | 562 |
| 551 // All Dart number types map to a JS double. | 563 // All Dart number types map to a JS double. |
| 552 if (_isNumberInJS(from) && _isNumberInJS(to)) { | 564 if (_isNumberInJS(from) && _isNumberInJS(to)) { |
| 553 // Make sure to check when converting to int. | 565 // Make sure to check when converting to int. |
| 554 if (from != types.intType && to == types.intType) { | 566 if (from != types.intType && to == types.intType) { |
| 555 // TODO(jmesserly): fuse this with notNull check. | 567 // TODO(jmesserly): fuse this with notNull check. |
| 556 return js.call('dart.asInt(#)', jsFrom); | 568 return _callHelper('asInt(#)', jsFrom); |
| 557 } | 569 } |
| 558 | 570 |
| 559 // A no-op in JavaScript. | 571 // A no-op in JavaScript. |
| 560 return jsFrom; | 572 return jsFrom; |
| 561 } | 573 } |
| 562 | 574 |
| 563 var type = _emitType(to, | 575 var type = _emitType(to, |
| 564 nameType: options.nameTypeTests || options.hoistTypeTests, | 576 nameType: options.nameTypeTests || options.hoistTypeTests, |
| 565 hoistType: options.hoistTypeTests); | 577 hoistType: options.hoistTypeTests); |
| 566 if (CoercionReifier.isImplicitCast(node)) { | 578 if (CoercionReifier.isImplicitCast(node)) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 if (t == types.stringType) return 'string'; | 612 if (t == types.stringType) return 'string'; |
| 601 if (t == types.boolType) return 'boolean'; | 613 if (t == types.boolType) return 'boolean'; |
| 602 return null; | 614 return null; |
| 603 } | 615 } |
| 604 | 616 |
| 605 @override | 617 @override |
| 606 visitFunctionTypeAlias(FunctionTypeAlias node) { | 618 visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 607 FunctionTypeAliasElement element = node.element; | 619 FunctionTypeAliasElement element = node.element; |
| 608 | 620 |
| 609 JS.Expression body = annotate( | 621 JS.Expression body = annotate( |
| 610 js.call('dart.typedef(#, () => #)', [ | 622 _callHelper('typedef(#, () => #)', [ |
| 611 js.string(element.name, "'"), | 623 js.string(element.name, "'"), |
| 612 _emitType(element.type, nameType: false, lowerTypedef: true) | 624 _emitType(element.type, nameType: false, lowerTypedef: true) |
| 613 ]), | 625 ]), |
| 614 node, | 626 node, |
| 615 element); | 627 element); |
| 616 | 628 |
| 617 var typeFormals = element.typeParameters; | 629 var typeFormals = element.typeParameters; |
| 618 if (typeFormals.isNotEmpty) { | 630 if (typeFormals.isNotEmpty) { |
| 619 return _defineClassTypeArguments(element, typeFormals, | 631 return _defineClassTypeArguments(element, typeFormals, |
| 620 js.statement('const # = #;', [element.name, body])); | 632 js.statement('const # = #;', [element.name, body])); |
| 621 } else { | 633 } else { |
| 622 return js.statement('# = #;', [_emitTopLevelName(element), body]); | 634 return js.statement('# = #;', [_emitTopLevelName(element), body]); |
| 623 } | 635 } |
| 624 } | 636 } |
| 625 | 637 |
| 626 @override | 638 @override |
| 627 JS.Expression visitTypeName(TypeName node) { | 639 JS.Expression visitTypeName(TypeName node) { |
| 628 if (node.type == null) { | 640 if (node.type == null) { |
| 629 // TODO(jmesserly): if the type fails to resolve, should we generate code | 641 // TODO(jmesserly): if the type fails to resolve, should we generate code |
| 630 // that throws instead? | 642 // that throws instead? |
| 631 assert(options.unsafeForceCompile || options.replCompile); | 643 assert(options.unsafeForceCompile || options.replCompile); |
| 632 return js.call('dart.dynamic'); | 644 return _callHelper('dynamic'); |
| 633 } | 645 } |
| 634 return _emitType(node.type); | 646 return _emitType(node.type); |
| 635 } | 647 } |
| 636 | 648 |
| 637 @override | 649 @override |
| 638 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { | 650 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { |
| 639 ClassElement element = node.element; | 651 ClassElement element = node.element; |
| 640 | 652 |
| 641 // Forward all generative constructors from the base class. | 653 // Forward all generative constructors from the base class. |
| 642 var methods = <JS.Method>[]; | 654 var methods = <JS.Method>[]; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 /// constructor. | 799 /// constructor. |
| 788 /// | 800 /// |
| 789 /// This ensures instances created by the unnamed constructor are functions. | 801 /// This ensures instances created by the unnamed constructor are functions. |
| 790 /// Named constructors are handled elsewhere, see [_defineNamedConstructors]. | 802 /// Named constructors are handled elsewhere, see [_defineNamedConstructors]. |
| 791 JS.Expression _emitCallableClass( | 803 JS.Expression _emitCallableClass( |
| 792 JS.ClassExpression classExpr, ConstructorElement unnamedCtor) { | 804 JS.ClassExpression classExpr, ConstructorElement unnamedCtor) { |
| 793 var ctor = new JS.NamedFunction( | 805 var ctor = new JS.NamedFunction( |
| 794 classExpr.name, _emitCallableClassConstructor(unnamedCtor)); | 806 classExpr.name, _emitCallableClassConstructor(unnamedCtor)); |
| 795 | 807 |
| 796 // Name the constructor function the same as the class. | 808 // Name the constructor function the same as the class. |
| 797 return js.call('dart.callableClass(#, #)', [ctor, classExpr]); | 809 return _callHelper('callableClass(#, #)', [ctor, classExpr]); |
| 798 } | 810 } |
| 799 | 811 |
| 800 /// Emits a constructor that ensures instances of this class are callable as | 812 /// Emits a constructor that ensures instances of this class are callable as |
| 801 /// functions in JavaScript. | 813 /// functions in JavaScript. |
| 802 JS.Fun _emitCallableClassConstructor(ConstructorElement ctor) { | 814 JS.Fun _emitCallableClassConstructor(ConstructorElement ctor) { |
| 803 return js.call( | 815 return js.call( |
| 804 r'''function (...args) { | 816 r'''function (...args) { |
| 805 function call(...args) { | 817 function call(...args) { |
| 806 return call.call.apply(call, args); | 818 return call.call.apply(call, args); |
| 807 } | 819 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 818 // We rely on ES6 static inheritance. All types that are represented by | 830 // We rely on ES6 static inheritance. All types that are represented by |
| 819 // class constructor functions will see these definitions, with [this] | 831 // class constructor functions will see these definitions, with [this] |
| 820 // being bound to the class constructor. | 832 // being bound to the class constructor. |
| 821 | 833 |
| 822 // The 'instanceof' checks don't work for primitive types (which have fast | 834 // The 'instanceof' checks don't work for primitive types (which have fast |
| 823 // definitions below) and don't work for native types. In those cases we | 835 // definitions below) and don't work for native types. In those cases we |
| 824 // fall through to the general purpose checking code. | 836 // fall through to the general purpose checking code. |
| 825 body.add(js.statement( | 837 body.add(js.statement( |
| 826 '#.is = function is_Object(o) {' | 838 '#.is = function is_Object(o) {' |
| 827 ' if (o instanceof this) return true;' | 839 ' if (o instanceof this) return true;' |
| 828 ' return dart.is(o, this);' | 840 ' return #.is(o, this);' |
| 829 '}', | 841 '}', |
| 830 className)); | 842 [className, _runtimeModule])); |
| 831 body.add(js.statement( | 843 body.add(js.statement( |
| 832 '#.as = function as_Object(o) {' | 844 '#.as = function as_Object(o) {' |
| 833 ' if (o == null || o instanceof this) return o;' | 845 ' if (o == null || o instanceof this) return o;' |
| 834 ' return dart.as(o, this);' | 846 ' return #.as(o, this);' |
| 835 '}', | 847 '}', |
| 836 className)); | 848 [className, _runtimeModule])); |
| 837 body.add(js.statement( | 849 body.add(js.statement( |
| 838 '#._check = function check_Object(o) {' | 850 '#._check = function check_Object(o) {' |
| 839 ' if (o == null || o instanceof this) return o;' | 851 ' if (o == null || o instanceof this) return o;' |
| 840 ' return dart.check(o, this);' | 852 ' return #.check(o, this);' |
| 841 '}', | 853 '}', |
| 842 className)); | 854 [className, _runtimeModule])); |
| 843 return; | 855 return; |
| 844 } | 856 } |
| 845 if (classElem == stringClass) { | 857 if (classElem == stringClass) { |
| 846 body.add(js.statement( | 858 body.add(js.statement( |
| 847 '#.is = function is_String(o) { return typeof o == "string"; }', | 859 '#.is = function is_String(o) { return typeof o == "string"; }', |
| 848 className)); | 860 className)); |
| 849 body.add(js.statement( | 861 body.add(js.statement( |
| 850 '#.as = function as_String(o) {' | 862 '#.as = function as_String(o) {' |
| 851 ' if (typeof o == "string" || o == null) return o;' | 863 ' if (typeof o == "string" || o == null) return o;' |
| 852 ' return dart.as(o, #);' | 864 ' return #.as(o, #);' |
| 853 '}', | 865 '}', |
| 854 [className, className])); | 866 [className, _runtimeModule, className])); |
| 855 body.add(js.statement( | 867 body.add(js.statement( |
| 856 '#._check = function check_String(o) {' | 868 '#._check = function check_String(o) {' |
| 857 ' if (typeof o == "string" || o == null) return o;' | 869 ' if (typeof o == "string" || o == null) return o;' |
| 858 ' return dart.check(o, #);' | 870 ' return #.check(o, #);' |
| 859 '}', | 871 '}', |
| 860 [className, className])); | 872 [className, _runtimeModule, className])); |
| 861 return; | 873 return; |
| 862 } | 874 } |
| 863 if (classElem == intClass) { | 875 if (classElem == intClass) { |
| 864 body.add(js.statement( | 876 body.add(js.statement( |
| 865 '#.is = function is_int(o) {' | 877 '#.is = function is_int(o) {' |
| 866 ' return typeof o == "number" && Math.floor(o) == o;' | 878 ' return typeof o == "number" && Math.floor(o) == o;' |
| 867 '}', | 879 '}', |
| 868 className)); | 880 className)); |
| 869 body.add(js.statement( | 881 body.add(js.statement( |
| 870 '#.as = function as_int(o) {' | 882 '#.as = function as_int(o) {' |
| 871 ' if ((typeof o == "number" && Math.floor(o) == o) || o == null)' | 883 ' if ((typeof o == "number" && Math.floor(o) == o) || o == null)' |
| 872 ' return o;' | 884 ' return o;' |
| 873 ' return dart.as(o, #);' | 885 ' return #.as(o, #);' |
| 874 '}', | 886 '}', |
| 875 [className, className])); | 887 [className, _runtimeModule, className])); |
| 876 body.add(js.statement( | 888 body.add(js.statement( |
| 877 '#._check = function check_int(o) {' | 889 '#._check = function check_int(o) {' |
| 878 ' if ((typeof o == "number" && Math.floor(o) == o) || o == null)' | 890 ' if ((typeof o == "number" && Math.floor(o) == o) || o == null)' |
| 879 ' return o;' | 891 ' return o;' |
| 880 ' return dart.check(o, #);' | 892 ' return #.check(o, #);' |
| 881 '}', | 893 '}', |
| 882 [className, className])); | 894 [className, _runtimeModule, className])); |
| 883 return; | 895 return; |
| 884 } | 896 } |
| 885 if (classElem == nullClass) { | 897 if (classElem == nullClass) { |
| 886 body.add(js.statement( | 898 body.add(js.statement( |
| 887 '#.is = function is_Null(o) { return o == null; }', className)); | 899 '#.is = function is_Null(o) { return o == null; }', className)); |
| 888 body.add(js.statement( | 900 body.add(js.statement( |
| 889 '#.as = function as_Null(o) {' | 901 '#.as = function as_Null(o) {' |
| 890 ' if (o == null) return o;' | 902 ' if (o == null) return o;' |
| 891 ' return dart.as(o, #);' | 903 ' return #.as(o, #);' |
| 892 '}', | 904 '}', |
| 893 [className, className])); | 905 [className, _runtimeModule, className])); |
| 894 body.add(js.statement( | 906 body.add(js.statement( |
| 895 '#._check = function check_Null(o) {' | 907 '#._check = function check_Null(o) {' |
| 896 ' if (o == null) return o;' | 908 ' if (o == null) return o;' |
| 897 ' return dart.check(o, #);' | 909 ' return #.check(o, #);' |
| 898 '}', | 910 '}', |
| 899 [className, className])); | 911 [className, _runtimeModule, className])); |
| 900 return; | 912 return; |
| 901 } | 913 } |
| 902 if (classElem == numClass) { | 914 if (classElem == numClass) { |
| 903 body.add(js.statement( | 915 body.add(js.statement( |
| 904 '#.is = function is_num(o) { return typeof o == "number"; }', | 916 '#.is = function is_num(o) { return typeof o == "number"; }', |
| 905 className)); | 917 className)); |
| 906 body.add(js.statement( | 918 body.add(js.statement( |
| 907 '#.as = function as_num(o) {' | 919 '#.as = function as_num(o) {' |
| 908 ' if (typeof o == "number" || o == null) return o;' | 920 ' if (typeof o == "number" || o == null) return o;' |
| 909 ' return dart.as(o, #);' | 921 ' return #.as(o, #);' |
| 910 '}', | 922 '}', |
| 911 [className, className])); | 923 [className, _runtimeModule, className])); |
| 912 body.add(js.statement( | 924 body.add(js.statement( |
| 913 '#._check = function check_num(o) {' | 925 '#._check = function check_num(o) {' |
| 914 ' if (typeof o == "number" || o == null) return o;' | 926 ' if (typeof o == "number" || o == null) return o;' |
| 915 ' return dart.check(o, #);' | 927 ' return #.check(o, #);' |
| 916 '}', | 928 '}', |
| 917 [className, className])); | 929 [className, _runtimeModule, className])); |
| 918 return; | 930 return; |
| 919 } | 931 } |
| 920 if (classElem == boolClass) { | 932 if (classElem == boolClass) { |
| 921 body.add(js.statement( | 933 body.add(js.statement( |
| 922 '#.is = function is_bool(o) { return o === true || o === false; }', | 934 '#.is = function is_bool(o) { return o === true || o === false; }', |
| 923 className)); | 935 className)); |
| 924 body.add(js.statement( | 936 body.add(js.statement( |
| 925 '#.as = function as_bool(o) {' | 937 '#.as = function as_bool(o) {' |
| 926 ' if (o === true || o === false || o == null) return o;' | 938 ' if (o === true || o === false || o == null) return o;' |
| 927 ' return dart.as(o, #);' | 939 ' return #.as(o, #);' |
| 928 '}', | 940 '}', |
| 929 [className, className])); | 941 [className, _runtimeModule, className])); |
| 930 body.add(js.statement( | 942 body.add(js.statement( |
| 931 '#._check = function check_bool(o) {' | 943 '#._check = function check_bool(o) {' |
| 932 ' if (o === true || o === false || o == null) return o;' | 944 ' if (o === true || o === false || o == null) return o;' |
| 933 ' return dart.check(o, #);' | 945 ' return #.check(o, #);' |
| 934 '}', | 946 '}', |
| 935 [className, className])); | 947 [className, _runtimeModule, className])); |
| 936 return; | 948 return; |
| 937 } | 949 } |
| 938 // TODO(sra): Add special cases for hot tests like `x is html.Element`. | 950 // TODO(sra): Add special cases for hot tests like `x is html.Element`. |
| 939 | 951 |
| 940 // `instanceof` check is futile for classes that are Interceptor classes. | 952 // `instanceof` check is futile for classes that are Interceptor classes. |
| 941 ClassElement parent = classElem; | 953 ClassElement parent = classElem; |
| 942 while (parent != objectClass) { | 954 while (parent != objectClass) { |
| 943 if (parent == interceptorClass) { | 955 if (parent == interceptorClass) { |
| 944 if (classElem == interceptorClass) { | 956 if (classElem == interceptorClass) { |
| 945 // Place non-instanceof version of checks on Interceptor. All | 957 // Place non-instanceof version of checks on Interceptor. All |
| 946 // interceptor classes will inherit the methods via ES6 class static | 958 // interceptor classes will inherit the methods via ES6 class static |
| 947 // inheritance. | 959 // inheritance. |
| 948 body.add(js.statement('dart.addTypeTests(#);', className)); | 960 body.add(_callHelperStatement('addTypeTests(#);', className)); |
| 949 | 961 |
| 950 // TODO(sra): We could place on the extension type a pointer to the | 962 // TODO(sra): We could place on the extension type a pointer to the |
| 951 // peer constructor and use that for the `instanceof` check, e.g. | 963 // peer constructor and use that for the `instanceof` check, e.g. |
| 952 // | 964 // |
| 953 // if (o instanceof this[_peerConstructor]) return o; | 965 // if (o instanceof this[_peerConstructor]) return o; |
| 954 // | 966 // |
| 955 } | 967 } |
| 956 return; | 968 return; |
| 957 } | 969 } |
| 958 parent = parent.type.superclass.element; | 970 parent = parent.type.superclass.element; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 976 return true; | 988 return true; |
| 977 } | 989 } |
| 978 | 990 |
| 979 assert(classElem != objectClass); | 991 assert(classElem != objectClass); |
| 980 bool thisIsSimple = isSimple(classElem); | 992 bool thisIsSimple = isSimple(classElem); |
| 981 bool superIsSimple = isSimple(classElem.type.superclass.element); | 993 bool superIsSimple = isSimple(classElem.type.superclass.element); |
| 982 | 994 |
| 983 if (thisIsSimple == superIsSimple) return; | 995 if (thisIsSimple == superIsSimple) return; |
| 984 | 996 |
| 985 if (thisIsSimple) { | 997 if (thisIsSimple) { |
| 986 body.add(js.statement('dart.addSimpleTypeTests(#);', className)); | 998 body.add(_callHelperStatement('addSimpleTypeTests(#);', className)); |
| 987 } else { | 999 } else { |
| 988 body.add(js.statement('dart.addTypeTests(#);', className)); | 1000 body.add(_callHelperStatement('addTypeTests(#);', className)); |
| 989 } | 1001 } |
| 990 } | 1002 } |
| 991 | 1003 |
| 992 void _emitSuperHelperSymbols( | 1004 void _emitSuperHelperSymbols( |
| 993 List<JS.TemporaryId> superHelperSymbols, List<JS.Statement> body) { | 1005 List<JS.TemporaryId> superHelperSymbols, List<JS.Statement> body) { |
| 994 for (var id in superHelperSymbols) { | 1006 for (var id in superHelperSymbols) { |
| 995 body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)])); | 1007 body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)])); |
| 996 } | 1008 } |
| 997 superHelperSymbols.clear(); | 1009 superHelperSymbols.clear(); |
| 998 } | 1010 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1096 // Create enum class | 1108 // Create enum class |
| 1097 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), | 1109 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), |
| 1098 _emitClassHeritage(element), [constructor, toStringF]); | 1110 _emitClassHeritage(element), [constructor, toStringF]); |
| 1099 var id = _emitTopLevelName(element); | 1111 var id = _emitTopLevelName(element); |
| 1100 var result = [ | 1112 var result = [ |
| 1101 js.statement('# = #', [id, classExpr]) | 1113 js.statement('# = #', [id, classExpr]) |
| 1102 ]; | 1114 ]; |
| 1103 | 1115 |
| 1104 // Create static fields for each enum value | 1116 // Create static fields for each enum value |
| 1105 for (var i = 0; i < fields.length; ++i) { | 1117 for (var i = 0; i < fields.length; ++i) { |
| 1106 result.add(js.statement('#.# = dart.const(new #(#));', | 1118 result.add(js.statement('#.# = #.const(new #(#));', |
| 1107 [id, fields[i].name, id, js.number(i)])); | 1119 [id, fields[i].name, _runtimeModule, id, js.number(i)])); |
| 1108 } | 1120 } |
| 1109 | 1121 |
| 1110 // Create static values list | 1122 // Create static values list |
| 1111 var values = new JS.ArrayInitializer(new List<JS.Expression>.from( | 1123 var values = new JS.ArrayInitializer(new List<JS.Expression>.from( |
| 1112 fields.map((f) => js.call('#.#', [id, f.name])))); | 1124 fields.map((f) => js.call('#.#', [id, f.name])))); |
| 1113 | 1125 |
| 1114 // dart.constList helper internally depends on _interceptors.JSArray. | 1126 // dart.constList helper internally depends on _interceptors.JSArray. |
| 1115 _declareBeforeUse(_jsArray); | 1127 _declareBeforeUse(_jsArray); |
| 1116 | 1128 |
| 1117 result.add(js.statement( | 1129 result.add(js.statement('#.values = #.constList(#, #);', |
| 1118 '#.values = dart.constList(#, #);', [id, values, _emitType(type)])); | 1130 [id, _runtimeModule, values, _emitType(type)])); |
| 1119 | 1131 |
| 1120 return _statement(result); | 1132 return _statement(result); |
| 1121 } | 1133 } |
| 1122 | 1134 |
| 1123 /// Wraps a possibly generic class in its type arguments. | 1135 /// Wraps a possibly generic class in its type arguments. |
| 1124 JS.Statement _defineClassTypeArguments(TypeDefiningElement element, | 1136 JS.Statement _defineClassTypeArguments(TypeDefiningElement element, |
| 1125 List<TypeParameterElement> formals, JS.Statement body) { | 1137 List<TypeParameterElement> formals, JS.Statement body) { |
| 1126 assert(formals.isNotEmpty); | 1138 assert(formals.isNotEmpty); |
| 1127 var genericCall = js.call('dart.generic((#) => { #; #; return #; })', [ | 1139 var genericCall = _callHelper('generic((#) => { #; #; return #; })', [ |
| 1128 _emitTypeFormals(formals), | 1140 _emitTypeFormals(formals), |
| 1129 _typeTable.discharge(formals), | 1141 _typeTable.discharge(formals), |
| 1130 body, | 1142 body, |
| 1131 element.name | 1143 element.name |
| 1132 ]); | 1144 ]); |
| 1133 if (element.library.isDartAsync && | 1145 if (element.library.isDartAsync && |
| 1134 (element.name == "Future" || element.name == "_Future")) { | 1146 (element.name == "Future" || element.name == "_Future")) { |
| 1135 genericCall = js.call('dart.flattenFutures(#)', [genericCall]); | 1147 genericCall = _callHelper('flattenFutures(#)', [genericCall]); |
| 1136 } | 1148 } |
| 1137 var genericDef = js.statement( | 1149 var genericDef = js.statement( |
| 1138 '# = #;', [_emitTopLevelName(element, suffix: r'$'), genericCall]); | 1150 '# = #;', [_emitTopLevelName(element, suffix: r'$'), genericCall]); |
| 1139 var dynType = fillDynamicTypeArgs(element.type); | 1151 var dynType = fillDynamicTypeArgs(element.type); |
| 1140 var genericInst = _emitType(dynType, lowerGeneric: true); | 1152 var genericInst = _emitType(dynType, lowerGeneric: true); |
| 1141 return js.statement( | 1153 return js.statement( |
| 1142 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]); | 1154 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]); |
| 1143 } | 1155 } |
| 1144 | 1156 |
| 1145 bool _deferIfNeeded(DartType type, ClassElement current) { | 1157 bool _deferIfNeeded(DartType type, ClassElement current) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1183 _hasDeferredSupertype.add(element); | 1195 _hasDeferredSupertype.add(element); |
| 1184 } | 1196 } |
| 1185 // We could choose to name the superclasses, but it's | 1197 // We could choose to name the superclasses, but it's |
| 1186 // not clear that there's much benefit | 1198 // not clear that there's much benefit |
| 1187 heritage = _emitType(supertype, nameType: false); | 1199 heritage = _emitType(supertype, nameType: false); |
| 1188 | 1200 |
| 1189 if (type.mixins.isNotEmpty) { | 1201 if (type.mixins.isNotEmpty) { |
| 1190 var mixins = | 1202 var mixins = |
| 1191 type.mixins.map((t) => _emitType(t, nameType: false)).toList(); | 1203 type.mixins.map((t) => _emitType(t, nameType: false)).toList(); |
| 1192 mixins.insert(0, heritage); | 1204 mixins.insert(0, heritage); |
| 1193 heritage = js.call('dart.mixin(#)', [mixins]); | 1205 heritage = _callHelper('mixin(#)', [mixins]); |
| 1194 } | 1206 } |
| 1195 | 1207 |
| 1196 _loader.finishTopLevel(element); | 1208 _loader.finishTopLevel(element); |
| 1197 | 1209 |
| 1198 return heritage; | 1210 return heritage; |
| 1199 } | 1211 } |
| 1200 | 1212 |
| 1201 /// Provide Dart getters and setters that forward to the underlying native | 1213 /// Provide Dart getters and setters that forward to the underlying native |
| 1202 /// field. Note that the Dart names are always symbolized to avoid | 1214 /// field. Note that the Dart names are always symbolized to avoid |
| 1203 /// conflicts. They will be installed as extension methods on the underlying | 1215 /// conflicts. They will be installed as extension methods on the underlying |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1403 var invocationProps = <JS.Property>[]; | 1415 var invocationProps = <JS.Property>[]; |
| 1404 addProperty(String name, JS.Expression value) { | 1416 addProperty(String name, JS.Expression value) { |
| 1405 invocationProps.add(new JS.Property(js.string(name), value)); | 1417 invocationProps.add(new JS.Property(js.string(name), value)); |
| 1406 } | 1418 } |
| 1407 | 1419 |
| 1408 var args = new JS.TemporaryId('args'); | 1420 var args = new JS.TemporaryId('args'); |
| 1409 var fnArgs = <JS.Parameter>[]; | 1421 var fnArgs = <JS.Parameter>[]; |
| 1410 JS.Expression positionalArgs; | 1422 JS.Expression positionalArgs; |
| 1411 | 1423 |
| 1412 if (method.type.namedParameterTypes.isNotEmpty) { | 1424 if (method.type.namedParameterTypes.isNotEmpty) { |
| 1413 addProperty( | 1425 addProperty('namedArguments', _callHelper('extractNamedArgs(#)', [args])); |
| 1414 'namedArguments', js.call('dart.extractNamedArgs(#)', [args])); | |
| 1415 } | 1426 } |
| 1416 | 1427 |
| 1417 if (method is MethodElement) { | 1428 if (method is MethodElement) { |
| 1418 addProperty('isMethod', js.boolean(true)); | 1429 addProperty('isMethod', js.boolean(true)); |
| 1419 | 1430 |
| 1420 fnArgs.add(new JS.RestParameter(args)); | 1431 fnArgs.add(new JS.RestParameter(args)); |
| 1421 positionalArgs = args; | 1432 positionalArgs = args; |
| 1422 } else { | 1433 } else { |
| 1423 var property = method as PropertyAccessorElement; | 1434 var property = method as PropertyAccessorElement; |
| 1424 if (property.isGetter) { | 1435 if (property.isGetter) { |
| 1425 addProperty('isGetter', js.boolean(true)); | 1436 addProperty('isGetter', js.boolean(true)); |
| 1426 | 1437 |
| 1427 positionalArgs = new JS.ArrayInitializer([]); | 1438 positionalArgs = new JS.ArrayInitializer([]); |
| 1428 } else if (property.isSetter) { | 1439 } else if (property.isSetter) { |
| 1429 addProperty('isSetter', js.boolean(true)); | 1440 addProperty('isSetter', js.boolean(true)); |
| 1430 | 1441 |
| 1431 fnArgs.add(args); | 1442 fnArgs.add(args); |
| 1432 positionalArgs = new JS.ArrayInitializer([args]); | 1443 positionalArgs = new JS.ArrayInitializer([args]); |
| 1433 } | 1444 } |
| 1434 } | 1445 } |
| 1435 | 1446 |
| 1436 var fnBody = | 1447 var fnBody = js.call('this.noSuchMethod(new #.InvocationImpl(#, #, #))', [ |
| 1437 js.call('this.noSuchMethod(new dart.InvocationImpl(#, #, #))', [ | 1448 _runtimeModule, |
| 1438 _declareMemberName(method), | 1449 _declareMemberName(method), |
| 1439 positionalArgs, | 1450 positionalArgs, |
| 1440 new JS.ObjectInitializer(invocationProps) | 1451 new JS.ObjectInitializer(invocationProps) |
| 1441 ]); | 1452 ]); |
| 1442 | 1453 |
| 1443 if (!method.returnType.isDynamic) { | 1454 if (!method.returnType.isDynamic) { |
| 1444 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]); | 1455 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]); |
| 1445 } | 1456 } |
| 1446 | 1457 |
| 1447 var fn = new JS.Fun(fnArgs, js.statement('{ return #; }', [fnBody]), | 1458 var fn = new JS.Fun(fnArgs, js.statement('{ return #; }', [fnBody]), |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 // simple code size optimization. | 1556 // simple code size optimization. |
| 1546 var parent = t.lookUpGetterInSuperclass('iterator', t.element.library); | 1557 var parent = t.lookUpGetterInSuperclass('iterator', t.element.library); |
| 1547 if (parent != null) return null; | 1558 if (parent != null) return null; |
| 1548 var parentType = findSupertype(t, _implementsIterable); | 1559 var parentType = findSupertype(t, _implementsIterable); |
| 1549 if (parentType != null) return null; | 1560 if (parentType != null) return null; |
| 1550 | 1561 |
| 1551 // Otherwise, emit the adapter method, which wraps the Dart iterator in | 1562 // Otherwise, emit the adapter method, which wraps the Dart iterator in |
| 1552 // an ES6 iterator. | 1563 // an ES6 iterator. |
| 1553 return new JS.Method( | 1564 return new JS.Method( |
| 1554 js.call('Symbol.iterator'), | 1565 js.call('Symbol.iterator'), |
| 1555 js.call('function() { return new dart.JsIterator(this.#); }', | 1566 js.call('function() { return new #.JsIterator(this.#); }', |
| 1556 [_emitMemberName('iterator', type: t)]) as JS.Fun); | 1567 [_runtimeModule, _emitMemberName('iterator', type: t)]) as JS.Fun); |
| 1557 } | 1568 } |
| 1558 | 1569 |
| 1559 JS.Expression _instantiateAnnotation(Annotation node) { | 1570 JS.Expression _instantiateAnnotation(Annotation node) { |
| 1560 var element = node.element; | 1571 var element = node.element; |
| 1561 if (element is ConstructorElement) { | 1572 if (element is ConstructorElement) { |
| 1562 return _emitInstanceCreationExpression(element, element.returnType, | 1573 return _emitInstanceCreationExpression(element, element.returnType, |
| 1563 node.constructorName, node.arguments, true); | 1574 node.constructorName, node.arguments, true); |
| 1564 } else { | 1575 } else { |
| 1565 return _visit(node.name); | 1576 return _visit(node.name); |
| 1566 } | 1577 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1583 .where((peer) => !peer.startsWith("!")) | 1594 .where((peer) => !peer.startsWith("!")) |
| 1584 .toList(); | 1595 .toList(); |
| 1585 } else { | 1596 } else { |
| 1586 return []; | 1597 return []; |
| 1587 } | 1598 } |
| 1588 } | 1599 } |
| 1589 | 1600 |
| 1590 void _registerExtensionType( | 1601 void _registerExtensionType( |
| 1591 ClassElement classElem, String jsPeerName, List<JS.Statement> body) { | 1602 ClassElement classElem, String jsPeerName, List<JS.Statement> body) { |
| 1592 if (jsPeerName != null) { | 1603 if (jsPeerName != null) { |
| 1593 body.add(js.statement('dart.registerExtension(dart.global.#, #);', | 1604 body.add(_callHelperStatement('registerExtension(#.global.#, #);', [ |
| 1594 [_propertyName(jsPeerName), _emitTopLevelName(classElem)])); | 1605 _runtimeModule, |
| 1606 _propertyName(jsPeerName), |
| 1607 _emitTopLevelName(classElem) |
| 1608 ])); |
| 1595 } | 1609 } |
| 1596 } | 1610 } |
| 1597 | 1611 |
| 1598 void _setBaseClass(ClassElement classElem, JS.Expression className, | 1612 void _setBaseClass(ClassElement classElem, JS.Expression className, |
| 1599 List<String> jsPeerNames, List<JS.Statement> body) { | 1613 List<String> jsPeerNames, List<JS.Statement> body) { |
| 1600 if (jsPeerNames.isNotEmpty && classElem.typeParameters.isNotEmpty) { | 1614 if (jsPeerNames.isNotEmpty && classElem.typeParameters.isNotEmpty) { |
| 1601 for (var peer in jsPeerNames) { | 1615 for (var peer in jsPeerNames) { |
| 1602 // TODO(jmesserly): we should just extend Array in the first place | 1616 // TODO(jmesserly): we should just extend Array in the first place |
| 1603 var newBaseClass = js.call('dart.global.#', [peer]); | 1617 var newBaseClass = _callHelper('global.#', [peer]); |
| 1604 body.add(js.statement( | 1618 body.add(_callHelperStatement( |
| 1605 'dart.setExtensionBaseClass(#, #);', [className, newBaseClass])); | 1619 'setExtensionBaseClass(#, #);', [className, newBaseClass])); |
| 1606 } | 1620 } |
| 1607 } else if (_hasDeferredSupertype.contains(classElem)) { | 1621 } else if (_hasDeferredSupertype.contains(classElem)) { |
| 1608 var newBaseClass = _emitType(classElem.type.superclass, | 1622 var newBaseClass = _emitType(classElem.type.superclass, |
| 1609 nameType: false, subClass: classElem, className: className); | 1623 nameType: false, subClass: classElem, className: className); |
| 1610 body.add( | 1624 body.add(_callHelperStatement( |
| 1611 js.statement('dart.setBaseClass(#, #);', [className, newBaseClass])); | 1625 'setBaseClass(#, #);', [className, newBaseClass])); |
| 1612 } | 1626 } |
| 1613 } | 1627 } |
| 1614 | 1628 |
| 1615 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, | 1629 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, |
| 1616 List<JS.Statement> body, JS.Expression className, bool isCallable) { | 1630 List<JS.Statement> body, JS.Expression className, bool isCallable) { |
| 1617 var code = isCallable | 1631 var code = isCallable |
| 1618 ? 'dart.defineNamedConstructorCallable(#, #, #);' | 1632 ? 'defineNamedConstructorCallable(#, #, #);' |
| 1619 : 'dart.defineNamedConstructor(#, #)'; | 1633 : 'defineNamedConstructor(#, #)'; |
| 1620 | 1634 |
| 1621 for (ConstructorDeclaration member in ctors) { | 1635 for (ConstructorDeclaration member in ctors) { |
| 1622 if (member.name != null && member.factoryKeyword == null) { | 1636 if (member.name != null && member.factoryKeyword == null) { |
| 1623 var args = [className, _constructorName(member.element)]; | 1637 var args = [className, _constructorName(member.element)]; |
| 1624 if (isCallable) { | 1638 if (isCallable) { |
| 1625 args.add(_emitCallableClassConstructor(member.element)); | 1639 args.add(_emitCallableClassConstructor(member.element)); |
| 1626 } | 1640 } |
| 1627 | 1641 |
| 1628 body.add(js.statement(code, args)); | 1642 body.add(_callHelperStatement(code, args)); |
| 1629 } | 1643 } |
| 1630 } | 1644 } |
| 1631 } | 1645 } |
| 1632 | 1646 |
| 1633 /// Emits static fields for a class, and initialize them eagerly if possible, | 1647 /// Emits static fields for a class, and initialize them eagerly if possible, |
| 1634 /// otherwise define them as lazy properties. | 1648 /// otherwise define them as lazy properties. |
| 1635 void _emitStaticFields( | 1649 void _emitStaticFields( |
| 1636 List<FieldDeclaration> staticFields, | 1650 List<FieldDeclaration> staticFields, |
| 1637 Set<FieldElement> staticFieldOverrides, | 1651 Set<FieldElement> staticFieldOverrides, |
| 1638 ClassElement classElem, | 1652 ClassElement classElem, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1651 } | 1665 } |
| 1652 if (lazyStatics.isNotEmpty) { | 1666 if (lazyStatics.isNotEmpty) { |
| 1653 body.add(_emitLazyFields(classElem, lazyStatics)); | 1667 body.add(_emitLazyFields(classElem, lazyStatics)); |
| 1654 } | 1668 } |
| 1655 } | 1669 } |
| 1656 | 1670 |
| 1657 void _emitClassMetadata(List<Annotation> metadata, JS.Expression className, | 1671 void _emitClassMetadata(List<Annotation> metadata, JS.Expression className, |
| 1658 List<JS.Statement> body) { | 1672 List<JS.Statement> body) { |
| 1659 // Metadata | 1673 // Metadata |
| 1660 if (options.emitMetadata && metadata.isNotEmpty) { | 1674 if (options.emitMetadata && metadata.isNotEmpty) { |
| 1661 body.add(js.statement('#[dart.metadata] = () => #;', [ | 1675 body.add(js.statement('#[#.metadata] = () => #;', [ |
| 1662 className, | 1676 className, |
| 1677 _runtimeModule, |
| 1663 new JS.ArrayInitializer( | 1678 new JS.ArrayInitializer( |
| 1664 new List<JS.Expression>.from(metadata.map(_instantiateAnnotation))) | 1679 new List<JS.Expression>.from(metadata.map(_instantiateAnnotation))) |
| 1665 ])); | 1680 ])); |
| 1666 } | 1681 } |
| 1667 } | 1682 } |
| 1668 | 1683 |
| 1669 /// If a concrete class implements one of our extensions, we might need to | 1684 /// If a concrete class implements one of our extensions, we might need to |
| 1670 /// add forwarders. | 1685 /// add forwarders. |
| 1671 void _defineExtensionMembers(List<ExecutableElement> extensions, | 1686 void _defineExtensionMembers(List<ExecutableElement> extensions, |
| 1672 JS.Expression className, List<JS.Statement> body) { | 1687 JS.Expression className, List<JS.Statement> body) { |
| 1673 // If a concrete class implements one of our extensions, we might need to | 1688 // If a concrete class implements one of our extensions, we might need to |
| 1674 // add forwarders. | 1689 // add forwarders. |
| 1675 if (extensions.isNotEmpty) { | 1690 if (extensions.isNotEmpty) { |
| 1676 var methodNames = <JS.Expression>[]; | 1691 var methodNames = <JS.Expression>[]; |
| 1677 for (var e in extensions) { | 1692 for (var e in extensions) { |
| 1678 methodNames.add(_declareMemberName(e, useExtension: false)); | 1693 methodNames.add(_declareMemberName(e, useExtension: false)); |
| 1679 } | 1694 } |
| 1680 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ | 1695 body.add(_callHelperStatement('defineExtensionMembers(#, #);', [ |
| 1681 className, | 1696 className, |
| 1682 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) | 1697 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) |
| 1683 ])); | 1698 ])); |
| 1684 } | 1699 } |
| 1685 } | 1700 } |
| 1686 | 1701 |
| 1687 /// Emit the signature on the class recording the runtime type information | 1702 /// Emit the signature on the class recording the runtime type information |
| 1688 void _emitClassSignature( | 1703 void _emitClassSignature( |
| 1689 List<MethodDeclaration> methods, | 1704 List<MethodDeclaration> methods, |
| 1690 List<FieldDeclaration> fields, | 1705 List<FieldDeclaration> fields, |
| 1691 ClassElement classElem, | 1706 ClassElement classElem, |
| 1692 List<ConstructorDeclaration> ctors, | 1707 List<ConstructorDeclaration> ctors, |
| 1693 List<ExecutableElement> extensions, | 1708 List<ExecutableElement> extensions, |
| 1694 JS.Expression className, | 1709 JS.Expression className, |
| 1695 List<JS.Statement> body) { | 1710 List<JS.Statement> body) { |
| 1696 if (classElem.interfaces.isNotEmpty) { | 1711 if (classElem.interfaces.isNotEmpty) { |
| 1697 body.add(js.statement('#[dart.implements] = () => #;', [ | 1712 body.add(js.statement('#[#.implements] = () => #;', [ |
| 1698 className, | 1713 className, |
| 1714 _runtimeModule, |
| 1699 new JS.ArrayInitializer( | 1715 new JS.ArrayInitializer( |
| 1700 new List<JS.Expression>.from(classElem.interfaces.map(_emitType))) | 1716 new List<JS.Expression>.from(classElem.interfaces.map(_emitType))) |
| 1701 ])); | 1717 ])); |
| 1702 } | 1718 } |
| 1703 | 1719 |
| 1704 var tStaticMethods = <JS.Property>[]; | 1720 var tStaticMethods = <JS.Property>[]; |
| 1705 var tInstanceMethods = <JS.Property>[]; | 1721 var tInstanceMethods = <JS.Property>[]; |
| 1706 var tStaticGetters = <JS.Property>[]; | 1722 var tStaticGetters = <JS.Property>[]; |
| 1707 var tInstanceGetters = <JS.Property>[]; | 1723 var tInstanceGetters = <JS.Property>[]; |
| 1708 var tStaticSetters = <JS.Property>[]; | 1724 var tStaticSetters = <JS.Property>[]; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1811 if (!tStaticMethods.isEmpty) { | 1827 if (!tStaticMethods.isEmpty) { |
| 1812 assert(!sNames.isEmpty); | 1828 assert(!sNames.isEmpty); |
| 1813 // TODO(vsm): Why do we need this names field? | 1829 // TODO(vsm): Why do we need this names field? |
| 1814 var aNames = new JS.Property( | 1830 var aNames = new JS.Property( |
| 1815 _propertyName('names'), new JS.ArrayInitializer(sNames)); | 1831 _propertyName('names'), new JS.ArrayInitializer(sNames)); |
| 1816 sigFields.add(build('statics', tStaticMethods)); | 1832 sigFields.add(build('statics', tStaticMethods)); |
| 1817 sigFields.add(aNames); | 1833 sigFields.add(aNames); |
| 1818 } | 1834 } |
| 1819 if (!sigFields.isEmpty || extensions.isNotEmpty) { | 1835 if (!sigFields.isEmpty || extensions.isNotEmpty) { |
| 1820 var sig = new JS.ObjectInitializer(sigFields); | 1836 var sig = new JS.ObjectInitializer(sigFields); |
| 1821 body.add(js.statement('dart.setSignature(#, #);', [className, sig])); | 1837 body.add(_callHelperStatement('setSignature(#, #);', [className, sig])); |
| 1822 } | 1838 } |
| 1823 // Add static property dart._runtimeType to Object. | 1839 // Add static property dart._runtimeType to Object. |
| 1824 // All other Dart classes will (statically) inherit this property. | 1840 // All other Dart classes will (statically) inherit this property. |
| 1825 if (classElem == objectClass) { | 1841 if (classElem == objectClass) { |
| 1826 body.add(js.statement('dart.tagComputed(#, () => #.#);', | 1842 body.add(_callHelperStatement('tagComputed(#, () => #.#);', |
| 1827 [className, emitLibraryName(dartCoreLibrary), 'Type'])); | 1843 [className, emitLibraryName(dartCoreLibrary), 'Type'])); |
| 1828 } | 1844 } |
| 1829 } | 1845 } |
| 1830 | 1846 |
| 1831 /// Ensure `dartx.` symbols we will use are present. | 1847 /// Ensure `dartx.` symbols we will use are present. |
| 1832 void _initExtensionSymbols( | 1848 void _initExtensionSymbols( |
| 1833 ClassElement classElem, | 1849 ClassElement classElem, |
| 1834 List<MethodDeclaration> methods, | 1850 List<MethodDeclaration> methods, |
| 1835 List<FieldDeclaration> fields, | 1851 List<FieldDeclaration> fields, |
| 1836 List<JS.Statement> body) { | 1852 List<JS.Statement> body) { |
| 1837 if (_extensionTypes.hasNativeSubtype(classElem.type)) { | 1853 if (_extensionTypes.hasNativeSubtype(classElem.type)) { |
| 1838 var dartxNames = <JS.Expression>[]; | 1854 var dartxNames = <JS.Expression>[]; |
| 1839 for (var m in methods) { | 1855 for (var m in methods) { |
| 1840 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { | 1856 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { |
| 1841 dartxNames.add(_declareMemberName(m.element, useExtension: false)); | 1857 dartxNames.add(_declareMemberName(m.element, useExtension: false)); |
| 1842 } | 1858 } |
| 1843 } | 1859 } |
| 1844 for (var fieldDecl in fields) { | 1860 for (var fieldDecl in fields) { |
| 1845 if (!fieldDecl.isStatic) { | 1861 if (!fieldDecl.isStatic) { |
| 1846 for (var field in fieldDecl.fields.variables) { | 1862 for (var field in fieldDecl.fields.variables) { |
| 1847 var e = field.element as FieldElement; | 1863 var e = field.element as FieldElement; |
| 1848 if (e.isPublic) { | 1864 if (e.isPublic) { |
| 1849 dartxNames.add(_declareMemberName(e.getter, useExtension: false)); | 1865 dartxNames.add(_declareMemberName(e.getter, useExtension: false)); |
| 1850 } | 1866 } |
| 1851 } | 1867 } |
| 1852 } | 1868 } |
| 1853 } | 1869 } |
| 1854 if (dartxNames.isNotEmpty) { | 1870 if (dartxNames.isNotEmpty) { |
| 1855 body.add(js.statement('dart.defineExtensionNames(#)', | 1871 body.add(_callHelperStatement('defineExtensionNames(#)', |
| 1856 [new JS.ArrayInitializer(dartxNames, multiline: true)])); | 1872 [new JS.ArrayInitializer(dartxNames, multiline: true)])); |
| 1857 } | 1873 } |
| 1858 } | 1874 } |
| 1859 } | 1875 } |
| 1860 | 1876 |
| 1861 List<ExecutableElement> _extensionsToImplement(ClassElement element) { | 1877 List<ExecutableElement> _extensionsToImplement(ClassElement element) { |
| 1862 var members = <ExecutableElement>[]; | 1878 var members = <ExecutableElement>[]; |
| 1863 if (_extensionTypes.isNativeClass(element)) return members; | 1879 if (_extensionTypes.isNativeClass(element)) return members; |
| 1864 | 1880 |
| 1865 // Collect all extension types we implement. | 1881 // Collect all extension types we implement. |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2325 | 2341 |
| 2326 // If we have a getter/setter pair, they need to be defined together. | 2342 // If we have a getter/setter pair, they need to be defined together. |
| 2327 if (node.isGetter) { | 2343 if (node.isGetter) { |
| 2328 PropertyAccessorElement element = node.element; | 2344 PropertyAccessorElement element = node.element; |
| 2329 var props = <JS.Method>[_emitTopLevelProperty(node)]; | 2345 var props = <JS.Method>[_emitTopLevelProperty(node)]; |
| 2330 var setter = element.correspondingSetter; | 2346 var setter = element.correspondingSetter; |
| 2331 if (setter != null) { | 2347 if (setter != null) { |
| 2332 props.add(_loader.emitDeclaration( | 2348 props.add(_loader.emitDeclaration( |
| 2333 setter, (node) => _emitTopLevelProperty(node))); | 2349 setter, (node) => _emitTopLevelProperty(node))); |
| 2334 } | 2350 } |
| 2335 return js.statement('dart.copyProperties(#, { # });', | 2351 return _callHelperStatement('copyProperties(#, { # });', |
| 2336 [emitLibraryName(currentLibrary), props]); | 2352 [emitLibraryName(currentLibrary), props]); |
| 2337 } | 2353 } |
| 2338 if (node.isSetter) { | 2354 if (node.isSetter) { |
| 2339 PropertyAccessorElement element = node.element; | 2355 PropertyAccessorElement element = node.element; |
| 2340 var props = <JS.Method>[_emitTopLevelProperty(node)]; | 2356 var props = <JS.Method>[_emitTopLevelProperty(node)]; |
| 2341 var getter = element.correspondingGetter; | 2357 var getter = element.correspondingGetter; |
| 2342 if (getter != null) { | 2358 if (getter != null) { |
| 2343 props.add(_loader.emitDeclaration( | 2359 props.add(_loader.emitDeclaration( |
| 2344 getter, (node) => _emitTopLevelProperty(node))); | 2360 getter, (node) => _emitTopLevelProperty(node))); |
| 2345 } | 2361 } |
| 2346 return js.statement('dart.copyProperties(#, { # });', | 2362 return _callHelperStatement('copyProperties(#, { # });', |
| 2347 [emitLibraryName(currentLibrary), props]); | 2363 [emitLibraryName(currentLibrary), props]); |
| 2348 } | 2364 } |
| 2349 | 2365 |
| 2350 var body = <JS.Statement>[]; | 2366 var body = <JS.Statement>[]; |
| 2351 var fn = _emitFunction(node.functionExpression); | 2367 var fn = _emitFunction(node.functionExpression); |
| 2352 | 2368 |
| 2353 if (currentLibrary.source.isInSystemLibrary && | 2369 if (currentLibrary.source.isInSystemLibrary && |
| 2354 _isInlineJSFunction(node.functionExpression)) { | 2370 _isInlineJSFunction(node.functionExpression)) { |
| 2355 fn = _simplifyPassThroughArrowFunCallBody(fn); | 2371 fn = _simplifyPassThroughArrowFunCallBody(fn); |
| 2356 } | 2372 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2435 return false; | 2451 return false; |
| 2436 } | 2452 } |
| 2437 return _loader.isLoaded(type.element); | 2453 return _loader.isLoaded(type.element); |
| 2438 } | 2454 } |
| 2439 | 2455 |
| 2440 JS.Expression _emitFunctionTagged(JS.Expression fn, DartType type, | 2456 JS.Expression _emitFunctionTagged(JS.Expression fn, DartType type, |
| 2441 {topLevel: false}) { | 2457 {topLevel: false}) { |
| 2442 var lazy = topLevel && !_typeIsLoaded(type); | 2458 var lazy = topLevel && !_typeIsLoaded(type); |
| 2443 var typeRep = _emitFunctionType(type, definite: true); | 2459 var typeRep = _emitFunctionType(type, definite: true); |
| 2444 if (lazy) { | 2460 if (lazy) { |
| 2445 return js.call('dart.lazyFn(#, () => #)', [fn, typeRep]); | 2461 return _callHelper('lazyFn(#, () => #)', [fn, typeRep]); |
| 2446 } else { | 2462 } else { |
| 2447 return js.call('dart.fn(#, #)', [fn, typeRep]); | 2463 return _callHelper('fn(#, #)', [fn, typeRep]); |
| 2448 } | 2464 } |
| 2449 } | 2465 } |
| 2450 | 2466 |
| 2451 /// Emits an arrow FunctionExpression node. | 2467 /// Emits an arrow FunctionExpression node. |
| 2452 /// | 2468 /// |
| 2453 /// This should be used for all places in Dart's AST where FunctionExpression | 2469 /// This should be used for all places in Dart's AST where FunctionExpression |
| 2454 /// appears and the function is actually in an Expression context. These | 2470 /// appears and the function is actually in an Expression context. These |
| 2455 /// correspond to arrow functions in Dart. | 2471 /// correspond to arrow functions in Dart. |
| 2456 /// | 2472 /// |
| 2457 /// Contrast with [_emitFunction]. | 2473 /// Contrast with [_emitFunction]. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2589 _asyncStarController = savedController; | 2605 _asyncStarController = savedController; |
| 2590 | 2606 |
| 2591 DartType returnType = _getExpectedReturnType(element); | 2607 DartType returnType = _getExpectedReturnType(element); |
| 2592 JS.Expression gen = new JS.Fun(jsParams, jsBody, | 2608 JS.Expression gen = new JS.Fun(jsParams, jsBody, |
| 2593 isGenerator: true, returnType: emitTypeRef(returnType)); | 2609 isGenerator: true, returnType: emitTypeRef(returnType)); |
| 2594 if (JS.This.foundIn(gen)) { | 2610 if (JS.This.foundIn(gen)) { |
| 2595 gen = js.call('#.bind(this)', gen); | 2611 gen = js.call('#.bind(this)', gen); |
| 2596 } | 2612 } |
| 2597 | 2613 |
| 2598 var T = _emitType(returnType); | 2614 var T = _emitType(returnType); |
| 2599 return js.call('dart.#(#)', [ | 2615 return _callHelper('#(#)', [ |
| 2600 kind, | 2616 kind, |
| 2601 [gen, T]..addAll(visitFormalParameterList(parameters, destructure: false)) | 2617 [gen, T]..addAll(visitFormalParameterList(parameters, destructure: false)) |
| 2602 ]); | 2618 ]); |
| 2603 } | 2619 } |
| 2604 | 2620 |
| 2605 @override | 2621 @override |
| 2606 JS.Statement visitFunctionDeclarationStatement( | 2622 JS.Statement visitFunctionDeclarationStatement( |
| 2607 FunctionDeclarationStatement node) { | 2623 FunctionDeclarationStatement node) { |
| 2608 var func = node.functionDeclaration; | 2624 var func = node.functionDeclaration; |
| 2609 if (func.isGetter || func.isSetter) { | 2625 if (func.isGetter || func.isSetter) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2629 | 2645 |
| 2630 /// Emits a simple identifier, including handling an inferred generic | 2646 /// Emits a simple identifier, including handling an inferred generic |
| 2631 /// function instantiation. | 2647 /// function instantiation. |
| 2632 @override | 2648 @override |
| 2633 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { | 2649 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { |
| 2634 var typeArgs = _getTypeArgs(node.staticElement, node.staticType); | 2650 var typeArgs = _getTypeArgs(node.staticElement, node.staticType); |
| 2635 var simpleId = _emitSimpleIdentifier(node); | 2651 var simpleId = _emitSimpleIdentifier(node); |
| 2636 if (typeArgs == null) { | 2652 if (typeArgs == null) { |
| 2637 return simpleId; | 2653 return simpleId; |
| 2638 } | 2654 } |
| 2639 return js.call('dart.gbind(#, #)', [simpleId, typeArgs]); | 2655 return _callHelper('gbind(#, #)', [simpleId, typeArgs]); |
| 2640 } | 2656 } |
| 2641 | 2657 |
| 2642 /// Emits a simple identifier, handling implicit `this` as well as | 2658 /// Emits a simple identifier, handling implicit `this` as well as |
| 2643 /// going through the qualified library name if necessary, but *not* handling | 2659 /// going through the qualified library name if necessary, but *not* handling |
| 2644 /// inferred generic function instantiation. | 2660 /// inferred generic function instantiation. |
| 2645 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) { | 2661 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) { |
| 2646 var accessor = node.staticElement; | 2662 var accessor = node.staticElement; |
| 2647 if (accessor == null) { | 2663 if (accessor == null) { |
| 2648 return js.commentExpression( | 2664 return js.commentExpression( |
| 2649 'Unimplemented unknown name', new JS.Identifier(node.name)); | 2665 'Unimplemented unknown name', new JS.Identifier(node.name)); |
| 2650 } | 2666 } |
| 2651 | 2667 |
| 2652 // Get the original declaring element. If we had a property accessor, this | 2668 // Get the original declaring element. If we had a property accessor, this |
| 2653 // indirects back to a (possibly synthetic) field. | 2669 // indirects back to a (possibly synthetic) field. |
| 2654 var element = accessor; | 2670 var element = accessor; |
| 2655 if (accessor is PropertyAccessorElement) element = accessor.variable; | 2671 if (accessor is PropertyAccessorElement) element = accessor.variable; |
| 2656 | 2672 |
| 2657 _declareBeforeUse(element); | 2673 _declareBeforeUse(element); |
| 2658 | 2674 |
| 2659 // type literal | 2675 // type literal |
| 2660 if (element is TypeDefiningElement) { | 2676 if (element is TypeDefiningElement) { |
| 2661 var typeName = _emitType(fillDynamicTypeArgs(element.type)); | 2677 var typeName = _emitType(fillDynamicTypeArgs(element.type)); |
| 2662 | 2678 |
| 2663 // If the type is a type literal expression in Dart code, wrap the raw | 2679 // If the type is a type literal expression in Dart code, wrap the raw |
| 2664 // runtime type in a "Type" instance. | 2680 // runtime type in a "Type" instance. |
| 2665 if (!_isInForeignJS && _isTypeLiteral(node)) { | 2681 if (!_isInForeignJS && _isTypeLiteral(node)) { |
| 2666 typeName = js.call('dart.wrapType(#)', typeName); | 2682 typeName = _callHelper('wrapType(#)', typeName); |
| 2667 } | 2683 } |
| 2668 | 2684 |
| 2669 return typeName; | 2685 return typeName; |
| 2670 } | 2686 } |
| 2671 | 2687 |
| 2672 // library member | 2688 // library member |
| 2673 if (element.enclosingElement is CompilationUnitElement) { | 2689 if (element.enclosingElement is CompilationUnitElement) { |
| 2674 return _emitTopLevelName(element); | 2690 return _emitTopLevelName(element); |
| 2675 } | 2691 } |
| 2676 | 2692 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2687 // library prefix. We don't need those because static calls can't use | 2703 // library prefix. We don't need those because static calls can't use |
| 2688 // the generic type. | 2704 // the generic type. |
| 2689 if (isStatic) { | 2705 if (isStatic) { |
| 2690 var dynType = _emitType(fillDynamicTypeArgs(type)); | 2706 var dynType = _emitType(fillDynamicTypeArgs(type)); |
| 2691 return new JS.PropertyAccess(dynType, member); | 2707 return new JS.PropertyAccess(dynType, member); |
| 2692 } | 2708 } |
| 2693 | 2709 |
| 2694 // For instance members, we add implicit-this. | 2710 // For instance members, we add implicit-this. |
| 2695 // For method tear-offs, we ensure it's a bound method. | 2711 // For method tear-offs, we ensure it's a bound method. |
| 2696 var tearOff = element is MethodElement && !inInvocationContext(node); | 2712 var tearOff = element is MethodElement && !inInvocationContext(node); |
| 2697 var code = (tearOff) ? 'dart.bind(this, #)' : 'this.#'; | 2713 if (tearOff) return _callHelper('bind(this, #)', member); |
| 2698 return js.call(code, member); | 2714 return js.call('this.#', member); |
| 2699 } | 2715 } |
| 2700 | 2716 |
| 2701 if (element is ParameterElement) { | 2717 if (element is ParameterElement) { |
| 2702 return _emitParameter(element); | 2718 return _emitParameter(element); |
| 2703 } | 2719 } |
| 2704 | 2720 |
| 2705 // If this is one of our compiler's temporary variables, return its JS form. | 2721 // If this is one of our compiler's temporary variables, return its JS form. |
| 2706 if (element is TemporaryVariableElement) { | 2722 if (element is TemporaryVariableElement) { |
| 2707 return element.jsVariable; | 2723 return element.jsVariable; |
| 2708 } | 2724 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2805 bool lowerTypedef: false, | 2821 bool lowerTypedef: false, |
| 2806 bool nameType: true, | 2822 bool nameType: true, |
| 2807 bool hoistType: true, | 2823 bool hoistType: true, |
| 2808 definite: false}) { | 2824 definite: false}) { |
| 2809 var parts = _emitFunctionTypeParts(type, | 2825 var parts = _emitFunctionTypeParts(type, |
| 2810 parameters: parameters, | 2826 parameters: parameters, |
| 2811 lowerTypedef: lowerTypedef, | 2827 lowerTypedef: lowerTypedef, |
| 2812 nameType: nameType, | 2828 nameType: nameType, |
| 2813 hoistType: hoistType); | 2829 hoistType: hoistType); |
| 2814 var helper = (definite) ? 'definiteFunctionType' : 'functionType'; | 2830 var helper = (definite) ? 'definiteFunctionType' : 'functionType'; |
| 2815 var fullType = js.call('dart.${helper}(#)', [parts]); | 2831 var fullType = _callHelper('${helper}(#)', [parts]); |
| 2816 if (!nameType) return fullType; | 2832 if (!nameType) return fullType; |
| 2817 return _typeTable.nameType(type, fullType, | 2833 return _typeTable.nameType(type, fullType, |
| 2818 hoistType: hoistType, definite: definite); | 2834 hoistType: hoistType, definite: definite); |
| 2819 } | 2835 } |
| 2820 | 2836 |
| 2821 JS.Expression _emitAnnotatedFunctionType( | 2837 JS.Expression _emitAnnotatedFunctionType( |
| 2822 FunctionType type, List<Annotation> metadata, | 2838 FunctionType type, List<Annotation> metadata, |
| 2823 {List<FormalParameter> parameters, | 2839 {List<FormalParameter> parameters, |
| 2824 bool lowerTypedef: false, | 2840 bool lowerTypedef: false, |
| 2825 bool nameType: true, | 2841 bool nameType: true, |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2901 /// if [hoistType] is true, then the named type will be hoisted. | 2917 /// if [hoistType] is true, then the named type will be hoisted. |
| 2902 JS.Expression _emitType(DartType type, | 2918 JS.Expression _emitType(DartType type, |
| 2903 {bool lowerTypedef: false, | 2919 {bool lowerTypedef: false, |
| 2904 bool lowerGeneric: false, | 2920 bool lowerGeneric: false, |
| 2905 bool nameType: true, | 2921 bool nameType: true, |
| 2906 bool hoistType: true, | 2922 bool hoistType: true, |
| 2907 ClassElement subClass, | 2923 ClassElement subClass, |
| 2908 JS.Expression className}) { | 2924 JS.Expression className}) { |
| 2909 // The void and dynamic types are not defined in core. | 2925 // The void and dynamic types are not defined in core. |
| 2910 if (type.isVoid) { | 2926 if (type.isVoid) { |
| 2911 return js.call('dart.void'); | 2927 return _callHelper('void'); |
| 2912 } else if (type.isDynamic) { | 2928 } else if (type.isDynamic) { |
| 2913 return js.call('dart.dynamic'); | 2929 return _callHelper('dynamic'); |
| 2914 } else if (type.isBottom) { | 2930 } else if (type.isBottom) { |
| 2915 return js.call('dart.bottom'); | 2931 return _callHelper('bottom'); |
| 2916 } | 2932 } |
| 2917 | 2933 |
| 2918 _declareBeforeUse(type.element); | 2934 _declareBeforeUse(type.element); |
| 2919 | 2935 |
| 2920 // TODO(jmesserly): like constants, should we hoist function types out of | 2936 // TODO(jmesserly): like constants, should we hoist function types out of |
| 2921 // methods? Similar issue with generic types. For all of these, we may want | 2937 // methods? Similar issue with generic types. For all of these, we may want |
| 2922 // to canonicalize them too, at least when inside the same library. | 2938 // to canonicalize them too, at least when inside the same library. |
| 2923 var name = type.name; | 2939 var name = type.name; |
| 2924 var element = type.element; | 2940 var element = type.element; |
| 2925 if (name == '' || name == null || lowerTypedef) { | 2941 if (name == '' || name == null || lowerTypedef) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3052 if (target is SuperExpression) { | 3068 if (target is SuperExpression) { |
| 3053 return _emitSetSuper(lhs, target, id, rhs); | 3069 return _emitSetSuper(lhs, target, id, rhs); |
| 3054 } | 3070 } |
| 3055 | 3071 |
| 3056 if (target != null && isDynamicInvoke(target)) { | 3072 if (target != null && isDynamicInvoke(target)) { |
| 3057 if (_inWhitelistCode(lhs)) { | 3073 if (_inWhitelistCode(lhs)) { |
| 3058 var vars = <JS.MetaLetVariable, JS.Expression>{}; | 3074 var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| 3059 var l = _visit(_bindValue(vars, 'l', target)); | 3075 var l = _visit(_bindValue(vars, 'l', target)); |
| 3060 var name = _emitMemberName(id.name); | 3076 var name = _emitMemberName(id.name); |
| 3061 return new JS.MetaLet(vars, [ | 3077 return new JS.MetaLet(vars, [ |
| 3062 js.call('(#[(#[dart._extensionType]) ? dartx[#] : #] = #)', | 3078 js.call('(#[(#[#._extensionType]) ? #[#] : #] = #)', [ |
| 3063 [l, l, name, name, _visit(rhs)]) | 3079 l, |
| 3080 l, |
| 3081 _runtimeModule, |
| 3082 name, |
| 3083 _extensionSymbolsModule, |
| 3084 name, |
| 3085 _visit(rhs) |
| 3086 ]) |
| 3064 ]); | 3087 ]); |
| 3065 } | 3088 } |
| 3066 return js.call('dart.#(#, #, #)', [ | 3089 return _callHelper('#(#, #, #)', [ |
| 3067 _emitDynamicOperationName('dput'), | 3090 _emitDynamicOperationName('dput'), |
| 3068 _visit(target), | 3091 _visit(target), |
| 3069 _emitMemberName(id.name), | 3092 _emitMemberName(id.name), |
| 3070 _visit(rhs) | 3093 _visit(rhs) |
| 3071 ]); | 3094 ]); |
| 3072 } | 3095 } |
| 3073 | 3096 |
| 3074 var accessor = id.staticElement; | 3097 var accessor = id.staticElement; |
| 3075 var element = | 3098 var element = |
| 3076 accessor is PropertyAccessorElement ? accessor.variable : accessor; | 3099 accessor is PropertyAccessorElement ? accessor.variable : accessor; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3089 } | 3112 } |
| 3090 } | 3113 } |
| 3091 | 3114 |
| 3092 return _badAssignment('Unhandled assignment', lhs, rhs); | 3115 return _badAssignment('Unhandled assignment', lhs, rhs); |
| 3093 } | 3116 } |
| 3094 | 3117 |
| 3095 JS.Expression _badAssignment(String problem, Expression lhs, Expression rhs) { | 3118 JS.Expression _badAssignment(String problem, Expression lhs, Expression rhs) { |
| 3096 // TODO(sra): We should get here only for compiler bugs or weirdness due to | 3119 // TODO(sra): We should get here only for compiler bugs or weirdness due to |
| 3097 // --unsafe-force-compile. Once those paths have been addressed, throw at | 3120 // --unsafe-force-compile. Once those paths have been addressed, throw at |
| 3098 // compile time. | 3121 // compile time. |
| 3099 return js.call('dart.throwUnimplementedError((#, #, #))', | 3122 return _callHelper('throwUnimplementedError((#, #, #))', |
| 3100 [js.string('$lhs ='), _visit(rhs), js.string(problem)]); | 3123 [js.string('$lhs ='), _visit(rhs), js.string(problem)]); |
| 3101 } | 3124 } |
| 3102 | 3125 |
| 3103 /// Emits assignment to a simple identifier. Handles all legal simple | 3126 /// Emits assignment to a simple identifier. Handles all legal simple |
| 3104 /// identifier assignment targets (local, top level library member, implicit | 3127 /// identifier assignment targets (local, top level library member, implicit |
| 3105 /// `this` or class, etc.) | 3128 /// `this` or class, etc.) |
| 3106 JS.Expression _emitSetSimpleIdentifier( | 3129 JS.Expression _emitSetSimpleIdentifier( |
| 3107 SimpleIdentifier node, Expression rhs) { | 3130 SimpleIdentifier node, Expression rhs) { |
| 3108 JS.Expression unimplemented() { | 3131 JS.Expression unimplemented() { |
| 3109 return _badAssignment("Unimplemented: unknown name '$node'", node, rhs); | 3132 return _badAssignment("Unimplemented: unknown name '$node'", node, rhs); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3339 var element = node.methodName.staticElement; | 3362 var element = node.methodName.staticElement; |
| 3340 bool isStatic = element is ExecutableElement && element.isStatic; | 3363 bool isStatic = element is ExecutableElement && element.isStatic; |
| 3341 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); | 3364 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); |
| 3342 | 3365 |
| 3343 JS.Expression jsTarget = _visit(target); | 3366 JS.Expression jsTarget = _visit(target); |
| 3344 if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) { | 3367 if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) { |
| 3345 if (_inWhitelistCode(target)) { | 3368 if (_inWhitelistCode(target)) { |
| 3346 var vars = <JS.MetaLetVariable, JS.Expression>{}; | 3369 var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| 3347 var l = _visit(_bindValue(vars, 'l', target)); | 3370 var l = _visit(_bindValue(vars, 'l', target)); |
| 3348 jsTarget = new JS.MetaLet(vars, [ | 3371 jsTarget = new JS.MetaLet(vars, [ |
| 3349 js.call('(#[(#[dart._extensionType]) ? dartx[#] : #]).bind(#)', | 3372 js.call('(#[(#[#._extensionType]) ? #[#] : #]).bind(#)', [ |
| 3350 [l, l, memberName, memberName, l]) | 3373 l, |
| 3374 l, |
| 3375 _runtimeModule, |
| 3376 memberName, |
| 3377 _extensionSymbolsModule, |
| 3378 memberName, |
| 3379 l |
| 3380 ]) |
| 3351 ]); | 3381 ]); |
| 3352 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); | 3382 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); |
| 3353 return new JS.Call(jsTarget, args); | 3383 return new JS.Call(jsTarget, args); |
| 3354 } | 3384 } |
| 3355 if (typeArgs != null) { | 3385 if (typeArgs != null) { |
| 3356 return js.call('dart.#(#, #, #, #)', [ | 3386 return _callHelper('#(#, #, #, #)', [ |
| 3357 _emitDynamicOperationName('dgsend'), | 3387 _emitDynamicOperationName('dgsend'), |
| 3358 jsTarget, | 3388 jsTarget, |
| 3359 new JS.ArrayInitializer(typeArgs), | 3389 new JS.ArrayInitializer(typeArgs), |
| 3360 memberName, | 3390 memberName, |
| 3361 args | 3391 args |
| 3362 ]); | 3392 ]); |
| 3363 } else { | 3393 } else { |
| 3364 return js.call('dart.#(#, #, #)', | 3394 return _callHelper('#(#, #, #)', |
| 3365 [_emitDynamicOperationName('dsend'), jsTarget, memberName, args]); | 3395 [_emitDynamicOperationName('dsend'), jsTarget, memberName, args]); |
| 3366 } | 3396 } |
| 3367 } | 3397 } |
| 3368 if (_isObjectMemberCall(target, name)) { | 3398 if (_isObjectMemberCall(target, name)) { |
| 3369 assert(typeArgs == null); // Object methods don't take type args. | 3399 assert(typeArgs == null); // Object methods don't take type args. |
| 3370 return js.call('dart.#(#, #)', [name, jsTarget, args]); | 3400 return _callHelper('#(#, #)', [name, jsTarget, args]); |
| 3371 } | 3401 } |
| 3372 | 3402 |
| 3373 jsTarget = new JS.PropertyAccess(jsTarget, memberName); | 3403 jsTarget = new JS.PropertyAccess(jsTarget, memberName); |
| 3374 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); | 3404 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); |
| 3375 | 3405 |
| 3376 return new JS.Call(jsTarget, args); | 3406 return new JS.Call(jsTarget, args); |
| 3377 } | 3407 } |
| 3378 | 3408 |
| 3379 JS.Expression _emitDynamicInvoke( | 3409 JS.Expression _emitDynamicInvoke( |
| 3380 InvocationExpression node, JS.Expression fn, List<JS.Expression> args) { | 3410 InvocationExpression node, JS.Expression fn, List<JS.Expression> args) { |
| 3381 var typeArgs = _emitInvokeTypeArguments(node); | 3411 var typeArgs = _emitInvokeTypeArguments(node); |
| 3382 if (typeArgs != null) { | 3412 if (typeArgs != null) { |
| 3383 return js.call('dart.dgcall(#, #, #)', | 3413 return _callHelper( |
| 3384 [fn, new JS.ArrayInitializer(typeArgs), args]); | 3414 'dgcall(#, #, #)', [fn, new JS.ArrayInitializer(typeArgs), args]); |
| 3385 } else { | 3415 } else { |
| 3386 if (_inWhitelistCode(node, isCall: true)) { | 3416 if (_inWhitelistCode(node, isCall: true)) { |
| 3387 return new JS.Call(fn, args); | 3417 return new JS.Call(fn, args); |
| 3388 } | 3418 } |
| 3389 return js.call('dart.dcall(#, #)', [fn, args]); | 3419 return _callHelper('dcall(#, #)', [fn, args]); |
| 3390 } | 3420 } |
| 3391 } | 3421 } |
| 3392 | 3422 |
| 3393 /// Emits a function call, to a top-level function, local function, or | 3423 /// Emits a function call, to a top-level function, local function, or |
| 3394 /// an expression. | 3424 /// an expression. |
| 3395 JS.Expression _emitFunctionCall(InvocationExpression node) { | 3425 JS.Expression _emitFunctionCall(InvocationExpression node) { |
| 3396 var fn = _visit(node.function); | 3426 var fn = _visit(node.function); |
| 3397 var args = _visit(node.argumentList) as List<JS.Expression>; | 3427 var args = _visit(node.argumentList) as List<JS.Expression>; |
| 3398 if (isDynamicInvoke(node.function)) { | 3428 if (isDynamicInvoke(node.function)) { |
| 3399 return _emitDynamicInvoke(node, fn, args); | 3429 return _emitDynamicInvoke(node, fn, args); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3622 JS.Statement visitExpressionStatement(ExpressionStatement node) => | 3652 JS.Statement visitExpressionStatement(ExpressionStatement node) => |
| 3623 _visit(node.expression).toStatement(); | 3653 _visit(node.expression).toStatement(); |
| 3624 | 3654 |
| 3625 @override | 3655 @override |
| 3626 JS.EmptyStatement visitEmptyStatement(EmptyStatement node) => | 3656 JS.EmptyStatement visitEmptyStatement(EmptyStatement node) => |
| 3627 new JS.EmptyStatement(); | 3657 new JS.EmptyStatement(); |
| 3628 | 3658 |
| 3629 @override | 3659 @override |
| 3630 JS.Statement visitAssertStatement(AssertStatement node) => | 3660 JS.Statement visitAssertStatement(AssertStatement node) => |
| 3631 // TODO(jmesserly): only emit in checked mode. | 3661 // TODO(jmesserly): only emit in checked mode. |
| 3632 js.statement('dart.assert(#);', _visit(node.condition)); | 3662 _callHelperStatement('assert(#);', _visit(node.condition)); |
| 3633 | 3663 |
| 3634 @override | 3664 @override |
| 3635 JS.Statement visitReturnStatement(ReturnStatement node) { | 3665 JS.Statement visitReturnStatement(ReturnStatement node) { |
| 3636 var e = node.expression; | 3666 var e = node.expression; |
| 3637 if (e == null) return new JS.Return(); | 3667 if (e == null) return new JS.Return(); |
| 3638 return (_visit(e) as JS.Expression).toReturn(); | 3668 return (_visit(e) as JS.Expression).toReturn(); |
| 3639 } | 3669 } |
| 3640 | 3670 |
| 3641 @override | 3671 @override |
| 3642 JS.Statement visitYieldStatement(YieldStatement node) { | 3672 JS.Statement visitYieldStatement(YieldStatement node) { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3832 } | 3862 } |
| 3833 } | 3863 } |
| 3834 | 3864 |
| 3835 JS.Expression objExpr; | 3865 JS.Expression objExpr; |
| 3836 if (target is ClassElement) { | 3866 if (target is ClassElement) { |
| 3837 objExpr = _emitTopLevelName(target); | 3867 objExpr = _emitTopLevelName(target); |
| 3838 } else { | 3868 } else { |
| 3839 objExpr = emitLibraryName(target); | 3869 objExpr = emitLibraryName(target); |
| 3840 } | 3870 } |
| 3841 | 3871 |
| 3842 return js.statement('dart.defineLazy(#, { # });', [objExpr, methods]); | 3872 return _callHelperStatement('defineLazy(#, { # });', [objExpr, methods]); |
| 3843 } | 3873 } |
| 3844 | 3874 |
| 3845 PropertyAccessorElement _findAccessor(VariableElement element, | 3875 PropertyAccessorElement _findAccessor(VariableElement element, |
| 3846 {bool getter}) { | 3876 {bool getter}) { |
| 3847 var parent = element.enclosingElement; | 3877 var parent = element.enclosingElement; |
| 3848 if (parent is ClassElement) { | 3878 if (parent is ClassElement) { |
| 3849 return getter | 3879 return getter |
| 3850 ? parent.getGetter(element.name) | 3880 ? parent.getGetter(element.name) |
| 3851 : parent.getSetter(element.name); | 3881 : parent.getSetter(element.name); |
| 3852 } | 3882 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3949 | 3979 |
| 3950 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => | 3980 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => |
| 3951 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); | 3981 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); |
| 3952 | 3982 |
| 3953 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); | 3983 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); |
| 3954 | 3984 |
| 3955 JS.Expression notNull(Expression expr) { | 3985 JS.Expression notNull(Expression expr) { |
| 3956 if (expr == null) return null; | 3986 if (expr == null) return null; |
| 3957 var jsExpr = _visit(expr); | 3987 var jsExpr = _visit(expr); |
| 3958 if (!isNullable(expr)) return jsExpr; | 3988 if (!isNullable(expr)) return jsExpr; |
| 3959 return js.call('dart.notNull(#)', jsExpr); | 3989 return _callHelper('notNull(#)', jsExpr); |
| 3960 } | 3990 } |
| 3961 | 3991 |
| 3962 @override | 3992 @override |
| 3963 JS.Expression visitBinaryExpression(BinaryExpression node) { | 3993 JS.Expression visitBinaryExpression(BinaryExpression node) { |
| 3964 var op = node.operator; | 3994 var op = node.operator; |
| 3965 | 3995 |
| 3966 // The operands of logical boolean operators are subject to boolean | 3996 // The operands of logical boolean operators are subject to boolean |
| 3967 // conversion. | 3997 // conversion. |
| 3968 if (op.type == TokenType.BAR_BAR || | 3998 if (op.type == TokenType.BAR_BAR || |
| 3969 op.type == TokenType.AMPERSAND_AMPERSAND) { | 3999 op.type == TokenType.AMPERSAND_AMPERSAND) { |
| 3970 return _visitTest(node); | 4000 return _visitTest(node); |
| 3971 } | 4001 } |
| 3972 | 4002 |
| 3973 var left = node.leftOperand; | 4003 var left = node.leftOperand; |
| 3974 var right = node.rightOperand; | 4004 var right = node.rightOperand; |
| 3975 | 4005 |
| 3976 var leftType = getStaticType(left); | 4006 var leftType = getStaticType(left); |
| 3977 var rightType = getStaticType(right); | 4007 var rightType = getStaticType(right); |
| 3978 | 4008 |
| 3979 var code; | 4009 var code; |
| 3980 if (op.type.isEqualityOperator) { | 4010 if (op.type.isEqualityOperator) { |
| 3981 // If we statically know LHS or RHS is null we can generate a clean check. | 4011 // If we statically know LHS or RHS is null we can generate a clean check. |
| 3982 // We can also do this if both sides are the same primitive type. | 4012 // We can also do this if both sides are the same primitive type. |
| 3983 if (_canUsePrimitiveEquality(left, right)) { | 4013 if (_canUsePrimitiveEquality(left, right)) { |
| 3984 code = op.type == TokenType.EQ_EQ ? '# == #' : '# != #'; | 4014 code = op.type == TokenType.EQ_EQ ? '# == #' : '# != #'; |
| 3985 } else if (left is SuperExpression) { | 4015 } else if (left is SuperExpression) { |
| 3986 return _emitSend(left, op.lexeme, [right]); | 4016 return _emitSend(left, op.lexeme, [right]); |
| 3987 } else { | 4017 } else { |
| 3988 var bang = op.type == TokenType.BANG_EQ ? '!' : ''; | 4018 var bang = op.type == TokenType.BANG_EQ ? '!' : ''; |
| 3989 code = '${bang}dart.equals(#, #)'; | 4019 code = '${bang}#.equals(#, #)'; |
| 4020 return js.call(code, [_runtimeModule, _visit(left), _visit(right)]); |
| 3990 } | 4021 } |
| 3991 return js.call(code, [_visit(left), _visit(right)]); | 4022 return js.call(code, [_visit(left), _visit(right)]); |
| 3992 } | 4023 } |
| 3993 | 4024 |
| 3994 if (op.type.lexeme == '??') { | 4025 if (op.type.lexeme == '??') { |
| 3995 // TODO(jmesserly): leave RHS for debugging? | 4026 // TODO(jmesserly): leave RHS for debugging? |
| 3996 // This should be a hint or warning for dead code. | 4027 // This should be a hint or warning for dead code. |
| 3997 if (!isNullable(left)) return _visit(left); | 4028 if (!isNullable(left)) return _visit(left); |
| 3998 | 4029 |
| 3999 var vars = <JS.MetaLetVariable, JS.Expression>{}; | 4030 var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4292 // as it will go, e.g. at the level the generic class is defined where type | 4323 // as it will go, e.g. at the level the generic class is defined where type |
| 4293 // params are available. | 4324 // params are available. |
| 4294 if (_currentFunction == null || usesTypeParams) return jsExpr; | 4325 if (_currentFunction == null || usesTypeParams) return jsExpr; |
| 4295 | 4326 |
| 4296 var temp = new JS.TemporaryId('const'); | 4327 var temp = new JS.TemporaryId('const'); |
| 4297 _moduleItems.add(js.statement('let #;', [temp])); | 4328 _moduleItems.add(js.statement('let #;', [temp])); |
| 4298 return js.call('# || (# = #)', [temp, temp, jsExpr]); | 4329 return js.call('# || (# = #)', [temp, temp, jsExpr]); |
| 4299 } | 4330 } |
| 4300 | 4331 |
| 4301 JS.Expression _emitConst(JS.Expression expr()) => | 4332 JS.Expression _emitConst(JS.Expression expr()) => |
| 4302 _cacheConst(() => js.call('dart.const(#)', expr())); | 4333 _cacheConst(() => _callHelper('const(#)', expr())); |
| 4303 | 4334 |
| 4304 /// Returns a new expression, which can be be used safely *once* on the | 4335 /// Returns a new expression, which can be be used safely *once* on the |
| 4305 /// left hand side, and *once* on the right side of an assignment. | 4336 /// left hand side, and *once* on the right side of an assignment. |
| 4306 /// For example: `expr1[expr2] += y` can be compiled as | 4337 /// For example: `expr1[expr2] += y` can be compiled as |
| 4307 /// `expr1[expr2] = expr1[expr2] + y`. | 4338 /// `expr1[expr2] = expr1[expr2] + y`. |
| 4308 /// | 4339 /// |
| 4309 /// The temporary scope will ensure `expr1` and `expr2` are only evaluated | 4340 /// The temporary scope will ensure `expr1` and `expr2` are only evaluated |
| 4310 /// once: `((x1, x2) => x1[x2] = x1[x2] + y)(expr1, expr2)`. | 4341 /// once: `((x1, x2) => x1[x2] = x1[x2] + y)(expr1, expr2)`. |
| 4311 /// | 4342 /// |
| 4312 /// If the expression does not end up using `x1` or `x2` more than once, or | 4343 /// If the expression does not end up using `x1` or `x2` more than once, or |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4554 _createTemporary('_', nodeTarget.staticType, nullable: false); | 4585 _createTemporary('_', nodeTarget.staticType, nullable: false); |
| 4555 var baseNode = _stripNullAwareOp(node, param); | 4586 var baseNode = _stripNullAwareOp(node, param); |
| 4556 tail.add( | 4587 tail.add( |
| 4557 new JS.ArrowFun(<JS.Parameter>[_visit(param)], _visit(baseNode))); | 4588 new JS.ArrowFun(<JS.Parameter>[_visit(param)], _visit(baseNode))); |
| 4558 node = nodeTarget; | 4589 node = nodeTarget; |
| 4559 } else { | 4590 } else { |
| 4560 break; | 4591 break; |
| 4561 } | 4592 } |
| 4562 } | 4593 } |
| 4563 if (tail.isEmpty) return _visit(node); | 4594 if (tail.isEmpty) return _visit(node); |
| 4564 return js.call( | 4595 return _callHelper( |
| 4565 'dart.nullSafe(#, #)', [_visit(node) as JS.Expression, tail.reversed]); | 4596 'nullSafe(#, #)', [_visit(node) as JS.Expression, tail.reversed]); |
| 4566 } | 4597 } |
| 4567 | 4598 |
| 4568 static Token _getOperator(Expression node) { | 4599 static Token _getOperator(Expression node) { |
| 4569 if (node is PropertyAccess) return node.operator; | 4600 if (node is PropertyAccess) return node.operator; |
| 4570 if (node is MethodInvocation) return node.operator; | 4601 if (node is MethodInvocation) return node.operator; |
| 4571 return null; | 4602 return null; |
| 4572 } | 4603 } |
| 4573 | 4604 |
| 4574 // TODO(jmesserly): this is dropping source location. | 4605 // TODO(jmesserly): this is dropping source location. |
| 4575 Expression _stripNullAwareOp(Expression node, Expression newTarget) { | 4606 Expression _stripNullAwareOp(Expression node, Expression newTarget) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4652 JS.Expression _emitAccessInternal(Expression target, Element member, | 4683 JS.Expression _emitAccessInternal(Expression target, Element member, |
| 4653 String memberName, List<JS.Expression> typeArgs) { | 4684 String memberName, List<JS.Expression> typeArgs) { |
| 4654 bool isStatic = member is ClassMemberElement && member.isStatic; | 4685 bool isStatic = member is ClassMemberElement && member.isStatic; |
| 4655 var name = _emitMemberName(memberName, | 4686 var name = _emitMemberName(memberName, |
| 4656 type: getStaticType(target), isStatic: isStatic); | 4687 type: getStaticType(target), isStatic: isStatic); |
| 4657 if (isDynamicInvoke(target)) { | 4688 if (isDynamicInvoke(target)) { |
| 4658 if (_inWhitelistCode(target)) { | 4689 if (_inWhitelistCode(target)) { |
| 4659 var vars = <JS.MetaLetVariable, JS.Expression>{}; | 4690 var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| 4660 var l = _visit(_bindValue(vars, 'l', target)); | 4691 var l = _visit(_bindValue(vars, 'l', target)); |
| 4661 return new JS.MetaLet(vars, [ | 4692 return new JS.MetaLet(vars, [ |
| 4662 js.call('(#[dart._extensionType]) ? #[dartx[#]] : #.#', | 4693 js.call('(#[#._extensionType]) ? #[#[#]] : #.#', |
| 4663 [l, l, name, l, name]) | 4694 [l, _runtimeModule, l, _extensionSymbolsModule, name, l, name]) |
| 4664 ]); | 4695 ]); |
| 4665 } | 4696 } |
| 4666 return js.call('dart.#(#, #)', | 4697 return _callHelper('#(#, #)', |
| 4667 [_emitDynamicOperationName('dload'), _visit(target), name]); | 4698 [_emitDynamicOperationName('dload'), _visit(target), name]); |
| 4668 } | 4699 } |
| 4669 | 4700 |
| 4670 var jsTarget = _visit(target); | 4701 var jsTarget = _visit(target); |
| 4671 bool isSuper = jsTarget is JS.Super; | 4702 bool isSuper = jsTarget is JS.Super; |
| 4672 | 4703 |
| 4673 if (isSuper && member is FieldElement && !member.isSynthetic) { | 4704 if (isSuper && member is FieldElement && !member.isSynthetic) { |
| 4674 // If super.x is actually a field, then x is an instance property since | 4705 // If super.x is actually a field, then x is an instance property since |
| 4675 // subclasses cannot override x. | 4706 // subclasses cannot override x. |
| 4676 jsTarget = new JS.This(); | 4707 jsTarget = new JS.This(); |
| 4677 } | 4708 } |
| 4678 | 4709 |
| 4679 JS.Expression result; | 4710 JS.Expression result; |
| 4680 if (member != null && member is MethodElement && !isStatic) { | 4711 if (member != null && member is MethodElement && !isStatic) { |
| 4681 // Tear-off methods: explicitly bind it. | 4712 // Tear-off methods: explicitly bind it. |
| 4682 if (isSuper) { | 4713 if (isSuper) { |
| 4683 result = js.call('dart.bind(this, #, #.#)', [name, jsTarget, name]); | 4714 result = _callHelper('bind(this, #, #.#)', [name, jsTarget, name]); |
| 4684 } else if (_isObjectMemberCall(target, memberName)) { | 4715 } else if (_isObjectMemberCall(target, memberName)) { |
| 4685 result = js.call('dart.bind(#, #, dart.#)', | 4716 result = _callHelper('bind(#, #, #.#)', |
| 4686 [jsTarget, _propertyName(memberName), memberName]); | 4717 [jsTarget, _propertyName(memberName), _runtimeModule, memberName]); |
| 4687 } else { | 4718 } else { |
| 4688 result = js.call('dart.bind(#, #)', [jsTarget, name]); | 4719 result = _callHelper('bind(#, #)', [jsTarget, name]); |
| 4689 } | 4720 } |
| 4690 } else if (_isObjectMemberCall(target, memberName)) { | 4721 } else if (_isObjectMemberCall(target, memberName)) { |
| 4691 result = js.call('dart.#(#)', [memberName, jsTarget]); | 4722 result = _callHelper('#(#)', [memberName, jsTarget]); |
| 4692 } else { | 4723 } else { |
| 4693 result = js.call('#.#', [jsTarget, name]); | 4724 result = js.call('#.#', [jsTarget, name]); |
| 4694 } | 4725 } |
| 4695 if (typeArgs == null) { | 4726 if (typeArgs == null) { |
| 4696 return result; | 4727 return result; |
| 4697 } | 4728 } |
| 4698 return js.call('dart.gbind(#, #)', [result, typeArgs]); | 4729 return _callHelper('gbind(#, #)', [result, typeArgs]); |
| 4699 } | 4730 } |
| 4700 | 4731 |
| 4701 /// Emits a generic send, like an operator method. | 4732 /// Emits a generic send, like an operator method. |
| 4702 /// | 4733 /// |
| 4703 /// **Please note** this function does not support method invocation syntax | 4734 /// **Please note** this function does not support method invocation syntax |
| 4704 /// `obj.name(args)` because that could be a getter followed by a call. | 4735 /// `obj.name(args)` because that could be a getter followed by a call. |
| 4705 /// See [visitMethodInvocation]. | 4736 /// See [visitMethodInvocation]. |
| 4706 JS.Expression _emitSend( | 4737 JS.Expression _emitSend( |
| 4707 Expression target, String name, List<Expression> args) { | 4738 Expression target, String name, List<Expression> args) { |
| 4708 var type = getStaticType(target); | 4739 var type = getStaticType(target); |
| 4709 var memberName = _emitMemberName(name, type: type); | 4740 var memberName = _emitMemberName(name, type: type); |
| 4710 if (isDynamicInvoke(target)) { | 4741 if (isDynamicInvoke(target)) { |
| 4711 if (_inWhitelistCode(target)) { | 4742 if (_inWhitelistCode(target)) { |
| 4712 var vars = <JS.MetaLetVariable, JS.Expression>{}; | 4743 var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| 4713 var l = _visit(_bindValue(vars, 'l', target)); | 4744 var l = _visit(_bindValue(vars, 'l', target)); |
| 4714 return new JS.MetaLet(vars, [ | 4745 return new JS.MetaLet(vars, [ |
| 4715 js.call('(#[(#[dart._extensionType]) ? dartx[#] : #]).call(#, #)', | 4746 js.call('(#[(#[#._extensionType]) ? #[#] : #]).call(#, #)', [ |
| 4716 [l, l, memberName, memberName, l, _visitList(args)]) | 4747 l, |
| 4748 l, |
| 4749 _runtimeModule, |
| 4750 memberName, |
| 4751 _extensionSymbolsModule, |
| 4752 memberName, |
| 4753 l, |
| 4754 _visitList(args) |
| 4755 ]) |
| 4717 ]); | 4756 ]); |
| 4718 } | 4757 } |
| 4719 // dynamic dispatch | 4758 // dynamic dispatch |
| 4720 var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name]; | 4759 var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name]; |
| 4721 if (dynamicHelper != null) { | 4760 if (dynamicHelper != null) { |
| 4722 return js.call('dart.$dynamicHelper(#, #)', | 4761 return _callHelper('$dynamicHelper(#, #)', |
| 4723 [_visit(target) as JS.Expression, _visitList(args)]); | 4762 [_visit(target) as JS.Expression, _visitList(args)]); |
| 4724 } else { | 4763 } else { |
| 4725 return js.call('dart.dsend(#, #, #)', | 4764 return _callHelper( |
| 4726 [_visit(target), memberName, _visitList(args)]); | 4765 'dsend(#, #, #)', [_visit(target), memberName, _visitList(args)]); |
| 4727 } | 4766 } |
| 4728 } | 4767 } |
| 4729 | 4768 |
| 4730 // Generic dispatch to a statically known method. | 4769 // Generic dispatch to a statically known method. |
| 4731 return js.call('#.#(#)', [_visit(target), memberName, _visitList(args)]); | 4770 return js.call('#.#(#)', [_visit(target), memberName, _visitList(args)]); |
| 4732 } | 4771 } |
| 4733 | 4772 |
| 4734 @override | 4773 @override |
| 4735 visitIndexExpression(IndexExpression node) { | 4774 visitIndexExpression(IndexExpression node) { |
| 4736 var target = _getTarget(node); | 4775 var target = _getTarget(node); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4760 _visitTest(node.condition), | 4799 _visitTest(node.condition), |
| 4761 _visit(node.thenExpression), | 4800 _visit(node.thenExpression), |
| 4762 _visit(node.elseExpression) | 4801 _visit(node.elseExpression) |
| 4763 ]); | 4802 ]); |
| 4764 } | 4803 } |
| 4765 | 4804 |
| 4766 @override | 4805 @override |
| 4767 visitThrowExpression(ThrowExpression node) { | 4806 visitThrowExpression(ThrowExpression node) { |
| 4768 var expr = _visit(node.expression); | 4807 var expr = _visit(node.expression); |
| 4769 if (node.parent is ExpressionStatement) { | 4808 if (node.parent is ExpressionStatement) { |
| 4770 return js.statement('dart.throw(#);', expr); | 4809 return _callHelperStatement('throw(#);', expr); |
| 4771 } else { | 4810 } else { |
| 4772 return js.call('dart.throw(#)', expr); | 4811 return _callHelper('throw(#)', expr); |
| 4773 } | 4812 } |
| 4774 } | 4813 } |
| 4775 | 4814 |
| 4776 @override | 4815 @override |
| 4777 visitRethrowExpression(RethrowExpression node) { | 4816 visitRethrowExpression(RethrowExpression node) { |
| 4778 if (node.parent is ExpressionStatement) { | 4817 if (node.parent is ExpressionStatement) { |
| 4779 return js.statement('throw #;', _visit(_catchParameter)); | 4818 return js.statement('throw #;', _visit(_catchParameter)); |
| 4780 } else { | 4819 } else { |
| 4781 return js.call('throw #', _visit(_catchParameter)); | 4820 return js.call('throw #', _visit(_catchParameter)); |
| 4782 } | 4821 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4965 var savedCatch = _catchParameter; | 5004 var savedCatch = _catchParameter; |
| 4966 if (node.catchKeyword != null) { | 5005 if (node.catchKeyword != null) { |
| 4967 var name = node.exceptionParameter; | 5006 var name = node.exceptionParameter; |
| 4968 if (name != null && name != _catchParameter) { | 5007 if (name != null && name != _catchParameter) { |
| 4969 body.add(js | 5008 body.add(js |
| 4970 .statement('let # = #;', [_visit(name), _visit(_catchParameter)])); | 5009 .statement('let # = #;', [_visit(name), _visit(_catchParameter)])); |
| 4971 _catchParameter = name; | 5010 _catchParameter = name; |
| 4972 } | 5011 } |
| 4973 if (node.stackTraceParameter != null) { | 5012 if (node.stackTraceParameter != null) { |
| 4974 var stackVar = node.stackTraceParameter.name; | 5013 var stackVar = node.stackTraceParameter.name; |
| 4975 body.add(js.statement( | 5014 body.add(js.statement('let # = #.stackTrace(#);', |
| 4976 'let # = dart.stackTrace(#);', [stackVar, _visit(name)])); | 5015 [stackVar, _runtimeModule, _visit(name)])); |
| 4977 } | 5016 } |
| 4978 } | 5017 } |
| 4979 | 5018 |
| 4980 body.add( | 5019 body.add( |
| 4981 new JS.Block(_visitList(node.body.statements) as List<JS.Statement>)); | 5020 new JS.Block(_visitList(node.body.statements) as List<JS.Statement>)); |
| 4982 _catchParameter = savedCatch; | 5021 _catchParameter = savedCatch; |
| 4983 return _statement(body); | 5022 return _statement(body); |
| 4984 } | 5023 } |
| 4985 | 5024 |
| 4986 @override | 5025 @override |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5048 ParameterizedType type = node.staticType; | 5087 ParameterizedType type = node.staticType; |
| 5049 var elementType = type.typeArguments.single; | 5088 var elementType = type.typeArguments.single; |
| 5050 // TODO(jmesserly): analyzer will usually infer `List<Object>` because | 5089 // TODO(jmesserly): analyzer will usually infer `List<Object>` because |
| 5051 // that is the least upper bound of the element types. So we rarely | 5090 // that is the least upper bound of the element types. So we rarely |
| 5052 // generate a plain `List<dynamic>` anymore. | 5091 // generate a plain `List<dynamic>` anymore. |
| 5053 if (!elementType.isDynamic || isConst) { | 5092 if (!elementType.isDynamic || isConst) { |
| 5054 // dart.list helper internally depends on _interceptors.JSArray. | 5093 // dart.list helper internally depends on _interceptors.JSArray. |
| 5055 _declareBeforeUse(_jsArray); | 5094 _declareBeforeUse(_jsArray); |
| 5056 if (isConst) { | 5095 if (isConst) { |
| 5057 var typeRep = _emitType(elementType); | 5096 var typeRep = _emitType(elementType); |
| 5058 list = js.call('dart.constList(#, #)', [list, typeRep]); | 5097 list = _callHelper('constList(#, #)', [list, typeRep]); |
| 5059 } else { | 5098 } else { |
| 5060 // Call `new JSArray<E>.of(list)` | 5099 // Call `new JSArray<E>.of(list)` |
| 5061 var jsArrayType = _jsArray.type.instantiate(type.typeArguments); | 5100 var jsArrayType = _jsArray.type.instantiate(type.typeArguments); |
| 5062 list = js.call('#.of(#)', [_emitType(jsArrayType), list]); | 5101 list = js.call('#.of(#)', [_emitType(jsArrayType), list]); |
| 5063 } | 5102 } |
| 5064 } | 5103 } |
| 5065 return list; | 5104 return list; |
| 5066 } | 5105 } |
| 5067 | 5106 |
| 5068 if (isConst) return _cacheConst(emitList); | 5107 if (isConst) return _cacheConst(emitList); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 5094 for (var e in entries) { | 5133 for (var e in entries) { |
| 5095 values.add(_visit(e.key)); | 5134 values.add(_visit(e.key)); |
| 5096 values.add(_visit(e.value)); | 5135 values.add(_visit(e.value)); |
| 5097 } | 5136 } |
| 5098 mapArguments = new JS.ArrayInitializer(values); | 5137 mapArguments = new JS.ArrayInitializer(values); |
| 5099 } | 5138 } |
| 5100 var types = <JS.Expression>[]; | 5139 var types = <JS.Expression>[]; |
| 5101 if (reifyTypeArgs) { | 5140 if (reifyTypeArgs) { |
| 5102 types.addAll(typeArgs.map((e) => _emitType(e))); | 5141 types.addAll(typeArgs.map((e) => _emitType(e))); |
| 5103 } | 5142 } |
| 5104 return js.call('dart.map(#, #)', [mapArguments, types]); | 5143 return _callHelper('map(#, #)', [mapArguments, types]); |
| 5105 } | 5144 } |
| 5106 | 5145 |
| 5107 if (node.constKeyword != null) return _emitConst(emitMap); | 5146 if (node.constKeyword != null) return _emitConst(emitMap); |
| 5108 return emitMap(); | 5147 return emitMap(); |
| 5109 } | 5148 } |
| 5110 | 5149 |
| 5111 @override | 5150 @override |
| 5112 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => | 5151 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => |
| 5113 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); | 5152 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); |
| 5114 | 5153 |
| 5115 @override | 5154 @override |
| 5116 JS.Expression visitAdjacentStrings(AdjacentStrings node) => | 5155 JS.Expression visitAdjacentStrings(AdjacentStrings node) => |
| 5117 _visitListToBinary(node.strings, '+'); | 5156 _visitListToBinary(node.strings, '+'); |
| 5118 | 5157 |
| 5119 @override | 5158 @override |
| 5120 JS.Expression visitStringInterpolation(StringInterpolation node) { | 5159 JS.Expression visitStringInterpolation(StringInterpolation node) { |
| 5121 return new JS.TaggedTemplate( | 5160 return new JS.TaggedTemplate( |
| 5122 js.call('dart.str'), new JS.TemplateString(_visitList(node.elements))); | 5161 _callHelper('str'), new JS.TemplateString(_visitList(node.elements))); |
| 5123 } | 5162 } |
| 5124 | 5163 |
| 5125 @override | 5164 @override |
| 5126 String visitInterpolationString(InterpolationString node) { | 5165 String visitInterpolationString(InterpolationString node) { |
| 5127 // TODO(jmesserly): this call adds quotes, and then we strip them off. | 5166 // TODO(jmesserly): this call adds quotes, and then we strip them off. |
| 5128 var str = js.escapedString(node.value, '`').value; | 5167 var str = js.escapedString(node.value, '`').value; |
| 5129 return str.substring(1, str.length - 1); | 5168 return str.substring(1, str.length - 1); |
| 5130 } | 5169 } |
| 5131 | 5170 |
| 5132 @override | 5171 @override |
| 5133 visitInterpolationExpression(InterpolationExpression node) => | 5172 visitInterpolationExpression(InterpolationExpression node) => |
| 5134 _visit(node.expression); | 5173 _visit(node.expression); |
| 5135 | 5174 |
| 5136 @override | 5175 @override |
| 5137 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value); | 5176 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value); |
| 5138 | 5177 |
| 5139 @override | 5178 @override |
| 5140 JS.Expression visitExpression(Expression node) => | 5179 JS.Expression visitExpression(Expression node) => |
| 5141 _unimplementedCall('Unimplemented ${node.runtimeType}: $node'); | 5180 _unimplementedCall('Unimplemented ${node.runtimeType}: $node'); |
| 5142 | 5181 |
| 5143 JS.Expression _unimplementedCall(String comment) { | 5182 JS.Expression _unimplementedCall(String comment) { |
| 5144 return js.call('dart.throw(#)', [js.escapedString(comment)]); | 5183 return _callHelper('throw(#)', [js.escapedString(comment)]); |
| 5145 } | 5184 } |
| 5146 | 5185 |
| 5147 @override | 5186 @override |
| 5148 visitNode(AstNode node) { | 5187 visitNode(AstNode node) { |
| 5149 // TODO(jmesserly): verify this is unreachable. | 5188 // TODO(jmesserly): verify this is unreachable. |
| 5150 throw 'Unimplemented ${node.runtimeType}: $node'; | 5189 throw 'Unimplemented ${node.runtimeType}: $node'; |
| 5151 } | 5190 } |
| 5152 | 5191 |
| 5153 _visit(AstNode node) { | 5192 _visit(AstNode node) { |
| 5154 if (node == null) return null; | 5193 if (node == null) return null; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5191 return finish(js.call(code, | 5230 return finish(js.call(code, |
| 5192 [_visitTest(node.leftOperand), _visitTest(node.rightOperand)])); | 5231 [_visitTest(node.leftOperand), _visitTest(node.rightOperand)])); |
| 5193 } | 5232 } |
| 5194 | 5233 |
| 5195 var op = node.operator.type.lexeme; | 5234 var op = node.operator.type.lexeme; |
| 5196 if (op == '&&') return shortCircuit('# && #'); | 5235 if (op == '&&') return shortCircuit('# && #'); |
| 5197 if (op == '||') return shortCircuit('# || #'); | 5236 if (op == '||') return shortCircuit('# || #'); |
| 5198 } | 5237 } |
| 5199 if (node is AsExpression && CoercionReifier.isImplicitCast(node)) { | 5238 if (node is AsExpression && CoercionReifier.isImplicitCast(node)) { |
| 5200 assert(node.staticType == types.boolType); | 5239 assert(node.staticType == types.boolType); |
| 5201 return js.call('dart.test(#)', _visit(node.expression)); | 5240 return _callHelper('test(#)', _visit(node.expression)); |
| 5202 } | 5241 } |
| 5203 JS.Expression result = _visit(node); | 5242 JS.Expression result = _visit(node); |
| 5204 if (isNullable(node)) result = js.call('dart.test(#)', result); | 5243 if (isNullable(node)) result = _callHelper('test(#)', result); |
| 5205 return result; | 5244 return result; |
| 5206 } | 5245 } |
| 5207 | 5246 |
| 5208 /// Like [_emitMemberName], but for declaration sites. | 5247 /// Like [_emitMemberName], but for declaration sites. |
| 5209 /// | 5248 /// |
| 5210 /// Unlike call sites, we always have an element available, so we can use it | 5249 /// Unlike call sites, we always have an element available, so we can use it |
| 5211 /// directly rather than computing the relevant options for [_emitMemberName]. | 5250 /// directly rather than computing the relevant options for [_emitMemberName]. |
| 5212 JS.Expression _declareMemberName(ExecutableElement e, {bool useExtension}) { | 5251 JS.Expression _declareMemberName(ExecutableElement e, {bool useExtension}) { |
| 5213 String name; | 5252 String name; |
| 5214 if (e is PropertyAccessorElement) { | 5253 if (e is PropertyAccessorElement) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5295 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. | 5334 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. |
| 5296 var baseType = type; | 5335 var baseType = type; |
| 5297 while (baseType is TypeParameterType) { | 5336 while (baseType is TypeParameterType) { |
| 5298 baseType = (baseType.element as TypeParameterElement).bound; | 5337 baseType = (baseType.element as TypeParameterElement).bound; |
| 5299 } | 5338 } |
| 5300 useExtension = baseType != null && | 5339 useExtension = baseType != null && |
| 5301 _extensionTypes.hasNativeSubtype(baseType) && | 5340 _extensionTypes.hasNativeSubtype(baseType) && |
| 5302 !isObjectMember(name); | 5341 !isObjectMember(name); |
| 5303 } | 5342 } |
| 5304 | 5343 |
| 5305 return useExtension ? js.call('dartx.#', result) : result; | 5344 return useExtension |
| 5345 ? js.call('#.#', [_extensionSymbolsModule, result]) |
| 5346 : result; |
| 5306 } | 5347 } |
| 5307 | 5348 |
| 5308 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) { | 5349 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) { |
| 5309 return _privateNames | 5350 return _privateNames |
| 5310 .putIfAbsent(library, () => new HashMap()) | 5351 .putIfAbsent(library, () => new HashMap()) |
| 5311 .putIfAbsent(name, () { | 5352 .putIfAbsent(name, () { |
| 5312 var id = new JS.TemporaryId(name); | 5353 var id = new JS.TemporaryId(name); |
| 5313 _moduleItems.add( | 5354 _moduleItems.add( |
| 5314 js.statement('const # = Symbol(#);', [id, js.string(id.name, "'")])); | 5355 js.statement('const # = Symbol(#);', [id, js.string(id.name, "'")])); |
| 5315 return id; | 5356 return id; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5398 return type; | 5439 return type; |
| 5399 } else if (type is InterfaceType && type.element == expectedType.element) { | 5440 } else if (type is InterfaceType && type.element == expectedType.element) { |
| 5400 return type.typeArguments[0]; | 5441 return type.typeArguments[0]; |
| 5401 } else { | 5442 } else { |
| 5402 // TODO(leafp): The above only handles the case where the return type | 5443 // TODO(leafp): The above only handles the case where the return type |
| 5403 // is exactly Future/Stream/Iterable. Handle the subtype case. | 5444 // is exactly Future/Stream/Iterable. Handle the subtype case. |
| 5404 return DynamicTypeImpl.instance; | 5445 return DynamicTypeImpl.instance; |
| 5405 } | 5446 } |
| 5406 } | 5447 } |
| 5407 | 5448 |
| 5449 JS.Expression _callHelper(String code, [args]) { |
| 5450 if (args is List) { |
| 5451 args.insert(0, _runtimeModule); |
| 5452 } else if (args != null) { |
| 5453 args = [_runtimeModule, args]; |
| 5454 } else { |
| 5455 args = _runtimeModule; |
| 5456 } |
| 5457 return js.call('#.$code', args); |
| 5458 } |
| 5459 |
| 5460 JS.Statement _callHelperStatement(String code, args) { |
| 5461 if (args is List) { |
| 5462 args.insert(0, _runtimeModule); |
| 5463 } else { |
| 5464 args = [_runtimeModule, args]; |
| 5465 } |
| 5466 return js.statement('#.$code', args); |
| 5467 } |
| 5468 |
| 5408 /// Maps whitelisted files to a list of whitelisted methods | 5469 /// Maps whitelisted files to a list of whitelisted methods |
| 5409 /// within the file. | 5470 /// within the file. |
| 5410 /// | 5471 /// |
| 5411 /// If the value is null, the entire file is whitelisted. | 5472 /// If the value is null, the entire file is whitelisted. |
| 5412 /// | 5473 /// |
| 5413 // TODO(jmesserly): why is this here, and what can we do to remove it? | 5474 // TODO(jmesserly): why is this here, and what can we do to remove it? |
| 5414 // | 5475 // |
| 5415 // Hard coded lists are completely unnecessary -- if a feature is needed, | 5476 // Hard coded lists are completely unnecessary -- if a feature is needed, |
| 5416 // metadata, type system features, or command line options are the right way | 5477 // metadata, type system features, or command line options are the right way |
| 5417 // to express it. | 5478 // to express it. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5512 } | 5573 } |
| 5513 | 5574 |
| 5514 bool isLibraryPrefix(Expression node) => | 5575 bool isLibraryPrefix(Expression node) => |
| 5515 node is SimpleIdentifier && node.staticElement is PrefixElement; | 5576 node is SimpleIdentifier && node.staticElement is PrefixElement; |
| 5516 | 5577 |
| 5517 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 5578 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
| 5518 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 5579 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
| 5519 | 5580 |
| 5520 bool _isDartRuntime(LibraryElement l) => | 5581 bool _isDartRuntime(LibraryElement l) => |
| 5521 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 5582 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
| OLD | NEW |