| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 var dart; | |
| 6 (function (dart) { | |
| 7 var defineProperty = Object.defineProperty; | |
| 8 var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | |
| 9 var getOwnPropertyNames = Object.getOwnPropertyNames; | |
| 10 | |
| 11 // Adapted from Angular.js | |
| 12 var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; | |
| 13 var FN_ARG_SPLIT = /,/; | |
| 14 var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; | |
| 15 var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; | |
| 16 | |
| 17 function formalParameterList(fn) { | |
| 18 var fnText,argDecl; | |
| 19 var args=[]; | |
| 20 fnText = fn.toString().replace(STRIP_COMMENTS, ''); | |
| 21 argDecl = fnText.match(FN_ARGS); | |
| 22 | |
| 23 var r = argDecl[1].split(FN_ARG_SPLIT); | |
| 24 for(var a in r){ | |
| 25 var arg = r[a]; | |
| 26 arg.replace(FN_ARG, function(all, underscore, name){ | |
| 27 args.push(name); | |
| 28 }); | |
| 29 } | |
| 30 return args; | |
| 31 } | |
| 32 | |
| 33 function dload(obj, field) { | |
| 34 if (!(field in obj)) { | |
| 35 throw new core.NoSuchMethodError(obj, field); | |
| 36 } | |
| 37 return obj[field]; | |
| 38 } | |
| 39 dart.dload = dload; | |
| 40 | |
| 41 // TODO(jmesserly): this should call noSuchMethod, not throw. | |
| 42 function throwNoSuchMethod(obj, name, args, opt_func) { | |
| 43 if (obj === void 0) obj = opt_func; | |
| 44 throw new core.NoSuchMethodError(obj, name, args); | |
| 45 } | |
| 46 | |
| 47 function checkAndCall(f, obj, args, name) { | |
| 48 if (!(f instanceof Function)) { | |
| 49 // Grab the `call` method if it's not a function. | |
| 50 if (f !== null) f = f.call; | |
| 51 if (!(f instanceof Function)) { | |
| 52 throwNoSuchMethod(obj, method, args); | |
| 53 } | |
| 54 } | |
| 55 var formals = formalParameterList(f); | |
| 56 // TODO(vsm): Type check args! We need to encode sufficient type info on f. | |
| 57 if (formals.length < args.length) { | |
| 58 throwNoSuchMethod(obj, name, args, f); | |
| 59 } else if (formals.length > args.length) { | |
| 60 for (var i = args.length; i < formals.length; ++i) { | |
| 61 if (formals[i].indexOf("opt$") != 0) { | |
| 62 throwNoSuchMethod(obj, name, args, f); | |
| 63 } | |
| 64 } | |
| 65 } | |
| 66 return f.apply(obj, args); | |
| 67 } | |
| 68 | |
| 69 function dinvokef(f/*, ...args*/) { | |
| 70 var args = Array.prototype.slice.call(arguments, 1); | |
| 71 return checkAndCall(f, void 0, args, 'call'); | |
| 72 } | |
| 73 dart.dinvokef = dinvokef; | |
| 74 | |
| 75 function dinvoke(obj, method/*, ...args*/) { | |
| 76 var args = Array.prototype.slice.call(arguments, 2); | |
| 77 return checkAndCall(obj[method], obj, args, method); | |
| 78 } | |
| 79 dart.dinvoke = dinvoke; | |
| 80 | |
| 81 function dindex(obj, index) { | |
| 82 return checkAndCall(obj.get, obj, [index], '[]'); | |
| 83 } | |
| 84 dart.dindex = dindex; | |
| 85 | |
| 86 function dsetindex(obj, index, value) { | |
| 87 return checkAndCall(obj.set, obj, [index, value], '[]='); | |
| 88 } | |
| 89 dart.dsetindex = dindex; | |
| 90 | |
| 91 function dbinary(left, op, right) { | |
| 92 return checkAndCall(left[op], left, [right], op); | |
| 93 } | |
| 94 dart.dbinary = dbinary; | |
| 95 | |
| 96 function as_(obj, type) { | |
| 97 // TODO(vsm): Implement. | |
| 98 // if (obj == null || is(obj, type)) return obj; | |
| 99 // throw new core.CastError(); | |
| 100 return obj; | |
| 101 } | |
| 102 dart.as = as_; | |
| 103 | |
| 104 function is(obj, type) { | |
| 105 // TODO(vsm): Implement. | |
| 106 throw new core.UnimplementedError(); | |
| 107 } | |
| 108 dart.is = is; | |
| 109 | |
| 110 function isGroundType(type) { | |
| 111 // TODO(vsm): Implement. | |
| 112 throw new core.UnimplementedError(); | |
| 113 } | |
| 114 dart.isGroundType = isGroundType; | |
| 115 | |
| 116 function arity(f) { | |
| 117 // TODO(vsm): Implement. | |
| 118 throw new core.UnimplementedError(); | |
| 119 } | |
| 120 dart.arity = arity; | |
| 121 | |
| 122 function equals(x, y) { | |
| 123 if (x === null || y === null) return x === y; | |
| 124 var eq = x['==']; | |
| 125 return eq ? eq.call(x, y) : x === y; | |
| 126 } | |
| 127 dart.equals = equals; | |
| 128 | |
| 129 /** Checks that `x` is not null or undefined. */ | |
| 130 function notNull(x) { | |
| 131 if (x == null) throw 'expected not-null value'; | |
| 132 return x; | |
| 133 } | |
| 134 dart.notNull = notNull; | |
| 135 | |
| 136 /** | |
| 137 * Defines a lazy property. | |
| 138 * After initial get or set, it will replace itself with a value property. | |
| 139 */ | |
| 140 // TODO(jmesserly): is this the best implementation for JS engines? | |
| 141 // TODO(jmesserly): reusing descriptor objects has been shown to improve | |
| 142 // performance in other projects (e.g. webcomponents.js ShadowDOM polyfill). | |
| 143 function defineLazyProperty(to, name, desc) { | |
| 144 var init = desc.get; | |
| 145 var writable = !!desc.set; | |
| 146 function lazySetter(value) { | |
| 147 defineProperty(to, name, { value: value, writable: writable }); | |
| 148 } | |
| 149 function lazyGetter() { | |
| 150 // Clear the init function to detect circular initialization. | |
| 151 var f = init; | |
| 152 if (f === null) throw 'circular initialization for field ' + name; | |
| 153 init = null; | |
| 154 | |
| 155 // Compute and store the value. | |
| 156 var value = f(); | |
| 157 lazySetter(value); | |
| 158 return value; | |
| 159 } | |
| 160 desc.get = lazyGetter; | |
| 161 desc.configurable = true; | |
| 162 if (writable) desc.set = lazySetter; | |
| 163 defineProperty(to, name, desc); | |
| 164 } | |
| 165 | |
| 166 function defineLazyProperties(to, from) { | |
| 167 var names = getOwnPropertyNames(from); | |
| 168 for (var i = 0; i < names.length; i++) { | |
| 169 var name = names[i]; | |
| 170 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); | |
| 171 } | |
| 172 } | |
| 173 dart.defineLazyProperties = defineLazyProperties; | |
| 174 | |
| 175 /** | |
| 176 * Copy properties from source to destination object. | |
| 177 * This operation is commonly called `mixin` in JS. | |
| 178 */ | |
| 179 function copyProperties(to, from) { | |
| 180 var names = getOwnPropertyNames(from); | |
| 181 for (var i = 0; i < names.length; i++) { | |
| 182 var name = names[i]; | |
| 183 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); | |
| 184 } | |
| 185 return to; | |
| 186 } | |
| 187 dart.copyProperties = copyProperties; | |
| 188 | |
| 189 /** | |
| 190 * Returns a new type that mixes members from base and all mixins. | |
| 191 * | |
| 192 * Each mixin applies in sequence, with further to the right ones overriding | |
| 193 * previous entries. | |
| 194 * | |
| 195 * For each mixin, we only take its own properties, not anything from its | |
| 196 * superclass (prototype). | |
| 197 */ | |
| 198 function mixin(base/*, ...mixins*/) { | |
| 199 // Inherit statics from Base to simulate ES6 class inheritance | |
| 200 // Conceptually this is: `class Mixin extends base {}` | |
| 201 function Mixin() { | |
| 202 // TODO(jmesserly): since we're using initializers and not constructors, | |
| 203 // we can just skip directly to dart.Object. | |
| 204 dart.Object.apply(this, arguments); | |
| 205 } | |
| 206 Mixin.__proto__ = base; | |
| 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++) { | |
| 212 copyProperties(Mixin.prototype, mixins[i].prototype); | |
| 213 } | |
| 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; | |
| 228 } | |
| 229 dart.mixin = mixin; | |
| 230 | |
| 231 /** | |
| 232 * Creates a dart:collection LinkedHashMap. | |
| 233 * | |
| 234 * For a map with string keys an object literal can be used, for example | |
| 235 * `map({'hi': 1, 'there': 2})`. | |
| 236 * | |
| 237 * Otherwise an array should be used, for example `map([1, 2, 3, 4])` will | |
| 238 * create a map with keys [1, 3] and values [2, 4]. Each key-value pair | |
| 239 * should be adjacent entries in the array. | |
| 240 * | |
| 241 * For a map with no keys the function can be called with no arguments, for | |
| 242 * example `map()`. | |
| 243 */ | |
| 244 // TODO(jmesserly): this could be faster | |
| 245 function map(values) { | |
| 246 var map = new collection.LinkedHashMap(); | |
| 247 if (Array.isArray(values)) { | |
| 248 for (var i = 0, end = values.length - 1; i < end; i += 2) { | |
| 249 var key = values[i]; | |
| 250 var value = values[i + 1]; | |
| 251 map.set(key, value); | |
| 252 } | |
| 253 } else if (typeof values === 'object') { | |
| 254 var keys = Object.getOwnPropertyNames(values); | |
| 255 for (var i = 0; i < keys.length; i++) { | |
| 256 var key = keys[i]; | |
| 257 var value = values[key]; | |
| 258 map.set(key, value); | |
| 259 } | |
| 260 } | |
| 261 return map; | |
| 262 } | |
| 263 | |
| 264 function assert(condition) { | |
| 265 // TODO(jmesserly): throw assertion error. | |
| 266 if (!condition) throw 'assertion failed'; | |
| 267 } | |
| 268 dart.assert = assert; | |
| 269 | |
| 270 function throw_(obj) { throw obj; } | |
| 271 dart.throw_ = throw_; | |
| 272 | |
| 273 /** | |
| 274 * Given a class and an initializer method name, creates a constructor | |
| 275 * function with the same name. For example `new SomeClass.name(args)`. | |
| 276 */ | |
| 277 function defineNamedConstructor(clazz, name) { | |
| 278 var proto = clazz.prototype; | |
| 279 var initMethod = proto[clazz.name + '$' + name]; | |
| 280 var ctor = function() { return initMethod.apply(this, arguments); } | |
| 281 ctor.prototype = proto; | |
| 282 clazz[name] = ctor; | |
| 283 } | |
| 284 dart.defineNamedConstructor = defineNamedConstructor; | |
| 285 | |
| 286 function stackTrace(exception) { | |
| 287 throw new core.UnimplementedError(); | |
| 288 } | |
| 289 dart.stackTrace = stackTrace; | |
| 290 | |
| 291 /** The Symbol for storing type arguments on a specialized generic type. */ | |
| 292 dart.typeSignature = Symbol('typeSignature'); | |
| 293 | |
| 294 /** Memoize a generic type constructor function. */ | |
| 295 function generic(typeConstructor) { | |
| 296 var length = typeConstructor.length; | |
| 297 if (length < 1) throw 'must have at least one generic type argument'; | |
| 298 | |
| 299 var resultMap = new Map(); | |
| 300 function makeGenericType(/*...arguments*/) { | |
| 301 if (arguments.length != length) { | |
| 302 throw 'requires ' + length + ' type arguments'; | |
| 303 } | |
| 304 | |
| 305 var value = resultMap; | |
| 306 for (var i = 0; i < length; i++) { | |
| 307 var arg = arguments[i]; | |
| 308 // TODO(jmesserly): assume `dynamic` here? | |
| 309 if (arg === void 0) throw 'undefined is not allowed as a type argument'; | |
| 310 | |
| 311 var map = value; | |
| 312 value = map.get(arg); | |
| 313 if (value === void 0) { | |
| 314 if (i + 1 == length) { | |
| 315 value = typeConstructor.apply(null, arguments); | |
| 316 // Save the type constructor and arguments for reflection. | |
| 317 if (value) { | |
| 318 var args = Array.prototype.slice.call(arguments); | |
| 319 value[dart.typeSignature] = [makeGenericType].concat(args); | |
| 320 } | |
| 321 } else { | |
| 322 value = new Map(); | |
| 323 } | |
| 324 map.set(arg, value); | |
| 325 } | |
| 326 } | |
| 327 return value; | |
| 328 } | |
| 329 return makeGenericType; | |
| 330 } | |
| 331 dart.generic = generic; | |
| 332 | |
| 333 | |
| 334 /** | |
| 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 dart.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 dart.Object | |
| 354 dart.Object.prototype.Object = function() {}; | |
| 355 dart.Object.prototype.constructor = dart.Object; | |
| 356 | |
| 357 })(dart || (dart = {})); | |
| OLD | NEW |