OLD | NEW |
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 /* This library defines runtime operations on objects used by the code | |
6 * generator. | |
7 */ | |
8 dart_library.library('dart/_operations', null, /* Imports */[ | 1 dart_library.library('dart/_operations', null, /* Imports */[ |
9 ], /* Lazy Imports */[ | 2 'dart/_utils' |
10 'dart/_utils', | 3 ], /* Lazy imports */[ |
11 'dart/async', | |
12 'dart/collection', | |
13 'dart/core', | |
14 'dart/_js_helper', | |
15 'dart/_classes', | 4 'dart/_classes', |
16 'dart/_errors', | 5 'dart/_errors', |
17 'dart/_rtti', | 6 'dart/_rtti', |
18 'dart/_types' | 7 'dart/_types', |
19 ], function(exports, dart_utils, async, collection, core, _js_helper, classes, e
rrors, rtti, | 8 'dart/core', |
20 types) { | 9 'dart/async', |
| 10 'dart/collection', |
| 11 'dart/_js_helper' |
| 12 ], function(exports, utils, classes, _errors, rtti, _types, core, async, collect
ion, _js_helper) { |
21 'use strict'; | 13 'use strict'; |
22 | 14 const getOwnNamesAndSymbols = utils.getOwnNamesAndSymbols; |
23 const getOwnNamesAndSymbols = dart_utils.getOwnNamesAndSymbols; | |
24 const throwError = dart_utils.throwError; | |
25 | |
26 const getOwnPropertyNames = Object.getOwnPropertyNames; | 15 const getOwnPropertyNames = Object.getOwnPropertyNames; |
27 const hasOwnProperty = Object.prototype.hasOwnProperty; | 16 const hasOwnProperty = Object.prototype.hasOwnProperty; |
28 | |
29 function _canonicalFieldName(obj, name, args, displayName) { | 17 function _canonicalFieldName(obj, name, args, displayName) { |
30 name = classes.canonicalMember(obj, name); | 18 name = classes.canonicalMember(obj, name); |
31 if (name) return name; | 19 if (name) return name; |
32 // TODO(jmesserly): in the future we might have types that "overlay" Dart | 20 throwNoSuchMethod(obj, displayName, args); |
33 // methods while also exposing the full native API, e.g. dart:html vs | |
34 // dart:dom. To support that we'd need to fall back to the normal name | |
35 // if an extension method wasn't found. | |
36 errors.throwNoSuchMethod(obj, displayName, args); | |
37 } | 21 } |
38 | |
39 function dload(obj, field) { | 22 function dload(obj, field) { |
40 field = _canonicalFieldName(obj, field, [], field); | 23 field = _canonicalFieldName(obj, field, [], field); |
41 if (classes.hasMethod(obj, field)) { | 24 if (classes.hasMethod(obj, field)) { |
42 return classes.bind(obj, field); | 25 return classes.bind(obj, field); |
43 } | 26 } |
44 // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain | |
45 // types. hasOwnProperty doesn't chase the proto chain. | |
46 // Also, do we want an NSM on regular JS objects? | |
47 // See: https://github.com/dart-lang/dev_compiler/issues/169 | |
48 let result = obj[field]; | 27 let result = obj[field]; |
49 return result; | 28 return result; |
50 } | 29 } |
51 exports.dload = dload; | |
52 | |
53 function dput(obj, field, value) { | 30 function dput(obj, field, value) { |
54 field = _canonicalFieldName(obj, field, [value], field); | 31 field = _canonicalFieldName(obj, field, [value], field); |
55 // TODO(vsm): Implement NSM and type checks. | |
56 // See: https://github.com/dart-lang/dev_compiler/issues/170 | |
57 obj[field] = value; | 32 obj[field] = value; |
58 return value; | 33 return value; |
59 } | 34 } |
60 exports.dput = dput; | |
61 | |
62 | |
63 /// Check that a function of a given type can be applied to | |
64 /// actuals. | |
65 function checkApply(type, actuals) { | 35 function checkApply(type, actuals) { |
66 if (actuals.length < type.args.length) return false; | 36 if (actuals.length < type.args.length) return false; |
67 let index = 0; | 37 let index = 0; |
68 for(let i = 0; i < type.args.length; ++i) { | 38 for (let i = 0; i < type.args.length; ++i) { |
69 if (!instanceOfOrNull(actuals[i], type.args[i])) return false; | 39 if (!instanceOfOrNull(actuals[i], type.args[i])) return false; |
70 ++index; | 40 ++index; |
71 } | 41 } |
72 if (actuals.length == type.args.length) return true; | 42 if (actuals.length == type.args.length) return true; |
73 let extras = actuals.length - type.args.length; | 43 let extras = actuals.length - type.args.length; |
74 if (type.optionals.length > 0) { | 44 if (type.optionals.length > 0) { |
75 if (extras > type.optionals.length) return false; | 45 if (extras > type.optionals.length) return false; |
76 for(let i = 0, j=index; i < extras; ++i, ++j) { | 46 for (let i = 0, j = index; i < extras; ++i, ++j) { |
77 if (!instanceOfOrNull(actuals[j], type.optionals[i])) return false; | 47 if (!instanceOfOrNull(actuals[j], type.optionals[i])) return false; |
78 } | 48 } |
79 return true; | 49 return true; |
80 } | 50 } |
81 // TODO(leafp): We can't tell when someone might be calling | |
82 // something expecting an optional argument with named arguments | |
83 | |
84 if (extras != 1) return false; | 51 if (extras != 1) return false; |
85 // An empty named list means no named arguments | |
86 if (getOwnPropertyNames(type.named).length == 0) return false; | 52 if (getOwnPropertyNames(type.named).length == 0) return false; |
87 let opts = actuals[index]; | 53 let opts = actuals[index]; |
88 let names = getOwnPropertyNames(opts); | 54 let names = getOwnPropertyNames(opts); |
89 // Type is something other than a map | |
90 if (names.length == 0) return false; | 55 if (names.length == 0) return false; |
91 for (var name of names) { | 56 for (var name of names) { |
92 if (!(hasOwnProperty.call(type.named, name))) { | 57 if (!hasOwnProperty.call(type.named, name)) { |
93 return false; | 58 return false; |
94 } | 59 } |
95 if (!instanceOfOrNull(opts[name], type.named[name])) return false; | 60 if (!instanceOfOrNull(opts[name], type.named[name])) return false; |
96 } | 61 } |
97 return true; | 62 return true; |
98 } | 63 } |
99 | |
100 function throwNoSuchMethod(obj, name, args, opt_func) { | 64 function throwNoSuchMethod(obj, name, args, opt_func) { |
101 if (obj === void 0) obj = opt_func; | 65 if (obj === void 0) obj = opt_func; |
102 errors.throwNoSuchMethod(obj, name, args); | 66 _errors.throwNoSuchMethod(obj, name, args); |
103 } | 67 } |
104 | |
105 function checkAndCall(f, ftype, obj, args, name) { | 68 function checkAndCall(f, ftype, obj, args, name) { |
106 if (!(f instanceof Function)) { | 69 if (!(f instanceof Function)) { |
107 // We're not a function (and hence not a method either) | |
108 // Grab the `call` method if it's not a function. | |
109 if (f != null) { | 70 if (f != null) { |
110 ftype = classes.getMethodType(f, 'call'); | 71 ftype = classes.getMethodType(f, 'call'); |
111 f = f.call; | 72 f = f.call; |
112 } | 73 } |
113 if (!(f instanceof Function)) { | 74 if (!(f instanceof Function)) { |
114 throwNoSuchMethod(obj, name, args); | 75 throwNoSuchMethod(obj, name, args); |
115 } | 76 } |
116 } | 77 } |
117 // If f is a function, but not a method (no method type) | |
118 // then it should have been a function valued field, so | |
119 // get the type from the function. | |
120 if (ftype === void 0) { | 78 if (ftype === void 0) { |
121 ftype = rtti.read(f); | 79 ftype = rtti.read(f); |
122 } | 80 } |
123 | |
124 if (!ftype) { | 81 if (!ftype) { |
125 // TODO(leafp): Allow JS objects to go through? | |
126 // This includes the DOM. | |
127 return f.apply(obj, args); | 82 return f.apply(obj, args); |
128 } | 83 } |
129 | |
130 if (checkApply(ftype, args)) { | 84 if (checkApply(ftype, args)) { |
131 return f.apply(obj, args); | 85 return f.apply(obj, args); |
132 } | 86 } |
133 | |
134 // TODO(leafp): throw a type error (rather than NSM) | |
135 // if the arity matches but the types are wrong. | |
136 throwNoSuchMethod(obj, name, args, f); | 87 throwNoSuchMethod(obj, name, args, f); |
137 } | 88 } |
138 | |
139 function dcall(f, ...args) { | 89 function dcall(f, ...args) { |
140 let ftype = rtti.read(f); | 90 let ftype = rtti.read(f); |
141 return checkAndCall(f, ftype, void 0, args, 'call'); | 91 return checkAndCall(f, ftype, void 0, args, 'call'); |
142 } | 92 } |
143 exports.dcall = dcall; | |
144 | |
145 /** Shared code for dsend, dindex, and dsetindex. */ | |
146 function callMethod(obj, name, args, displayName) { | 93 function callMethod(obj, name, args, displayName) { |
147 let symbol = _canonicalFieldName(obj, name, args, displayName); | 94 let symbol = _canonicalFieldName(obj, name, args, displayName); |
148 let f = obj != null ? obj[symbol] : null; | 95 let f = obj != null ? obj[symbol] : null; |
149 let ftype = classes.getMethodType(obj, name); | 96 let ftype = classes.getMethodType(obj, name); |
150 return checkAndCall(f, ftype, obj, args, displayName); | 97 return checkAndCall(f, ftype, obj, args, displayName); |
151 } | 98 } |
152 | |
153 function dsend(obj, method, ...args) { | 99 function dsend(obj, method, ...args) { |
154 return callMethod(obj, method, args, method); | 100 return callMethod(obj, method, args, method); |
155 } | 101 } |
156 exports.dsend = dsend; | |
157 | |
158 function dindex(obj, index) { | 102 function dindex(obj, index) { |
159 return callMethod(obj, 'get', [index], '[]'); | 103 return callMethod(obj, 'get', [index], '[]'); |
160 } | 104 } |
161 exports.dindex = dindex; | |
162 | |
163 function dsetindex(obj, index, value) { | 105 function dsetindex(obj, index, value) { |
164 callMethod(obj, 'set', [index, value], '[]='); | 106 callMethod(obj, 'set', [index, value], '[]='); |
165 return value; | 107 return value; |
166 } | 108 } |
167 exports.dsetindex = dsetindex; | |
168 | |
169 function _ignoreTypeFailure(actual, type) { | 109 function _ignoreTypeFailure(actual, type) { |
170 // TODO(vsm): Remove this hack ... | 110 let isSubtype = _types.isSubtype; |
171 // This is primarily due to the lack of generic methods, | 111 if (isSubtype(type, core.Iterable) && isSubtype(actual, core.Iterable) || is
Subtype(type, async.Future) && isSubtype(actual, async.Future) || isSubtype(type
, core.Map) && isSubtype(actual, core.Map) || isSubtype(type, core.Function) &&
isSubtype(actual, core.Function) || isSubtype(type, async.Stream) && isSubtype(a
ctual, async.Stream) || isSubtype(type, async.StreamSubscription) && isSubtype(a
ctual, async.StreamSubscription)) { |
172 // but we need to triage all the errors. | 112 console.warn('Ignoring cast fail from ' + _types.typeName(actual) + ' to '
+ _types.typeName(type)); |
173 let isSubtype = types.isSubtype; | |
174 if (isSubtype(type, core.Iterable) && isSubtype(actual, core.Iterable) || | |
175 isSubtype(type, async.Future) && isSubtype(actual, async.Future) || | |
176 isSubtype(type, core.Map) && isSubtype(actual, core.Map) || | |
177 isSubtype(type, core.Function) && isSubtype(actual, core.Function) || | |
178 isSubtype(type, async.Stream) && isSubtype(actual, async.Stream) || | |
179 isSubtype(type, async.StreamSubscription) && | |
180 isSubtype(actual, async.StreamSubscription)) { | |
181 console.warn('Ignoring cast fail from ' + types.typeName(actual) + | |
182 ' to ' + types.typeName(type)); | |
183 return true; | 113 return true; |
184 } | 114 } |
185 return false; | 115 return false; |
186 } | 116 } |
187 | |
188 function strongInstanceOf(obj, type, ignoreFromWhiteList) { | 117 function strongInstanceOf(obj, type, ignoreFromWhiteList) { |
189 let actual = rtti.realRuntimeType(obj); | 118 let actual = rtti.realRuntimeType(obj); |
190 if (types.isSubtype(actual, type) || actual == types.jsobject) return true; | 119 if (_types.isSubtype(actual, type) || actual == _types.jsobject) return true
; |
191 if (ignoreFromWhiteList == void 0) return false; | 120 if (ignoreFromWhiteList == void 0) return false; |
192 if (types.isGroundType(type)) return false; | 121 if (_types.isGroundType(type)) return false; |
193 if (_ignoreTypeFailure(actual, type)) return true; | 122 if (_ignoreTypeFailure(actual, type)) return true; |
194 return false; | 123 return false; |
195 } | 124 } |
196 exports.strongInstanceOf = strongInstanceOf; | |
197 | |
198 function instanceOfOrNull(obj, type) { | 125 function instanceOfOrNull(obj, type) { |
199 if ((obj == null) || strongInstanceOf(obj, type, true)) return true; | 126 if (obj == null || strongInstanceOf(obj, type, true)) return true; |
200 return false; | 127 return false; |
201 } | 128 } |
202 | |
203 function instanceOf(obj, type) { | 129 function instanceOf(obj, type) { |
204 if (strongInstanceOf(obj, type)) return true; | 130 if (strongInstanceOf(obj, type)) return true; |
205 // TODO(#296): This is perhaps too eager to throw a StrongModeError? | 131 if (_types.isGroundType(type)) return false; |
206 // It will throw on <int>[] is List<String>. | |
207 // TODO(vsm): We can statically detect many cases where this | |
208 // check is unnecessary. | |
209 if (types.isGroundType(type)) return false; | |
210 let actual = rtti.realRuntimeType(obj); | 132 let actual = rtti.realRuntimeType(obj); |
211 dart_utils.throwStrongModeError('Strong mode is check failure: ' + | 133 utils.throwStrongModeError('Strong mode is check failure: ' + _types.typeNam
e(actual) + ' does not soundly subtype ' + _types.typeName(type)); |
212 types.typeName(actual) + ' does not soundly subtype ' + | |
213 types.typeName(type)); | |
214 } | 134 } |
215 exports.instanceOf = instanceOf; | |
216 | |
217 function cast(obj, type) { | 135 function cast(obj, type) { |
218 // TODO(#296): This is perhaps too eager to throw a StrongModeError? | |
219 // TODO(vsm): handle non-nullable types | |
220 if (instanceOfOrNull(obj, type)) return obj; | 136 if (instanceOfOrNull(obj, type)) return obj; |
221 let actual = rtti.realRuntimeType(obj); | 137 let actual = rtti.realRuntimeType(obj); |
222 if (types.isGroundType(type)) errors.throwCastError(actual, type); | 138 if (_types.isGroundType(type)) _errors.throwCastError(actual, type); |
223 | |
224 if (_ignoreTypeFailure(actual, type)) return obj; | 139 if (_ignoreTypeFailure(actual, type)) return obj; |
225 | 140 utils.throwStrongModeError('Strong mode cast failure from ' + _types.typeNam
e(actual) + ' to ' + _types.typeName(type)); |
226 dart_utils.throwStrongModeError('Strong mode cast failure from ' + | |
227 types.typeName(actual) + ' to ' + types.typeName(type)); | |
228 } | 141 } |
229 exports.cast = cast; | |
230 | |
231 function asInt(obj) { | 142 function asInt(obj) { |
232 if (obj == null) { | 143 if (obj == null) { |
233 return null; | 144 return null; |
234 } | 145 } |
235 if (Math.floor(obj) != obj) { | 146 if (Math.floor(obj) != obj) { |
236 // Note: null will also be caught by this check | 147 _errors.throwCastError(rtti.realRuntimeType(obj), core.int); |
237 errors.throwCastError(rtti.realRuntimeType(obj), core.int); | |
238 } | 148 } |
239 return obj; | 149 return obj; |
240 } | 150 } |
241 exports.asInt = asInt; | |
242 | |
243 function arity(f) { | 151 function arity(f) { |
244 // TODO(jmesserly): need to parse optional params. | 152 return {min: f.length, max: f.length}; |
245 // In ES6, length is the number of required arguments. | |
246 return { min: f.length, max: f.length }; | |
247 } | 153 } |
248 exports.arity = arity; | |
249 | |
250 function equals(x, y) { | 154 function equals(x, y) { |
251 if (x == null || y == null) return x == y; | 155 if (x == null || y == null) return x == y; |
252 let eq = x['==']; | 156 let eq = x['==']; |
253 return eq ? eq.call(x, y) : x === y; | 157 return eq ? eq.call(x, y) : x === y; |
254 } | 158 } |
255 exports.equals = equals; | |
256 | |
257 /** Checks that `x` is not null or undefined. */ | |
258 function notNull(x) { | 159 function notNull(x) { |
259 if (x == null) errors.throwNullValueError(); | 160 if (x == null) _errors.throwNullValueError(); |
260 return x; | 161 return x; |
261 } | 162 } |
262 exports.notNull = notNull; | |
263 | |
264 /** | |
265 * Creates a dart:collection LinkedHashMap. | |
266 * | |
267 * For a map with string keys an object literal can be used, for example | |
268 * `map({'hi': 1, 'there': 2})`. | |
269 * | |
270 * Otherwise an array should be used, for example `map([1, 2, 3, 4])` will | |
271 * create a map with keys [1, 3] and values [2, 4]. Each key-value pair | |
272 * should be adjacent entries in the array. | |
273 * | |
274 * For a map with no keys the function can be called with no arguments, for | |
275 * example `map()`. | |
276 */ | |
277 // TODO(jmesserly): this could be faster | |
278 function map(values) { | 163 function map(values) { |
279 let map = collection.LinkedHashMap.new(); | 164 let map = collection.LinkedHashMap.new(); |
280 if (Array.isArray(values)) { | 165 if (Array.isArray(values)) { |
281 for (let i = 0, end = values.length - 1; i < end; i += 2) { | 166 for (let i = 0, end = values.length - 1; i < end; i += 2) { |
282 let key = values[i]; | 167 let key = values[i]; |
283 let value = values[i + 1]; | 168 let value = values[i + 1]; |
284 map.set(key, value); | 169 map.set(key, value); |
285 } | 170 } |
286 } else if (typeof values === 'object') { | 171 } else if (typeof values === 'object') { |
287 for (let key of getOwnPropertyNames(values)) { | 172 for (let key of getOwnPropertyNames(values)) { |
288 map.set(key, values[key]); | 173 map.set(key, values[key]); |
289 } | 174 } |
290 } | 175 } |
291 return map; | 176 return map; |
292 } | 177 } |
293 exports.map = map; | |
294 | |
295 function assert(condition) { | 178 function assert(condition) { |
296 if (!condition) errors.throwAssertionError(); | 179 if (!condition) _errors.throwAssertionError(); |
297 } | 180 } |
298 exports.assert = assert; | 181 const _stack = new WeakMap(); |
299 | 182 function throw$(obj) { |
300 let _stack = new WeakMap(); | |
301 function throw_(obj) { | |
302 if (obj != null && (typeof obj == 'object' || typeof obj == 'function')) { | 183 if (obj != null && (typeof obj == 'object' || typeof obj == 'function')) { |
303 // TODO(jmesserly): couldn't we store the most recent stack in a single | |
304 // variable? There should only be one active stack trace. That would | |
305 // allow it to work for things like strings and numbers. | |
306 _stack.set(obj, new Error()); | 184 _stack.set(obj, new Error()); |
307 } | 185 } |
308 throw obj; | 186 throw obj; |
309 } | 187 } |
310 exports.throw = throw_; | |
311 | |
312 function getError(exception) { | 188 function getError(exception) { |
313 var stack = _stack.get(exception); | 189 var stack = _stack.get(exception); |
314 return stack !== void 0 ? stack : exception; | 190 return stack !== void 0 ? stack : exception; |
315 } | 191 } |
316 | |
317 // This is a utility function: it is only intended to be called from dev | |
318 // tools. | |
319 function stackPrint(exception) { | 192 function stackPrint(exception) { |
320 var error = getError(exception); | 193 var error = getError(exception); |
321 console.log(error.stack ? error.stack : 'No stack trace for: ' + error); | 194 console.log(error.stack ? error.stack : 'No stack trace for: ' + error); |
322 } | 195 } |
323 exports.stackPrint = stackPrint; | |
324 | |
325 function stackTrace(exception) { | 196 function stackTrace(exception) { |
326 var error = getError(exception); | 197 var error = getError(exception); |
327 return _js_helper.getTraceFromException(error); | 198 return _js_helper.getTraceFromException(error); |
328 } | 199 } |
329 exports.stackTrace = stackTrace; | |
330 | |
331 /** | |
332 * Implements a sequence of .? operations. | |
333 * | |
334 * Will call each successive callback, unless one returns null, which stops | |
335 * the sequence. | |
336 */ | |
337 function nullSafe(obj, ...callbacks) { | 200 function nullSafe(obj, ...callbacks) { |
338 if (obj == null) return obj; | 201 if (obj == null) return obj; |
339 for (const callback of callbacks) { | 202 for (const callback of callbacks) { |
340 obj = callback(obj); | 203 obj = callback(obj); |
341 if (obj == null) break; | 204 if (obj == null) break; |
342 } | 205 } |
343 return obj; | 206 return obj; |
344 } | 207 } |
345 exports.nullSafe = nullSafe; | 208 const _value = Symbol("_value"); |
346 | |
347 let _value = Symbol('_value'); | |
348 /** | |
349 * Looks up a sequence of [keys] in [map], recursively, and | |
350 * returns the result. If the value is not found, [valueFn] will be called to | |
351 * add it. For example: | |
352 * | |
353 * let map = new Map(); | |
354 * putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world'); | |
355 * | |
356 * ... will create a Map with a structure like: | |
357 * | |
358 * { 1: { 2: { 'hi ': { 'there ': 'world' } } } } | |
359 */ | |
360 function multiKeyPutIfAbsent(map, keys, valueFn) { | 209 function multiKeyPutIfAbsent(map, keys, valueFn) { |
361 for (let k of keys) { | 210 for (let k of keys) { |
362 let value = map.get(k); | 211 let value = map.get(k); |
363 if (!value) { | 212 if (!value) { |
364 // TODO(jmesserly): most of these maps are very small (e.g. 1 item), | |
365 // so it may be worth optimizing for that. | |
366 map.set(k, value = new Map()); | 213 map.set(k, value = new Map()); |
367 } | 214 } |
368 map = value; | 215 map = value; |
369 } | 216 } |
370 if (map.has(_value)) return map.get(_value); | 217 if (map.has(_value)) return map.get(_value); |
371 let value = valueFn(); | 218 let value = valueFn(); |
372 map.set(_value, value); | 219 map.set(_value, value); |
373 return value; | 220 return value; |
374 } | 221 } |
375 | |
376 /** The global constant table. */ | |
377 const constants = new Map(); | 222 const constants = new Map(); |
378 | 223 function const$(obj) { |
379 /** | |
380 * Canonicalize a constant object. | |
381 * | |
382 * Preconditions: | |
383 * - `obj` is an objects or array, not a primitive. | |
384 * - nested values of the object are themselves already canonicalized. | |
385 */ | |
386 function constant(obj) { | |
387 let objectKey = [rtti.realRuntimeType(obj)]; | 224 let objectKey = [rtti.realRuntimeType(obj)]; |
388 // TODO(jmesserly): there's no guarantee in JS that names/symbols are | |
389 // returned in the same order. | |
390 // | |
391 // We could probably get the same order if we're judicious about | |
392 // initializing fields in a consistent order across all const constructors. | |
393 // Alternatively we need a way to sort them to make consistent. | |
394 // | |
395 // Right now we use the (name,value) pairs in sequence, which prevents | |
396 // an object with incorrect field values being returned, but won't | |
397 // canonicalize correctly if key order is different. | |
398 for (let name of getOwnNamesAndSymbols(obj)) { | 225 for (let name of getOwnNamesAndSymbols(obj)) { |
399 objectKey.push(name); | 226 objectKey.push(name); |
400 objectKey.push(obj[name]); | 227 objectKey.push(obj[name]); |
401 } | 228 } |
402 return multiKeyPutIfAbsent(constants, objectKey, () => obj); | 229 return multiKeyPutIfAbsent(constants, objectKey, () => obj); |
403 } | 230 } |
404 exports.const = constant; | |
405 | |
406 | |
407 // The following are helpers for Object methods when the receiver | |
408 // may be null or primitive. These should only be generated by | |
409 // the compiler. | |
410 function hashCode(obj) { | 231 function hashCode(obj) { |
411 if (obj == null) { | 232 if (obj == null) { |
412 return 0; | 233 return 0; |
413 } | 234 } |
414 // TODO(vsm): What should we do for primitives and non-Dart objects? | |
415 switch (typeof obj) { | 235 switch (typeof obj) { |
416 case "number": | 236 case "number": |
417 case "boolean": | 237 case "boolean": |
418 return obj & 0x1FFFFFFF; | 238 { |
419 case "string": | 239 return obj & 0x1FFFFFFF; |
420 // TODO(vsm): Call the JSString hashCode? | 240 } |
421 return obj.length; | 241 case "string": |
| 242 { |
| 243 return obj.length; |
| 244 } |
422 } | 245 } |
423 return obj.hashCode; | 246 return obj.hashCode; |
424 } | 247 } |
425 exports.hashCode = hashCode; | |
426 | |
427 function toString(obj) { | 248 function toString(obj) { |
428 if (obj == null) { | 249 if (obj == null) { |
429 return "null"; | 250 return "null"; |
430 } | 251 } |
431 return obj.toString(); | 252 return obj.toString(); |
432 } | 253 } |
433 exports.toString = toString; | |
434 | |
435 function noSuchMethod(obj, invocation) { | 254 function noSuchMethod(obj, invocation) { |
436 if (obj == null) { | 255 if (obj == null) { |
437 errors.throwNoSuchMethod(obj, invocation.memberName, | 256 throwNoSuchMethod(obj, invocation.memberName, invocation.positionalArgumen
ts, invocation.namedArguments); |
438 invocation.positionalArguments, invocation.namedArguments); | |
439 } | 257 } |
440 switch (typeof obj) { | 258 switch (typeof obj) { |
441 case "number": | 259 case "number": |
442 case "boolean": | 260 case "boolean": |
443 case "string": | 261 case "string": |
444 errors.throwNoSuchMethod(obj, invocation.memberName, | 262 { |
445 invocation.positionalArguments, invocation.namedArguments); | 263 throwNoSuchMethod(obj, invocation.memberName, invocation.positionalArgum
ents, invocation.namedArguments); |
| 264 } |
446 } | 265 } |
447 return obj.noSuchMethod(invocation); | 266 return obj.noSuchMethod(invocation); |
448 } | 267 } |
449 exports.noSuchMethod = noSuchMethod; | 268 const JsIterator = class JsIterator { |
450 | |
451 class JsIterator { | |
452 constructor(dartIterator) { | 269 constructor(dartIterator) { |
453 this.dartIterator = dartIterator; | 270 this.dartIterator = dartIterator; |
454 } | 271 } |
455 next() { | 272 next() { |
456 let i = this.dartIterator; | 273 let i = this.dartIterator; |
457 let done = !i.moveNext(); | 274 let done = !i.moveNext(); |
458 return { done: done, value: done ? void 0 : i.current }; | 275 return {done: done, value: done ? void 0 : i.current}; |
459 } | 276 } |
460 } | 277 }; |
| 278 // Exports: |
| 279 exports.getOwnNamesAndSymbols = getOwnNamesAndSymbols; |
| 280 exports.getOwnPropertyNames = getOwnPropertyNames; |
| 281 exports.hasOwnProperty = hasOwnProperty; |
| 282 exports.dload = dload; |
| 283 exports.dput = dput; |
| 284 exports.checkApply = checkApply; |
| 285 exports.throwNoSuchMethod = throwNoSuchMethod; |
| 286 exports.checkAndCall = checkAndCall; |
| 287 exports.dcall = dcall; |
| 288 exports.callMethod = callMethod; |
| 289 exports.dsend = dsend; |
| 290 exports.dindex = dindex; |
| 291 exports.dsetindex = dsetindex; |
| 292 exports.strongInstanceOf = strongInstanceOf; |
| 293 exports.instanceOfOrNull = instanceOfOrNull; |
| 294 exports.instanceOf = instanceOf; |
| 295 exports.cast = cast; |
| 296 exports.asInt = asInt; |
| 297 exports.arity = arity; |
| 298 exports.equals = equals; |
| 299 exports.notNull = notNull; |
| 300 exports.map = map; |
| 301 exports.assert = assert; |
| 302 exports.throw = throw$; |
| 303 exports.getError = getError; |
| 304 exports.stackPrint = stackPrint; |
| 305 exports.stackTrace = stackTrace; |
| 306 exports.nullSafe = nullSafe; |
| 307 exports.multiKeyPutIfAbsent = multiKeyPutIfAbsent; |
| 308 exports.constants = constants; |
| 309 exports.const = const$; |
| 310 exports.hashCode = hashCode; |
| 311 exports.toString = toString; |
| 312 exports.noSuchMethod = noSuchMethod; |
461 exports.JsIterator = JsIterator; | 313 exports.JsIterator = JsIterator; |
462 | |
463 | |
464 }); | 314 }); |
OLD | NEW |