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

Side by Side Diff: test/generated_sdk/lib/_internal/compiler/js_lib/js_array.dart

Issue 1153003003: fixes #40, extension methods for primitive types (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of _interceptors; 5 part of _interceptors;
6 6
7 /** 7 /**
8 * The interceptor class for [List]. The compiler recognizes this 8 * The interceptor class for [List]. The compiler recognizes this
9 * class as an interceptor, and changes references to [:this:] to 9 * class as an interceptor, and changes references to [:this:] to
10 * actually use the receiver of the method, which is generated as an extra 10 * actually use the receiver of the method, which is generated as an extra
11 * argument added to each member. 11 * argument added to each member.
12 */ 12 */
13 @JsName(name: 'Array') 13 @JsPeerInterface(name: 'Array')
14 class JSArray<E> implements List<E>, JSIndexable { 14 class JSArray<E> implements List<E>, JSIndexable {
15 15
16 const JSArray(); 16 const JSArray();
17 17
18 /** 18 /**
19 * Returns a fresh JavaScript Array, marked as fixed-length. 19 * Constructor for adding type parameters to an existing JavaScript Array.
20 *
21 * [length] must be a non-negative integer.
22 */ 20 */
23 factory JSArray.fixed(int length) { 21 factory JSArray.typed(allocation) =>
24 // Explicit type test is necessary to guard against JavaScript conversions 22 // TODO(jmesserly): skip this when E is dynamic and Object.
25 // in unchecked mode. 23 JS('-dynamic', 'dart.list(#, #)', allocation, E);
26 if ((length is !int) || (length < 0)) {
27 throw new ArgumentError("Length must be a non-negative integer: $length");
28 }
29 return new JSArray<E>.markFixed(JS('', 'new Array(#)', length));
30 }
31 24
32 /** 25 // TODO(jmesserly): consider a fixed array subclass instead.
33 * Returns a fresh growable JavaScript Array of zero length length. 26 factory JSArray.markFixed(allocation) =>
34 */ 27 new JSArray<E>.typed(markFixedList(allocation));
35 factory JSArray.emptyGrowable() => new JSArray<E>.markGrowable(JS('', '[]'));
36 28
37 /** 29 factory JSArray.markGrowable(allocation) = JSArray.typed;
38 * Returns a fresh growable JavaScript Array with initial length.
39 *
40 * [validatedLength] must be a non-negative integer.
41 */
42 factory JSArray.growable(int length) {
43 // Explicit type test is necessary to guard against JavaScript conversions
44 // in unchecked mode.
45 if ((length is !int) || (length < 0)) {
46 throw new ArgumentError("Length must be a non-negative integer: $length");
47 }
48 return new JSArray<E>.markGrowable(JS('', 'new Array(#)', length));
49 }
50
51 /**
52 * Constructor for adding type parameters to an existing JavaScript Array.
53 * The compiler specially recognizes this constructor.
54 *
55 * var a = new JSArray<int>.typed(JS('JSExtendableArray', '[]'));
56 * a is List<int> --> true
57 * a is List<String> --> false
58 *
59 * Usually either the [JSArray.markFixed] or [JSArray.markGrowable]
60 * constructors is used instead.
61 *
62 * The input must be a JavaScript Array. The JS form is just a re-assertion
63 * to help type analysis when the input type is sloppy.
64 */
65 factory JSArray.typed(allocation) => JS('JSArray', '#', allocation);
66
67 factory JSArray.markFixed(allocation) =>
68 JS('JSFixedArray', '#', markFixedList(new JSArray<E>.typed(allocation)));
69
70 factory JSArray.markGrowable(allocation) =>
71 JS('JSExtendableArray', '#', new JSArray<E>.typed(allocation));
72 30
73 static List markFixedList(List list) { 31 static List markFixedList(List list) {
74 // Functions are stored in the hidden class and not as properties in 32 // Functions are stored in the hidden class and not as properties in
75 // the object. We never actually look at the value, but only want 33 // the object. We never actually look at the value, but only want
76 // to know if the property exists. 34 // to know if the property exists.
77 JS('void', r'#.fixed$length = Array', list); 35 JS('void', r'#.fixed$length = Array', list);
78 return JS('JSFixedArray', '#', list); 36 return list;
79 }
80
81 checkMutable(reason) {
82 if (this is !JSMutableArray) {
83 throw new UnsupportedError(reason);
84 }
85 } 37 }
86 38
87 checkGrowable(reason) { 39 checkGrowable(reason) {
88 if (JS('bool', r'#.fixed$length', this)) { 40 if (JS('bool', r'#.fixed$length', this)) {
89 throw new UnsupportedError(reason); 41 throw new UnsupportedError(reason);
90 } 42 }
91 } 43 }
92 44
93 void add(E value) { 45 void add(E value) {
94 checkGrowable('add'); 46 checkGrowable('add');
95 JS('void', r'#.push(#)', this, value); 47 JS('void', r'#.push(#)', this, value);
96 } 48 }
97 49
98 E removeAt(int index) { 50 E removeAt(int index) {
99 if (index is !int) throw new ArgumentError(index); 51 if (index is !int) throw new ArgumentError(index);
100 if (index < 0 || index >= length) { 52 if (index < 0 || index >= length) {
101 throw new RangeError.value(index); 53 throw new RangeError.value(index);
102 } 54 }
103 checkGrowable('removeAt'); 55 checkGrowable('removeAt');
104 return JS('var', r'#.splice(#, 1)[0]', this, index); 56 return JS('-dynamic', r'#.splice(#, 1)[0]', this, index);
105 } 57 }
106 58
107 void insert(int index, E value) { 59 void insert(int index, E value) {
108 if (index is !int) throw new ArgumentError(index); 60 if (index is !int) throw new ArgumentError(index);
109 if (index < 0 || index > length) { 61 if (index < 0 || index > length) {
110 throw new RangeError.value(index); 62 throw new RangeError.value(index);
111 } 63 }
112 checkGrowable('insert'); 64 checkGrowable('insert');
113 JS('void', r'#.splice(#, 0, #)', this, index, value); 65 JS('void', r'#.splice(#, 0, #)', this, index, value);
114 } 66 }
115 67
116 void insertAll(int index, Iterable<E> iterable) { 68 void insertAll(int index, Iterable<E> iterable) {
117 checkGrowable('insertAll'); 69 checkGrowable('insertAll');
118 IterableMixinWorkaround.insertAllList(this, index, iterable); 70 IterableMixinWorkaround.insertAllList(this, index, iterable);
119 } 71 }
120 72
121 void setAll(int index, Iterable<E> iterable) { 73 void setAll(int index, Iterable<E> iterable) {
122 checkMutable('setAll');
123 IterableMixinWorkaround.setAllList(this, index, iterable); 74 IterableMixinWorkaround.setAllList(this, index, iterable);
124 } 75 }
125 76
126 E removeLast() { 77 E removeLast() {
127 checkGrowable('removeLast'); 78 checkGrowable('removeLast');
128 if (length == 0) throw new RangeError.value(-1); 79 if (length == 0) throw new RangeError.value(-1);
129 return JS('var', r'#.pop()', this); 80 return JS('var', r'#.pop()', this);
130 } 81 }
131 82
132 bool remove(Object element) { 83 bool remove(Object element) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 } 189 }
239 if (end == null) { 190 if (end == null) {
240 end = length; 191 end = length;
241 } else { 192 } else {
242 if (end is !int) throw new ArgumentError(end); 193 if (end is !int) throw new ArgumentError(end);
243 if (end < start || end > length) { 194 if (end < start || end > length) {
244 throw new RangeError.range(end, start, length); 195 throw new RangeError.range(end, start, length);
245 } 196 }
246 } 197 }
247 if (start == end) return <E>[]; 198 if (start == end) return <E>[];
248 return new JSArray<E>.markGrowable( 199 return new JSArray<E>.typed(
249 JS('', r'#.slice(#, #)', this, start, end)); 200 JS('', r'#.slice(#, #)', this, start, end));
250 } 201 }
251 202
252 203
253 Iterable<E> getRange(int start, int end) { 204 Iterable<E> getRange(int start, int end) {
254 return new IterableMixinWorkaround<E>().getRangeList(this, start, end); 205 return new IterableMixinWorkaround<E>().getRangeList(this, start, end);
255 } 206 }
256 207
257 E get first { 208 E get first {
258 if (length > 0) return this[0]; 209 if (length > 0) return this[0];
(...skipping 22 matching lines...) Expand all
281 } 232 }
282 Lists.copy(this, 233 Lists.copy(this,
283 end, 234 end,
284 this, 235 this,
285 start, 236 start,
286 receiverLength - end); 237 receiverLength - end);
287 this.length = receiverLength - (end - start); 238 this.length = receiverLength - (end - start);
288 } 239 }
289 240
290 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { 241 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
291 checkMutable('set range');
292 IterableMixinWorkaround.setRangeList(this, start, end, iterable, skipCount); 242 IterableMixinWorkaround.setRangeList(this, start, end, iterable, skipCount);
293 } 243 }
294 244
295 void fillRange(int start, int end, [E fillValue]) { 245 void fillRange(int start, int end, [E fillValue]) {
296 checkMutable('fill range');
297 IterableMixinWorkaround.fillRangeList(this, start, end, fillValue); 246 IterableMixinWorkaround.fillRangeList(this, start, end, fillValue);
298 } 247 }
299 248
300 void replaceRange(int start, int end, Iterable<E> iterable) { 249 void replaceRange(int start, int end, Iterable<E> iterable) {
301 checkGrowable('removeRange');
302 IterableMixinWorkaround.replaceRangeList(this, start, end, iterable); 250 IterableMixinWorkaround.replaceRangeList(this, start, end, iterable);
303 } 251 }
304 252
305 bool any(bool f(E element)) => IterableMixinWorkaround.any(this, f); 253 bool any(bool f(E element)) => IterableMixinWorkaround.any(this, f);
306 254
307 bool every(bool f(E element)) => IterableMixinWorkaround.every(this, f); 255 bool every(bool f(E element)) => IterableMixinWorkaround.every(this, f);
308 256
309 Iterable<E> get reversed => 257 Iterable<E> get reversed =>
310 new IterableMixinWorkaround<E>().reversedList(this); 258 new IterableMixinWorkaround<E>().reversedList(this);
311 259
312 void sort([int compare(E a, E b)]) { 260 void sort([int compare(E a, E b)]) {
313 checkMutable('sort');
314 IterableMixinWorkaround.sortList(this, compare); 261 IterableMixinWorkaround.sortList(this, compare);
315 } 262 }
316 263
317 void shuffle([Random random]) { 264 void shuffle([Random random]) {
318 IterableMixinWorkaround.shuffleList(this, random); 265 IterableMixinWorkaround.shuffleList(this, random);
319 } 266 }
320 267
321 int indexOf(Object element, [int start = 0]) { 268 int indexOf(Object element, [int start = 0]) {
322 return IterableMixinWorkaround.indexOfList(this, element, start); 269 return IterableMixinWorkaround.indexOfList(this, element, start);
323 } 270 }
324 271
325 int lastIndexOf(Object element, [int start]) { 272 int lastIndexOf(Object element, [int start]) {
326 return IterableMixinWorkaround.lastIndexOfList(this, element, start); 273 return IterableMixinWorkaround.lastIndexOfList(this, element, start);
327 } 274 }
328 275
329 bool contains(Object other) { 276 bool contains(Object other) {
330 for (int i = 0; i < length; i++) { 277 for (int i = 0; i < length; i++) {
331 if (this[i] == other) return true; 278 if (this[i] == other) return true;
332 } 279 }
333 return false; 280 return false;
334 } 281 }
335 282
336 bool get isEmpty => length == 0; 283 bool get isEmpty => length == 0;
337 284
338 bool get isNotEmpty => !isEmpty; 285 bool get isNotEmpty => !isEmpty;
339 286
340 String toString() => ListBase.listToString(this); 287 String toString() => ListBase.listToString(this);
341 288
342 List<E> toList({ bool growable: true }) { 289 List<E> toList({ bool growable: true }) {
343 if (growable) { 290 var list = JS('', '#.slice()', this);
344 return new JSArray<E>.markGrowable(JS('', '#.slice()', this)); 291 if (!growable) markFixedList(list);
345 } else { 292 return new JSArray<E>.typed(list);
346 return new JSArray<E>.markFixed(JS('', '#.slice()', this));
347 }
348 } 293 }
349 294
350 Set<E> toSet() => new Set<E>.from(this); 295 Set<E> toSet() => new Set<E>.from(this);
351 296
352 Iterator<E> get iterator => new ListIterator<E>(this); 297 Iterator<E> get iterator => new ListIterator<E>(this);
353 298
354 int get hashCode => Primitives.objectHashCode(this); 299 int get hashCode => Primitives.objectHashCode(this);
355 300
356 int get length => JS('JSUInt32', r'#.length', this); 301 int get length => JS('JSUInt32', r'#.length', this);
357 302
358 void set length(int newLength) { 303 void set length(int newLength) {
359 if (newLength is !int) throw new ArgumentError(newLength); 304 if (newLength is !int) throw new ArgumentError(newLength);
360 if (newLength < 0) throw new RangeError.value(newLength); 305 if (newLength < 0) throw new RangeError.value(newLength);
361 checkGrowable('set length'); 306 checkGrowable('set length');
362 JS('void', r'#.length = #', this, newLength); 307 JS('void', r'#.length = #', this, newLength);
363 } 308 }
364 309
365 E operator [](int index) { 310 E operator [](int index) {
366 if (index is !int) throw new ArgumentError(index); 311 if (index is !int) throw new ArgumentError(index);
367 if (index >= length || index < 0) throw new RangeError.value(index); 312 if (index >= length || index < 0) throw new RangeError.value(index);
368 return JS('var', '#[#]', this, index); 313 return JS('var', '#[#]', this, index);
369 } 314 }
370 315
371 void operator []=(int index, E value) { 316 void operator []=(int index, E value) {
372 checkMutable('indexed set');
373 if (index is !int) throw new ArgumentError(index); 317 if (index is !int) throw new ArgumentError(index);
374 if (index >= length || index < 0) throw new RangeError.value(index); 318 if (index >= length || index < 0) throw new RangeError.value(index);
375 JS('void', r'#[#] = #', this, index, value); 319 JS('void', r'#[#] = #', this, index, value);
376 } 320 }
377 321
378 Map<int, E> asMap() { 322 Map<int, E> asMap() {
379 return new IterableMixinWorkaround<E>().asMapList(this); 323 return new IterableMixinWorkaround<E>().asMapList(this);
380 } 324 }
381 } 325 }
382 326
383 /** 327 /**
384 * Dummy subclasses that allow the backend to track more precise 328 * Dummy subclasses that allow the backend to track more precise
385 * information about arrays through their type. The CPA type inference 329 * information about arrays through their type. The CPA type inference
386 * relies on the fact that these classes do not override [] nor []=. 330 * relies on the fact that these classes do not override [] nor []=.
387 */ 331 */
388 class JSMutableArray<E> extends JSArray<E> implements JSMutableIndexable {} 332 class JSMutableArray<E> extends JSArray<E> implements JSMutableIndexable {}
389 class JSFixedArray<E> extends JSMutableArray<E> {} 333 class JSFixedArray<E> extends JSMutableArray<E> {}
390 class JSExtendableArray<E> extends JSMutableArray<E> {} 334 class JSExtendableArray<E> extends JSMutableArray<E> {}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698