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

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

Issue 2979353002: implement `Invocation.typeArguments` in DDC (Closed)
Patch Set: fix Created 3 years, 5 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 mixin(base, @rest mixins) => JS( 23 mixin(base, @rest mixins) => JS('', '''(() => {
24 '',
25 '''(() => {
26 // Create an initializer for the mixin, so when derived constructor calls 24 // Create an initializer for the mixin, so when derived constructor calls
27 // super, we can correctly initialize base and mixins. 25 // super, we can correctly initialize base and mixins.
28 26
29 // Create a class that will hold all of the mixin methods. 27 // Create a class that will hold all of the mixin methods.
30 class Mixin extends $base {} 28 class Mixin extends $base {}
31 // Save the original constructor. For ClassTypeAlias definitions, this 29 // Save the original constructor. For ClassTypeAlias definitions, this
32 // is the concrete type. We embed metadata (e.g., implemented interfaces) 30 // is the concrete type. We embed metadata (e.g., implemented interfaces)
33 // on this constructor and need to access that from runtime instances. 31 // on this constructor and need to access that from runtime instances.
34 let constructor = Mixin.prototype.constructor; 32 let constructor = Mixin.prototype.constructor;
35 // Copy each mixin's methods, with later ones overwriting earlier entries. 33 // Copy each mixin's methods, with later ones overwriting earlier entries.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 clazz, _implements, clazz, _implements); 104 clazz, _implements, clazz, _implements);
107 105
108 /// The Symbol for storing type arguments on a specialized generic type. 106 /// The Symbol for storing type arguments on a specialized generic type.
109 final _typeArguments = JS('', 'Symbol("typeArguments")'); 107 final _typeArguments = JS('', 'Symbol("typeArguments")');
110 108
111 final _originalDeclaration = JS('', 'Symbol("originalDeclaration")'); 109 final _originalDeclaration = JS('', 'Symbol("originalDeclaration")');
112 110
113 final mixinNew = JS('', 'Symbol("dart.mixinNew")'); 111 final mixinNew = JS('', 'Symbol("dart.mixinNew")');
114 112
115 /// Wrap a generic class builder function with future flattening. 113 /// Wrap a generic class builder function with future flattening.
116 flattenFutures(builder) => JS( 114 flattenFutures(builder) => JS('', '''(() => {
117 '',
118 '''(() => {
119 function flatten(T) { 115 function flatten(T) {
120 if (!T) return $builder($dynamic); 116 if (!T) return $builder($dynamic);
121 let futureClass = $getGenericClass($Future); 117 let futureClass = $getGenericClass($Future);
122 //TODO(leafp): This only handles the direct flattening case. 118 //TODO(leafp): This only handles the direct flattening case.
123 // It would probably be good to at least search up the class 119 // It would probably be good to at least search up the class
124 // hierarchy. If we keep doing flattening long term, we may 120 // hierarchy. If we keep doing flattening long term, we may
125 // want to implement the full future flattening per spec. 121 // want to implement the full future flattening per spec.
126 if ($getGenericClass(T) == futureClass) { 122 if ($getGenericClass(T) == futureClass) {
127 let args = $getGenericArgs(T); 123 let args = $getGenericArgs(T);
128 if (args) return $builder(args[0]); 124 if (args) return $builder(args[0]);
129 } 125 }
130 return $builder(T); 126 return $builder(T);
131 } 127 }
132 return flatten; 128 return flatten;
133 })()'''); 129 })()''');
134 130
135 /// Memoize a generic type constructor function. 131 /// Memoize a generic type constructor function.
136 generic(typeConstructor, [setBaseClass]) => JS( 132 generic(typeConstructor, [setBaseClass]) => JS('', '''(() => {
137 '',
138 '''(() => {
139 let length = $typeConstructor.length; 133 let length = $typeConstructor.length;
140 if (length < 1) { 134 if (length < 1) {
141 $throwInternalError('must have at least one generic type argument'); 135 $throwInternalError('must have at least one generic type argument');
142 } 136 }
143 let resultMap = new Map(); 137 let resultMap = new Map();
144 function makeGenericType(...args) { 138 function makeGenericType(...args) {
145 if (args.length != length && args.length != 0) { 139 if (args.length != length && args.length != 0) {
146 $throwInternalError('requires ' + length + ' or 0 type arguments'); 140 $throwInternalError('requires ' + length + ' or 0 type arguments');
147 } 141 }
148 while (args.length < length) args.push($dynamic); 142 while (args.length < length) args.push($dynamic);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 252
259 finalFieldType(type, metadata) => 253 finalFieldType(type, metadata) =>
260 JS('', '{ type: #, isFinal: true, metadata: # }', type, metadata); 254 JS('', '{ type: #, isFinal: true, metadata: # }', type, metadata);
261 255
262 fieldType(type, metadata) => 256 fieldType(type, metadata) =>
263 JS('', '{ type: #, isFinal: false, metadata: # }', type, metadata); 257 JS('', '{ type: #, isFinal: false, metadata: # }', type, metadata);
264 258
265 /// Get the type of a constructor from a class using the stored signature 259 /// Get the type of a constructor from a class using the stored signature
266 /// If name is undefined, returns the type of the default constructor 260 /// If name is undefined, returns the type of the default constructor
267 /// Returns undefined if the constructor is not found. 261 /// Returns undefined if the constructor is not found.
268 classGetConstructorType(cls, name) => JS( 262 classGetConstructorType(cls, name) => JS('', '''(() => {
269 '',
270 '''(() => {
271 if(!$name) $name = 'new'; 263 if(!$name) $name = 'new';
272 if ($cls === void 0) return void 0; 264 if ($cls === void 0) return void 0;
273 if ($cls == null) return void 0; 265 if ($cls == null) return void 0;
274 let sigCtor = $cls[$_constructorSig]; 266 let sigCtor = $cls[$_constructorSig];
275 if (sigCtor === void 0) return void 0; 267 if (sigCtor === void 0) return void 0;
276 return sigCtor[$name]; 268 return sigCtor[$name];
277 })()'''); 269 })()''');
278 270
279 // Set up the method signature field on the constructor 271 // Set up the method signature field on the constructor
280 _setInstanceSignature(f, sigF, kind) => defineMemoizedGetter( 272 _setInstanceSignature(f, sigF, kind) => defineMemoizedGetter(
(...skipping 29 matching lines...) Expand all
310 _setStaticFieldSignature(f, sigF) => 302 _setStaticFieldSignature(f, sigF) =>
311 JS('', '$defineMemoizedGetter($f, $_staticFieldSig, $sigF)'); 303 JS('', '$defineMemoizedGetter($f, $_staticFieldSig, $sigF)');
312 304
313 _setStaticGetterSignature(f, sigF) => 305 _setStaticGetterSignature(f, sigF) =>
314 JS('', '$defineMemoizedGetter($f, $_staticGetterSig, $sigF)'); 306 JS('', '$defineMemoizedGetter($f, $_staticGetterSig, $sigF)');
315 307
316 _setStaticSetterSignature(f, sigF) => 308 _setStaticSetterSignature(f, sigF) =>
317 JS('', '$defineMemoizedGetter($f, $_staticSetterSig, $sigF)'); 309 JS('', '$defineMemoizedGetter($f, $_staticSetterSig, $sigF)');
318 310
319 // Set the lazily computed runtime type field on static methods 311 // Set the lazily computed runtime type field on static methods
320 _setStaticTypes(f, names) => JS( 312 _setStaticTypes(f, names) => JS('', '''(() => {
321 '',
322 '''(() => {
323 for (let name of $names) { 313 for (let name of $names) {
324 // TODO(vsm): Need to generate static methods. 314 // TODO(vsm): Need to generate static methods.
325 if (!$f[name]) continue; 315 if (!$f[name]) continue;
326 $tagLazy($f[name], function() { 316 $tagLazy($f[name], function() {
327 return $f[$_staticSig][name]; 317 return $f[$_staticSig][name];
328 }) 318 })
329 } 319 }
330 })()'''); 320 })()''');
331 321
332 /// Set up the type signature of a class (constructor object) 322 /// Set up the type signature of a class (constructor object)
333 /// f is a constructor object 323 /// f is a constructor object
334 /// signature is an object containing optional properties as follows: 324 /// signature is an object containing optional properties as follows:
335 /// methods: A function returning an object mapping method names 325 /// methods: A function returning an object mapping method names
336 /// to method types. The function is evaluated lazily and cached. 326 /// to method types. The function is evaluated lazily and cached.
337 /// statics: A function returning an object mapping static method 327 /// statics: A function returning an object mapping static method
338 /// names to types. The function is evaluated lazily and cached. 328 /// names to types. The function is evaluated lazily and cached.
339 /// names: An array of the names of the static methods. Used to 329 /// names: An array of the names of the static methods. Used to
340 /// permit eagerly setting the runtimeType field on the methods 330 /// permit eagerly setting the runtimeType field on the methods
341 /// while still lazily computing the type descriptor object. 331 /// while still lazily computing the type descriptor object.
342 /// fields: A function returning an object mapping instance field 332 /// fields: A function returning an object mapping instance field
343 /// names to types. 333 /// names to types.
344 setSignature(f, signature) => JS( 334 setSignature(f, signature) => JS('', '''(() => {
345 '',
346 '''(() => {
347 // TODO(ochafik): Deconstruct these when supported by Chrome. 335 // TODO(ochafik): Deconstruct these when supported by Chrome.
348 let constructors = 336 let constructors =
349 ('constructors' in signature) ? signature.constructors : () => ({}); 337 ('constructors' in signature) ? signature.constructors : () => ({});
350 let methods = 338 let methods =
351 ('methods' in signature) ? signature.methods : () => ({}); 339 ('methods' in signature) ? signature.methods : () => ({});
352 let fields = 340 let fields =
353 ('fields' in signature) ? signature.fields : () => ({}); 341 ('fields' in signature) ? signature.fields : () => ({});
354 let getters = 342 let getters =
355 ('getters' in signature) ? signature.getters : () => ({}); 343 ('getters' in signature) ? signature.getters : () => ({});
356 let setters = 344 let setters =
(...skipping 13 matching lines...) Expand all
370 $_setFieldSignature($f, fields); 358 $_setFieldSignature($f, fields);
371 $_setGetterSignature($f, getters); 359 $_setGetterSignature($f, getters);
372 $_setSetterSignature($f, setters); 360 $_setSetterSignature($f, setters);
373 $_setStaticSignature($f, statics); 361 $_setStaticSignature($f, statics);
374 $_setStaticFieldSignature($f, staticFields); 362 $_setStaticFieldSignature($f, staticFields);
375 $_setStaticGetterSignature($f, staticGetters); 363 $_setStaticGetterSignature($f, staticGetters);
376 $_setStaticSetterSignature($f, staticSetters); 364 $_setStaticSetterSignature($f, staticSetters);
377 $_setStaticTypes($f, names); 365 $_setStaticTypes($f, names);
378 })()'''); 366 })()''');
379 367
380 bool _hasSigEntry(type, sigF, name) => JS( 368 bool _hasSigEntry(type, sigF, name) => JS('bool', '''(() => {
381 'bool',
382 '''(() => {
383 let sigObj = $type[$sigF]; 369 let sigObj = $type[$sigF];
384 if (sigObj === void 0) return false; 370 if (sigObj === void 0) return false;
385 return $name in sigObj; 371 return $name in sigObj;
386 })()'''); 372 })()''');
387 373
388 bool hasMethod(type, name) => _hasSigEntry(type, _methodSig, name); 374 bool hasMethod(type, name) => _hasSigEntry(type, _methodSig, name);
389 bool hasGetter(type, name) => _hasSigEntry(type, _getterSig, name); 375 bool hasGetter(type, name) => _hasSigEntry(type, _getterSig, name);
390 bool hasSetter(type, name) => _hasSigEntry(type, _setterSig, name); 376 bool hasSetter(type, name) => _hasSigEntry(type, _setterSig, name);
391 bool hasField(type, name) => _hasSigEntry(type, _fieldSig, name); 377 bool hasField(type, name) => _hasSigEntry(type, _fieldSig, name);
392 378
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 var names = getOwnPropertyNames(coreObjProto); 420 var names = getOwnPropertyNames(coreObjProto);
435 for (int i = 0; i < JS('int', '#.length', names); ++i) { 421 for (int i = 0; i < JS('int', '#.length', names); ++i) {
436 var name = JS('', '#[#]', names, i); 422 var name = JS('', '#[#]', names, i);
437 var desc = getOwnPropertyDescriptor(coreObjProto, name); 423 var desc = getOwnPropertyDescriptor(coreObjProto, name);
438 defineProperty(jsProto, getExtensionSymbol(name), desc); 424 defineProperty(jsProto, getExtensionSymbol(name), desc);
439 } 425 }
440 } 426 }
441 427
442 final _extensionMap = JS('', 'new Map()'); 428 final _extensionMap = JS('', 'new Map()');
443 429
444 _applyExtension(jsType, dartExtType) => JS( 430 _applyExtension(jsType, dartExtType) => JS('', '''(() => {
445 '',
446 '''(() => {
447 // TODO(vsm): Not all registered js types are real. 431 // TODO(vsm): Not all registered js types are real.
448 if (!$jsType) return; 432 if (!$jsType) return;
449 433
450 let jsProto = $jsType.prototype; 434 let jsProto = $jsType.prototype;
451 435
452 // TODO(vsm): This sometimes doesn't exist on FF. These types will be 436 // TODO(vsm): This sometimes doesn't exist on FF. These types will be
453 // broken. 437 // broken.
454 if (!jsProto) return; 438 if (!jsProto) return;
455 439
456 $_installProperties(jsProto, $dartExtType, jsProto[$_extensionType]); 440 $_installProperties(jsProto, $dartExtType, jsProto[$_extensionType]);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 /// 482 ///
499 /// Results in: 483 /// Results in:
500 /// 484 ///
501 /// MyType.prototype[dartx.add] = MyType.prototype.add; 485 /// MyType.prototype[dartx.add] = MyType.prototype.add;
502 /// MyType.prototype[dartx.remove] = MyType.prototype.remove; 486 /// MyType.prototype[dartx.remove] = MyType.prototype.remove;
503 /// 487 ///
504 // TODO(jmesserly): essentially this gives two names to the same method. 488 // TODO(jmesserly): essentially this gives two names to the same method.
505 // This benefit is roughly equivalent call performance either way, but the 489 // This benefit is roughly equivalent call performance either way, but the
506 // cost is we need to call defineExtensionMembers any time a subclass 490 // cost is we need to call defineExtensionMembers any time a subclass
507 // overrides one of these methods. 491 // overrides one of these methods.
508 defineExtensionMembers(type, methodNames) => JS( 492 defineExtensionMembers(type, methodNames) => JS('', '''(() => {
509 '',
510 '''(() => {
511 let proto = $type.prototype; 493 let proto = $type.prototype;
512 for (let name of $methodNames) { 494 for (let name of $methodNames) {
513 let method = $getOwnPropertyDescriptor(proto, name); 495 let method = $getOwnPropertyDescriptor(proto, name);
514 $defineProperty(proto, $getExtensionSymbol(name), method); 496 $defineProperty(proto, $getExtensionSymbol(name), method);
515 } 497 }
516 // Ensure the signature is available too. 498 // Ensure the signature is available too.
517 // TODO(jmesserly): not sure if we can do this in a cleaner way. Essentially 499 // TODO(jmesserly): not sure if we can do this in a cleaner way. Essentially
518 // we need to copy the signature (and in the future, other data like 500 // we need to copy the signature (and in the future, other data like
519 // annotations) any time we copy a method as part of our metaprogramming. 501 // annotations) any time we copy a method as part of our metaprogramming.
520 // It might be more friendly to JS metaprogramming if we include this info 502 // It might be more friendly to JS metaprogramming if we include this info
(...skipping 19 matching lines...) Expand all
540 upgradeSig($_getterSig); 522 upgradeSig($_getterSig);
541 upgradeSig($_setterSig); 523 upgradeSig($_setterSig);
542 })()'''); 524 })()''');
543 525
544 /// Sets the type of `obj` to be `type` 526 /// Sets the type of `obj` to be `type`
545 setType(obj, type) { 527 setType(obj, type) {
546 JS('', '#.__proto__ = #.prototype', obj, type); 528 JS('', '#.__proto__ = #.prototype', obj, type);
547 return obj; 529 return obj;
548 } 530 }
549 531
550 /// Sets the element type of a list literal.
551 list(obj, elementType) =>
552 setType(obj, JS('', '#(#)', getGenericClass(JSArray), elementType));
553
554 /// Link the extension to the type it's extending as a base class. 532 /// Link the extension to the type it's extending as a base class.
555 setBaseClass(derived, base) { 533 setBaseClass(derived, base) {
556 JS('', '#.prototype.__proto__ = #.prototype', derived, base); 534 JS('', '#.prototype.__proto__ = #.prototype', derived, base);
557 // We use __proto__ to track the superclass hierarchy (see isSubtype). 535 // We use __proto__ to track the superclass hierarchy (see isSubtype).
558 JS('', '#.__proto__ = #', derived, base); 536 JS('', '#.__proto__ = #', derived, base);
559 } 537 }
560 538
561 /// Like [setBaseClass], but for generic extension types such as `JSArray<E>`. 539 /// Like [setBaseClass], but for generic extension types such as `JSArray<E>`.
562 setExtensionBaseClass(dartType, jsType) { 540 setExtensionBaseClass(dartType, jsType) {
563 // Mark the generic type as an extension type and link the prototype objects. 541 // Mark the generic type as an extension type and link the prototype objects.
564 var dartProto = JS('', '#.prototype', dartType); 542 var dartProto = JS('', '#.prototype', dartType);
565 JS('', '#[#] = #', dartProto, _extensionType, dartType); 543 JS('', '#[#] = #', dartProto, _extensionType, dartType);
566 JS('', '#.__proto__ = #.prototype', dartProto, jsType); 544 JS('', '#.__proto__ = #.prototype', dartProto, jsType);
567 } 545 }
568 546
569 defineEnumValues(enumClass, names) { 547 defineEnumValues(enumClass, names) {
570 var values = []; 548 var values = [];
571 for (var i = 0; i < JS('int', '#.length', names); i++) { 549 for (var i = 0; i < JS('int', '#.length', names); i++) {
572 var value = const_(JS('', 'new #.new(#)', enumClass, i)); 550 var value = const_(JS('', 'new #.new(#)', enumClass, i));
573 JS('', '#.push(#)', values, value); 551 JS('', '#.push(#)', values, value);
574 defineValue(enumClass, JS('', '#[#]', names, i), value); 552 defineValue(enumClass, JS('', '#[#]', names, i), value);
575 } 553 }
576 JS('', '#.values = #', enumClass, constList(values, enumClass)); 554 JS('', '#.values = #', enumClass, constList(values, enumClass));
577 } 555 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698