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 |