| 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, _js_primitives; | 5 var dart, _js_helper, _js_primitives; |
| 6 (function (dart) { | 6 (function (dart) { |
| 7 'use strict'; | 7 'use strict'; |
| 8 | 8 |
| 9 // TODO(vsm): This is referenced (as init.globalState) from |
| 10 // isolate_helper.dart. Where should it go? |
| 11 // See: https://github.com/dart-lang/dev_compiler/issues/164 |
| 12 dart.globalState = null; |
| 13 |
| 9 let defineProperty = Object.defineProperty; | 14 let defineProperty = Object.defineProperty; |
| 10 let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | 15 let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
| 11 let getOwnPropertyNames = Object.getOwnPropertyNames; | 16 let getOwnPropertyNames = Object.getOwnPropertyNames; |
| 12 let getOwnPropertySymbols = Object.getOwnPropertySymbols; | 17 let getOwnPropertySymbols = Object.getOwnPropertySymbols; |
| 13 | 18 |
| 14 function getOwnNamesAndSymbols(obj) { | 19 function getOwnNamesAndSymbols(obj) { |
| 15 return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj)); | 20 return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj)); |
| 16 } | 21 } |
| 17 | 22 |
| 18 // Adapted from Angular.js | 23 // Adapted from Angular.js |
| (...skipping 11 matching lines...) Expand all Loading... |
| 30 let r = argDecl[1].split(FN_ARG_SPLIT); | 35 let r = argDecl[1].split(FN_ARG_SPLIT); |
| 31 for (let arg of r) { | 36 for (let arg of r) { |
| 32 arg.replace(FN_ARG, function(all, underscore, name){ | 37 arg.replace(FN_ARG, function(all, underscore, name){ |
| 33 args.push(name); | 38 args.push(name); |
| 34 }); | 39 }); |
| 35 } | 40 } |
| 36 return args; | 41 return args; |
| 37 } | 42 } |
| 38 | 43 |
| 39 function dload(obj, field) { | 44 function dload(obj, field) { |
| 40 if (!(field in obj)) { | 45 // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain |
| 41 throw new core.NoSuchMethodError(obj, field); | 46 // types. hasOwnProperty doesn't chase the proto chain. |
| 42 } | 47 // Also, do we want an NSM on regular JS objects? |
| 48 // See: https://github.com/dart-lang/dev_compiler/issues/169 |
| 43 var result = obj[field]; | 49 var result = obj[field]; |
| 44 if (typeof result == "function") { | 50 |
| 45 // We can't tell if the result needs binding. Fortunately binding the | 51 // TODO(vsm): Check this more robustly. |
| 46 // same function twice has no effect, so we can simply attempt to bind. | 52 if (typeof result == "function" && |
| 53 !Object.prototype.hasOwnProperty.call(obj, field)) { |
| 54 // This appears to be a method tearoff. Bind this. |
| 47 return result.bind(obj); | 55 return result.bind(obj); |
| 48 } | 56 } |
| 49 return result; | 57 return result; |
| 50 } | 58 } |
| 51 dart.dload = dload; | 59 dart.dload = dload; |
| 52 | 60 |
| 61 function dput(obj, field, value) { |
| 62 // TODO(vsm): Implement NSM and type checks. |
| 63 // See: https://github.com/dart-lang/dev_compiler/issues/170 |
| 64 obj[field] = value; |
| 65 } |
| 66 dart.dput = dput; |
| 67 |
| 53 // TODO(jmesserly): this should call noSuchMethod, not throw. | 68 // TODO(jmesserly): this should call noSuchMethod, not throw. |
| 54 function throwNoSuchMethod(obj, name, args, opt_func) { | 69 function throwNoSuchMethod(obj, name, args, opt_func) { |
| 55 if (obj === void 0) obj = opt_func; | 70 if (obj === void 0) obj = opt_func; |
| 56 throw new core.NoSuchMethodError(obj, name, args); | 71 throw new core.NoSuchMethodError(obj, name, args); |
| 57 } | 72 } |
| 58 | 73 |
| 59 function checkAndCall(f, obj, args, name) { | 74 function checkAndCall(f, obj, args, name) { |
| 60 if (!(f instanceof Function)) { | 75 if (!(f instanceof Function)) { |
| 61 // Grab the `call` method if it's not a function. | 76 // Grab the `call` method if it's not a function. |
| 62 if (f !== null) f = f.call; | 77 if (f !== null) f = f.call; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 80 */ | 95 */ |
| 81 return f.apply(obj, args); | 96 return f.apply(obj, args); |
| 82 } | 97 } |
| 83 | 98 |
| 84 function dcall(f/*, ...args*/) { | 99 function dcall(f/*, ...args*/) { |
| 85 let args = Array.prototype.slice.call(arguments, 1); | 100 let args = Array.prototype.slice.call(arguments, 1); |
| 86 return checkAndCall(f, void 0, args, 'call'); | 101 return checkAndCall(f, void 0, args, 'call'); |
| 87 } | 102 } |
| 88 dart.dcall = dcall; | 103 dart.dcall = dcall; |
| 89 | 104 |
| 105 // TODO(vsm): Automatically build this. |
| 106 // All dynamic methods should check for these. |
| 107 // See: https://github.com/dart-lang/dev_compiler/issues/142 |
| 108 var _extensionMethods = { |
| 109 // Lazy - as these symbols may not be loaded yet. |
| 110 // TODO(vsm): This should record / check the receiver type |
| 111 // as well. E.g., only look for core.$map if the receiver |
| 112 // is an Iterable. |
| 113 'map': () => core.$map, |
| 114 }; |
| 115 |
| 90 function dsend(obj, method/*, ...args*/) { | 116 function dsend(obj, method/*, ...args*/) { |
| 91 let args = Array.prototype.slice.call(arguments, 2); | 117 let args = Array.prototype.slice.call(arguments, 2); |
| 92 return checkAndCall(obj[method], obj, args, method); | 118 var f = obj[method]; |
| 119 if (f === void 0) { |
| 120 var symbol = _extensionMethods[method](); |
| 121 f = obj[symbol]; |
| 122 } |
| 123 return checkAndCall(f, obj, args, method); |
| 93 } | 124 } |
| 94 dart.dsend = dsend; | 125 dart.dsend = dsend; |
| 95 | 126 |
| 96 function dindex(obj, index) { | 127 function dindex(obj, index) { |
| 97 // TODO(jmesserly): remove this special case once Array extensions are | 128 // TODO(jmesserly): remove this special case once Array extensions are |
| 98 // hooked up. | 129 // hooked up. |
| 99 if (obj instanceof Array && realRuntimeType(index) == core.int) { | 130 if (obj instanceof Array && realRuntimeType(index) == core.int) { |
| 100 return obj[index]; | 131 return obj[index]; |
| 101 } | 132 } |
| 102 return checkAndCall(obj.get, obj, [index], '[]'); | 133 return checkAndCall(obj.get, obj, [index], '[]'); |
| 103 } | 134 } |
| 104 dart.dindex = dindex; | 135 dart.dindex = dindex; |
| 105 | 136 |
| 106 function dsetindex(obj, index, value) { | 137 function dsetindex(obj, index, value) { |
| 107 return checkAndCall(obj.set, obj, [index, value], '[]='); | 138 return checkAndCall(obj.set, obj, [index, value], '[]='); |
| 108 } | 139 } |
| 109 dart.dsetindex = dsetindex; | 140 dart.dsetindex = dsetindex; |
| 110 | 141 |
| 111 /** | 142 /** |
| 112 * Returns bound `method`. | 143 * Returns bound `method`. |
| 113 * This helper function avoids needing a temp for `obj`. | 144 * This helper function avoids needing a temp for `obj`. |
| 114 */ | 145 */ |
| 115 function bind(obj, method) { | 146 function bind(obj, method) { |
| 116 // This is a static bind (dynamic would use `dload`) so no need to check | 147 // This is a static bind (dynamic would use `dload`) so no need to check |
| 117 // if `method` is really there on `obj`.` | 148 // if `method` is really there on `obj`.` |
| 118 return obj[method].bind(obj); | 149 return obj[method].bind(obj); |
| 119 } | 150 } |
| 120 dart.bind = bind; | 151 dart.bind = bind; |
| 121 | 152 |
| 153 function typeToString(type) { |
| 154 if (typeof(type) == "function") { |
| 155 var name = type.name; |
| 156 var args = type[dart.typeArguments]; |
| 157 if (args) { |
| 158 name += '<'; |
| 159 for (var i = 0; i < args.length; ++i) { |
| 160 if (i > 0) name += ', '; |
| 161 name += typeToString(args[i]); |
| 162 } |
| 163 name += '>'; |
| 164 } |
| 165 return name; |
| 166 } else { |
| 167 return type.toString(); |
| 168 } |
| 169 } |
| 170 dart.typeName = typeToString; |
| 171 |
| 122 function cast(obj, type) { | 172 function cast(obj, type) { |
| 123 // TODO(vsm): handle non-nullable types | 173 // TODO(vsm): handle non-nullable types |
| 124 if (obj == null) return obj; | 174 if (obj == null) return obj; |
| 125 let actual = realRuntimeType(obj); | 175 let actual = realRuntimeType(obj); |
| 126 if (isSubtype(actual, type)) return obj; | 176 if (isSubtype(actual, type)) return obj; |
| 177 // TODO(vsm): Remove this hack ... due to |
| 178 // lack of generic methods. |
| 179 if (isSubtype(type, core.Iterable) && isSubtype(actual, core.Iterable) || |
| 180 isSubtype(type, async.Future) && isSubtype(actual, async.Future) || |
| 181 isSubtype(type, core.Map) && isSubtype(actual, core.Map)) { |
| 182 console.log('Warning: ignoring cast fail from ' + typeToString(actual) + '
to ' + typeToString(type)); |
| 183 return obj; |
| 184 } |
| 185 // console.log('Error: cast fail from ' + typeToString(actual) + ' to ' + ty
peToString(type)); |
| 127 throw new _js_helper.CastErrorImplementation(actual, type); | 186 throw new _js_helper.CastErrorImplementation(actual, type); |
| 128 } | 187 } |
| 129 dart.as = cast; | 188 dart.as = cast; |
| 130 | 189 |
| 131 | 190 |
| 132 // TODO(vsm): How should we encode the runtime type? | 191 // TODO(vsm): How should we encode the runtime type? |
| 133 let _runtimeType = Symbol('_runtimeType'); | 192 let _runtimeType = Symbol('_runtimeType'); |
| 134 | 193 |
| 135 function checkPrimitiveType(obj) { | 194 function checkPrimitiveType(obj) { |
| 136 switch (typeof obj) { | 195 switch (typeof obj) { |
| (...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 let initMethod = proto[name]; | 833 let initMethod = proto[name]; |
| 775 let ctor = function() { return initMethod.apply(this, arguments); } | 834 let ctor = function() { return initMethod.apply(this, arguments); } |
| 776 ctor.prototype = proto; | 835 ctor.prototype = proto; |
| 777 // Use defineProperty so we don't hit a property defined on Function, | 836 // Use defineProperty so we don't hit a property defined on Function, |
| 778 // like `caller` and `arguments`. | 837 // like `caller` and `arguments`. |
| 779 defineProperty(clazz, name, { value: ctor, configurable: true }); | 838 defineProperty(clazz, name, { value: ctor, configurable: true }); |
| 780 } | 839 } |
| 781 dart.defineNamedConstructor = defineNamedConstructor; | 840 dart.defineNamedConstructor = defineNamedConstructor; |
| 782 | 841 |
| 783 function stackTrace(exception) { | 842 function stackTrace(exception) { |
| 784 throw new core.UnimplementedError(); | 843 return _js_helper.getTraceFromException(exception); |
| 785 } | 844 } |
| 786 dart.stackTrace = stackTrace; | 845 dart.stackTrace = stackTrace; |
| 787 | 846 |
| 788 /** The Symbol for storing type arguments on a specialized generic type. */ | 847 /** The Symbol for storing type arguments on a specialized generic type. */ |
| 789 dart.typeArguments = Symbol('typeArguments'); | 848 dart.typeArguments = Symbol('typeArguments'); |
| 790 dart.originalDeclaration = Symbol('originalDeclaration'); | 849 dart.originalDeclaration = Symbol('originalDeclaration'); |
| 791 | 850 |
| 792 /** Memoize a generic type constructor function. */ | 851 /** Memoize a generic type constructor function. */ |
| 793 function generic(typeConstructor) { | 852 function generic(typeConstructor) { |
| 794 let length = typeConstructor.length; | 853 let length = typeConstructor.length; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 // initializing them, but easier to not depend on that. | 935 // initializing them, but easier to not depend on that. |
| 877 for (let name of getOwnNamesAndSymbols(obj)) { | 936 for (let name of getOwnNamesAndSymbols(obj)) { |
| 878 // TODO(jmesserly): we can make this faster if needed. | 937 // TODO(jmesserly): we can make this faster if needed. |
| 879 objectKey.push(name); | 938 objectKey.push(name); |
| 880 objectKey.push(obj[name]); | 939 objectKey.push(obj[name]); |
| 881 } | 940 } |
| 882 return multiKeyPutIfAbsent(constants, objectKey, () => obj); | 941 return multiKeyPutIfAbsent(constants, objectKey, () => obj); |
| 883 } | 942 } |
| 884 dart.const = constant; | 943 dart.const = constant; |
| 885 | 944 |
| 945 // TODO(vsm): Rationalize these type methods. We're currently using the |
| 946 // setType / proto scheme for nominal types (e.g., classes) and the |
| 947 // setRuntimeType / field scheme for structural types (e.g., functions |
| 948 // - and only in tests for now). |
| 949 // See: https://github.com/dart-lang/dev_compiler/issues/172 |
| 950 |
| 886 /** Sets the type of `obj` to be `type` */ | 951 /** Sets the type of `obj` to be `type` */ |
| 887 function setType(obj, type) { | 952 function setType(obj, type) { |
| 888 obj.__proto__ = type.prototype; | 953 obj.__proto__ = type.prototype; |
| 954 // Note, we generate code of the form: |
| 955 // - return dart.setType([], List$(E)) |
| 889 return obj; | 956 return obj; |
| 890 } | 957 } |
| 891 dart.setType = setType; | 958 dart.setType = setType; |
| 892 | 959 |
| 893 /** Sets the internal runtime type of `obj` to be `type` */ | 960 /** Sets the internal runtime type of `obj` to be `type` */ |
| 894 function setRuntimeType(obj, type) { | 961 function setRuntimeType(obj, type) { |
| 895 obj[_runtimeType] = type; | 962 obj[_runtimeType] = type; |
| 896 } | 963 } |
| 897 dart.setRuntimeType = setRuntimeType; | 964 dart.setRuntimeType = setRuntimeType; |
| 898 | 965 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 962 // TODO(jmesserly): right now this is a sentinel. It should be a type object | 1029 // TODO(jmesserly): right now this is a sentinel. It should be a type object |
| 963 // of some sort, assuming we keep around `dynamic` at runtime. | 1030 // of some sort, assuming we keep around `dynamic` at runtime. |
| 964 dart.dynamic = { toString() { return 'dynamic'; } }; | 1031 dart.dynamic = { toString() { return 'dynamic'; } }; |
| 965 dart.void = { toString() { return 'void'; } }; | 1032 dart.void = { toString() { return 'void'; } }; |
| 966 dart.bottom = { toString() { return 'bottom'; } }; | 1033 dart.bottom = { toString() { return 'bottom'; } }; |
| 967 | 1034 |
| 968 dart.global = window || global; | 1035 dart.global = window || global; |
| 969 dart.JsSymbol = Symbol; | 1036 dart.JsSymbol = Symbol; |
| 970 | 1037 |
| 971 function import_(value) { | 1038 function import_(value) { |
| 972 // TODO(jmesserly): throw once we're loading all of core libs. | 1039 // TODO(vsm): Change this to a hard throw. |
| 973 if (!value && console) console.warn('missing required module'); | 1040 // For now, we're missing some libraries. E.g., dart:js: |
| 1041 // https://github.com/dart-lang/dev_compiler/issues/168 |
| 1042 if (!value) { |
| 1043 console.log('missing required module'); |
| 1044 } |
| 974 return value; | 1045 return value; |
| 975 } | 1046 } |
| 976 dart.import = import_; | 1047 dart.import = import_; |
| 977 | 1048 |
| 978 function lazyImport(value) { | 1049 function lazyImport(value) { |
| 979 return defineLibrary(value, {}); | 1050 return defineLibrary(value, {}); |
| 980 } | 1051 } |
| 981 dart.lazyImport = lazyImport; | 1052 dart.lazyImport = lazyImport; |
| 982 | 1053 |
| 983 function defineLibrary(value, defaultValue) { | 1054 function defineLibrary(value, defaultValue) { |
| 984 return value ? value : defaultValue; | 1055 return value ? value : defaultValue; |
| 985 } | 1056 } |
| 986 dart.defineLibrary = defineLibrary; | 1057 dart.defineLibrary = defineLibrary; |
| 987 | 1058 |
| 988 // TODO(jmesserly): hack to bootstrap the SDK | 1059 // TODO(jmesserly): hack to bootstrap the SDK |
| 989 _js_helper = _js_helper || {}; | 1060 _js_helper = _js_helper || {}; |
| 990 _js_helper.checkNum = notNull; | 1061 _js_helper.checkNum = notNull; |
| 991 | 1062 |
| 992 _js_primitives = _js_primitives || {}; | 1063 _js_primitives = _js_primitives || {}; |
| 993 _js_primitives.printString = (s) => console.log(s); | 1064 _js_primitives.printString = (s) => console.log(s); |
| 994 | 1065 |
| 1066 // TODO(vsm): Plumb this correctly. |
| 1067 // See: https://github.com/dart-lang/dev_compiler/issues/40 |
| 1068 String.prototype.contains = function(sub) { return this.indexOf(sub) >= 0; } |
| 1069 let _split = String.prototype.split; |
| 1070 String.prototype.split = function() { |
| 1071 let result = _split.apply(this, arguments); |
| 1072 dart.setType(result, core.List$(core.String)); |
| 1073 return result; |
| 1074 } |
| 1075 String.prototype.get = function(i) { |
| 1076 return this[i]; |
| 1077 } |
| 1078 String.prototype.codeUnitAt = function(i) { |
| 1079 return this.charCodeAt(i); |
| 1080 } |
| 1081 String.prototype.replaceAllMapped = function(from, cb) { |
| 1082 return this.replace(from.multiple, function() { |
| 1083 // Remove offset & string from the result array |
| 1084 var matches = arguments; |
| 1085 matches.splice(-2, 2); |
| 1086 // The callback receives match, p1, ..., pn |
| 1087 return cb(matches); |
| 1088 }); |
| 1089 } |
| 1090 String.prototype['+'] = function (arg) { return this.valueOf() + arg; }; |
| 1091 |
| 1092 Boolean.prototype['!'] = function () { return !this.valueOf(); }; |
| 1093 Boolean.prototype['&&'] = function (arg) { return this.valueOf() && arg; }; |
| 1094 Boolean.prototype['||'] = function (arg) { return this.valueOf() || arg; }; |
| 1095 Number.prototype['<'] = function (arg) { return this.valueOf() < arg; }; |
| 1096 Number.prototype['<='] = function (arg) { return this.valueOf() <= arg; }; |
| 1097 Number.prototype['>'] = function (arg) { return this.valueOf() > arg; }; |
| 1098 Number.prototype['+'] = function (arg) { return this.valueOf() + arg; }; |
| 1099 |
| 1100 // TODO(vsm): DOM facades? |
| 1101 // See: https://github.com/dart-lang/dev_compiler/issues/173 |
| 1102 NodeList.prototype.get = function (i) { return this[i]; }; |
| 1103 NamedNodeMap.prototype.get = function (i) { return this[i]; }; |
| 1104 DOMTokenList.prototype.get = function (i) { return this[i]; }; |
| 1105 |
| 995 })(dart || (dart = {})); | 1106 })(dart || (dart = {})); |
| OLD | NEW |