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 |