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 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 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 825 let constants = new Map(); | 831 let constants = new Map(); |
| 826 | 832 |
| 827 /** | 833 /** |
| 828 * Canonicalize a constant object. | 834 * Canonicalize a constant object. |
| 829 * | 835 * |
| 830 * Preconditions: | 836 * Preconditions: |
| 831 * - `obj` is an objects or array, not a primitive. | 837 * - `obj` is an objects or array, not a primitive. |
| 832 * - nested values of the object are themselves already canonicalized. | 838 * - nested values of the object are themselves already canonicalized. |
| 833 */ | 839 */ |
| 834 function constant(obj) { | 840 function constant(obj) { |
| 835 let objectKey = [getRuntimeType(obj)]; | 841 let objectKey = [realRuntimeType(obj)]; |
| 836 // There's no guarantee in JS that names/symbols are returned in the same | 842 // 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 | 843 // order. We could probably get the same order if we're judicious about |
| 838 // initializing them, but easier to not depend on that. | 844 // initializing them, but easier to not depend on that. |
| 839 for (let name of getOwnNamesAndSymbols(obj)) { | 845 for (let name of getOwnNamesAndSymbols(obj)) { |
| 840 // TODO(jmesserly): we can make this faster if needed. | 846 // TODO(jmesserly): we can make this faster if needed. |
| 841 objectKey.push(name); | 847 objectKey.push(name); |
| 842 objectKey.push(obj[name]); | 848 objectKey.push(obj[name]); |
| 843 } | 849 } |
| 844 return multiKeyPutIfAbsent(constants, objectKey, () => obj); | 850 return multiKeyPutIfAbsent(constants, objectKey, () => obj); |
| 845 } | 851 } |
| 846 dart.const = constant; | 852 dart.const = constant; |
| 847 | 853 |
| 848 /** Sets the runtime type of `obj` to be `type` */ | 854 /** Sets the runtime type of `obj` to be `type` */ |
| 849 function setType(obj, type) { | 855 function setType(obj, type) { |
| 850 obj[runtimeType] = type; | 856 obj[_runtimeType] = type; |
| 851 } | 857 } |
| 852 dart.setType = setType; | 858 dart.setType = setType; |
| 853 | 859 |
| 860 // The following are helpers for Object methods when the receiver | |
| 861 // may be null or primitive. These should only be generated by | |
| 862 // the compiler. | |
| 863 function hashCode(obj) { | |
| 864 if (obj == null) { | |
| 865 return 0; | |
| 866 } | |
| 867 // TODO(vsm): What should we do for primitives and non-Dart objects? | |
| 868 switch (typeof obj) { | |
| 869 case "number": | |
| 870 case "boolean": | |
| 871 return obj & 0x1FFFFFFF; | |
| 872 case "string": | |
| 873 // TODO(vsm): Call the JSString hashCode? | |
| 874 return obj.length; | |
| 875 } | |
| 876 return obj.hashCode; | |
| 877 } | |
| 878 dart.hashCode = hashCode; | |
| 879 | |
| 880 function runtimeType(obj) { | |
| 881 var result = checkPrimitiveType(obj); | |
| 882 if (result !== null) return result; | |
| 883 return obj.runtimeType; | |
| 884 } | |
| 885 dart.runtimeType = runtimeType; | |
| 886 | |
| 887 function toString(obj) { | |
| 888 if (obj == null) { | |
| 889 return "null"; | |
| 890 } | |
| 891 return obj.toString(); | |
| 892 } | |
| 893 dart.toString = toString; | |
| 894 | |
| 895 function noSuchMethod(obj, invocation) { | |
| 896 if (obj == null) { | |
| 897 throw new core.NoSuchMethodError(obj, invocation.memberName, | |
|
Jennifer Messerly
2015/04/23 21:09:30
could this be like:
return core.Object.noSuch
vsm
2015/04/23 21:23:29
This feels mildly dangerous ... depending on how O
| |
| 898 invocation.positionalArguments, invocation.namedArguments); | |
| 899 } | |
| 900 switch (typeof obj) { | |
| 901 case "number": | |
| 902 case "boolean": | |
| 903 case "string": | |
| 904 throw new core.NoSuchMethodError(obj, invocation.memberName, | |
|
Jennifer Messerly
2015/04/23 21:09:30
this too
| |
| 905 invocation.positionalArguments, invocation.namedArguments); | |
| 906 } | |
| 907 return obj.noSuchMethod(invocation); | |
| 908 } | |
| 909 dart.noSuchMethod = noSuchMethod; | |
| 910 | |
| 854 // TODO(jmesserly): right now this is a sentinel. It should be a type object | 911 // TODO(jmesserly): right now this is a sentinel. It should be a type object |
| 855 // of some sort, assuming we keep around `dynamic` at runtime. | 912 // of some sort, assuming we keep around `dynamic` at runtime. |
| 856 dart.dynamic = { toString() { return 'dynamic'; } }; | 913 dart.dynamic = { toString() { return 'dynamic'; } }; |
| 857 dart.void = { toString() { return 'void'; } }; | 914 dart.void = { toString() { return 'void'; } }; |
| 858 dart.bottom = { toString() { return 'bottom'; } }; | 915 dart.bottom = { toString() { return 'bottom'; } }; |
| 859 | 916 |
| 860 dart.global = window || global; | 917 dart.global = window || global; |
| 861 dart.JsSymbol = Symbol; | 918 dart.JsSymbol = Symbol; |
| 862 | 919 |
| 863 // TODO(jmesserly): hack to bootstrap the SDK | 920 // TODO(jmesserly): hack to bootstrap the SDK |
| 864 _js_helper = _js_helper || {}; | 921 _js_helper = _js_helper || {}; |
| 865 _js_helper.checkNum = notNull; | 922 _js_helper.checkNum = notNull; |
| 866 | 923 |
| 867 })(dart || (dart = {})); | 924 })(dart || (dart = {})); |
| OLD | NEW |