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 /// This library defines runtime operations on objects used by the code | 5 /// This library defines runtime operations on objects used by the code |
| 6 /// generator. | 6 /// generator. |
| 7 part of dart._runtime; | 7 part of dart._runtime; |
| 8 | 8 |
| 9 _canonicalFieldName(obj, name, args, displayName) => JS('', '''(() => { | 9 _canonicalFieldName(obj, name, args, displayName) => JS('', '''(() => { |
| 10 $name = $canonicalMember($obj, $name); | 10 $name = $canonicalMember($obj, $name); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 $throwStrongModeError('call to JS object `' + $obj + | 114 $throwStrongModeError('call to JS object `' + $obj + |
| 115 '` with type arguments <' + $typeArgs + '> is not supported.'); | 115 '` with type arguments <' + $typeArgs + '> is not supported.'); |
| 116 } | 116 } |
| 117 return $f.apply($obj, $args); | 117 return $f.apply($obj, $args); |
| 118 } | 118 } |
| 119 | 119 |
| 120 // Apply type arguments | 120 // Apply type arguments |
| 121 let formalCount = $ftype[$_typeFormalCount]; | 121 let formalCount = $ftype[$_typeFormalCount]; |
| 122 if (formalCount != null) { | 122 if (formalCount != null) { |
| 123 if ($typeArgs == null) { | 123 if ($typeArgs == null) { |
| 124 $typeArgs = Array(formalCount).fill($dynamicR); | 124 $typeArgs = Array(formalCount).fill($dynamic); |
| 125 } else if ($typeArgs.length != formalCount) { | 125 } else if ($typeArgs.length != formalCount) { |
| 126 // TODO(jmesserly): is this the right error? | 126 // TODO(jmesserly): is this the right error? |
| 127 $throwStrongModeError( | 127 $throwStrongModeError( |
| 128 'incorrect number of arguments to generic function ' + | 128 'incorrect number of arguments to generic function ' + |
| 129 $typeName($ftype) + ', got <' + $typeArgs + '> expected ' + | 129 $typeName($ftype) + ', got <' + $typeArgs + '> expected ' + |
| 130 formalCount + '.'); | 130 formalCount + '.'); |
| 131 } | 131 } |
| 132 // Instantiate the function. | 132 // Instantiate the function. |
| 133 $ftype = $ftype(...$typeArgs); | 133 $ftype = $ftype(...$typeArgs); |
| 134 } else if ($typeArgs != null) { | 134 } else if ($typeArgs != null) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 261 return { min: $f.length, max: $f.length }; | 261 return { min: $f.length, max: $f.length }; |
| 262 })()'''); | 262 })()'''); |
| 263 | 263 |
| 264 equals(x, y) => JS('', '''(() => { | 264 equals(x, y) => JS('', '''(() => { |
| 265 if ($x == null || $y == null) return $x == $y; | 265 if ($x == null || $y == null) return $x == $y; |
| 266 let eq = $x['==']; | 266 let eq = $x['==']; |
| 267 return eq ? eq.call($x, $y) : $x === $y; | 267 return eq ? eq.call($x, $y) : $x === $y; |
| 268 })()'''); | 268 })()'''); |
| 269 | 269 |
| 270 /// Checks that `x` is not null or undefined. */ | 270 /// Checks that `x` is not null or undefined. */ |
| 271 notNull(x) => JS('', '''(() => { | 271 notNull(x) { |
| 272 if ($x == null) $throwNullValueError(); | 272 if (x == null) throwNullValueError(); |
| 273 return $x; | 273 return x; |
| 274 })()'''); | 274 } |
| 275 | 275 |
| 276 /// | 276 /// |
| 277 /// Creates a dart:collection LinkedHashMap. | 277 /// Creates a dart:collection LinkedHashMap. |
| 278 /// | 278 /// |
| 279 /// For a map with string keys an object literal can be used, for example | 279 /// For a map with string keys an object literal can be used, for example |
| 280 /// `map({'hi': 1, 'there': 2})`. | 280 /// `map({'hi': 1, 'there': 2})`. |
| 281 /// | 281 /// |
| 282 /// Otherwise an array should be used, for example `map([1, 2, 3, 4])` will | 282 /// Otherwise an array should be used, for example `map([1, 2, 3, 4])` will |
| 283 /// create a map with keys [1, 3] and values [2, 4]. Each key-value pair | 283 /// create a map with keys [1, 3] and values [2, 4]. Each key-value pair |
| 284 /// should be adjacent entries in the array. | 284 /// should be adjacent entries in the array. |
| 285 /// | 285 /// |
| 286 /// For a map with no keys the function can be called with no arguments, for | 286 /// For a map with no keys the function can be called with no arguments, for |
| 287 /// example `map()`. | 287 /// example `map()`. |
| 288 /// | 288 /// |
| 289 // TODO(jmesserly): this could be faster | 289 // TODO(jmesserly): this could be faster |
| 290 // TODO(jmesserly): we can use default values `= dynamic` once #417 is fixed. | 290 // TODO(jmesserly): we can use default values `= dynamic` once #417 is fixed. |
| 291 // TODO(jmesserly): move this to classes for consistentcy with list literals? | 291 // TODO(jmesserly): move this to classes for consistentcy with list literals? |
| 292 map(values, [K, V]) => JS('', '''(() => { | 292 map(values, [K, V]) => JS('', '''(() => { |
| 293 if ($K == null) $K = $dynamicR; | 293 if ($K == null) $K = $dynamic; |
| 294 if ($V == null) $V = $dynamicR; | 294 if ($V == null) $V = $dynamic; |
| 295 let map = ${getGenericClass(LinkedHashMap)}($K, $V).new(); | 295 let map = ${getGenericClass(LinkedHashMap)}($K, $V).new(); |
| 296 if (Array.isArray($values)) { | 296 if (Array.isArray($values)) { |
| 297 for (let i = 0, end = $values.length - 1; i < end; i += 2) { | 297 for (let i = 0, end = $values.length - 1; i < end; i += 2) { |
| 298 let key = $values[i]; | 298 let key = $values[i]; |
| 299 let value = $values[i + 1]; | 299 let value = $values[i + 1]; |
| 300 map.set(key, value); | 300 map.set(key, value); |
| 301 } | 301 } |
| 302 } else if (typeof $values === 'object') { | 302 } else if (typeof $values === 'object') { |
| 303 for (let key of $getOwnPropertyNames($values)) { | 303 for (let key of $getOwnPropertyNames($values)) { |
| 304 map.set(key, $values[key]); | 304 map.set(key, $values[key]); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 412 objectKey.push(name); | 412 objectKey.push(name); |
| 413 objectKey.push($obj[name]); | 413 objectKey.push($obj[name]); |
| 414 } | 414 } |
| 415 return $multiKeyPutIfAbsent($constants, objectKey, () => $obj); | 415 return $multiKeyPutIfAbsent($constants, objectKey, () => $obj); |
| 416 })()'''); | 416 })()'''); |
| 417 | 417 |
| 418 | 418 |
| 419 // The following are helpers for Object methods when the receiver | 419 // The following are helpers for Object methods when the receiver |
| 420 // may be null or primitive. These should only be generated by | 420 // may be null or primitive. These should only be generated by |
| 421 // the compiler. | 421 // the compiler. |
| 422 hashCode(obj) => JS('', '''(() => { | 422 hashCode(obj) { |
| 423 if ($obj == null) { | 423 if (obj == null) return 0; |
| 424 return 0; | 424 |
| 425 switch (JS('String', 'typeof #', obj)) { | |
| 426 case "number": | |
| 427 return JS('','# & 0x1FFFFFFF', obj); | |
| 428 case "boolean": | |
| 429 // From JSBool.hashCode, see comment there. | |
| 430 return JS('', '# ? (2 * 3 * 23 * 3761) : (269 * 811)', obj); | |
| 425 } | 431 } |
| 426 // TODO(vsm): What should we do for primitives and non-Dart objects? | 432 |
| 427 switch (typeof $obj) { | 433 var extension = getExtensionType(obj); |
| 428 case "number": | 434 if (extension != null) { |
| 429 case "boolean": | 435 return JS('', '#[dartx.hashCode]', obj); |
| 430 return $obj & 0x1FFFFFFF; | |
| 431 case "string": | |
| 432 // TODO(vsm): Call the JSString hashCode? | |
| 433 return $obj.length; | |
| 434 } | 436 } |
| 435 return $obj.hashCode; | 437 return JS('', '#.hashCode', obj); |
| 436 })()'''); | 438 } |
| 437 | 439 |
| 438 toString(obj) => JS('', '''(() => { | 440 @JSExportName('toString') |
| 439 if ($obj == null) { | 441 _toString(obj) { |
| 440 return "null"; | 442 if (obj == null) return "null"; |
| 443 | |
| 444 var extension = getExtensionType(obj); | |
| 445 if (extension != null) { | |
| 446 return JS('', '#[dartx.toString]()', obj); | |
| 441 } | 447 } |
| 442 return $obj.toString(); | 448 return JS('', '#.toString()', obj); |
| 443 })()'''); | 449 } |
| 444 | 450 |
| 445 noSuchMethod(obj, invocation) => JS('', '''(() => { | 451 // TODO(jmesserly): is the argument type verified statically? |
| 446 if ($obj == null) { | 452 noSuchMethod(obj, Invocation invocation) { |
| 447 $throwNoSuchMethod($obj, $invocation.memberName, | 453 if (obj == null) { |
| 448 $invocation.positionalArguments, $invocation.namedArguments); | 454 throw new NoSuchMethodError( |
| 455 null, | |
| 456 invocation.memberName, | |
| 457 invocation.positionalArguments, | |
| 458 invocation.namedArguments); | |
| 449 } | 459 } |
| 450 switch (typeof $obj) { | 460 // TODO(jmesserly): I don't think any extension types define nSM. If they |
| 451 case "number": | 461 // do we need to add a cast here. |
|
vsm
2016/05/09 20:55:56
Can we sanity check?
var extension = getExtension
Jennifer Messerly
2016/05/10 00:33:57
Not sure I follow that code example, but yes I wen
| |
| 452 case "boolean": | 462 return JS('', '#.noSuchMethod(#)', obj, invocation); |
| 453 case "string": | 463 } |
| 454 $throwNoSuchMethod($obj, $invocation.memberName, | 464 |
| 455 $invocation.positionalArguments, $invocation.namedArguments); | 465 runtimeType(obj) { |
| 466 // Handle primitives where the method isn't on the object. | |
| 467 var result = _checkPrimitiveType(obj); | |
| 468 if (result != null) return wrapType(result); | |
| 469 | |
| 470 // Delegate to the (possibly user-defined) method on the object. | |
| 471 var extension = getExtensionType(obj); | |
| 472 if (extension != null) { | |
| 473 return JS('', '#[dartx.runtimeType]', obj); | |
| 456 } | 474 } |
| 457 return $obj.noSuchMethod($invocation); | 475 return JS('', '#.runtimeType', obj); |
| 458 })()'''); | 476 } |
| 459 | 477 |
| 460 final JsIterator = JS('', ''' | 478 final JsIterator = JS('', ''' |
| 461 class JsIterator { | 479 class JsIterator { |
| 462 constructor(dartIterator) { | 480 constructor(dartIterator) { |
| 463 this.dartIterator = dartIterator; | 481 this.dartIterator = dartIterator; |
| 464 } | 482 } |
| 465 next() { | 483 next() { |
| 466 let i = this.dartIterator; | 484 let i = this.dartIterator; |
| 467 let done = !i.moveNext(); | 485 let done = !i.moveNext(); |
| 468 return { done: done, value: done ? void 0 : i.current }; | 486 return { done: done, value: done ? void 0 : i.current }; |
| 469 } | 487 } |
| 470 } | 488 } |
| 471 '''); | 489 '''); |
| OLD | NEW |