| 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 // 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 dart_library.library('dart_runtime/_classes', null, /* Imports */[ | 13 dart_library.library('dart/_classes', null, /* Imports */[ |
| 14 ], /* Lazy Imports */[ | 14 ], /* Lazy Imports */[ |
| 15 'dart/core', | 15 'dart/core', |
| 16 'dart/_interceptors', | 16 'dart/_interceptors', |
| 17 'dart_runtime/_types', | 17 'dart/_types', |
| 18 'dart_runtime/_rtti', | 18 'dart/_rtti', |
| 19 ], function(exports, core, _interceptors, types, rtti) { | 19 ], function(exports, core, _interceptors, types, rtti) { |
| 20 'use strict'; | 20 'use strict'; |
| 21 | 21 |
| 22 const assert = dart_utils.assert; | 22 const assert = dart_utils.assert; |
| 23 const copyProperties = dart_utils.copyProperties; | 23 const copyProperties = dart_utils.copyProperties; |
| 24 const copyTheseProperties = dart_utils.copyTheseProperties; | 24 const copyTheseProperties = dart_utils.copyTheseProperties; |
| 25 const defineMemoizedGetter = dart_utils.defineMemoizedGetter; | 25 const defineMemoizedGetter = dart_utils.defineMemoizedGetter; |
| 26 const safeGetOwnProperty = dart_utils.safeGetOwnProperty; | 26 const safeGetOwnProperty = dart_utils.safeGetOwnProperty; |
| 27 const throwInternalError = dart_utils.throwInternalError; | 27 const throwInternalError = dart_utils.throwInternalError; |
| 28 | 28 |
| 29 const defineProperty = Object.defineProperty; | 29 const defineProperty = Object.defineProperty; |
| 30 const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | 30 const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
| 31 const getOwnPropertySymbols = Object.getOwnPropertySymbols; | 31 const getOwnPropertySymbols = Object.getOwnPropertySymbols; |
| 32 | 32 |
| 33 const slice = [].slice; | |
| 34 | |
| 35 /** The Symbol for storing type arguments on a specialized generic type. */ | 33 /** The Symbol for storing type arguments on a specialized generic type. */ |
| 36 const _mixins = Symbol('mixins'); | 34 const _mixins = Symbol('mixins'); |
| 37 const _implements = Symbol('implements'); | 35 const _implements = Symbol('implements'); |
| 38 exports.implements = _implements; | 36 exports.implements = _implements; |
| 39 const _metadata = Symbol('metadata'); | 37 const _metadata = Symbol('metadata'); |
| 40 exports.metadata = _metadata; | 38 exports.metadata = _metadata; |
| 41 | 39 |
| 42 /** | 40 /** |
| 43 * Returns a new type that mixes members from base and all mixins. | 41 * Returns a new type that mixes members from base and all mixins. |
| 44 * | 42 * |
| 45 * Each mixin applies in sequence, with further to the right ones overriding | 43 * Each mixin applies in sequence, with further to the right ones overriding |
| 46 * previous entries. | 44 * previous entries. |
| 47 * | 45 * |
| 48 * For each mixin, we only take its own properties, not anything from its | 46 * For each mixin, we only take its own properties, not anything from its |
| 49 * superclass (prototype). | 47 * superclass (prototype). |
| 50 */ | 48 */ |
| 51 function mixin(base/*, ...mixins*/) { | 49 function mixin(base, ...mixins) { |
| 52 // Create an initializer for the mixin, so when derived constructor calls | 50 // Create an initializer for the mixin, so when derived constructor calls |
| 53 // super, we can correctly initialize base and mixins. | 51 // super, we can correctly initialize base and mixins. |
| 54 let mixins = slice.call(arguments, 1); | |
| 55 | 52 |
| 56 // Create a class that will hold all of the mixin methods. | 53 // Create a class that will hold all of the mixin methods. |
| 57 class Mixin extends base { | 54 class Mixin extends base { |
| 58 // Initializer method: run mixin initializers, then the base. | 55 // Initializer method: run mixin initializers, then the base. |
| 59 [base.name](/*...args*/) { | 56 [base.name](...args) { |
| 60 // Run mixin initializers. They cannot have arguments. | 57 // Run mixin initializers. They cannot have arguments. |
| 61 // Run them backwards so most-derived mixin is initialized first. | 58 // Run them backwards so most-derived mixin is initialized first. |
| 62 for (let i = mixins.length - 1; i >= 0; i--) { | 59 for (let i = mixins.length - 1; i >= 0; i--) { |
| 63 let mixin = mixins[i]; | 60 let mixin = mixins[i]; |
| 64 let init = mixin.prototype[mixin.name]; | 61 let init = mixin.prototype[mixin.name]; |
| 65 if (init) init.call(this); | 62 if (init) init.call(this); |
| 66 } | 63 } |
| 67 // Run base initializer. | 64 // Run base initializer. |
| 68 let init = base.prototype[base.name]; | 65 let init = base.prototype[base.name]; |
| 69 if (init) init.apply(this, arguments); | 66 if (init) init.apply(this, args); |
| 70 } | 67 } |
| 71 } | 68 } |
| 72 // Copy each mixin's methods, with later ones overwriting earlier entries. | 69 // Copy each mixin's methods, with later ones overwriting earlier entries. |
| 73 for (let m of mixins) { | 70 for (let m of mixins) { |
| 74 copyProperties(Mixin.prototype, m.prototype); | 71 copyProperties(Mixin.prototype, m.prototype); |
| 75 } | 72 } |
| 76 | 73 |
| 77 // Set the signature of the Mixin class to be the composition | 74 // Set the signature of the Mixin class to be the composition |
| 78 // of the signatures of the mixins. | 75 // of the signatures of the mixins. |
| 79 setSignature(Mixin, { | 76 setSignature(Mixin, { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 106 let _typeArguments = Symbol('typeArguments'); | 103 let _typeArguments = Symbol('typeArguments'); |
| 107 let _originalDeclaration = Symbol('originalDeclaration'); | 104 let _originalDeclaration = Symbol('originalDeclaration'); |
| 108 | 105 |
| 109 /** Memoize a generic type constructor function. */ | 106 /** Memoize a generic type constructor function. */ |
| 110 function generic(typeConstructor) { | 107 function generic(typeConstructor) { |
| 111 let length = typeConstructor.length; | 108 let length = typeConstructor.length; |
| 112 if (length < 1) { | 109 if (length < 1) { |
| 113 throwInternalError('must have at least one generic type argument'); | 110 throwInternalError('must have at least one generic type argument'); |
| 114 } | 111 } |
| 115 let resultMap = new Map(); | 112 let resultMap = new Map(); |
| 116 function makeGenericType(/*...arguments*/) { | 113 function makeGenericType(...args) { |
| 117 if (arguments.length != length && arguments.length != 0) { | 114 if (args.length != length && args.length != 0) { |
| 118 throwInternalError('requires ' + length + ' or 0 type arguments'); | 115 throwInternalError('requires ' + length + ' or 0 type arguments'); |
| 119 } | 116 } |
| 120 let args = slice.call(arguments); | |
| 121 while (args.length < length) args.push(types.dynamic); | 117 while (args.length < length) args.push(types.dynamic); |
| 122 | 118 |
| 123 let value = resultMap; | 119 let value = resultMap; |
| 124 for (let i = 0; i < length; i++) { | 120 for (let i = 0; i < length; i++) { |
| 125 let arg = args[i]; | 121 let arg = args[i]; |
| 126 if (arg == null) { | 122 if (arg == null) { |
| 127 throwInternalError('type arguments should not be null: ' | 123 throwInternalError('type arguments should not be null: ' |
| 128 + typeConstructor); | 124 + typeConstructor); |
| 129 } | 125 } |
| 130 let map = value; | 126 let map = value; |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 * | 355 * |
| 360 * defineExtensionMembers(MyType, ['add', 'remove']); | 356 * defineExtensionMembers(MyType, ['add', 'remove']); |
| 361 * | 357 * |
| 362 * Results in: | 358 * Results in: |
| 363 * | 359 * |
| 364 * MyType.prototype[dartx.add] = MyType.prototype.add; | 360 * MyType.prototype[dartx.add] = MyType.prototype.add; |
| 365 * MyType.prototype[dartx.remove] = MyType.prototype.remove; | 361 * MyType.prototype[dartx.remove] = MyType.prototype.remove; |
| 366 */ | 362 */ |
| 367 // TODO(jmesserly): essentially this gives two names to the same method. | 363 // TODO(jmesserly): essentially this gives two names to the same method. |
| 368 // This benefit is roughly equivalent call performance either way, but the | 364 // This benefit is roughly equivalent call performance either way, but the |
| 369 // cost is we need to call defineExtensionMembers any time a subclass | 365 // cost is we need to call defineExtensionMembers any time a subclass |
| 370 // overrides one of these methods. | 366 // overrides one of these methods. |
| 371 function defineExtensionMembers(type, methodNames) { | 367 function defineExtensionMembers(type, methodNames) { |
| 372 let proto = type.prototype; | 368 let proto = type.prototype; |
| 373 for (let name of methodNames) { | 369 for (let name of methodNames) { |
| 374 let method = getOwnPropertyDescriptor(proto, name); | 370 let method = getOwnPropertyDescriptor(proto, name); |
| 375 defineProperty(proto, getExtensionSymbol(name), method); | 371 defineProperty(proto, getExtensionSymbol(name), method); |
| 376 } | 372 } |
| 377 // Ensure the signature is available too. | 373 // Ensure the signature is available too. |
| 378 // TODO(jmesserly): not sure if we can do this in a cleaner way. Essentially | 374 // TODO(jmesserly): not sure if we can do this in a cleaner way. Essentially |
| 379 // we need to copy the signature (and in the future, other data like | 375 // we need to copy the signature (and in the future, other data like |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 } | 409 } |
| 414 exports.list = list; | 410 exports.list = list; |
| 415 | 411 |
| 416 function setBaseClass(derived, base) { | 412 function setBaseClass(derived, base) { |
| 417 // Link the extension to the type it's extending as a base class. | 413 // Link the extension to the type it's extending as a base class. |
| 418 derived.prototype.__proto__ = base.prototype; | 414 derived.prototype.__proto__ = base.prototype; |
| 419 } | 415 } |
| 420 exports.setBaseClass = setBaseClass; | 416 exports.setBaseClass = setBaseClass; |
| 421 | 417 |
| 422 }); | 418 }); |
| OLD | NEW |