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 let defineProperty = Object.defineProperty; | 9 let defineProperty = Object.defineProperty; |
10 let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | 10 let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
11 let getOwnPropertyNames = Object.getOwnPropertyNames; | 11 let getOwnPropertyNames = Object.getOwnPropertyNames; |
12 let getOwnPropertySymbols = Object.getOwnPropertySymbols; | 12 let getOwnPropertySymbols = Object.getOwnPropertySymbols; |
13 | 13 |
| 14 function getOwnNamesAndSymbols(obj) { |
| 15 return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj)); |
| 16 } |
| 17 |
14 // Adapted from Angular.js | 18 // Adapted from Angular.js |
15 let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; | 19 let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; |
16 let FN_ARG_SPLIT = /,/; | 20 let FN_ARG_SPLIT = /,/; |
17 let FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; | 21 let FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; |
18 let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; | 22 let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; |
19 | 23 |
20 function formalParameterList(fn) { | 24 function formalParameterList(fn) { |
21 let fnText,argDecl; | 25 let fnText,argDecl; |
22 let args=[]; | 26 let args=[]; |
23 fnText = fn.toString().replace(STRIP_COMMENTS, ''); | 27 fnText = fn.toString().replace(STRIP_COMMENTS, ''); |
24 argDecl = fnText.match(FN_ARGS); | 28 argDecl = fnText.match(FN_ARGS); |
25 | 29 |
26 let r = argDecl[1].split(FN_ARG_SPLIT); | 30 let r = argDecl[1].split(FN_ARG_SPLIT); |
27 for(let a in r) { | 31 for (let arg of r) { |
28 let arg = r[a]; | |
29 arg.replace(FN_ARG, function(all, underscore, name){ | 32 arg.replace(FN_ARG, function(all, underscore, name){ |
30 args.push(name); | 33 args.push(name); |
31 }); | 34 }); |
32 } | 35 } |
33 return args; | 36 return args; |
34 } | 37 } |
35 | 38 |
36 function dload(obj, field) { | 39 function dload(obj, field) { |
37 if (!(field in obj)) { | 40 if (!(field in obj)) { |
38 throw new core.NoSuchMethodError(obj, field); | 41 throw new core.NoSuchMethodError(obj, field); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 } | 320 } |
318 | 321 |
319 // TODO(jmesserly): this isn't currently used, but it could be if we want | 322 // TODO(jmesserly): this isn't currently used, but it could be if we want |
320 // `obj is NonGroundType<T,S>` to be rejected at runtime instead of compile | 323 // `obj is NonGroundType<T,S>` to be rejected at runtime instead of compile |
321 // time. | 324 // time. |
322 function isGroundType(type) { | 325 function isGroundType(type) { |
323 // TODO(vsm): Cache this if we start using it at runtime. | 326 // TODO(vsm): Cache this if we start using it at runtime. |
324 | 327 |
325 if (type instanceof AbstractFunctionType) { | 328 if (type instanceof AbstractFunctionType) { |
326 if (!_isTop(type.returnType, false)) return false; | 329 if (!_isTop(type.returnType, false)) return false; |
327 for (var i = 0; i < type.args.length; ++i) { | 330 for (let i = 0; i < type.args.length; ++i) { |
328 if (!_isBottom(type.args[i], true)) return false; | 331 if (!_isBottom(type.args[i], true)) return false; |
329 } | 332 } |
330 for (var i = 0; i < type.optionals.length; ++i) { | 333 for (let i = 0; i < type.optionals.length; ++i) { |
331 if (!_isBottom(type.optionals[i], true)) return false; | 334 if (!_isBottom(type.optionals[i], true)) return false; |
332 } | 335 } |
333 var names = Object.getOwnPropertyNames(type.named); | 336 var names = getOwnPropertyNames(type.named); |
334 for (var i = 0; i < names.length; ++i) { | 337 for (let i = 0; i < names.length; ++i) { |
335 if (!_isBottom(type.named[names[i]], true)) return false; | 338 if (!_isBottom(type.named[names[i]], true)) return false; |
336 } | 339 } |
337 return true; | 340 return true; |
338 } | 341 } |
339 | 342 |
340 let typeArgs = safeGetOwnProperty(type, dart.typeArguments); | 343 let typeArgs = safeGetOwnProperty(type, dart.typeArguments); |
341 if (!typeArgs) return true; | 344 if (!typeArgs) return true; |
342 for (let t of typeArgs) { | 345 for (let t of typeArgs) { |
343 if (t != core.Object && t != dart.dynamic) return false; | 346 if (t != core.Object && t != dart.dynamic) return false; |
344 } | 347 } |
(...skipping 30 matching lines...) Expand all Loading... |
375 | 378 |
376 class AbstractFunctionType { | 379 class AbstractFunctionType { |
377 constructor() { | 380 constructor() { |
378 this._stringValue = null; | 381 this._stringValue = null; |
379 } | 382 } |
380 | 383 |
381 get name() { | 384 get name() { |
382 if (this._stringValue) return this._stringValue; | 385 if (this._stringValue) return this._stringValue; |
383 | 386 |
384 var buffer = '('; | 387 var buffer = '('; |
385 for (var i = 0; i < this.args.length; ++i) { | 388 for (let i = 0; i < this.args.length; ++i) { |
386 if (i > 0) { | 389 if (i > 0) { |
387 buffer += ', '; | 390 buffer += ', '; |
388 } | 391 } |
389 buffer += _typeName(this.args[i]); | 392 buffer += _typeName(this.args[i]); |
390 } | 393 } |
391 if (this.optionals.length > 0) { | 394 if (this.optionals.length > 0) { |
392 if (this.args.length > 0) buffer += ', '; | 395 if (this.args.length > 0) buffer += ', '; |
393 buffer += '['; | 396 buffer += '['; |
394 for (var i = 0; i < this.optionals.length; ++i) { | 397 for (let i = 0; i < this.optionals.length; ++i) { |
395 if (i > 0) { | 398 if (i > 0) { |
396 buffer += ', '; | 399 buffer += ', '; |
397 } | 400 } |
398 buffer += _typeName(this.optionals[i]); | 401 buffer += _typeName(this.optionals[i]); |
399 } | 402 } |
400 buffer += ']'; | 403 buffer += ']'; |
401 } else if (this.named.length > 0) { | 404 } else if (this.named.length > 0) { |
402 if (this.args.length > 0) buffer += ', '; | 405 if (this.args.length > 0) buffer += ', '; |
403 buffer += '{'; | 406 buffer += '{'; |
404 let names = Object.getOwnPropertyNames(this.named).sort(); | 407 let names = getOwnPropertyNames(this.named).sort(); |
405 for (var i = 0; i < names.length; ++i) { | 408 for (let i = 0; i < names.length; ++i) { |
406 if (i > 0) { | 409 if (i > 0) { |
407 buffer += ', '; | 410 buffer += ', '; |
408 } | 411 } |
409 buffer += names[i] + ': ' + _typeName(this.named[names[i]]); | 412 buffer += names[i] + ': ' + _typeName(this.named[names[i]]); |
410 } | 413 } |
411 buffer += '}'; | 414 buffer += '}'; |
412 } | 415 } |
413 | 416 |
414 buffer += ') -> ' + _typeName(this.returnType); | 417 buffer += ') -> ' + _typeName(this.returnType); |
415 this._stringValue = buffer; | 418 this._stringValue = buffer; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 } | 519 } |
517 } | 520 } |
518 | 521 |
519 let args1 = ft1.args; | 522 let args1 = ft1.args; |
520 let args2 = ft2.args; | 523 let args2 = ft2.args; |
521 | 524 |
522 if (args1.length > args2.length) { | 525 if (args1.length > args2.length) { |
523 return false; | 526 return false; |
524 } | 527 } |
525 | 528 |
526 for (var i = 0; i < args1.length; ++i) { | 529 for (let i = 0; i < args1.length; ++i) { |
527 if (!isSubtype_(args2[i], args1[i], true)) { | 530 if (!isSubtype_(args2[i], args1[i], true)) { |
528 return false; | 531 return false; |
529 } | 532 } |
530 } | 533 } |
531 | 534 |
532 let optionals1 = ft1.optionals; | 535 let optionals1 = ft1.optionals; |
533 let optionals2 = ft2.optionals; | 536 let optionals2 = ft2.optionals; |
534 | 537 |
535 if (args1.length + optionals1.length < args2.length + optionals2.length) { | 538 if (args1.length + optionals1.length < args2.length + optionals2.length) { |
536 return false; | 539 return false; |
537 } | 540 } |
538 | 541 |
539 var j = 0; | 542 var j = 0; |
540 for (var i = args1.length; i < args2.length; ++i, ++j) { | 543 for (let i = args1.length; i < args2.length; ++i, ++j) { |
541 if (!isSubtype_(args2[i], optionals1[j], true)) { | 544 if (!isSubtype_(args2[i], optionals1[j], true)) { |
542 return false; | 545 return false; |
543 } | 546 } |
544 } | 547 } |
545 | 548 |
546 for (var i = 0; i < optionals2.length; ++i, ++j) { | 549 for (let i = 0; i < optionals2.length; ++i, ++j) { |
547 if (!isSubtype_(optionals2[i], optionals1[j], true)) { | 550 if (!isSubtype_(optionals2[i], optionals1[j], true)) { |
548 return false; | 551 return false; |
549 } | 552 } |
550 } | 553 } |
551 | 554 |
552 let named1 = ft1.named; | 555 let named1 = ft1.named; |
553 let named2 = ft2.named; | 556 let named2 = ft2.named; |
554 | 557 |
555 let names = Object.getOwnPropertyNames(named2); | 558 let names = getOwnPropertyNames(named2); |
556 for (var i = 0; i < names.length; ++i) { | 559 for (let i = 0; i < names.length; ++i) { |
557 let name = names[i]; | 560 let name = names[i]; |
558 let n1 = named1[name] | 561 let n1 = named1[name]; |
559 let n2 = named2[name]; | 562 let n2 = named2[name]; |
560 if (n1 === void 0) { | 563 if (n1 === void 0) { |
561 return false; | 564 return false; |
562 } | 565 } |
563 if (!isSubtype_(n2, n1, true)) { | 566 if (!isSubtype_(n2, n1, true)) { |
564 return false; | 567 return false; |
565 } | 568 } |
566 } | 569 } |
567 | 570 |
568 return true; | 571 return true; |
(...skipping 23 matching lines...) Expand all Loading... |
592 lazySetter(value); | 595 lazySetter(value); |
593 return value; | 596 return value; |
594 } | 597 } |
595 desc.get = lazyGetter; | 598 desc.get = lazyGetter; |
596 desc.configurable = true; | 599 desc.configurable = true; |
597 if (writable) desc.set = lazySetter; | 600 if (writable) desc.set = lazySetter; |
598 defineProperty(to, name, desc); | 601 defineProperty(to, name, desc); |
599 } | 602 } |
600 | 603 |
601 function defineLazy(to, from) { | 604 function defineLazy(to, from) { |
602 let names = getOwnPropertyNames(from); | 605 for (let name of getOwnNamesAndSymbols(from)) { |
603 for (let i = 0; i < names.length; i++) { | |
604 let name = names[i]; | |
605 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); | 606 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); |
606 } | 607 } |
607 } | 608 } |
608 // TODO(jmesserly): these are identical, but this makes it easier to grep for. | 609 // TODO(jmesserly): these are identical, but this makes it easier to grep for. |
609 dart.defineLazyClass = defineLazy; | 610 dart.defineLazyClass = defineLazy; |
610 dart.defineLazyProperties = defineLazy; | 611 dart.defineLazyProperties = defineLazy; |
611 dart.defineLazyClassGeneric = defineLazyProperty; | 612 dart.defineLazyClassGeneric = defineLazyProperty; |
612 | 613 |
613 /** | 614 /** |
614 * Copy properties from source to destination object. | 615 * Copy properties from source to destination object. |
615 * This operation is commonly called `mixin` in JS. | 616 * This operation is commonly called `mixin` in JS. |
616 */ | 617 */ |
617 function copyProperties(to, from) { | 618 function copyProperties(to, from) { |
618 function copyPropertiesHelper(names) { | 619 for (let name of getOwnNamesAndSymbols(from)) { |
619 for (let i = 0; i < names.length; i++) { | 620 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); |
620 let name = names[i]; | |
621 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); | |
622 } | |
623 } | 621 } |
624 copyPropertiesHelper(getOwnPropertyNames(from)); | |
625 copyPropertiesHelper(getOwnPropertySymbols(from)); | |
626 return to; | 622 return to; |
627 } | 623 } |
628 dart.copyProperties = copyProperties; | 624 dart.copyProperties = copyProperties; |
629 | 625 |
630 /** | 626 /** |
631 * This is called whenever a derived class needs to introduce a new field, | 627 * This is called whenever a derived class needs to introduce a new field, |
632 * shadowing a field or getter/setter pair on its parent. | 628 * shadowing a field or getter/setter pair on its parent. |
633 * | 629 * |
634 * This is important because otherwise, trying to read or write the field | 630 * This is important because otherwise, trying to read or write the field |
635 * would end up calling the getter or setter, and one of those might not even | 631 * would end up calling the getter or setter, and one of those might not even |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 // TODO(jmesserly): this could be faster | 705 // TODO(jmesserly): this could be faster |
710 function map(values) { | 706 function map(values) { |
711 let map = new collection.LinkedHashMap(); | 707 let map = new collection.LinkedHashMap(); |
712 if (Array.isArray(values)) { | 708 if (Array.isArray(values)) { |
713 for (let i = 0, end = values.length - 1; i < end; i += 2) { | 709 for (let i = 0, end = values.length - 1; i < end; i += 2) { |
714 let key = values[i]; | 710 let key = values[i]; |
715 let value = values[i + 1]; | 711 let value = values[i + 1]; |
716 map.set(key, value); | 712 map.set(key, value); |
717 } | 713 } |
718 } else if (typeof values === 'object') { | 714 } else if (typeof values === 'object') { |
719 for (let key of Object.getOwnPropertyNames(values)) { | 715 for (let key of getOwnPropertyNames(values)) { |
720 map.set(key, values[key]); | 716 map.set(key, values[key]); |
721 } | 717 } |
722 } | 718 } |
723 return map; | 719 return map; |
724 } | 720 } |
725 dart.map = map; | 721 dart.map = map; |
726 | 722 |
727 function assert(condition) { | 723 function assert(condition) { |
728 // TODO(jmesserly): throw assertion error. | 724 // TODO(jmesserly): throw assertion error. |
729 if (!condition) throw 'assertion failed'; | 725 if (!condition) throw 'assertion failed'; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 } | 785 } |
790 map.set(arg, value); | 786 map.set(arg, value); |
791 } | 787 } |
792 } | 788 } |
793 return value; | 789 return value; |
794 } | 790 } |
795 return makeGenericType; | 791 return makeGenericType; |
796 } | 792 } |
797 dart.generic = generic; | 793 dart.generic = generic; |
798 | 794 |
| 795 let _value = Symbol('_value'); |
| 796 /** |
| 797 * Looks up a sequence of [keys] in [map], recursively, and |
| 798 * returns the result. If the value is not found, [valueFn] will be called to |
| 799 * add it. For example: |
| 800 * |
| 801 * var map = new Map(); |
| 802 * putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world'); |
| 803 * |
| 804 * ... will create a Map with a structure like: |
| 805 * |
| 806 * { 1: { 2: { 'hi ': { 'there ': 'world' } } } } |
| 807 */ |
| 808 function multiKeyPutIfAbsent(map, keys, valueFn) { |
| 809 for (let k of keys) { |
| 810 let value = map.get(k); |
| 811 if (!value) { |
| 812 // TODO(jmesserly): most of these maps are very small (e.g. 1 item), |
| 813 // so it may be worth optimizing for that. |
| 814 map.set(k, value = new Map()); |
| 815 } |
| 816 map = value; |
| 817 } |
| 818 if (map.has(_value)) return map.get(_value); |
| 819 let value = valueFn(); |
| 820 map.set(_value, value); |
| 821 return value; |
| 822 } |
| 823 |
| 824 /** The global constant table. */ |
| 825 let constants = new Map(); |
| 826 |
| 827 /** |
| 828 * Canonicalize a constant object. |
| 829 * |
| 830 * Preconditions: |
| 831 * - `obj` is an objects or array, not a primitive. |
| 832 * - nested values of the object are themselves already canonicalized. |
| 833 */ |
| 834 function constant(obj) { |
| 835 let objectKey = [getRuntimeType(obj)]; |
| 836 // There's no guarantee in JS that names/symbols are returned in the same |
| 837 // order. We could probably get the same order if we're judicious about |
| 838 // initializing them, but easier to not depend on that. |
| 839 for (let name of getOwnNamesAndSymbols(obj)) { |
| 840 // TODO(jmesserly): we can make this faster if needed. |
| 841 objectKey.push(name); |
| 842 objectKey.push(obj[name]); |
| 843 } |
| 844 return multiKeyPutIfAbsent(constants, objectKey, () => obj); |
| 845 } |
| 846 dart.const = constant; |
| 847 |
799 /** Sets the runtime type of `obj` to be `type` */ | 848 /** Sets the runtime type of `obj` to be `type` */ |
800 function setType(obj, type) { | 849 function setType(obj, type) { |
801 obj[runtimeType] = type; | 850 obj[runtimeType] = type; |
802 } | 851 } |
803 dart.setType = setType; | 852 dart.setType = setType; |
804 | 853 |
805 // TODO(jmesserly): right now this is a sentinel. It should be a type object | 854 // TODO(jmesserly): right now this is a sentinel. It should be a type object |
806 // of some sort, assuming we keep around `dynamic` at runtime. | 855 // of some sort, assuming we keep around `dynamic` at runtime. |
807 dart.dynamic = { toString() { return 'dynamic'; } }; | 856 dart.dynamic = { toString() { return 'dynamic'; } }; |
808 dart.void = { toString() { return 'void'; } }; | 857 dart.void = { toString() { return 'void'; } }; |
809 dart.bottom = { toString() { return 'bottom'; } }; | 858 dart.bottom = { toString() { return 'bottom'; } }; |
810 | 859 |
811 dart.global = window || global; | 860 dart.global = window || global; |
812 dart.JsSymbol = Symbol; | 861 dart.JsSymbol = Symbol; |
813 | 862 |
814 // TODO(jmesserly): hack to bootstrap the SDK | 863 // TODO(jmesserly): hack to bootstrap the SDK |
815 _js_helper = _js_helper || {}; | 864 _js_helper = _js_helper || {}; |
816 _js_helper.checkNum = notNull; | 865 _js_helper.checkNum = notNull; |
817 | 866 |
818 })(dart || (dart = {})); | 867 })(dart || (dart = {})); |
OLD | NEW |