| 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; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 | 89 |
| 90 function dsend(obj, method/*, ...args*/) { | 90 function dsend(obj, method/*, ...args*/) { |
| 91 let args = Array.prototype.slice.call(arguments, 2); | 91 let args = Array.prototype.slice.call(arguments, 2); |
| 92 return checkAndCall(obj[method], obj, args, method); | 92 return checkAndCall(obj[method], obj, args, method); |
| 93 } | 93 } |
| 94 dart.dsend = dsend; | 94 dart.dsend = dsend; |
| 95 | 95 |
| 96 function dindex(obj, index) { | 96 function dindex(obj, index) { |
| 97 // TODO(jmesserly): remove this special case once Array extensions are | 97 // TODO(jmesserly): remove this special case once Array extensions are |
| 98 // hooked up. | 98 // hooked up. |
| 99 if (obj instanceof Array && getRuntimeType(index) == core.int) { | 99 if (obj instanceof Array && realRuntimeType(index) == core.int) { |
| 100 return obj[index]; | 100 return obj[index]; |
| 101 } | 101 } |
| 102 return checkAndCall(obj.get, obj, [index], '[]'); | 102 return checkAndCall(obj.get, obj, [index], '[]'); |
| 103 } | 103 } |
| 104 dart.dindex = dindex; | 104 dart.dindex = dindex; |
| 105 | 105 |
| 106 function dsetindex(obj, index, value) { | 106 function dsetindex(obj, index, value) { |
| 107 return checkAndCall(obj.set, obj, [index, value], '[]='); | 107 return checkAndCall(obj.set, obj, [index, value], '[]='); |
| 108 } | 108 } |
| 109 dart.dsetindex = dsetindex; | 109 dart.dsetindex = dsetindex; |
| 110 | 110 |
| 111 /** | 111 /** |
| 112 * Returns bound `method`. | 112 * Returns bound `method`. |
| 113 * This helper function avoids needing a temp for `obj`. | 113 * This helper function avoids needing a temp for `obj`. |
| 114 */ | 114 */ |
| 115 function bind(obj, method) { | 115 function bind(obj, method) { |
| 116 // This is a static bind (dynamic would use `dload`) so no need to check | 116 // This is a static bind (dynamic would use `dload`) so no need to check |
| 117 // if `method` is really there on `obj`.` | 117 // if `method` is really there on `obj`.` |
| 118 return obj[method].bind(obj); | 118 return obj[method].bind(obj); |
| 119 } | 119 } |
| 120 dart.bind = bind; | 120 dart.bind = bind; |
| 121 | 121 |
| 122 function cast(obj, type) { | 122 function cast(obj, type) { |
| 123 // TODO(vsm): handle non-nullable types | 123 // TODO(vsm): handle non-nullable types |
| 124 if (obj == null) return obj; | 124 if (obj == null) return obj; |
| 125 let actual = getRuntimeType(obj); | 125 let actual = realRuntimeType(obj); |
| 126 if (isSubtype(actual, type)) return obj; | 126 if (isSubtype(actual, type)) return obj; |
| 127 throw new _js_helper.CastErrorImplementation(actual, type); | 127 throw new _js_helper.CastErrorImplementation(actual, type); |
| 128 } | 128 } |
| 129 dart.as = cast; | 129 dart.as = cast; |
| 130 | 130 |
| 131 | 131 |
| 132 // TODO(vsm): How should we encode the runtime type? | 132 // TODO(vsm): How should we encode the runtime type? |
| 133 let runtimeType = Symbol('runtimeType'); | 133 let _runtimeType = Symbol('_runtimeType'); |
| 134 | 134 |
| 135 /** | 135 function checkPrimitiveType(obj) { |
| 136 * Returns the runtime type of obj. This is the same as `obj.runtimeType` | |
| 137 * but will not call an overridden getter. | |
| 138 * | |
| 139 * Currently this will return null for non-Dart objects. | |
| 140 */ | |
| 141 function getRuntimeType(obj) { | |
| 142 switch (typeof obj) { | 136 switch (typeof obj) { |
| 143 case "undefined": | 137 case "undefined": |
| 144 return core.Null; | 138 return core.Null; |
| 145 case "number": | 139 case "number": |
| 146 return Math.floor(obj) == obj ? core.int : core.double; | 140 return Math.floor(obj) == obj ? core.int : core.double; |
| 147 case "boolean": | 141 case "boolean": |
| 148 return core.bool; | 142 return core.bool; |
| 149 case "string": | 143 case "string": |
| 150 return core.String; | 144 return core.String; |
| 151 case "symbol": | 145 case "symbol": |
| 152 return Symbol; | 146 return Symbol; |
| 153 } | 147 } |
| 154 // Undefined is handled above. For historical reasons, | 148 // Undefined is handled above. For historical reasons, |
| 155 // typeof null == "object" in JS. | 149 // typeof null == "object" in JS. |
| 156 if (obj === null) return core.Null; | 150 if (obj === null) return core.Null; |
| 151 return null; |
| 152 } |
| 153 |
| 154 /** |
| 155 * Returns the runtime type of obj. This is the same as `obj.realRuntimeType` |
| 156 * but will not call an overridden getter. |
| 157 * |
| 158 * Currently this will return null for non-Dart objects. |
| 159 */ |
| 160 function realRuntimeType(obj) { |
| 161 var result = checkPrimitiveType(obj); |
| 162 if (result !== null) return result; |
| 157 // TODO(vsm): Should we treat Dart and JS objects differently here? | 163 // TODO(vsm): Should we treat Dart and JS objects differently here? |
| 158 // E.g., we can check if obj instanceof core.Object to differentiate. | 164 // E.g., we can check if obj instanceof core.Object to differentiate. |
| 159 var result = obj[runtimeType]; | 165 result = obj[_runtimeType]; |
| 160 if (result) return result; | 166 if (result) return result; |
| 161 result = obj.constructor; | 167 result = obj.constructor; |
| 162 if (result == Function) { | 168 if (result == Function) { |
| 163 return getFunctionType(obj); | 169 return getFunctionType(obj); |
| 164 } | 170 } |
| 165 return result; | 171 return result; |
| 166 } | 172 } |
| 167 dart.getRuntimeType = getRuntimeType; | 173 dart.realRuntimeType = realRuntimeType; |
| 168 | 174 |
| 169 function instanceOf(obj, type) { | 175 function instanceOf(obj, type) { |
| 170 return isSubtype(getRuntimeType(obj), type); | 176 return isSubtype(realRuntimeType(obj), type); |
| 171 } | 177 } |
| 172 dart.is = instanceOf; | 178 dart.is = instanceOf; |
| 173 | 179 |
| 174 /** | 180 /** |
| 175 * Computes the canonical type. | 181 * Computes the canonical type. |
| 176 * This maps JS types onto their corresponding Dart Type. | 182 * This maps JS types onto their corresponding Dart Type. |
| 177 */ | 183 */ |
| 178 // TODO(jmesserly): lots more needs to be done here. | 184 // TODO(jmesserly): lots more needs to be done here. |
| 179 function canonicalType(t) { | 185 function canonicalType(t) { |
| 180 if (t === Object) return core.Object; | 186 if (t === Object) return core.Object; |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 let constants = new Map(); | 847 let constants = new Map(); |
| 842 | 848 |
| 843 /** | 849 /** |
| 844 * Canonicalize a constant object. | 850 * Canonicalize a constant object. |
| 845 * | 851 * |
| 846 * Preconditions: | 852 * Preconditions: |
| 847 * - `obj` is an objects or array, not a primitive. | 853 * - `obj` is an objects or array, not a primitive. |
| 848 * - nested values of the object are themselves already canonicalized. | 854 * - nested values of the object are themselves already canonicalized. |
| 849 */ | 855 */ |
| 850 function constant(obj) { | 856 function constant(obj) { |
| 851 let objectKey = [getRuntimeType(obj)]; | 857 let objectKey = [realRuntimeType(obj)]; |
| 852 // There's no guarantee in JS that names/symbols are returned in the same | 858 // There's no guarantee in JS that names/symbols are returned in the same |
| 853 // order. We could probably get the same order if we're judicious about | 859 // order. We could probably get the same order if we're judicious about |
| 854 // initializing them, but easier to not depend on that. | 860 // initializing them, but easier to not depend on that. |
| 855 for (let name of getOwnNamesAndSymbols(obj)) { | 861 for (let name of getOwnNamesAndSymbols(obj)) { |
| 856 // TODO(jmesserly): we can make this faster if needed. | 862 // TODO(jmesserly): we can make this faster if needed. |
| 857 objectKey.push(name); | 863 objectKey.push(name); |
| 858 objectKey.push(obj[name]); | 864 objectKey.push(obj[name]); |
| 859 } | 865 } |
| 860 return multiKeyPutIfAbsent(constants, objectKey, () => obj); | 866 return multiKeyPutIfAbsent(constants, objectKey, () => obj); |
| 861 } | 867 } |
| 862 dart.const = constant; | 868 dart.const = constant; |
| 863 | 869 |
| 864 /** Sets the runtime type of `obj` to be `type` */ | 870 /** Sets the runtime type of `obj` to be `type` */ |
| 865 function setType(obj, type) { | 871 function setType(obj, type) { |
| 866 obj[runtimeType] = type; | 872 obj[_runtimeType] = type; |
| 867 } | 873 } |
| 868 dart.setType = setType; | 874 dart.setType = setType; |
| 869 | 875 |
| 876 // The following are helpers for Object methods when the receiver |
| 877 // may be null or primitive. These should only be generated by |
| 878 // the compiler. |
| 879 function hashCode(obj) { |
| 880 if (obj == null) { |
| 881 return 0; |
| 882 } |
| 883 // TODO(vsm): What should we do for primitives and non-Dart objects? |
| 884 switch (typeof obj) { |
| 885 case "number": |
| 886 case "boolean": |
| 887 return obj & 0x1FFFFFFF; |
| 888 case "string": |
| 889 // TODO(vsm): Call the JSString hashCode? |
| 890 return obj.length; |
| 891 } |
| 892 return obj.hashCode; |
| 893 } |
| 894 dart.hashCode = hashCode; |
| 895 |
| 896 function runtimeType(obj) { |
| 897 var result = checkPrimitiveType(obj); |
| 898 if (result !== null) return result; |
| 899 return obj.runtimeType; |
| 900 } |
| 901 dart.runtimeType = runtimeType; |
| 902 |
| 903 function toString(obj) { |
| 904 if (obj == null) { |
| 905 return "null"; |
| 906 } |
| 907 return obj.toString(); |
| 908 } |
| 909 dart.toString = toString; |
| 910 |
| 911 function noSuchMethod(obj, invocation) { |
| 912 if (obj == null) { |
| 913 throw new core.NoSuchMethodError(obj, invocation.memberName, |
| 914 invocation.positionalArguments, invocation.namedArguments); |
| 915 } |
| 916 switch (typeof obj) { |
| 917 case "number": |
| 918 case "boolean": |
| 919 case "string": |
| 920 throw new core.NoSuchMethodError(obj, invocation.memberName, |
| 921 invocation.positionalArguments, invocation.namedArguments); |
| 922 } |
| 923 return obj.noSuchMethod(invocation); |
| 924 } |
| 925 dart.noSuchMethod = noSuchMethod; |
| 926 |
| 870 // TODO(jmesserly): right now this is a sentinel. It should be a type object | 927 // TODO(jmesserly): right now this is a sentinel. It should be a type object |
| 871 // of some sort, assuming we keep around `dynamic` at runtime. | 928 // of some sort, assuming we keep around `dynamic` at runtime. |
| 872 dart.dynamic = { toString() { return 'dynamic'; } }; | 929 dart.dynamic = { toString() { return 'dynamic'; } }; |
| 873 dart.void = { toString() { return 'void'; } }; | 930 dart.void = { toString() { return 'void'; } }; |
| 874 dart.bottom = { toString() { return 'bottom'; } }; | 931 dart.bottom = { toString() { return 'bottom'; } }; |
| 875 | 932 |
| 876 dart.global = window || global; | 933 dart.global = window || global; |
| 877 dart.JsSymbol = Symbol; | 934 dart.JsSymbol = Symbol; |
| 878 | 935 |
| 879 // TODO(jmesserly): hack to bootstrap the SDK | 936 // TODO(jmesserly): hack to bootstrap the SDK |
| 880 _js_helper = _js_helper || {}; | 937 _js_helper = _js_helper || {}; |
| 881 _js_helper.checkNum = notNull; | 938 _js_helper.checkNum = notNull; |
| 882 | 939 |
| 883 })(dart || (dart = {})); | 940 })(dart || (dart = {})); |
| OLD | NEW |