Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Side by Side Diff: lib/src/codegen/js_codegen.dart

Issue 1058653002: implement mixins in subtype checks, more codegen fixes (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dev_compiler.src.codegen.js_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap; 7 import 'dart:collection' show HashSet, HashMap;
8 import 'dart:io' show Directory, File; 8 import 'dart:io' show Directory, File;
9 9
10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 ConstantEvaluator _constEvaluator; 61 ConstantEvaluator _constEvaluator;
62 62
63 final _exports = <String>[]; 63 final _exports = <String>[];
64 final _lazyFields = <VariableDeclaration>[]; 64 final _lazyFields = <VariableDeclaration>[];
65 final _properties = <FunctionDeclaration>[]; 65 final _properties = <FunctionDeclaration>[];
66 final _privateNames = new HashSet<String>(); 66 final _privateNames = new HashSet<String>();
67 final _pendingPrivateNames = <String>[]; 67 final _pendingPrivateNames = <String>[];
68 68
69 /// Classes we have not emitted yet. Values can be [ClassDeclaration] or 69 /// Classes we have not emitted yet. Values can be [ClassDeclaration] or
70 /// [ClassTypeAlias]. 70 /// [ClassTypeAlias].
71 final _pendingClasses = new HashMap<ClassElement, CompilationUnitMember>(); 71 final _pendingClasses = new HashMap<Element, CompilationUnitMember>();
72 72
73 /// Memoized results of [_lazyClass]. 73 /// Memoized results of [_lazyClass].
74 final _lazyClassMemo = new HashMap<ClassElement, bool>(); 74 final _lazyClassMemo = new HashMap<Element, bool>();
75 75
76 /// Memoized results of [_inLibraryCycle]. 76 /// Memoized results of [_inLibraryCycle].
77 final _libraryCycleMemo = new HashMap<LibraryElement, bool>(); 77 final _libraryCycleMemo = new HashMap<LibraryElement, bool>();
78 78
79 JSCodegenVisitor(this.libraryInfo, this.rules, this._checkerReporter); 79 JSCodegenVisitor(this.libraryInfo, this.rules, this._checkerReporter);
80 80
81 LibraryElement get currentLibrary => libraryInfo.library; 81 LibraryElement get currentLibrary => libraryInfo.library;
82 82
83 /// The name for the library's exports inside itself. 83 /// The name for the library's exports inside itself.
84 /// This much be a constant because we interpolate it into template strings, 84 /// This much be a constant because we interpolate it into template strings,
(...skipping 16 matching lines...) Expand all
101 } 101 }
102 } 102 }
103 } 103 }
104 var body = <JS.Statement>[]; 104 var body = <JS.Statement>[];
105 105
106 // Collect classes we need to emit, used for: 106 // Collect classes we need to emit, used for:
107 // * tracks what we've emitted so we don't emit twice 107 // * tracks what we've emitted so we don't emit twice
108 // * provides a mapping from ClassElement back to the ClassDeclaration. 108 // * provides a mapping from ClassElement back to the ClassDeclaration.
109 for (var unit in library.partsThenLibrary) { 109 for (var unit in library.partsThenLibrary) {
110 for (var decl in unit.declarations) { 110 for (var decl in unit.declarations) {
111 if (decl is ClassDeclaration || decl is ClassTypeAlias) { 111 if (decl is ClassDeclaration ||
112 decl is ClassTypeAlias ||
113 decl is FunctionTypeAlias) {
112 _pendingClasses[decl.element] = decl; 114 _pendingClasses[decl.element] = decl;
113 } 115 }
114 } 116 }
115 } 117 }
116 118
117 for (var unit in library.partsThenLibrary) body.add(_visit(unit)); 119 for (var unit in library.partsThenLibrary) body.add(_visit(unit));
118 120
119 assert(_pendingClasses.isEmpty); 121 assert(_pendingClasses.isEmpty);
120 122
121 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); 123 if (_exports.isNotEmpty) body.add(js.comment('Exports:'));
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 255
254 String _jsTypeofName(DartType t) { 256 String _jsTypeofName(DartType t) {
255 if (rules.isIntType(t) || rules.isDoubleType(t)) return 'number'; 257 if (rules.isIntType(t) || rules.isDoubleType(t)) return 'number';
256 if (rules.isStringType(t)) return 'string'; 258 if (rules.isStringType(t)) return 'string';
257 if (rules.isBoolType(t)) return 'boolean'; 259 if (rules.isBoolType(t)) return 'boolean';
258 return null; 260 return null;
259 } 261 }
260 262
261 @override 263 @override
262 visitFunctionTypeAlias(FunctionTypeAlias node) { 264 visitFunctionTypeAlias(FunctionTypeAlias node) {
263 // TODO(vsm): Do we need to record type info the generated code for a 265 // If we've already emitted this class, skip it.
Jennifer Messerly 2015/04/01 22:31:31 all of these changes were because we do a type che
264 // typedef? 266 var type = node.element.type;
267 if (_pendingClasses.remove(node.element) == null) return null;
268
269 var classDecl = new JS.ClassDeclaration(new JS.ClassExpression(
Jennifer Messerly 2015/04/01 22:31:31 not sure if class is really what we want long term
vsm 2015/04/01 23:04:57 We might want this to be some sort of type object.
Jennifer Messerly 2015/04/01 23:22:56 yeah, something that is an instance of Type. Right
270 new JS.Identifier(type.name),
271 _emitTypeName(rules.provider.functionType), []));
272
273 return _finishClassDef(type, classDecl);
265 } 274 }
266 275
267 @override 276 @override
268 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type); 277 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type);
269 278
270 @override 279 @override
271 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { 280 JS.Statement visitClassTypeAlias(ClassTypeAlias node) {
272 // If we've already emitted this class, skip it. 281 // If we've already emitted this class, skip it.
273 var classElem = node.element; 282 var type = node.element.type;
274 if (_pendingClasses.remove(classElem) == null) return null; 283 if (_pendingClasses.remove(node.element) == null) return null;
275 284
276 var name = node.name.name; 285 var name = node.name.name;
277 var heritage = 286 var heritage =
278 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]); 287 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]);
279 var classDecl = new JS.ClassDeclaration( 288 var classDecl = new JS.ClassDeclaration(
280 new JS.ClassExpression(new JS.Identifier(name), heritage, [])); 289 new JS.ClassExpression(new JS.Identifier(name), heritage, []));
281 290
282 return _finishClassDef(classElem, classDecl); 291 return _finishClassDef(type, classDecl);
283 } 292 }
284 293
285 @override 294 @override
286 JS.Statement visitClassDeclaration(ClassDeclaration node) { 295 JS.Statement visitClassDeclaration(ClassDeclaration node) {
287 // If we've already emitted this class, skip it. 296 // If we've already emitted this class, skip it.
288 var classElem = node.element; 297 var type = node.element.type;
289 if (_pendingClasses.remove(classElem) == null) return null; 298 if (_pendingClasses.remove(node.element) == null) return null;
290 if (_getJsNameAnnotation(node) != null) return null; 299 if (_getJsNameAnnotation(node) != null) return null;
291 300
292 currentClass = node; 301 currentClass = node;
293 302
294 var ctors = <ConstructorDeclaration>[]; 303 var ctors = <ConstructorDeclaration>[];
295 var fields = <FieldDeclaration>[]; 304 var fields = <FieldDeclaration>[];
296 var staticFields = <FieldDeclaration>[]; 305 var staticFields = <FieldDeclaration>[];
297 for (var member in node.members) { 306 for (var member in node.members) {
298 if (member is ConstructorDeclaration) { 307 if (member is ConstructorDeclaration) {
299 ctors.add(member); 308 ctors.add(member);
300 } else if (member is FieldDeclaration) { 309 } else if (member is FieldDeclaration) {
301 (member.isStatic ? staticFields : fields).add(member); 310 (member.isStatic ? staticFields : fields).add(member);
302 } 311 }
303 } 312 }
304 313
305 var classExpr = new JS.ClassExpression(new JS.Identifier(classElem.name), 314 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name),
306 _classHeritage(node), _emitClassMethods(node, ctors, fields)); 315 _classHeritage(node), _emitClassMethods(node, ctors, fields));
307 316
308 var body = _finishClassMembers(classElem, classExpr, ctors, staticFields); 317 var body =
318 _finishClassMembers(node.element, classExpr, ctors, staticFields);
309 currentClass = null; 319 currentClass = null;
310 320
311 return _finishClassDef(classElem, body); 321 return _finishClassDef(type, body);
312 } 322 }
313 323
314 @override 324 @override
315 JS.Statement visitEnumDeclaration(EnumDeclaration node) => 325 JS.Statement visitEnumDeclaration(EnumDeclaration node) =>
316 _unimplementedCall("Unimplemented enum: $node").toStatement(); 326 _unimplementedCall("Unimplemented enum: $node").toStatement();
317 327
318 /// Given a class element and body, complete the class declaration. 328 /// Given a class element and body, complete the class declaration.
319 /// This handles generic type parameters, laziness (in library-cycle cases), 329 /// This handles generic type parameters, laziness (in library-cycle cases),
320 /// and ensuring dependencies are loaded first. 330 /// and ensuring dependencies are loaded first.
321 JS.Statement _finishClassDef(ClassElement classElem, JS.Statement body) { 331 JS.Statement _finishClassDef(ParameterizedType type, JS.Statement body) {
322 var name = classElem.name; 332 var name = type.name;
323 var genericName = '$name\$'; 333 var genericName = '$name\$';
324 334
325 JS.Statement genericDef; 335 JS.Statement genericDef;
326 JS.Expression genericInst; 336 JS.Expression genericInst;
327 if (classElem.typeParameters.isNotEmpty) { 337 if (type.typeParameters.isNotEmpty) {
328 genericDef = _emitGenericClassDef(classElem, body); 338 genericDef = _emitGenericClassDef(type, body);
329 var dynamicArgs = new List.filled(
330 classElem.typeParameters.length, js.call('dart.dynamic'));
vsm 2015/04/01 23:04:57 Shouldn't we fill in with core.Object?
Jennifer Messerly 2015/04/01 23:22:56 It's handled in dart_runtime by the generic functi
vsm 2015/04/01 23:34:47 If we have x is T somewhere in the body of the cla
Jennifer Messerly 2015/04/02 16:11:08 yes, like I said it happens in dart_runtime :) htt
vsm 2015/04/02 16:30:54 Aha! :-)
331
332 var target = genericName; 339 var target = genericName;
333 if (_needQualifiedName(classElem)) { 340 if (_needQualifiedName(type.element)) {
334 target = js.call('#.#', [_exportsVar, genericName]); 341 target = js.call('#.#', [_exportsVar, genericName]);
335 } 342 }
336 genericInst = js.call('#(#)', [target, dynamicArgs]); 343 genericInst = js.call('#()', [target]);
337 } 344 }
338 345
339 // The base class and all mixins must be declared before this class. 346 // The base class and all mixins must be declared before this class.
340 if (_lazyClass(classElem)) { 347 if (_lazyClass(type)) {
341 // TODO(jmesserly): the lazy class def is a simple solution for now. 348 // TODO(jmesserly): the lazy class def is a simple solution for now.
342 // We may want to consider other options in the future. 349 // We may want to consider other options in the future.
343 350
344 if (genericDef != null) { 351 if (genericDef != null) {
345 return js.statement( 352 return js.statement(
346 '{ #; dart.defineLazyClassGeneric(#, #, { get: # }); }', [ 353 '{ #; dart.defineLazyClassGeneric(#, #, { get: # }); }', [
347 genericDef, 354 genericDef,
348 _exportsVar, 355 _exportsVar,
349 js.string(name, "'"), 356 js.string(name, "'"),
350 genericName 357 genericName
351 ]); 358 ]);
352 } 359 }
353 360
354 return js.statement( 361 return js.statement(
355 'dart.defineLazyClass(#, { get #() { #; return #; } });', [ 362 'dart.defineLazyClass(#, { get #() { #; return #; } });', [
356 _exportsVar, 363 _exportsVar,
357 _propertyName(name), 364 _propertyName(name),
358 body, 365 body,
359 name 366 name
360 ]); 367 ]);
361 } 368 }
362 369
363 if (isPublic(name)) _exports.add(name); 370 if (isPublic(name)) _exports.add(name);
364 371
365 if (genericDef != null) { 372 if (genericDef != null) {
366 body = js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); 373 body = js.statement('{ #; let # = #; }', [genericDef, name, genericInst]);
367 if (isPublic(name)) _exports.add(genericName);
368 } 374 }
369 375
370 if (classElem.type.isObject) return body; 376 if (type.isObject) return body;
371 377
372 // If we're not lazy, we still need to ensure our dependencies are 378 // If we're not lazy, we still need to ensure our dependencies are
373 // generated first. 379 // generated first.
374 var classDefs = <JS.Statement>[]; 380 var classDefs = <JS.Statement>[];
375 _emitClassIfNeeded(classDefs, classElem.supertype.element); 381 if (type is InterfaceType) {
376 for (var m in classElem.mixins) { 382 _emitClassIfNeeded(classDefs, type.superclass);
377 _emitClassIfNeeded(classDefs, m.element); 383 for (var m in type.element.mixins) {
384 _emitClassIfNeeded(classDefs, m);
385 }
386 } else if (type is FunctionType) {
387 _emitClassIfNeeded(classDefs, rules.provider.functionType);
378 } 388 }
379 classDefs.add(body); 389 classDefs.add(body);
380 return _statement(classDefs); 390 return _statement(classDefs);
381 } 391 }
382 392
383 void _emitClassIfNeeded(List<JS.Statement> defs, ClassElement base) { 393 void _emitClassIfNeeded(List<JS.Statement> defs, DartType base) {
384 // We can only emit classes from this library. 394 // We can only emit classes from this library.
385 if (base.library != currentLibrary) return; 395 if (base.element.library != currentLibrary) return;
386 396
387 var baseNode = _pendingClasses[base]; 397 var baseNode = _pendingClasses[base.element];
388 if (baseNode != null) defs.add(visitClassDeclaration(baseNode)); 398 if (baseNode != null) defs.add(visitClassDeclaration(baseNode));
389 } 399 }
390 400
391 /// Returns true if the supertype or mixins aren't loaded. 401 /// Returns true if the supertype or mixins aren't loaded.
392 /// If that is the case, we'll emit a lazy class definition. 402 /// If that is the case, we'll emit a lazy class definition.
393 bool _lazyClass(ClassElement cls) { 403 bool _lazyClass(DartType type) {
394 if (cls.type.isObject) return false; 404 if (type.isObject) return false;
395 405
396 assert(cls.library == currentLibrary); 406 // Use the element as the key, as those are unique whereas generic types
397 var result = _lazyClassMemo[cls]; 407 // can have their arguments substituted.
408 assert(type.element.library == currentLibrary);
409 var result = _lazyClassMemo[type.element];
398 if (result != null) return result; 410 if (result != null) return result;
399 411
400 result = _classMightNotBeLoaded(cls.supertype.element); 412 if (type is InterfaceType) {
401 for (var mixin in cls.mixins) { 413 result = _typeMightNotBeLoaded(type.superclass) ||
402 if (result) break; 414 type.mixins.any(_typeMightNotBeLoaded);
403 result = _classMightNotBeLoaded(mixin.element); 415 } else if (type is FunctionType) {
416 result = _typeMightNotBeLoaded(rules.provider.functionType);
404 } 417 }
405 return _lazyClassMemo[cls] = result; 418 return _lazyClassMemo[type.element] = result;
406 } 419 }
407 420
408 /// Curated order to minimize lazy classes needed by dart:core and its 421 /// Curated order to minimize lazy classes needed by dart:core and its
409 /// transitive SDK imports. 422 /// transitive SDK imports.
410 static const CORELIB_ORDER = const [ 423 static const CORELIB_ORDER = const [
411 'dart.core', 424 'dart.core',
412 'dart.collection', 425 'dart.collection',
413 'dart._internal' 426 'dart._internal'
414 ]; 427 ];
415 428
416 /// Returns true if the class might not be loaded. 429 /// Returns true if the class might not be loaded.
417 /// 430 ///
418 /// If the class is from our library, this can happen because it's lazy. 431 /// If the class is from our library, this can happen because it's lazy.
419 /// 432 ///
420 /// If the class is from a different library, it could happen if we're in 433 /// If the class is from a different library, it could happen if we're in
421 /// a library cycle. In other words, if that different library depends back 434 /// a library cycle. In other words, if that different library depends back
422 /// on this library via some transitive import path. 435 /// on this library via some transitive import path.
423 /// 436 ///
424 /// If we could control the global import ordering, we could eliminate some 437 /// If we could control the global import ordering, we could eliminate some
425 /// of these cases, by ordering the imports of the cyclic libraries in an 438 /// of these cases, by ordering the imports of the cyclic libraries in an
426 /// optimal way. For example, we could order the libraries in a cycle to 439 /// optimal way. For example, we could order the libraries in a cycle to
427 /// minimize laziness. However, we currently assume we cannot control the 440 /// minimize laziness. However, we currently assume we cannot control the
428 /// order that the cycle of libraries will be loaded in. 441 /// order that the cycle of libraries will be loaded in.
429 bool _classMightNotBeLoaded(ClassElement cls) { 442 bool _typeMightNotBeLoaded(DartType type) {
430 if (cls.library == currentLibrary) return _lazyClass(cls); 443 var library = type.element.library;
444 if (library == currentLibrary) return _lazyClass(type);
431 445
432 // The SDK is a special case: we optimize the order to prevent laziness. 446 // The SDK is a special case: we optimize the order to prevent laziness.
433 if (cls.library.isInSdk) { 447 if (library.isInSdk) {
434 // SDK is loaded before non-SDK libraies 448 // SDK is loaded before non-SDK libraies
435 if (!currentLibrary.isInSdk) return false; 449 if (!currentLibrary.isInSdk) return false;
436 450
437 // Compute the order of both SDK libraries. If unknown, assume it's after. 451 // Compute the order of both SDK libraries. If unknown, assume it's after.
438 var classOrder = CORELIB_ORDER.indexOf(cls.library.name); 452 var classOrder = CORELIB_ORDER.indexOf(library.name);
439 if (classOrder == -1) classOrder = CORELIB_ORDER.length; 453 if (classOrder == -1) classOrder = CORELIB_ORDER.length;
440 454
441 var currentOrder = CORELIB_ORDER.indexOf(currentLibrary.name); 455 var currentOrder = CORELIB_ORDER.indexOf(currentLibrary.name);
442 if (currentOrder == -1) currentOrder = CORELIB_ORDER.length; 456 if (currentOrder == -1) currentOrder = CORELIB_ORDER.length;
443 457
444 // If the dart:* library we are currently compiling is loaded after the 458 // If the dart:* library we are currently compiling is loaded after the
445 // class's library, then we know the class is available. 459 // class's library, then we know the class is available.
446 if (classOrder != currentOrder) return currentOrder < classOrder; 460 if (classOrder != currentOrder) return currentOrder < classOrder;
447 461
448 // If we don't know the order of the class's library or the current 462 // If we don't know the order of the class's library or the current
449 // library, do the normal cycle check. (Not all SDK libs are cycles.) 463 // library, do the normal cycle check. (Not all SDK libs are cycles.)
450 } 464 }
451 465
452 return _inLibraryCycle(cls.library); 466 return _inLibraryCycle(library);
453 } 467 }
454 468
455 /// Returns true if [library] depends on the [currentLibrary] via some 469 /// Returns true if [library] depends on the [currentLibrary] via some
456 /// transitive import. 470 /// transitive import.
457 bool _inLibraryCycle(LibraryElement library) { 471 bool _inLibraryCycle(LibraryElement library) {
458 // SDK libs don't depend on things outside the SDK. 472 // SDK libs don't depend on things outside the SDK.
459 // (We can reach this via the recursive call below.) 473 // (We can reach this via the recursive call below.)
460 if (library.isInSdk && !currentLibrary.isInSdk) return false; 474 if (library.isInSdk && !currentLibrary.isInSdk) return false;
461 475
462 var result = _libraryCycleMemo[library]; 476 var result = _libraryCycleMemo[library];
463 if (result != null) return result; 477 if (result != null) return result;
464 478
465 result = library == currentLibrary; 479 result = library == currentLibrary;
466 _libraryCycleMemo[library] = result; 480 _libraryCycleMemo[library] = result;
467 for (var e in library.imports) { 481 for (var e in library.imports) {
468 if (result) break; 482 if (result) break;
469 result = _inLibraryCycle(e.importedLibrary); 483 result = _inLibraryCycle(e.importedLibrary);
470 } 484 }
471 for (var e in library.exports) { 485 for (var e in library.exports) {
472 if (result) break; 486 if (result) break;
473 result = _inLibraryCycle(e.exportedLibrary); 487 result = _inLibraryCycle(e.exportedLibrary);
474 } 488 }
475 return _libraryCycleMemo[library] = result; 489 return _libraryCycleMemo[library] = result;
476 } 490 }
477 491
478 JS.Statement _emitGenericClassDef(ClassElement cls, JS.Statement body) { 492 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) {
479 var name = cls.name; 493 var name = type.name;
480 var genericName = '$name\$'; 494 var genericName = '$name\$';
481 var typeParams = cls.typeParameters.map((p) => p.name); 495 var typeParams = type.typeParameters.map((p) => p.name);
496 if (isPublic(name)) _exports.add(genericName);
482 return js.statement('let # = dart.generic(function(#) { #; return #; });', [ 497 return js.statement('let # = dart.generic(function(#) { #; return #; });', [
483 genericName, 498 genericName,
484 typeParams, 499 typeParams,
485 body, 500 body,
486 name 501 name
487 ]); 502 ]);
488 } 503 }
489 504
490 JS.Expression _classHeritage(ClassDeclaration node) { 505 JS.Expression _classHeritage(ClassDeclaration node) {
491 if (node.element.type.isObject) return null; 506 if (node.element.type.isObject) return null;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 // Instead we use the same trick as named constructors, and do them as 643 // Instead we use the same trick as named constructors, and do them as
629 // instance methods that perform initialization. 644 // instance methods that perform initialization.
630 // TODO(jmesserly): we'll need to rethink this once the ES6 spec and V8 645 // TODO(jmesserly): we'll need to rethink this once the ES6 spec and V8
631 // settles. See <https://github.com/dart-lang/dev_compiler/issues/51>. 646 // settles. See <https://github.com/dart-lang/dev_compiler/issues/51>.
632 // Performance of this pattern is likely to be bad. 647 // Performance of this pattern is likely to be bad.
633 name = js.string('constructor', "'"); 648 name = js.string('constructor', "'");
634 // Mark the parameter as no-rename. 649 // Mark the parameter as no-rename.
635 var args = new JS.Identifier('arguments', allowRename: false); 650 var args = new JS.Identifier('arguments', allowRename: false);
636 body = js.statement('''{ 651 body = js.statement('''{
637 // Get the class name for this instance. 652 // Get the class name for this instance.
638 var name = this.constructor.name; 653 let name = this.constructor.name;
639 // Call the default constructor. 654 // Call the default constructor.
640 var init = this[name]; 655 let init = this[name];
641 var result = void 0; 656 let result = void 0;
642 if (init) result = init.apply(this, #); 657 if (init) result = init.apply(this, #);
643 return result === void 0 ? this : result; 658 return result === void 0 ? this : result;
644 }''', args); 659 }''', args);
645 } else { 660 } else {
646 body = _emitConstructorBody(node, fields); 661 body = _emitConstructorBody(node, fields);
647 } 662 }
648 663
649 // We generate constructors as initializer methods in the class; 664 // We generate constructors as initializer methods in the class;
650 // this allows use of `super` for instance methods/properties. 665 // this allows use of `super` for instance methods/properties.
651 // It also avoids V8 restrictions on `super` in default constructors. 666 // It also avoids V8 restrictions on `super` in default constructors.
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 } 1034 }
1020 1035
1021 if (typeArgs != null) { 1036 if (typeArgs != null) {
1022 result = js.call('#(#)', [result, typeArgs]); 1037 result = js.call('#(#)', [result, typeArgs]);
1023 } 1038 }
1024 return result; 1039 return result;
1025 } 1040 }
1026 1041
1027 bool _needQualifiedName(Element element) { 1042 bool _needQualifiedName(Element element) {
1028 var lib = element.library; 1043 var lib = element.library;
1029 1044 if (lib == null) return false;
1030 return lib != null && 1045 if (lib != currentLibrary) return true;
1031 (lib != currentLibrary || 1046 if (element is ClassElement) return _lazyClass(element.type);
1032 element is ClassElement && _lazyClass(element)); 1047 if (element is FunctionTypeAliasElement) return _lazyClass(element.type);
1048 return false;
1033 } 1049 }
1034 1050
1035 JS.Node _emitDPutIfDynamic( 1051 JS.Node _emitDPutIfDynamic(
1036 Expression target, SimpleIdentifier id, Expression rhs) { 1052 Expression target, SimpleIdentifier id, Expression rhs) {
1037 if (rules.isDynamicTarget(target)) { 1053 if (rules.isDynamicTarget(target)) {
1038 return js.call('dart.dput(#, #, #)', [ 1054 return js.call('dart.dput(#, #, #)', [
1039 _visit(target), 1055 _visit(target),
1040 js.string(id.name, "'"), 1056 js.string(id.name, "'"),
1041 _visit(rhs) 1057 _visit(rhs)
1042 ]); 1058 ]);
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 2400
2385 // TODO(jmesserly): in many cases marking the end will be unncessary. 2401 // TODO(jmesserly): in many cases marking the end will be unncessary.
2386 printer.mark(_location(node.end)); 2402 printer.mark(_location(node.end));
2387 } 2403 }
2388 2404
2389 String _getIdentifier(AstNode node) { 2405 String _getIdentifier(AstNode node) {
2390 if (node is SimpleIdentifier) return node.name; 2406 if (node is SimpleIdentifier) return node.name;
2391 return null; 2407 return null;
2392 } 2408 }
2393 } 2409 }
OLDNEW
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | lib/src/js/printer.dart » ('j') | lib/src/js/printer.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698