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

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart

Issue 2934623003: fix #29753, use ES5 constructors for ddc (Closed)
Patch Set: rebase Created 3 years, 6 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 /// This library defines the operations that define and manipulate Dart 5 /// This library defines the operations that define and manipulate Dart
6 /// classes. Included in this are: 6 /// classes. Included in this are:
7 /// - Generics 7 /// - Generics
8 /// - Class metadata 8 /// - Class metadata
9 /// - Extension methods 9 /// - Extension methods
10 /// 10 ///
11 11
12 // TODO(leafp): Consider splitting some of this out. 12 // TODO(leafp): Consider splitting some of this out.
13 part of dart._runtime; 13 part of dart._runtime;
14 14
15 /// 15 ///
16 /// Returns a new type that mixes members from base and all mixins. 16 /// Returns a new type that mixes members from base and all mixins.
17 /// 17 ///
18 /// Each mixin applies in sequence, with further to the right ones overriding 18 /// Each mixin applies in sequence, with further to the right ones overriding
19 /// previous entries. 19 /// previous entries.
20 /// 20 ///
21 /// For each mixin, we only take its own properties, not anything from its 21 /// For each mixin, we only take its own properties, not anything from its
22 /// superclass (prototype). 22 /// superclass (prototype).
23 ///
24 mixin(base, @rest mixins) => JS( 23 mixin(base, @rest mixins) => JS(
25 '', 24 '',
26 '''(() => { 25 '''(() => {
27 // Create an initializer for the mixin, so when derived constructor calls 26 // Create an initializer for the mixin, so when derived constructor calls
28 // super, we can correctly initialize base and mixins. 27 // super, we can correctly initialize base and mixins.
29 28
30 // Create a class that will hold all of the mixin methods. 29 // Create a class that will hold all of the mixin methods.
31 class Mixin extends $base {} 30 class Mixin extends $base {}
32 // Save the original constructor. For ClassTypeAlias definitions, this 31 // Save the original constructor. For ClassTypeAlias definitions, this
33 // is the concrete type. We embed metadata (e.g., implemented interfaces) 32 // is the concrete type. We embed metadata (e.g., implemented interfaces)
34 // on this constructor and need to access that from runtime instances. 33 // on this constructor and need to access that from runtime instances.
35 let constructor = Mixin.prototype.constructor; 34 let constructor = Mixin.prototype.constructor;
36 // Copy each mixin's methods, with later ones overwriting earlier entries. 35 // Copy each mixin's methods, with later ones overwriting earlier entries.
37 for (let m of $mixins) { 36 for (let m of $mixins) {
38 $copyProperties(Mixin.prototype, m.prototype); 37 $copyProperties(Mixin.prototype, m.prototype);
39 } 38 }
40 // Restore original Mixin constructor. 39 // Restore original Mixin JS constructor.
41 Mixin.prototype.constructor = constructor; 40 Mixin.prototype.constructor = constructor;
42 // Initializer methods: run mixin initializers, then the base. 41 // Dart constructors: run mixin constructors, then the base constructors.
43 Mixin.prototype.new = function(...args) { 42 for (let memberName of $getOwnNamesAndSymbols($base)) {
44 // Run mixin initializers. They cannot have arguments. 43 let member = $safeGetOwnProperty($base, memberName);
45 // Run them backwards so most-derived mixin is initialized first. 44 if (typeof member == "function" && member.prototype === base.prototype) {
46 for (let i = $mixins.length - 1; i >= 0; i--) { 45 $defineValue(Mixin, memberName, function(...args) {
47 $mixins[i].prototype.new.call(this);
48 }
49 // Run base initializer.
50 $base.prototype.new.apply(this, args);
51 };
52 let namedCtors = ${safeGetOwnProperty(base, _namedConstructors)};
53 if ($base[$_namedConstructors] != null) {
54 for (let namedCtor of $base[$_namedConstructors]) {
55 Mixin.prototype[namedCtor] = function(...args) {
56 // Run mixin initializers. They cannot have arguments. 46 // Run mixin initializers. They cannot have arguments.
57 // Run them backwards so most-derived mixin is initialized first. 47 // Run them backwards so most-derived mixin is initialized first.
58 for (let i = $mixins.length - 1; i >= 0; i--) { 48 for (let i = $mixins.length - 1; i >= 0; i--) {
59 $mixins[i].prototype.new.call(this); 49 $mixins[i].new.call(this);
60 } 50 }
61 // Run base initializer. 51 // Run base initializer.
62 $base.prototype[namedCtor].apply(this, args); 52 $base[memberName].apply(this, args);
63 }; 53 }).prototype = Mixin.prototype;
64 $defineNamedConstructor(Mixin, namedCtor);
65 } 54 }
66 } 55 }
67 56
68 // Set the signature of the Mixin class to be the composition 57 // Set the signature of the Mixin class to be the composition
69 // of the signatures of the mixins. 58 // of the signatures of the mixins.
70 $setSignature(Mixin, { 59 $setSignature(Mixin, {
71 methods: () => { 60 methods: () => {
72 let s = {}; 61 let s = {};
73 for (let m of $mixins) { 62 for (let m of $mixins) {
74 if (m[$_methodSig]) $copyProperties(s, m[$_methodSig]); 63 if (m[$_methodSig]) $copyProperties(s, m[$_methodSig]);
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 let sigObj = $type[$sigF]; 379 let sigObj = $type[$sigF];
391 if (sigObj === void 0) return false; 380 if (sigObj === void 0) return false;
392 return $name in sigObj; 381 return $name in sigObj;
393 })()'''); 382 })()''');
394 383
395 hasMethod(type, name) => _hasSigEntry(type, _methodSig, name); 384 hasMethod(type, name) => _hasSigEntry(type, _methodSig, name);
396 hasGetter(type, name) => _hasSigEntry(type, _getterSig, name); 385 hasGetter(type, name) => _hasSigEntry(type, _getterSig, name);
397 hasSetter(type, name) => _hasSigEntry(type, _setterSig, name); 386 hasSetter(type, name) => _hasSigEntry(type, _setterSig, name);
398 hasField(type, name) => _hasSigEntry(type, _fieldSig, name); 387 hasField(type, name) => _hasSigEntry(type, _fieldSig, name);
399 388
400 /// Given a class and an initializer method name, creates a constructor
401 /// function with the same name.
402 ///
403 /// After we define the named constructor, the class can be constructed with
404 /// `new SomeClass.name(args)`.
405 defineNamedConstructor(clazz, name) => JS(
406 '',
407 '''(() => {
408 let proto = $clazz.prototype;
409 let initMethod = proto[$name];
410 let ctor = function(...args) { initMethod.apply(this, args); };
411 ctor.prototype = proto;
412 // Use defineProperty so we don't hit a property defined on Function,
413 // like `caller` and `arguments`.
414 $defineProperty($clazz, $name, { value: ctor, configurable: true });
415
416 let namedCtors = ${safeGetOwnProperty(clazz, _namedConstructors)};
417 if (namedCtors == null) $clazz[$_namedConstructors] = namedCtors = [];
418 namedCtors.push($name);
419 })()''');
420
421 final _namedConstructors = JS('', 'Symbol("_namedConstructors")');
422
423 final _extensionType = JS('', 'Symbol("extensionType")'); 389 final _extensionType = JS('', 'Symbol("extensionType")');
424 390
425 getExtensionType(obj) => JS('', '#[#]', obj, _extensionType); 391 getExtensionType(obj) => JS('', '#[#]', obj, _extensionType);
426 392
427 final dartx = JS('', 'dartx'); 393 final dartx = JS('', 'dartx');
428 394
429 getExtensionSymbol(name) { 395 getExtensionSymbol(name) {
430 var sym = JS('', 'dartx[#]', name); 396 var sym = JS('', 'dartx[#]', name);
431 if (sym == null) { 397 if (sym == null) {
432 sym = JS('', 'Symbol("dartx." + #.toString())', name); 398 sym = JS('', 'Symbol("dartx." + #.toString())', name);
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 return JS( 558 return JS(
593 '', 559 '',
594 '''(() => { 560 '''(() => {
595 if ($base) { 561 if ($base) {
596 $derived.prototype[$_extensionType] = $derived; 562 $derived.prototype[$_extensionType] = $derived;
597 $derived.prototype.__proto__ = $base.prototype 563 $derived.prototype.__proto__ = $base.prototype
598 } 564 }
599 })()'''); 565 })()''');
600 } 566 }
601 567
602 /// Given a special constructor function that creates a function instances, 568 defineEnumValues(enumClass, names) {
603 /// and a class with a `call` method, merge them so the constructor function 569 var values = [];
604 /// will have the correct methods and prototype. 570 for (var i = 0; i < JS('int', '#.length', names); i++) {
605 /// 571 var value = const_(JS('', 'new #.new(#)', enumClass, i));
606 /// For example: 572 JS('', '#.push(#)', values, value);
607 /// 573 defineValue(enumClass, JS('', '#[#]', names, i), value);
608 /// lib.Foo = dart.callableClass( 574 }
609 /// function Foo { function call(...args) { ... } ... return call; }, 575 JS('', '#.values = #', enumClass, constList(values, enumClass));
610 /// class Foo { call(x) { ... } });
611 /// ...
612 /// let f = new lib.Foo();
613 /// f(42);
614 callableClass(callableCtor, classExpr) {
615 JS('', '#.prototype = #.prototype', callableCtor, classExpr);
616 // We're not going to use the original class, so we can safely replace it to
617 // point at this constructor for the runtime type information.
618 JS('', '#.prototype.constructor = #', callableCtor, callableCtor);
619 JS('', '#.__proto__ = #', callableCtor, classExpr);
620 return callableCtor;
621 } 576 }
622
623 /// Given a class and an initializer method name and a call method, creates a
624 /// constructor function with the same name.
625 ///
626 /// For example it can be called with `new SomeClass.name(args)`.
627 ///
628 /// The constructor
629 defineNamedConstructorCallable(clazz, name, ctor) => JS(
630 '',
631 '''(() => {
632 ctor.prototype = $clazz.prototype;
633 // Use defineProperty so we don't hit a property defined on Function,
634 // like `caller` and `arguments`.
635 $defineProperty($clazz, $name, { value: ctor, configurable: true });
636
637 let namedCtors = ${safeGetOwnProperty(clazz, _namedConstructors)};
638 if (namedCtors == null) $clazz[$_namedConstructors] = namedCtors = [];
639 namedCtors.push($name);
640 })()''');
641
642 defineEnumValues(enumClass, names) => JS(
643 '',
644 '''(() => {
645 let values = [];
646 for (var i = 0; i < $names.length; i++) {
647 let value = $const_(new $enumClass(i));
648 values.push(value);
649 Object.defineProperty($enumClass, $names[i],
650 { value: value, configurable: true });
651 }
652 $enumClass.values = $constList(values, $enumClass);
653 })()''');
OLDNEW
« no previous file with comments | « pkg/dev_compiler/test/codegen_expected/varargs.js ('k') | pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698