Chromium Code Reviews| 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, _js_helper; | 5 var dart, _js_helper; |
| 6 (function (dart) { | 6 (function (dart) { |
| 7 'use strict'; | 7 'use strict'; |
| 8 | 8 |
| 9 var defineProperty = Object.defineProperty; | 9 let defineProperty = Object.defineProperty; |
| 10 var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | 10 let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
| 11 var getOwnPropertyNames = Object.getOwnPropertyNames; | 11 let getOwnPropertyNames = Object.getOwnPropertyNames; |
| 12 | 12 |
| 13 // Adapted from Angular.js | 13 // Adapted from Angular.js |
| 14 var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; | 14 let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; |
| 15 var FN_ARG_SPLIT = /,/; | 15 let FN_ARG_SPLIT = /,/; |
| 16 var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; | 16 let FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; |
| 17 var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; | 17 let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; |
| 18 | 18 |
| 19 function formalParameterList(fn) { | 19 function formalParameterList(fn) { |
| 20 var fnText,argDecl; | 20 let fnText,argDecl; |
| 21 var args=[]; | 21 let args=[]; |
| 22 fnText = fn.toString().replace(STRIP_COMMENTS, ''); | 22 fnText = fn.toString().replace(STRIP_COMMENTS, ''); |
| 23 argDecl = fnText.match(FN_ARGS); | 23 argDecl = fnText.match(FN_ARGS); |
| 24 | 24 |
| 25 var r = argDecl[1].split(FN_ARG_SPLIT); | 25 let r = argDecl[1].split(FN_ARG_SPLIT); |
| 26 for(var a in r) { | 26 for(let a in r) { |
| 27 var arg = r[a]; | 27 let arg = r[a]; |
| 28 arg.replace(FN_ARG, function(all, underscore, name){ | 28 arg.replace(FN_ARG, function(all, underscore, name){ |
| 29 args.push(name); | 29 args.push(name); |
| 30 }); | 30 }); |
| 31 } | 31 } |
| 32 return args; | 32 return args; |
| 33 } | 33 } |
| 34 | 34 |
| 35 function dload(obj, field) { | 35 function dload(obj, field) { |
| 36 if (!(field in obj)) { | 36 if (!(field in obj)) { |
| 37 throw new core.NoSuchMethodError(obj, field); | 37 throw new core.NoSuchMethodError(obj, field); |
| 38 } | 38 } |
| 39 return obj[field]; | 39 return obj[field]; |
| 40 } | 40 } |
| 41 dart.dload = dload; | 41 dart.dload = dload; |
| 42 | 42 |
| 43 // TODO(jmesserly): this should call noSuchMethod, not throw. | 43 // TODO(jmesserly): this should call noSuchMethod, not throw. |
| 44 function throwNoSuchMethod(obj, name, args, opt_func) { | 44 function throwNoSuchMethod(obj, name, args, opt_func) { |
| 45 if (obj === void 0) obj = opt_func; | 45 if (obj === void 0) obj = opt_func; |
| 46 throw new core.NoSuchMethodError(obj, name, args); | 46 throw new core.NoSuchMethodError(obj, name, args); |
| 47 } | 47 } |
| 48 | 48 |
| 49 function checkAndCall(f, obj, args, name) { | 49 function checkAndCall(f, obj, args, name) { |
| 50 if (!(f instanceof Function)) { | 50 if (!(f instanceof Function)) { |
| 51 // Grab the `call` method if it's not a function. | 51 // Grab the `call` method if it's not a function. |
| 52 if (f !== null) f = f.call; | 52 if (f !== null) f = f.call; |
| 53 if (!(f instanceof Function)) { | 53 if (!(f instanceof Function)) { |
| 54 throwNoSuchMethod(obj, method, args); | 54 throwNoSuchMethod(obj, method, args); |
| 55 } | 55 } |
| 56 } | 56 } |
| 57 var formals = formalParameterList(f); | 57 let formals = formalParameterList(f); |
| 58 // TODO(vsm): Type check args! We need to encode sufficient type info on f. | 58 // TODO(vsm): Type check args! We need to encode sufficient type info on f. |
| 59 if (formals.length < args.length) { | 59 if (formals.length < args.length) { |
| 60 throwNoSuchMethod(obj, name, args, f); | 60 throwNoSuchMethod(obj, name, args, f); |
| 61 } else if (formals.length > args.length) { | 61 } else if (formals.length > args.length) { |
| 62 for (var i = args.length; i < formals.length; ++i) { | 62 for (let i = args.length; i < formals.length; ++i) { |
| 63 if (formals[i].indexOf("opt$") != 0) { | 63 if (formals[i].indexOf("opt$") != 0) { |
| 64 throwNoSuchMethod(obj, name, args, f); | 64 throwNoSuchMethod(obj, name, args, f); |
| 65 } | 65 } |
| 66 } | 66 } |
| 67 } | 67 } |
| 68 return f.apply(obj, args); | 68 return f.apply(obj, args); |
| 69 } | 69 } |
| 70 | 70 |
| 71 function dinvokef(f/*, ...args*/) { | 71 function dinvokef(f/*, ...args*/) { |
| 72 var args = Array.prototype.slice.call(arguments, 1); | 72 let args = Array.prototype.slice.call(arguments, 1); |
| 73 return checkAndCall(f, void 0, args, 'call'); | 73 return checkAndCall(f, void 0, args, 'call'); |
| 74 } | 74 } |
| 75 dart.dinvokef = dinvokef; | 75 dart.dinvokef = dinvokef; |
| 76 | 76 |
| 77 function dinvoke(obj, method/*, ...args*/) { | 77 function dinvoke(obj, method/*, ...args*/) { |
| 78 var args = Array.prototype.slice.call(arguments, 2); | 78 let args = Array.prototype.slice.call(arguments, 2); |
| 79 return checkAndCall(obj[method], obj, args, method); | 79 return checkAndCall(obj[method], obj, args, method); |
| 80 } | 80 } |
| 81 dart.dinvoke = dinvoke; | 81 dart.dinvoke = dinvoke; |
| 82 | 82 |
| 83 function dindex(obj, index) { | 83 function dindex(obj, index) { |
| 84 return checkAndCall(obj.get, obj, [index], '[]'); | 84 return checkAndCall(obj.get, obj, [index], '[]'); |
| 85 } | 85 } |
| 86 dart.dindex = dindex; | 86 dart.dindex = dindex; |
| 87 | 87 |
| 88 function dsetindex(obj, index, value) { | 88 function dsetindex(obj, index, value) { |
| 89 return checkAndCall(obj.set, obj, [index, value], '[]='); | 89 return checkAndCall(obj.set, obj, [index, value], '[]='); |
| 90 } | 90 } |
| 91 dart.dsetindex = dindex; | 91 dart.dsetindex = dindex; |
| 92 | 92 |
| 93 function dbinary(left, op, right) { | 93 function dbinary(left, op, right) { |
| 94 return checkAndCall(left[op], left, [right], op); | 94 return checkAndCall(left[op], left, [right], op); |
| 95 } | 95 } |
| 96 dart.dbinary = dbinary; | 96 dart.dbinary = dbinary; |
| 97 | 97 |
| 98 function as_(obj, type) { | 98 function cast(obj, type) { |
| 99 // TODO(vsm): Implement. | 99 if (obj == null) return obj; |
|
vsm
2015/04/01 15:38:00
Can you add a TODO(vsm) here about handling non-nu
Jennifer Messerly
2015/04/01 15:57:32
sure thing :)
| |
| 100 // if (obj == null || is(obj, type)) return obj; | 100 let actual = getRuntimeType(obj); |
| 101 // throw new core.CastError(); | 101 if (isSubtype(actual, type)) return obj; |
| 102 return obj; | 102 throw new _js_helper.CastErrorImplementation(actual, type); |
| 103 } | 103 } |
| 104 dart.as = as_; | 104 dart.as = cast; |
| 105 | 105 |
| 106 function is(obj, type) { | 106 /** |
| 107 // TODO(vsm): Implement. | 107 * Returns the runtime type of obj. This is the same as `obj.runtimeType` |
| 108 throw new core.UnimplementedError(); | 108 * but will not call an overridden getter. |
| 109 * | |
| 110 * Currently this will return null for non-Dart objects. | |
| 111 */ | |
| 112 function getRuntimeType(obj) { | |
| 113 switch (typeof obj) { | |
| 114 case "undefined": | |
| 115 return core.Null; | |
| 116 case "number": | |
| 117 return Math.floor(obj) == obj ? core.int : core.double; | |
| 118 case "boolean": | |
| 119 return core.bool; | |
| 120 case "string": | |
| 121 return core.String; | |
| 122 case "symbol": | |
| 123 return Symbol; | |
| 124 } | |
| 125 // Undefined is handled above. For historical reasons, | |
| 126 // typeof null == "object" in JS. | |
| 127 if (obj === null) return core.Null; | |
| 128 return obj.constructor; | |
| 109 } | 129 } |
| 110 dart.is = is; | 130 dart.getRuntimeType = getRuntimeType; |
| 131 | |
| 132 function instanceOf(obj, type) { | |
|
vsm
2015/04/01 15:38:00
This needs a test for null:
if (obj == null) {
Jennifer Messerly
2015/04/01 15:57:32
yeah, I saw that code, but it seems like null is a
vsm
2015/04/01 16:29:40
The problem is the opposite case:
isSubtype(core
Jennifer Messerly
2015/04/01 16:41:22
chatted about this & added a test case. I think we
| |
| 133 return isSubtype(getRuntimeType(obj), type); | |
| 134 } | |
| 135 dart.is = instanceOf; | |
| 136 | |
| 137 /** | |
| 138 * Computes the canonical type. | |
| 139 * This maps JS types onto their corresponding Dart Type. | |
| 140 */ | |
| 141 // TODO(jmesserly): lots more needs to be done here. | |
| 142 function canonicalType(t) { | |
| 143 if (t === Object) return core.Object; | |
| 144 if (t === Function) return core.Function; | |
| 145 if (t === Array) return core.List; | |
| 146 | |
| 147 // We shouldn't normally get here with these types, unless something strange | |
| 148 // happens like subclassing Number in JS and passing it to Dart. | |
| 149 if (t === String) return core.String; | |
| 150 if (t === Number) return core.double; | |
| 151 if (t === Boolean) return core.bool; | |
| 152 return t; | |
| 153 } | |
| 154 | |
| 155 let subtypeMap = new Map(); | |
| 156 function isSubtype(t1, t2) { | |
| 157 // See if we already know the answer | |
| 158 // TODO(jmesserly): general purpose memoize function? | |
| 159 let map = subtypeMap.get(t1); | |
| 160 let result; | |
| 161 if (map) { | |
| 162 result = map.get(t2); | |
| 163 if (result !== void 0) return result; | |
| 164 } else { | |
| 165 subtypeMap.set(t1, map = new Map()); | |
| 166 } | |
| 167 map.set(t2, result = isSubtype_(t1, t2)); | |
| 168 return result; | |
| 169 } | |
| 170 dart.isSubtype = isSubtype; | |
| 171 | |
| 172 function isSubtype_(t1, t2) { | |
| 173 t1 = canonicalType(t1); | |
| 174 t2 = canonicalType(t2); | |
| 175 if (t1 == t2) return true; | |
| 176 | |
| 177 // In Dart, dynamic is effectively both top and bottom. | |
| 178 // Here, we treat dynamic as top - the base type of everything. | |
|
vsm
2015/04/01 15:38:00
We'll need to update as per recent CL. Both dynam
Jennifer Messerly
2015/04/01 15:57:32
sounds good. happy to update either now or after y
| |
| 179 if (t1 == dart.dynamic) return false; | |
| 180 if (t2 == dart.dynamic) return true; | |
| 181 | |
| 182 if (t2 == core.Object) return true; | |
| 183 if (t1 == core.Object) return false; | |
| 184 | |
| 185 // "Traditional" name-based subtype check. | |
| 186 if (isClassSubType(t1, t2)) { | |
| 187 return true; | |
| 188 } | |
| 189 | |
| 190 // Function subtyping. | |
| 191 // TODO(jmesserly): implement. | |
| 192 return false; | |
| 193 } | |
| 194 | |
| 195 function safeGetOwnProperty(obj, name) { | |
| 196 var desc = getOwnPropertyDescriptor(obj, name); | |
| 197 if (desc) return desc.value; | |
| 198 } | |
| 199 | |
| 200 function isClassSubType(t1, t2) { | |
| 201 // We support Dart's covariant generics with the caveat that we do not | |
| 202 // substitute bottom for dynamic in subtyping rules. | |
| 203 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow: | |
| 204 // - S !<: S<T1, ..., Tn> | |
| 205 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn> | |
| 206 if (t1 == t2) return true; | |
| 207 | |
| 208 if (t1 == core.Object) return false; | |
| 209 | |
| 210 // Check if t1 and t2 have the same raw type. If so, check covariance on | |
| 211 // type parameters. | |
| 212 let raw1 = safeGetOwnProperty(t1, dart.originalDeclaration); | |
| 213 let raw2 = safeGetOwnProperty(t2, dart.originalDeclaration); | |
| 214 if (raw1 != null && raw1 == raw2) { | |
| 215 let typeArguments1 = safeGetOwnProperty(t1, dart.typeArguments); | |
| 216 let typeArguments2 = safeGetOwnProperty(t2, dart.typeArguments); | |
| 217 let length = typeArguments1.length; | |
| 218 if (typeArguments2.length == 0) { | |
| 219 // t2 is the raw form of t1 | |
| 220 return true; | |
| 221 } else if (length == 0) { | |
| 222 // t1 is raw, but t2 is not | |
| 223 return false; | |
| 224 } | |
| 225 assert(length == typeArguments2.length); | |
| 226 for (let i = 0; i < length; ++i) { | |
| 227 if (!isSubtype(typeArguments1[i], typeArguments2[i])) { | |
| 228 return false; | |
| 229 } | |
| 230 } | |
| 231 return true; | |
| 232 } | |
| 233 | |
| 234 // Check superclass. | |
| 235 if (isClassSubType(t1.__proto__, t2)) return true; | |
|
vsm
2015/04/01 15:37:59
This won't cover mixins, right? The application o
Jennifer Messerly
2015/04/01 15:57:32
doh! Good catch. It seems like the Dart code might
vsm
2015/04/01 16:29:40
Yeah, updating my CL too. :-)
| |
| 236 | |
| 237 // Check interfaces. | |
| 238 let getInterfaces = safeGetOwnProperty(t1, dart.implements); | |
| 239 if (getInterfaces) { | |
| 240 for (let i1 of getInterfaces()) { | |
| 241 // TODO(jmesserly): remove the != null check once we can load core libs. | |
| 242 if (i1 != null && isClassSubType(i1, t2)) return true; | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 return false; | |
| 247 } | |
| 111 | 248 |
| 112 function closureWrap(obj, type) { | 249 function closureWrap(obj, type) { |
| 113 // TODO(vsm): Remove this once we handle in the checker. | 250 // TODO(vsm): Remove this once we handle in the checker. |
| 114 return obj; | 251 return obj; |
| 115 } | 252 } |
| 116 dart.closureWrap = closureWrap; | 253 dart.closureWrap = closureWrap; |
| 117 | 254 |
| 255 // TODO(jmesserly): do we need this function? | |
|
vsm
2015/04/01 15:38:00
We may want to keep this around if we want to reje
Jennifer Messerly
2015/04/01 15:57:32
sounds good. Updated the comment
| |
| 118 function isGroundType(type) { | 256 function isGroundType(type) { |
| 119 // TODO(vsm): Implement. | 257 let typeArgs = safeGetOwnProperty(type, dart.typeArguments); |
| 120 throw new core.UnimplementedError(); | 258 if (!typeArgs) return true; |
| 259 for (let t of typeArgs) { | |
| 260 if (t != core.Object && t != dart.dynamic) return false; | |
| 261 } | |
| 262 return true; | |
| 121 } | 263 } |
| 122 dart.isGroundType = isGroundType; | 264 dart.isGroundType = isGroundType; |
| 123 | 265 |
| 124 function arity(f) { | 266 function arity(f) { |
| 125 // TODO(vsm): Implement. | 267 // TODO(jmesserly): need to parse optional params. |
| 126 throw new core.UnimplementedError(); | 268 // In ES6, length is the number of required arguments. |
| 269 return { min: f.length, max: f.length }; | |
| 127 } | 270 } |
| 128 dart.arity = arity; | 271 dart.arity = arity; |
| 129 | 272 |
| 130 function equals(x, y) { | 273 function equals(x, y) { |
| 131 if (x == null || y == null) return x == y; | 274 if (x == null || y == null) return x == y; |
| 132 var eq = x['==']; | 275 let eq = x['==']; |
| 133 return eq ? eq.call(x, y) : x == y; | 276 return eq ? eq.call(x, y) : x == y; |
| 134 } | 277 } |
| 135 dart.equals = equals; | 278 dart.equals = equals; |
| 136 | 279 |
| 137 /** Checks that `x` is not null or undefined. */ | 280 /** Checks that `x` is not null or undefined. */ |
| 138 function notNull(x) { | 281 function notNull(x) { |
| 139 if (x == null) throw 'expected not-null value'; | 282 if (x == null) throw 'expected not-null value'; |
| 140 return x; | 283 return x; |
| 141 } | 284 } |
| 142 dart.notNull = notNull; | 285 dart.notNull = notNull; |
| 143 | 286 |
| 144 /** | 287 /** |
| 145 * Defines a lazy property. | 288 * Defines a lazy property. |
| 146 * After initial get or set, it will replace itself with a value property. | 289 * After initial get or set, it will replace itself with a value property. |
| 147 */ | 290 */ |
| 148 // TODO(jmesserly): is this the best implementation for JS engines? | 291 // TODO(jmesserly): is this the best implementation for JS engines? |
| 149 // TODO(jmesserly): reusing descriptor objects has been shown to improve | 292 // TODO(jmesserly): reusing descriptor objects has been shown to improve |
| 150 // performance in other projects (e.g. webcomponents.js ShadowDOM polyfill). | 293 // performance in other projects (e.g. webcomponents.js ShadowDOM polyfill). |
| 151 function defineLazyProperty(to, name, desc) { | 294 function defineLazyProperty(to, name, desc) { |
| 152 var init = desc.get; | 295 let init = desc.get; |
| 153 var writable = !!desc.set; | 296 let writable = !!desc.set; |
| 154 function lazySetter(value) { | 297 function lazySetter(value) { |
| 155 defineProperty(to, name, { value: value, writable: writable }); | 298 defineProperty(to, name, { value: value, writable: writable }); |
| 156 } | 299 } |
| 157 function lazyGetter() { | 300 function lazyGetter() { |
| 158 // Clear the init function to detect circular initialization. | 301 // Clear the init function to detect circular initialization. |
| 159 var f = init; | 302 let f = init; |
| 160 if (f === null) throw 'circular initialization for field ' + name; | 303 if (f === null) throw 'circular initialization for field ' + name; |
| 161 init = null; | 304 init = null; |
| 162 | 305 |
| 163 // Compute and store the value. | 306 // Compute and store the value. |
| 164 var value = f(); | 307 let value = f(); |
| 165 lazySetter(value); | 308 lazySetter(value); |
| 166 return value; | 309 return value; |
| 167 } | 310 } |
| 168 desc.get = lazyGetter; | 311 desc.get = lazyGetter; |
| 169 desc.configurable = true; | 312 desc.configurable = true; |
| 170 if (writable) desc.set = lazySetter; | 313 if (writable) desc.set = lazySetter; |
| 171 defineProperty(to, name, desc); | 314 defineProperty(to, name, desc); |
| 172 } | 315 } |
| 173 | 316 |
| 174 function defineLazy(to, from) { | 317 function defineLazy(to, from) { |
| 175 var names = getOwnPropertyNames(from); | 318 let names = getOwnPropertyNames(from); |
| 176 for (var i = 0; i < names.length; i++) { | 319 for (let i = 0; i < names.length; i++) { |
| 177 var name = names[i]; | 320 let name = names[i]; |
| 178 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); | 321 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); |
| 179 } | 322 } |
| 180 } | 323 } |
| 181 // TODO(jmesserly): these are identical, but this makes it easier to grep for. | 324 // TODO(jmesserly): these are identical, but this makes it easier to grep for. |
| 182 dart.defineLazyClass = defineLazy; | 325 dart.defineLazyClass = defineLazy; |
| 183 dart.defineLazyProperties = defineLazy; | 326 dart.defineLazyProperties = defineLazy; |
| 184 dart.defineLazyClassGeneric = defineLazyProperty; | 327 dart.defineLazyClassGeneric = defineLazyProperty; |
| 185 | 328 |
| 186 /** | 329 /** |
| 187 * Copy properties from source to destination object. | 330 * Copy properties from source to destination object. |
| 188 * This operation is commonly called `mixin` in JS. | 331 * This operation is commonly called `mixin` in JS. |
| 189 */ | 332 */ |
| 190 function copyProperties(to, from) { | 333 function copyProperties(to, from) { |
| 191 var names = getOwnPropertyNames(from); | 334 let names = getOwnPropertyNames(from); |
| 192 for (var i = 0; i < names.length; i++) { | 335 for (let i = 0; i < names.length; i++) { |
| 193 var name = names[i]; | 336 let name = names[i]; |
| 194 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); | 337 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); |
| 195 } | 338 } |
| 196 return to; | 339 return to; |
| 197 } | 340 } |
| 198 dart.copyProperties = copyProperties; | 341 dart.copyProperties = copyProperties; |
| 199 | 342 |
| 200 | 343 |
| 201 /** The Symbol for storing type arguments on a specialized generic type. */ | 344 /** The Symbol for storing type arguments on a specialized generic type. */ |
| 202 dart.mixins = Symbol('mixins'); | 345 dart.mixins = Symbol('mixins'); |
| 203 dart.implements = Symbol('implements') | 346 dart.implements = Symbol('implements'); |
| 204 | 347 |
| 205 /** | 348 /** |
| 206 * Returns a new type that mixes members from base and all mixins. | 349 * Returns a new type that mixes members from base and all mixins. |
| 207 * | 350 * |
| 208 * Each mixin applies in sequence, with further to the right ones overriding | 351 * Each mixin applies in sequence, with further to the right ones overriding |
| 209 * previous entries. | 352 * previous entries. |
| 210 * | 353 * |
| 211 * For each mixin, we only take its own properties, not anything from its | 354 * For each mixin, we only take its own properties, not anything from its |
| 212 * superclass (prototype). | 355 * superclass (prototype). |
| 213 */ | 356 */ |
| 214 function mixin(base/*, ...mixins*/) { | 357 function mixin(base/*, ...mixins*/) { |
| 215 // Create an initializer for the mixin, so when derived constructor calls | 358 // Create an initializer for the mixin, so when derived constructor calls |
| 216 // super, we can correctly initialize base and mixins. | 359 // super, we can correctly initialize base and mixins. |
| 217 var mixins = Array.prototype.slice.call(arguments, 1); | 360 let mixins = Array.prototype.slice.call(arguments, 1); |
| 218 | 361 |
| 219 // Create a class that will hold all of the mixin methods. | 362 // Create a class that will hold all of the mixin methods. |
| 220 class Mixin extends base { | 363 class Mixin extends base { |
| 221 // Initializer method: run mixin initializers, then the base. | 364 // Initializer method: run mixin initializers, then the base. |
| 222 [base.name](/*...args*/) { | 365 [base.name](/*...args*/) { |
| 223 // Run mixin initializers. They cannot have arguments. | 366 // Run mixin initializers. They cannot have arguments. |
| 224 // Run them backwards so most-derived mixin is initialized first. | 367 // Run them backwards so most-derived mixin is initialized first. |
| 225 for (var i = mixins.length - 1; i >= 0; i--) { | 368 for (let i = mixins.length - 1; i >= 0; i--) { |
| 226 var mixin = mixins[i]; | 369 let mixin = mixins[i]; |
| 227 mixin.prototype[mixin.name].call(this); | 370 mixin.prototype[mixin.name].call(this); |
| 228 } | 371 } |
| 229 // Run base initializer. | 372 // Run base initializer. |
| 230 base.prototype[base.name].apply(this, arguments); | 373 base.prototype[base.name].apply(this, arguments); |
| 231 } | 374 } |
| 232 } | 375 } |
| 233 // Copy each mixin's methods, with later ones overwriting earlier entries. | 376 // Copy each mixin's methods, with later ones overwriting earlier entries. |
| 234 for (var i = 0; i < mixins.length; i++) { | 377 for (let m of mixins) { |
| 235 copyProperties(Mixin.prototype, mixins[i].prototype); | 378 copyProperties(Mixin.prototype, m.prototype); |
| 236 } | 379 } |
| 237 // Save mixins for reflection | 380 // Save mixins for reflection |
| 238 Mixin[dart.mixins] = mixins; | 381 Mixin[dart.mixins] = mixins; |
| 239 return Mixin; | 382 return Mixin; |
| 240 } | 383 } |
| 241 dart.mixin = mixin; | 384 dart.mixin = mixin; |
| 242 | 385 |
| 243 /** | 386 /** |
| 244 * Creates a dart:collection LinkedHashMap. | 387 * Creates a dart:collection LinkedHashMap. |
| 245 * | 388 * |
| 246 * For a map with string keys an object literal can be used, for example | 389 * For a map with string keys an object literal can be used, for example |
| 247 * `map({'hi': 1, 'there': 2})`. | 390 * `map({'hi': 1, 'there': 2})`. |
| 248 * | 391 * |
| 249 * Otherwise an array should be used, for example `map([1, 2, 3, 4])` will | 392 * Otherwise an array should be used, for example `map([1, 2, 3, 4])` will |
| 250 * create a map with keys [1, 3] and values [2, 4]. Each key-value pair | 393 * create a map with keys [1, 3] and values [2, 4]. Each key-value pair |
| 251 * should be adjacent entries in the array. | 394 * should be adjacent entries in the array. |
| 252 * | 395 * |
| 253 * For a map with no keys the function can be called with no arguments, for | 396 * For a map with no keys the function can be called with no arguments, for |
| 254 * example `map()`. | 397 * example `map()`. |
| 255 */ | 398 */ |
| 256 // TODO(jmesserly): this could be faster | 399 // TODO(jmesserly): this could be faster |
| 257 function map(values) { | 400 function map(values) { |
| 258 var map = new collection.LinkedHashMap(); | 401 let map = new collection.LinkedHashMap(); |
| 259 if (Array.isArray(values)) { | 402 if (Array.isArray(values)) { |
| 260 for (var i = 0, end = values.length - 1; i < end; i += 2) { | 403 for (let i = 0, end = values.length - 1; i < end; i += 2) { |
| 261 var key = values[i]; | 404 let key = values[i]; |
| 262 var value = values[i + 1]; | 405 let value = values[i + 1]; |
| 263 map.set(key, value); | 406 map.set(key, value); |
| 264 } | 407 } |
| 265 } else if (typeof values === 'object') { | 408 } else if (typeof values === 'object') { |
| 266 var keys = Object.getOwnPropertyNames(values); | 409 for (let key of Object.getOwnPropertyNames(values)) { |
| 267 for (var i = 0; i < keys.length; i++) { | 410 map.set(key, values[key]); |
| 268 var key = keys[i]; | |
| 269 var value = values[key]; | |
| 270 map.set(key, value); | |
| 271 } | 411 } |
| 272 } | 412 } |
| 273 return map; | 413 return map; |
| 274 } | 414 } |
| 275 dart.map = map; | 415 dart.map = map; |
| 276 | 416 |
| 277 function assert(condition) { | 417 function assert(condition) { |
| 278 // TODO(jmesserly): throw assertion error. | 418 // TODO(jmesserly): throw assertion error. |
| 279 if (!condition) throw 'assertion failed'; | 419 if (!condition) throw 'assertion failed'; |
| 280 } | 420 } |
| 281 dart.assert = assert; | 421 dart.assert = assert; |
| 282 | 422 |
| 283 function throw_(obj) { throw obj; } | 423 function throw_(obj) { throw obj; } |
| 284 dart.throw_ = throw_; | 424 dart.throw_ = throw_; |
| 285 | 425 |
| 286 /** | 426 /** |
| 287 * Given a class and an initializer method name, creates a constructor | 427 * Given a class and an initializer method name, creates a constructor |
| 288 * function with the same name. For example `new SomeClass.name(args)`. | 428 * function with the same name. For example `new SomeClass.name(args)`. |
| 289 */ | 429 */ |
| 290 function defineNamedConstructor(clazz, name) { | 430 function defineNamedConstructor(clazz, name) { |
| 291 var proto = clazz.prototype; | 431 let proto = clazz.prototype; |
| 292 var initMethod = proto[name]; | 432 let initMethod = proto[name]; |
| 293 var ctor = function() { return initMethod.apply(this, arguments); } | 433 let ctor = function() { return initMethod.apply(this, arguments); } |
| 294 ctor.prototype = proto; | 434 ctor.prototype = proto; |
| 295 clazz[name] = ctor; | 435 clazz[name] = ctor; |
| 296 } | 436 } |
| 297 dart.defineNamedConstructor = defineNamedConstructor; | 437 dart.defineNamedConstructor = defineNamedConstructor; |
| 298 | 438 |
| 299 function stackTrace(exception) { | 439 function stackTrace(exception) { |
| 300 throw new core.UnimplementedError(); | 440 throw new core.UnimplementedError(); |
| 301 } | 441 } |
| 302 dart.stackTrace = stackTrace; | 442 dart.stackTrace = stackTrace; |
| 303 | 443 |
| 304 /** The Symbol for storing type arguments on a specialized generic type. */ | 444 /** The Symbol for storing type arguments on a specialized generic type. */ |
| 305 dart.typeSignature = Symbol('typeSignature'); | 445 dart.typeArguments = Symbol('typeArguments'); |
| 446 dart.originalDeclaration = Symbol('originalDeclaration'); | |
|
Jennifer Messerly
2015/04/01 00:32:35
better name suggestions?
| |
| 306 | 447 |
| 307 /** Memoize a generic type constructor function. */ | 448 /** Memoize a generic type constructor function. */ |
| 308 function generic(typeConstructor) { | 449 function generic(typeConstructor) { |
| 309 var length = typeConstructor.length; | 450 let length = typeConstructor.length; |
| 310 if (length < 1) throw 'must have at least one generic type argument'; | 451 if (length < 1) throw Error('must have at least one generic type argument'); |
| 311 | 452 |
| 312 var resultMap = new Map(); | 453 let resultMap = new Map(); |
| 313 function makeGenericType(/*...arguments*/) { | 454 function makeGenericType(/*...arguments*/) { |
| 314 if (arguments.length != length && arguments.length != 0) { | 455 if (arguments.length != length && arguments.length != 0) { |
| 315 throw 'requires ' + length + ' or 0 type arguments'; | 456 throw Error('requires ' + length + ' or 0 type arguments'); |
| 316 } | 457 } |
| 458 let args = Array.prototype.slice.call(arguments); | |
| 459 while (args.length < length) args.push(dart.dynamic); | |
| 317 | 460 |
| 318 var value = resultMap; | 461 let value = resultMap; |
| 319 for (var i = 0; i < length; i++) { | 462 for (let i = 0; i < length; i++) { |
| 320 var arg = arguments[i]; | 463 let arg = args[i]; |
| 321 if (arg === void 0) arg = dart.dynamic; | 464 if (arg == null) { |
| 322 | 465 throw Error('type arguments should not be null: ' + typeConstructor); |
| 323 var map = value; | 466 } |
| 467 let map = value; | |
| 324 value = map.get(arg); | 468 value = map.get(arg); |
| 325 if (value === void 0) { | 469 if (value === void 0) { |
| 326 if (i + 1 == length) { | 470 if (i + 1 == length) { |
| 327 value = typeConstructor.apply(null, arguments); | 471 value = typeConstructor.apply(null, args); |
| 328 // Save the type constructor and arguments for reflection. | 472 // Save the type constructor and arguments for reflection. |
| 329 if (value) { | 473 if (value) { |
| 330 var args = Array.prototype.slice.call(arguments); | 474 value[dart.typeArguments] = args; |
| 331 value[dart.typeSignature] = [makeGenericType].concat(args); | 475 value[dart.originalDeclaration] = makeGenericType; |
| 332 } | 476 } |
| 333 } else { | 477 } else { |
| 334 value = new Map(); | 478 value = new Map(); |
| 335 } | 479 } |
| 336 map.set(arg, value); | 480 map.set(arg, value); |
| 337 } | 481 } |
| 338 } | 482 } |
| 339 return value; | 483 return value; |
| 340 } | 484 } |
| 341 return makeGenericType; | 485 return makeGenericType; |
| 342 } | 486 } |
| 343 dart.generic = generic; | 487 dart.generic = generic; |
| 344 | 488 |
| 345 // TODO(jmesserly): right now this is a sentinel. It should be a type object | 489 // TODO(jmesserly): right now this is a sentinel. It should be a type object |
| 346 // of some sort, assuming we keep around `dynamic` at runtime. | 490 // of some sort, assuming we keep around `dynamic` at runtime. |
| 347 dart.dynamic = Object.create(null); | 491 dart.dynamic = { toString() { return 'dynamic'; } }; |
| 348 | 492 |
| 349 dart.JsSymbol = Symbol; | 493 dart.JsSymbol = Symbol; |
| 350 | 494 |
| 351 // TODO(jmesserly): hack to bootstrap the SDK | 495 // TODO(jmesserly): hack to bootstrap the SDK |
| 352 _js_helper = _js_helper || {}; | 496 _js_helper = _js_helper || {}; |
| 353 _js_helper.checkNum = notNull; | 497 _js_helper.checkNum = notNull; |
| 354 | 498 |
| 355 })(dart || (dart = {})); | 499 })(dart || (dart = {})); |
| OLD | NEW |