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

Side by Side Diff: src/js/array.js

Issue 2164923002: Make toLocaleString on arrays always call toLocaleString on its elements. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 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
« no previous file with comments | « no previous file | test/mjsunit/array-tostring.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 (function(global, utils, extrasUtils) { 5 (function(global, utils, extrasUtils) {
6 6
7 "use strict"; 7 "use strict";
8 8
9 %CheckIsBootstrapping(); 9 %CheckIsBootstrapping();
10 10
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 return new constructor(length); 43 return new constructor(length);
44 } 44 }
45 45
46 46
47 function KeySortCompare(a, b) { 47 function KeySortCompare(a, b) {
48 return a - b; 48 return a - b;
49 } 49 }
50 50
51 function GetSortedArrayKeys(array, indices) { 51 function GetSortedArrayKeys(array, indices) {
52 if (IS_NUMBER(indices)) { 52 if (IS_NUMBER(indices)) {
53 var keys = new InternalArray();
54 // It's an interval 53 // It's an interval
55 var limit = indices; 54 var limit = indices;
55 var keys = new InternalArray();
56 for (var i = 0; i < limit; ++i) { 56 for (var i = 0; i < limit; ++i) {
57 var e = array[i]; 57 var e = array[i];
58 if (!IS_UNDEFINED(e) || i in array) { 58 if (!IS_UNDEFINED(e) || i in array) {
59 keys.push(i); 59 keys.push(i);
60 } 60 }
61 } 61 }
62 return keys; 62 return keys;
63 } 63 }
64 return InnerArraySort(indices, indices.length, KeySortCompare); 64 return InnerArraySort(indices, indices.length, KeySortCompare);
65 } 65 }
66 66
67 67
68 function SparseJoinWithSeparatorJS(array, keys, length, convert, separator) { 68 function SparseJoinWithSeparatorJS(array, keys, length, use_locale, separator) {
69 var keys_length = keys.length; 69 var keys_length = keys.length;
70 var elements = new InternalArray(keys_length * 2); 70 var elements = new InternalArray(keys_length * 2);
71 for (var i = 0; i < keys_length; i++) { 71 for (var i = 0; i < keys_length; i++) {
72 var key = keys[i]; 72 var key = keys[i];
73 var e = array[key];
74 elements[i * 2] = key; 73 elements[i * 2] = key;
75 elements[i * 2 + 1] = IS_STRING(e) ? e : convert(e); 74 elements[i * 2 + 1] = ConvertToString(use_locale, array[key]);
76 } 75 }
77 return %SparseJoinWithSeparator(elements, length, separator); 76 return %SparseJoinWithSeparator(elements, length, separator);
78 } 77 }
79 78
80 79
81 // Optimized for sparse arrays if separator is ''. 80 // Optimized for sparse arrays if separator is ''.
82 function SparseJoin(array, keys, convert) { 81 function SparseJoin(array, keys, use_locale) {
83 var keys_length = keys.length; 82 var keys_length = keys.length;
84 var elements = new InternalArray(keys_length); 83 var elements = new InternalArray(keys_length);
85 for (var i = 0; i < keys_length; i++) { 84 for (var i = 0; i < keys_length; i++) {
86 var e = array[keys[i]]; 85 elements[i] = ConvertToString(use_locale, array[keys[i]]);
87 elements[i] = IS_STRING(e) ? e : convert(e);
88 } 86 }
89 return %StringBuilderConcat(elements, keys_length, ''); 87 return %StringBuilderConcat(elements, keys_length, '');
90 } 88 }
91 89
92 90
93 function UseSparseVariant(array, length, is_array, touched) { 91 function UseSparseVariant(array, length, is_array, touched) {
94 // Only use the sparse variant on arrays that are likely to be sparse and the 92 // Only use the sparse variant on arrays that are likely to be sparse and the
95 // number of elements touched in the operation is relatively small compared to 93 // number of elements touched in the operation is relatively small compared to
96 // the overall size of the array. 94 // the overall size of the array.
97 if (!is_array || length < 1000 || %HasComplexElements(array)) { 95 if (!is_array || length < 1000 || %HasComplexElements(array)) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 for (var i = 0; i < length; i++) { 128 for (var i = 0; i < length; i++) {
131 if (values[i] === v) return true; 129 if (values[i] === v) return true;
132 } 130 }
133 return false; 131 return false;
134 } 132 }
135 133
136 // Global list of arrays visited during toString, toLocaleString and 134 // Global list of arrays visited during toString, toLocaleString and
137 // join invocations. 135 // join invocations.
138 var visited_arrays = new Stack(); 136 var visited_arrays = new Stack();
139 137
140 function DoJoin(array, length, is_array, separator, convert) { 138 function DoJoin(array, length, is_array, separator, use_locale) {
141 if (UseSparseVariant(array, length, is_array, length)) { 139 if (UseSparseVariant(array, length, is_array, length)) {
142 %NormalizeElements(array); 140 %NormalizeElements(array);
143 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, length)); 141 var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, length));
144 if (separator === '') { 142 if (separator === '') {
145 if (keys.length === 0) return ''; 143 if (keys.length === 0) return '';
146 return SparseJoin(array, keys, convert); 144 return SparseJoin(array, keys, use_locale);
147 } else { 145 } else {
148 return SparseJoinWithSeparatorJS(array, keys, length, convert, separator); 146 return SparseJoinWithSeparatorJS(
147 array, keys, length, use_locale, separator);
149 } 148 }
150 } 149 }
151 150
152 // Fast case for one-element arrays. 151 // Fast case for one-element arrays.
153 if (length === 1) { 152 if (length === 1) {
154 var e = array[0]; 153 return ConvertToString(use_locale, array[0]);
155 return IS_STRING(e) ? e : convert(e);
156 } 154 }
157 155
158 // Construct an array for the elements. 156 // Construct an array for the elements.
159 var elements = new InternalArray(length); 157 var elements = new InternalArray(length);
158 for (var i = 0; i < length; i++) {
159 elements[i] = ConvertToString(use_locale, array[i]);
160 }
160 161
161 // We pull the empty separator check outside the loop for speed!
162 if (separator === '') { 162 if (separator === '') {
163 for (var i = 0; i < length; i++) {
164 var e = array[i];
165 elements[i] = IS_STRING(e) ? e : convert(e);
166 }
167 return %StringBuilderConcat(elements, length, ''); 163 return %StringBuilderConcat(elements, length, '');
164 } else {
165 return %StringBuilderJoin(elements, length, separator);
168 } 166 }
169 // Non-empty separator case.
170 // If the first element is a number then use the heuristic that the
171 // remaining elements are also likely to be numbers.
172 var e = array[0];
173 if (IS_NUMBER(e)) {
174 elements[0] = %_NumberToString(e);
175 for (var i = 1; i < length; i++) {
176 e = array[i];
177 if (IS_NUMBER(e)) {
178 elements[i] = %_NumberToString(e);
179 } else {
180 elements[i] = IS_STRING(e) ? e : convert(e);
181 }
182 }
183 } else {
184 elements[0] = IS_STRING(e) ? e : convert(e);
185 for (var i = 1; i < length; i++) {
186 e = array[i];
187 elements[i] = IS_STRING(e) ? e : convert(e);
188 }
189 }
190 return %StringBuilderJoin(elements, length, separator);
191 } 167 }
192 168
193 function Join(array, length, separator, convert) { 169 function Join(array, length, separator, use_locale) {
194 if (length === 0) return ''; 170 if (length === 0) return '';
195 171
196 var is_array = IS_ARRAY(array); 172 var is_array = IS_ARRAY(array);
197 173
198 if (is_array) { 174 if (is_array) {
199 // If the array is cyclic, return the empty string for already 175 // If the array is cyclic, return the empty string for already
200 // visited arrays. 176 // visited arrays.
201 if (StackHas(visited_arrays, array)) return ''; 177 if (StackHas(visited_arrays, array)) return '';
202 StackPush(visited_arrays, array); 178 StackPush(visited_arrays, array);
203 } 179 }
204 180
205 // Attempt to convert the elements. 181 // Attempt to convert the elements.
206 try { 182 try {
207 return DoJoin(array, length, is_array, separator, convert); 183 return DoJoin(array, length, is_array, separator, use_locale);
208 } finally { 184 } finally {
209 // Make sure to remove the last element of the visited array no 185 // Make sure to remove the last element of the visited array no
210 // matter what happens. 186 // matter what happens.
211 if (is_array) StackPop(visited_arrays); 187 if (is_array) StackPop(visited_arrays);
212 } 188 }
213 } 189 }
214 190
215 191
216 function ConvertToString(x) { 192 function ConvertToString(use_locale, x) {
217 if (IS_NULL_OR_UNDEFINED(x)) return ''; 193 if (IS_NULL_OR_UNDEFINED(x)) return '';
218 return TO_STRING(x); 194 return TO_STRING(use_locale ? x.toLocaleString() : x);
219 } 195 }
220 196
221 197
222 function ConvertToLocaleString(e) {
223 if (IS_NULL_OR_UNDEFINED(e)) return '';
224 return TO_STRING(e.toLocaleString());
225 }
226
227
228 // This function implements the optimized splice implementation that can use 198 // This function implements the optimized splice implementation that can use
229 // special array operations to handle sparse arrays in a sensible fashion. 199 // special array operations to handle sparse arrays in a sensible fashion.
230 function SparseSlice(array, start_i, del_count, len, deleted_elements) { 200 function SparseSlice(array, start_i, del_count, len, deleted_elements) {
231 // Move deleted elements to a new array (the return value from splice). 201 // Move deleted elements to a new array (the return value from splice).
232 var indices = %GetArrayKeys(array, start_i + del_count); 202 var indices = %GetArrayKeys(array, start_i + del_count);
233 if (IS_NUMBER(indices)) { 203 if (IS_NUMBER(indices)) {
234 var limit = indices; 204 var limit = indices;
235 for (var i = start_i; i < limit; ++i) { 205 for (var i = start_i; i < limit; ++i) {
236 var current = array[i]; 206 var current = array[i];
237 if (!IS_UNDEFINED(current) || i in array) { 207 if (!IS_UNDEFINED(current) || i in array) {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 331
362 // ------------------------------------------------------------------- 332 // -------------------------------------------------------------------
363 333
364 334
365 function ArrayToString() { 335 function ArrayToString() {
366 var array; 336 var array;
367 var func; 337 var func;
368 if (IS_ARRAY(this)) { 338 if (IS_ARRAY(this)) {
369 func = this.join; 339 func = this.join;
370 if (func === ArrayJoin) { 340 if (func === ArrayJoin) {
371 return Join(this, this.length, ',', ConvertToString); 341 return Join(this, this.length, ',', false);
372 } 342 }
373 array = this; 343 array = this;
374 } else { 344 } else {
375 array = TO_OBJECT(this); 345 array = TO_OBJECT(this);
376 func = array.join; 346 func = array.join;
377 } 347 }
378 if (!IS_CALLABLE(func)) { 348 if (!IS_CALLABLE(func)) {
379 return %_Call(ObjectToString, array); 349 return %_Call(ObjectToString, array);
380 } 350 }
381 return %_Call(func, array); 351 return %_Call(func, array);
382 } 352 }
383 353
384 354
385 function InnerArrayToLocaleString(array, length) { 355 function InnerArrayToLocaleString(array, length) {
386 var len = TO_LENGTH(length); 356 return Join(array, TO_LENGTH(length), ',', true);
387 if (len === 0) return "";
388 return Join(array, len, ',', ConvertToLocaleString);
389 } 357 }
390 358
391 359
392 function ArrayToLocaleString() { 360 function ArrayToLocaleString() {
393 var array = TO_OBJECT(this); 361 var array = TO_OBJECT(this);
394 var arrayLen = array.length; 362 var arrayLen = array.length;
395 return InnerArrayToLocaleString(array, arrayLen); 363 return InnerArrayToLocaleString(array, arrayLen);
396 } 364 }
397 365
398 366
399 function InnerArrayJoin(separator, array, length) { 367 function InnerArrayJoin(separator, array, length) {
400 if (IS_UNDEFINED(separator)) { 368 if (IS_UNDEFINED(separator)) {
401 separator = ','; 369 separator = ',';
402 } else { 370 } else {
403 separator = TO_STRING(separator); 371 separator = TO_STRING(separator);
404 } 372 }
405 373
406 // Fast case for one-element arrays. 374 // Fast case for one-element arrays.
407 if (length === 1) { 375 if (length === 1) {
408 var e = array[0]; 376 var e = array[0];
409 if (IS_NULL_OR_UNDEFINED(e)) return ''; 377 if (IS_NULL_OR_UNDEFINED(e)) return '';
410 return TO_STRING(e); 378 return TO_STRING(e);
411 } 379 }
412 380
413 return Join(array, length, separator, ConvertToString); 381 return Join(array, length, separator, false);
414 } 382 }
415 383
416 384
417 function ArrayJoin(separator) { 385 function ArrayJoin(separator) {
418 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join"); 386 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join");
419 387
420 var array = TO_OBJECT(this); 388 var array = TO_OBJECT(this);
421 var length = TO_LENGTH(array.length); 389 var length = TO_LENGTH(array.length);
422 390
423 return InnerArrayJoin(separator, array, length); 391 return InnerArrayJoin(separator, array, length);
(...skipping 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after
1778 %InstallToContext([ 1746 %InstallToContext([
1779 "array_pop", ArrayPop, 1747 "array_pop", ArrayPop,
1780 "array_push", ArrayPush, 1748 "array_push", ArrayPush,
1781 "array_shift", ArrayShift, 1749 "array_shift", ArrayShift,
1782 "array_splice", ArraySplice, 1750 "array_splice", ArraySplice,
1783 "array_slice", ArraySlice, 1751 "array_slice", ArraySlice,
1784 "array_unshift", ArrayUnshift, 1752 "array_unshift", ArrayUnshift,
1785 ]); 1753 ]);
1786 1754
1787 }); 1755 });
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/array-tostring.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698