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 var dart; | 5 var dart; |
6 (function (dart) { | 6 (function (dart) { |
| 7 'use strict'; |
| 8 |
7 var defineProperty = Object.defineProperty; | 9 var defineProperty = Object.defineProperty; |
8 var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | 10 var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
9 var getOwnPropertyNames = Object.getOwnPropertyNames; | 11 var getOwnPropertyNames = Object.getOwnPropertyNames; |
10 | 12 |
11 // Adapted from Angular.js | 13 // Adapted from Angular.js |
12 var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; | 14 var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; |
13 var FN_ARG_SPLIT = /,/; | 15 var FN_ARG_SPLIT = /,/; |
14 var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; | 16 var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; |
15 var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; | 17 var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; |
16 | 18 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 var value = f(); | 158 var value = f(); |
157 lazySetter(value); | 159 lazySetter(value); |
158 return value; | 160 return value; |
159 } | 161 } |
160 desc.get = lazyGetter; | 162 desc.get = lazyGetter; |
161 desc.configurable = true; | 163 desc.configurable = true; |
162 if (writable) desc.set = lazySetter; | 164 if (writable) desc.set = lazySetter; |
163 defineProperty(to, name, desc); | 165 defineProperty(to, name, desc); |
164 } | 166 } |
165 | 167 |
166 function defineLazyProperties(to, from) { | 168 function defineLazy(to, from) { |
167 var names = getOwnPropertyNames(from); | 169 var names = getOwnPropertyNames(from); |
168 for (var i = 0; i < names.length; i++) { | 170 for (var i = 0; i < names.length; i++) { |
169 var name = names[i]; | 171 var name = names[i]; |
170 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); | 172 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); |
171 } | 173 } |
172 } | 174 } |
173 dart.defineLazyProperties = defineLazyProperties; | 175 // TODO(jmesserly): these are identical, but this makes it easier to grep for. |
| 176 dart.defineLazyClass = defineLazy; |
| 177 dart.defineLazyProperties = defineLazy; |
| 178 dart.defineLazyClassGeneric = defineLazyProperty; |
174 | 179 |
175 /** | 180 /** |
176 * Copy properties from source to destination object. | 181 * Copy properties from source to destination object. |
177 * This operation is commonly called `mixin` in JS. | 182 * This operation is commonly called `mixin` in JS. |
178 */ | 183 */ |
179 function copyProperties(to, from) { | 184 function copyProperties(to, from) { |
180 var names = getOwnPropertyNames(from); | 185 var names = getOwnPropertyNames(from); |
181 for (var i = 0; i < names.length; i++) { | 186 for (var i = 0; i < names.length; i++) { |
182 var name = names[i]; | 187 var name = names[i]; |
183 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); | 188 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); |
184 } | 189 } |
185 return to; | 190 return to; |
186 } | 191 } |
187 dart.copyProperties = copyProperties; | 192 dart.copyProperties = copyProperties; |
188 | 193 |
189 /** | 194 /** |
190 * Returns a new type that mixes members from base and all mixins. | 195 * Returns a new type that mixes members from base and all mixins. |
191 * | 196 * |
192 * Each mixin applies in sequence, with further to the right ones overriding | 197 * Each mixin applies in sequence, with further to the right ones overriding |
193 * previous entries. | 198 * previous entries. |
194 * | 199 * |
195 * For each mixin, we only take its own properties, not anything from its | 200 * For each mixin, we only take its own properties, not anything from its |
196 * superclass (prototype). | 201 * superclass (prototype). |
197 */ | 202 */ |
198 function mixin(base/*, ...mixins*/) { | 203 function mixin(base/*, ...mixins*/) { |
199 // Inherit statics from Base to simulate ES6 class inheritance | 204 // Create an initializer for the mixin, so when derived constructor calls |
200 // Conceptually this is: `class Mixin extends base {}` | 205 // super, we can correctly initialize base and mixins. |
201 function Mixin() { | 206 var mixins = Array.prototype.slice.call(arguments, 1); |
202 // TODO(jmesserly): since we're using initializers and not constructors, | 207 |
203 // we can just skip directly to core.Object. | 208 // Create a class that will hold all of the mixin methods. |
204 core.Object.apply(this, arguments); | 209 class Mixin extends base { |
| 210 // Initializer method: run mixin initializers, then the base. |
| 211 [base.name](/*...args*/) { |
| 212 // Run mixin initializers. They cannot have arguments. |
| 213 // Run them backwards so most-derived mixin is initialized first. |
| 214 for (var i = mixins.length - 1; i >= 0; i--) { |
| 215 var mixin = mixins[i]; |
| 216 mixin.prototype[mixin.name].call(this); |
| 217 } |
| 218 // Run base initializer. |
| 219 base.prototype[base.name].apply(this, arguments); |
| 220 } |
205 } | 221 } |
206 Mixin.__proto__ = base; | 222 // Copy each mixin's methods, with later ones overwriting earlier entries. |
207 Mixin.prototype = Object.create(base.prototype); | |
208 Mixin.prototype.constructor = Mixin; | |
209 // Copy each mixin, with later ones overwriting earlier entries. | |
210 var mixins = Array.prototype.slice.call(arguments, 1); | |
211 for (var i = 0; i < mixins.length; i++) { | 223 for (var i = 0; i < mixins.length; i++) { |
212 copyProperties(Mixin.prototype, mixins[i].prototype); | 224 copyProperties(Mixin.prototype, mixins[i].prototype); |
213 } | 225 } |
214 // Create an initializer for the mixin, so when derived constructor calls | |
215 // super, we can correctly initialize base and mixins. | |
216 var baseCtor = base.prototype[base.name]; | |
217 Mixin.prototype[base.name] = function() { | |
218 // Run mixin initializers. They cannot have arguments. | |
219 // Run them backwards so most-derived mixin is initialized first. | |
220 for (var i = mixins.length - 1; i >= 0; i--) { | |
221 var mixin = mixins[i]; | |
222 mixin.prototype[mixin.name].call(this); | |
223 } | |
224 // Run base initializer. | |
225 baseCtor.apply(this, arguments); | |
226 } | |
227 return Mixin; | 226 return Mixin; |
228 } | 227 } |
229 dart.mixin = mixin; | 228 dart.mixin = mixin; |
230 | 229 |
231 /** | 230 /** |
232 * Creates a dart:collection LinkedHashMap. | 231 * Creates a dart:collection LinkedHashMap. |
233 * | 232 * |
234 * For a map with string keys an object literal can be used, for example | 233 * For a map with string keys an object literal can be used, for example |
235 * `map({'hi': 1, 'there': 2})`. | 234 * `map({'hi': 1, 'there': 2})`. |
236 * | 235 * |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 | 297 |
299 var resultMap = new Map(); | 298 var resultMap = new Map(); |
300 function makeGenericType(/*...arguments*/) { | 299 function makeGenericType(/*...arguments*/) { |
301 if (arguments.length != length) { | 300 if (arguments.length != length) { |
302 throw 'requires ' + length + ' type arguments'; | 301 throw 'requires ' + length + ' type arguments'; |
303 } | 302 } |
304 | 303 |
305 var value = resultMap; | 304 var value = resultMap; |
306 for (var i = 0; i < length; i++) { | 305 for (var i = 0; i < length; i++) { |
307 var arg = arguments[i]; | 306 var arg = arguments[i]; |
308 // TODO(jmesserly): assume `dynamic` here? | 307 if (arg === void 0) arg = dart.dynamic; |
309 if (arg === void 0) throw 'undefined is not allowed as a type argument'; | |
310 | 308 |
311 var map = value; | 309 var map = value; |
312 value = map.get(arg); | 310 value = map.get(arg); |
313 if (value === void 0) { | 311 if (value === void 0) { |
314 if (i + 1 == length) { | 312 if (i + 1 == length) { |
315 value = typeConstructor.apply(null, arguments); | 313 value = typeConstructor.apply(null, arguments); |
316 // Save the type constructor and arguments for reflection. | 314 // Save the type constructor and arguments for reflection. |
317 if (value) { | 315 if (value) { |
318 var args = Array.prototype.slice.call(arguments); | 316 var args = Array.prototype.slice.call(arguments); |
319 value[dart.typeSignature] = [makeGenericType].concat(args); | 317 value[dart.typeSignature] = [makeGenericType].concat(args); |
320 } | 318 } |
321 } else { | 319 } else { |
322 value = new Map(); | 320 value = new Map(); |
323 } | 321 } |
324 map.set(arg, value); | 322 map.set(arg, value); |
325 } | 323 } |
326 } | 324 } |
327 return value; | 325 return value; |
328 } | 326 } |
329 return makeGenericType; | 327 return makeGenericType; |
330 } | 328 } |
331 dart.generic = generic; | 329 dart.generic = generic; |
332 | 330 |
333 | 331 // TODO(jmesserly): this is just a placeholder. |
334 /** | 332 dart.dynamic = Object.create(null); |
335 * Implements Dart constructor behavior. Because of V8 `super` [constructor | |
336 * restrictions](https://code.google.com/p/v8/issues/detail?id=3330#c65) we | |
337 * cannot currently emit actual ES6 constructors with super calls. Instead | |
338 * we use the same trick as named constructors, and do them as instance | |
339 * methods that perform initialization. | |
340 */ | |
341 // TODO(jmesserly): we'll need to rethink this once the ES6 spec and V8 | |
342 // settles. See <https://github.com/dart-lang/dart-dev-compiler/issues/51>. | |
343 // Performance of this pattern is likely to be bad. | |
344 core.Object = function Object() { | |
345 // Get the class name for this instance. | |
346 var name = this.constructor.name; | |
347 // Call the default constructor. | |
348 var init = this[name]; | |
349 var result = void 0; | |
350 if (init) result = init.apply(this, arguments); | |
351 return result === void 0 ? this : result; | |
352 }; | |
353 // The initializer for Object | |
354 core.Object.prototype.Object = function() {}; | |
355 core.Object.prototype.constructor = core.Object; | |
356 | 333 |
357 })(dart || (dart = {})); | 334 })(dart || (dart = {})); |
OLD | NEW |