Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(673)

Side by Side Diff: tool/input_sdk/private/ddc_runtime/operations.dart

Issue 1962823002: fix #552, Object members on native types (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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 ''');
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698