| 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 /// |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 } | 56 } |
| 57 return s; | 57 return s; |
| 58 } | 58 } |
| 59 }); | 59 }); |
| 60 | 60 |
| 61 // Save mixins for reflection | 61 // Save mixins for reflection |
| 62 Mixin[$_mixins] = $mixins; | 62 Mixin[$_mixins] = $mixins; |
| 63 return Mixin; | 63 return Mixin; |
| 64 })()'''); | 64 })()'''); |
| 65 | 65 |
| 66 |
| 67 /// The Symbol for storing type arguments on a specialized generic type. |
| 68 final _mixins = JS('', 'Symbol("mixins")'); |
| 69 |
| 66 getMixins(clazz) => JS('', '$clazz[$_mixins]'); | 70 getMixins(clazz) => JS('', '$clazz[$_mixins]'); |
| 67 | 71 |
| 68 getImplements(clazz) => JS('', '$clazz[$implements_]'); | 72 @JSExportName('implements') |
| 73 final _implements = JS('', 'Symbol("implements")'); |
| 74 |
| 75 getImplements(clazz) => JS('', '#[#]', clazz, _implements); |
| 69 | 76 |
| 70 /// The Symbol for storing type arguments on a specialized generic type. | 77 /// The Symbol for storing type arguments on a specialized generic type. |
| 71 final _typeArguments = JS('', 'Symbol("typeArguments")'); | 78 final _typeArguments = JS('', 'Symbol("typeArguments")'); |
| 79 |
| 72 final _originalDeclaration = JS('', 'Symbol("originalDeclaration")'); | 80 final _originalDeclaration = JS('', 'Symbol("originalDeclaration")'); |
| 73 | 81 |
| 74 /// Memoize a generic type constructor function. | 82 /// Memoize a generic type constructor function. |
| 75 generic(typeConstructor) => JS('', '''(() => { | 83 generic(typeConstructor) => JS('', '''(() => { |
| 76 let length = $typeConstructor.length; | 84 let length = $typeConstructor.length; |
| 77 if (length < 1) { | 85 if (length < 1) { |
| 78 $throwInternalError('must have at least one generic type argument'); | 86 $throwInternalError('must have at least one generic type argument'); |
| 79 } | 87 } |
| 80 let resultMap = new Map(); | 88 let resultMap = new Map(); |
| 81 function makeGenericType(...args) { | 89 function makeGenericType(...args) { |
| 82 if (args.length != length && args.length != 0) { | 90 if (args.length != length && args.length != 0) { |
| 83 $throwInternalError('requires ' + length + ' or 0 type arguments'); | 91 $throwInternalError('requires ' + length + ' or 0 type arguments'); |
| 84 } | 92 } |
| 85 while (args.length < length) args.push($dynamicR); | 93 while (args.length < length) args.push($dynamic); |
| 86 | 94 |
| 87 let value = resultMap; | 95 let value = resultMap; |
| 88 for (let i = 0; i < length; i++) { | 96 for (let i = 0; i < length; i++) { |
| 89 let arg = args[i]; | 97 let arg = args[i]; |
| 90 if (arg == null) { | 98 if (arg == null) { |
| 91 $throwInternalError('type arguments should not be null: ' | 99 $throwInternalError('type arguments should not be null: ' |
| 92 + $typeConstructor); | 100 + $typeConstructor); |
| 93 } | 101 } |
| 94 let map = value; | 102 let map = value; |
| 95 value = map.get(arg); | 103 value = map.get(arg); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 let initMethod = proto[$name]; | 256 let initMethod = proto[$name]; |
| 249 let ctor = function() { return initMethod.apply(this, arguments); }; | 257 let ctor = function() { return initMethod.apply(this, arguments); }; |
| 250 ctor.prototype = proto; | 258 ctor.prototype = proto; |
| 251 // Use defineProperty so we don't hit a property defined on Function, | 259 // Use defineProperty so we don't hit a property defined on Function, |
| 252 // like `caller` and `arguments`. | 260 // like `caller` and `arguments`. |
| 253 $defineProperty($clazz, $name, { value: ctor, configurable: true }); | 261 $defineProperty($clazz, $name, { value: ctor, configurable: true }); |
| 254 })()'''); | 262 })()'''); |
| 255 | 263 |
| 256 final _extensionType = JS('', 'Symbol("extensionType")'); | 264 final _extensionType = JS('', 'Symbol("extensionType")'); |
| 257 | 265 |
| 258 getExtensionType(obj) => JS('', '$obj[$_extensionType]'); | 266 getExtensionType(obj) => JS('', '#[#]', obj, _extensionType); |
| 259 | 267 |
| 260 final dartx = JS('', 'dartx'); | 268 final dartx = JS('', 'dartx'); |
| 261 | 269 |
| 262 getExtensionSymbol(name) => JS('', '''(() => { | 270 getExtensionSymbol(name) { |
| 263 let sym = $dartx[$name]; | 271 var sym = JS('', 'dartx[#]', name); |
| 264 if (!sym) $dartx[$name] = sym = Symbol('dartx.' + $name.toString()); | 272 if (sym == null) { |
| 273 sym = JS('', 'Symbol("dartx." + #.toString())', name); |
| 274 JS('', 'dartx[#] = #', name, sym); |
| 275 } |
| 265 return sym; | 276 return sym; |
| 266 })()'''); | 277 } |
| 267 | 278 |
| 268 defineExtensionNames(names) => JS('', '$names.forEach($getExtensionSymbol)'); | 279 defineExtensionNames(names) => |
| 280 JS('', '#.forEach(#)', names, getExtensionSymbol); |
| 269 | 281 |
| 270 // Install properties in prototype order. Properties / descriptors from | 282 // Install properties in prototype order. Properties / descriptors from |
| 271 // more specific types should overwrite ones from less specific types. | 283 // more specific types should overwrite ones from less specific types. |
| 272 _installProperties(jsProto, extProto) => JS('', '''(() => { | 284 _installProperties(jsProto, extProto) { |
| 273 if (extProto !== $Object.prototype && extProto !== jsProto) { | 285 var coreObjProto = JS('', '#.prototype', Object); |
| 274 $_installProperties(jsProto, extProto.__proto__); | 286 if (JS('bool', '# === #', extProto, coreObjProto)) { |
| 287 // core.Object members need to be copied from the non-symbol name to the |
| 288 // symbol name. |
| 289 for (var name in getOwnPropertyNames(coreObjProto)) { |
| 290 var desc = getOwnPropertyDescriptor(coreObjProto, name); |
| 291 defineProperty(jsProto, getExtensionSymbol(name), desc); |
| 292 } |
| 293 return; |
| 275 } | 294 } |
| 276 $copyTheseProperties(jsProto, extProto, $getOwnPropertySymbols(extProto)); | 295 if (JS('bool', '# !== #', jsProto, extProto)) { |
| 277 })()'''); | 296 _installProperties(jsProto, JS('', '#.__proto__', extProto)); |
| 297 } |
| 298 copyTheseProperties(jsProto, extProto, getOwnPropertySymbols(extProto)); |
| 299 } |
| 278 | 300 |
| 279 /// | 301 /// |
| 280 /// Copy symbols from the prototype of the source to destination. | 302 /// Copy symbols from the prototype of the source to destination. |
| 281 /// These are the only properties safe to copy onto an existing public | 303 /// These are the only properties safe to copy onto an existing public |
| 282 /// JavaScript class. | 304 /// JavaScript class. |
| 283 /// | 305 /// |
| 284 registerExtension(jsType, dartExtType) => JS('', '''(() => { | 306 registerExtension(jsType, dartExtType) => JS('', '''(() => { |
| 285 // TODO(vsm): Not all registered js types are real. | 307 // TODO(vsm): Not all registered js types are real. |
| 286 if (!jsType) return; | 308 if (!jsType) return; |
| 287 | 309 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 })()'''); | 386 })()'''); |
| 365 | 387 |
| 366 /// Sets the element type of a list literal. | 388 /// Sets the element type of a list literal. |
| 367 list(obj, elementType) => | 389 list(obj, elementType) => |
| 368 JS('', '$setType($obj, ${getGenericClass(JSArray)}($elementType))'); | 390 JS('', '$setType($obj, ${getGenericClass(JSArray)}($elementType))'); |
| 369 | 391 |
| 370 setBaseClass(derived, base) => JS('', '''(() => { | 392 setBaseClass(derived, base) => JS('', '''(() => { |
| 371 // Link the extension to the type it's extending as a base class. | 393 // Link the extension to the type it's extending as a base class. |
| 372 $derived.prototype.__proto__ = $base.prototype; | 394 $derived.prototype.__proto__ = $base.prototype; |
| 373 })()'''); | 395 })()'''); |
| OLD | NEW |