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

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

Issue 1470193002: Array/TypedArray/ArrayBuffer method subclassing and @@species (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 11 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 | « src/js/runtime.js ('k') | src/messages.h » ('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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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) { 5 (function(global, utils) {
6 6
7 "use strict"; 7 "use strict";
8 8
9 %CheckIsBootstrapping(); 9 %CheckIsBootstrapping();
10 10
11 // ------------------------------------------------------------------- 11 // -------------------------------------------------------------------
12 // Imports 12 // Imports
13 13
14 var ArrayFrom; 14 var ArrayFrom;
15 var ArrayToString; 15 var ArrayToString;
16 var ArrayValues; 16 var ArrayValues;
17 var GlobalArray = global.Array; 17 var GlobalArray = global.Array;
18 var GlobalArrayBuffer = global.ArrayBuffer; 18 var GlobalArrayBuffer = global.ArrayBuffer;
19 var GlobalDataView = global.DataView; 19 var GlobalDataView = global.DataView;
20 var GlobalObject = global.Object; 20 var GlobalObject = global.Object;
21 var InternalArray = utils.InternalArray;
21 var InnerArrayCopyWithin; 22 var InnerArrayCopyWithin;
22 var InnerArrayEvery; 23 var InnerArrayEvery;
23 var InnerArrayFill; 24 var InnerArrayFill;
24 var InnerArrayFilter; 25 var InnerArrayFilter;
25 var InnerArrayFind; 26 var InnerArrayFind;
26 var InnerArrayFindIndex; 27 var InnerArrayFindIndex;
27 var InnerArrayForEach; 28 var InnerArrayForEach;
28 var InnerArrayIncludes; 29 var InnerArrayIncludes;
29 var InnerArrayIndexOf; 30 var InnerArrayIndexOf;
30 var InnerArrayJoin; 31 var InnerArrayJoin;
31 var InnerArrayLastIndexOf; 32 var InnerArrayLastIndexOf;
32 var InnerArrayReduce; 33 var InnerArrayReduce;
33 var InnerArrayReduceRight; 34 var InnerArrayReduceRight;
34 var InnerArraySome; 35 var InnerArraySome;
35 var InnerArraySort; 36 var InnerArraySort;
36 var InnerArrayToLocaleString; 37 var InnerArrayToLocaleString;
37 var InternalArray = utils.InternalArray; 38 var InternalArray = utils.InternalArray;
38 var IsNaN; 39 var IsNaN;
39 var MakeRangeError; 40 var MakeRangeError;
40 var MakeTypeError; 41 var MakeTypeError;
41 var MaxSimple; 42 var MaxSimple;
42 var MinSimple; 43 var MinSimple;
43 var PackedArrayReverse; 44 var PackedArrayReverse;
45 var SpeciesConstructor;
44 var ToPositiveInteger; 46 var ToPositiveInteger;
45 var iteratorSymbol = utils.ImportNow("iterator_symbol"); 47 var iteratorSymbol = utils.ImportNow("iterator_symbol");
46 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); 48 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
47 49
48 macro TYPED_ARRAYS(FUNCTION) 50 macro TYPED_ARRAYS(FUNCTION)
49 // arrayIds below should be synchronized with Runtime_TypedArrayInitialize. 51 // arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
50 FUNCTION(1, Uint8Array, 1) 52 FUNCTION(1, Uint8Array, 1)
51 FUNCTION(2, Int8Array, 1) 53 FUNCTION(2, Int8Array, 1)
52 FUNCTION(3, Uint16Array, 2) 54 FUNCTION(3, Uint16Array, 2)
53 FUNCTION(4, Int16Array, 2) 55 FUNCTION(4, Int16Array, 2)
(...skipping 26 matching lines...) Expand all
80 InnerArrayJoin = from.InnerArrayJoin; 82 InnerArrayJoin = from.InnerArrayJoin;
81 InnerArrayLastIndexOf = from.InnerArrayLastIndexOf; 83 InnerArrayLastIndexOf = from.InnerArrayLastIndexOf;
82 InnerArrayReduce = from.InnerArrayReduce; 84 InnerArrayReduce = from.InnerArrayReduce;
83 InnerArrayReduceRight = from.InnerArrayReduceRight; 85 InnerArrayReduceRight = from.InnerArrayReduceRight;
84 InnerArraySome = from.InnerArraySome; 86 InnerArraySome = from.InnerArraySome;
85 InnerArraySort = from.InnerArraySort; 87 InnerArraySort = from.InnerArraySort;
86 InnerArrayToLocaleString = from.InnerArrayToLocaleString; 88 InnerArrayToLocaleString = from.InnerArrayToLocaleString;
87 IsNaN = from.IsNaN; 89 IsNaN = from.IsNaN;
88 MakeRangeError = from.MakeRangeError; 90 MakeRangeError = from.MakeRangeError;
89 MakeTypeError = from.MakeTypeError; 91 MakeTypeError = from.MakeTypeError;
90 MakeTypeError = from.MakeTypeError;
91 MaxSimple = from.MaxSimple;
92 MaxSimple = from.MaxSimple; 92 MaxSimple = from.MaxSimple;
93 MinSimple = from.MinSimple; 93 MinSimple = from.MinSimple;
94 MinSimple = from.MinSimple;
95 PackedArrayReverse = from.PackedArrayReverse; 94 PackedArrayReverse = from.PackedArrayReverse;
95 SpeciesConstructor = from.SpeciesConstructor;
96 ToPositiveInteger = from.ToPositiveInteger; 96 ToPositiveInteger = from.ToPositiveInteger;
97 }); 97 });
98 98
99 // --------------- Typed Arrays --------------------- 99 // --------------- Typed Arrays ---------------------
100 100
101 function TypedArrayDefaultConstructor(typedArray) {
102 switch (%_ClassOf(typedArray)) {
103 macro TYPED_ARRAY_CONSTRUCTOR_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
104 case "NAME":
105 return GlobalNAME;
106 endmacro
107 TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR_CASE)
108 }
109 // The TypeError should not be generated since all callers should
110 // have already called ValidateTypedArray.
111 throw MakeTypeError(kIncompatibleMethodReceiver,
112 "TypedArrayDefaultConstructor", this);
113 }
114
115 function TypedArrayCreate(constructor, arg0, arg1, arg2, skipCheckLength) {
116 if (IS_UNDEFINED(arg1)) {
117 var newTypedArray = new constructor(arg0);
118 } else {
119 var newTypedArray = new constructor(arg0, arg1, arg2);
120 }
121 if (!%_IsTypedArray(newTypedArray)) throw MakeTypeError(kNotTypedArray);
122 // TODO(littledan): Check for being detached, here and elsewhere
123 if (!skipCheckLength && %_TypedArrayGetLength(newTypedArray) < arg0) {
124 throw MakeTypeError(kTypedArrayTooShort);
125 }
126 return newTypedArray;
127 }
128
129 function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2, skipCheckLength) {
130 var defaultConstructor = TypedArrayDefaultConstructor(exemplar);
131 var constructor = SpeciesConstructor(exemplar, defaultConstructor);
132 return TypedArrayCreate(constructor, arg0, arg1, arg2, skipCheckLength);
133 }
134
101 macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) 135 macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
102 function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) { 136 function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
103 if (!IS_UNDEFINED(byteOffset)) { 137 if (!IS_UNDEFINED(byteOffset)) {
104 byteOffset = ToPositiveInteger(byteOffset, kInvalidTypedArrayLength); 138 byteOffset = ToPositiveInteger(byteOffset, kInvalidTypedArrayLength);
105 } 139 }
106 if (!IS_UNDEFINED(length)) { 140 if (!IS_UNDEFINED(length)) {
107 length = ToPositiveInteger(length, kInvalidTypedArrayLength); 141 length = ToPositiveInteger(length, kInvalidTypedArrayLength);
108 } 142 }
109 143
110 var bufferByteLength = %_ArrayBufferGetByteLength(buffer); 144 var bufferByteLength = %_ArrayBufferGetByteLength(buffer);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 } 237 }
204 238
205 function NAMEConstructor(arg1, arg2, arg3) { 239 function NAMEConstructor(arg1, arg2, arg3) {
206 if (!IS_UNDEFINED(new.target)) { 240 if (!IS_UNDEFINED(new.target)) {
207 if (IS_ARRAYBUFFER(arg1) || IS_SHAREDARRAYBUFFER(arg1)) { 241 if (IS_ARRAYBUFFER(arg1) || IS_SHAREDARRAYBUFFER(arg1)) {
208 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3); 242 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3);
209 } else if (IS_NUMBER(arg1) || IS_STRING(arg1) || 243 } else if (IS_NUMBER(arg1) || IS_STRING(arg1) ||
210 IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) { 244 IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) {
211 NAMEConstructByLength(this, arg1); 245 NAMEConstructByLength(this, arg1);
212 } else { 246 } else {
247 // TODO(littledan): If arg1 is a TypedArray, follow the constructor
248 // path in ES2015 22.2.4.3, and call SpeciesConstructor, in a
249 // path that seems to be an optimized version of what's below, but
250 // in an observably different way.
213 var iteratorFn = arg1[iteratorSymbol]; 251 var iteratorFn = arg1[iteratorSymbol];
214 if (IS_UNDEFINED(iteratorFn) || iteratorFn === ArrayValues) { 252 if (IS_UNDEFINED(iteratorFn) || iteratorFn === ArrayValues) {
215 NAMEConstructByArrayLike(this, arg1); 253 NAMEConstructByArrayLike(this, arg1);
216 } else { 254 } else {
217 NAMEConstructByIterable(this, arg1, iteratorFn); 255 NAMEConstructByIterable(this, arg1, iteratorFn);
218 } 256 }
219 } 257 }
220 } else { 258 } else {
221 throw MakeTypeError(kConstructorNotFunction, "NAME") 259 throw MakeTypeError(kConstructorNotFunction, "NAME")
222 } 260 }
(...skipping 21 matching lines...) Expand all
244 endInt = MinSimple(endInt, srcLength); 282 endInt = MinSimple(endInt, srcLength);
245 } 283 }
246 284
247 if (endInt < beginInt) { 285 if (endInt < beginInt) {
248 endInt = beginInt; 286 endInt = beginInt;
249 } 287 }
250 288
251 var newLength = endInt - beginInt; 289 var newLength = endInt - beginInt;
252 var beginByteOffset = 290 var beginByteOffset =
253 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE; 291 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE;
254 return new GlobalNAME(%TypedArrayGetBuffer(this), 292 return TypedArraySpeciesCreate(this, %TypedArrayGetBuffer(this),
255 beginByteOffset, newLength); 293 beginByteOffset, newLength, true);
256 } 294 }
257 endmacro 295 endmacro
258 296
259 TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR) 297 TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR)
260 298
261 function TypedArraySubArray(begin, end) { 299 function TypedArraySubArray(begin, end) {
262 switch (%_ClassOf(this)) { 300 switch (%_ClassOf(this)) {
263 macro TYPED_ARRAY_SUBARRAY_CASE(ARRAY_ID, NAME, ELEMENT_SIZE) 301 macro TYPED_ARRAY_SUBARRAY_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
264 case "NAME": 302 case "NAME":
265 return %_Call(NAMESubArray, this, begin, end); 303 return %_Call(NAMESubArray, this, begin, end);
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 } 451 }
414 452
415 function TypedArrayGetToStringTag() { 453 function TypedArrayGetToStringTag() {
416 if (!%_IsTypedArray(this)) return; 454 if (!%_IsTypedArray(this)) return;
417 var name = %_ClassOf(this); 455 var name = %_ClassOf(this);
418 if (IS_UNDEFINED(name)) return; 456 if (IS_UNDEFINED(name)) return;
419 return name; 457 return name;
420 } 458 }
421 459
422 460
423 function ConstructTypedArray(constructor, arg) {
424 // TODO(littledan): This is an approximation of the spec, which requires
425 // that only real TypedArray classes should be accepted (22.2.2.1.1)
426 if (!%IsConstructor(constructor) || IS_UNDEFINED(constructor.prototype) ||
427 !%HasOwnProperty(constructor.prototype, "BYTES_PER_ELEMENT")) {
428 throw MakeTypeError(kNotTypedArray);
429 }
430
431 // TODO(littledan): The spec requires that, rather than directly calling
432 // the constructor, a TypedArray is created with the proper proto and
433 // underlying size and element size, and elements are put in one by one.
434 // By contrast, this would allow subclasses to make a radically different
435 // constructor with different semantics.
436 return new constructor(arg);
437 }
438
439
440 function ConstructTypedArrayLike(typedArray, arg) {
441 // TODO(littledan): The spec requires that we actuallly use
442 // typedArray.constructor[Symbol.species] (bug v8:4093)
443 // Also, it should default to the default constructor from
444 // table 49 if typedArray.constructor doesn't exist.
445 return ConstructTypedArray(typedArray.constructor, arg);
446 }
447
448
449 function TypedArrayCopyWithin(target, start, end) { 461 function TypedArrayCopyWithin(target, start, end) {
450 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); 462 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
451 463
452 var length = %_TypedArrayGetLength(this); 464 var length = %_TypedArrayGetLength(this);
453 465
454 // TODO(littledan): Replace with a memcpy for better performance 466 // TODO(littledan): Replace with a memcpy for better performance
455 return InnerArrayCopyWithin(target, start, end, this, length); 467 return InnerArrayCopyWithin(target, start, end, this, length);
456 } 468 }
457 %FunctionSetLength(TypedArrayCopyWithin, 2); 469 %FunctionSetLength(TypedArrayCopyWithin, 2);
458 470
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 504
493 // ES6 draft 07-15-13, section 22.2.3.9 505 // ES6 draft 07-15-13, section 22.2.3.9
494 function TypedArrayFilter(f, thisArg) { 506 function TypedArrayFilter(f, thisArg) {
495 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); 507 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
496 508
497 var length = %_TypedArrayGetLength(this); 509 var length = %_TypedArrayGetLength(this);
498 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); 510 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
499 var result = new InternalArray(); 511 var result = new InternalArray();
500 InnerArrayFilter(f, thisArg, this, length, result); 512 InnerArrayFilter(f, thisArg, this, length, result);
501 var captured = result.length; 513 var captured = result.length;
502 var output = ConstructTypedArrayLike(this, captured); 514 var output = TypedArraySpeciesCreate(this, captured);
503 for (var i = 0; i < captured; i++) { 515 for (var i = 0; i < captured; i++) {
504 output[i] = result[i]; 516 output[i] = result[i];
505 } 517 }
506 return output; 518 return output;
507 } 519 }
508 %FunctionSetLength(TypedArrayFilter, 1); 520 %FunctionSetLength(TypedArrayFilter, 1);
509 521
510 522
511 // ES6 draft 07-15-13, section 22.2.3.10 523 // ES6 draft 07-15-13, section 22.2.3.10
512 function TypedArrayFind(predicate, thisArg) { 524 function TypedArrayFind(predicate, thisArg) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 %_ArgumentsLength()); 606 %_ArgumentsLength());
595 } 607 }
596 %FunctionSetLength(TypedArrayLastIndexOf, 1); 608 %FunctionSetLength(TypedArrayLastIndexOf, 1);
597 609
598 610
599 // ES6 draft 07-15-13, section 22.2.3.18 611 // ES6 draft 07-15-13, section 22.2.3.18
600 function TypedArrayMap(f, thisArg) { 612 function TypedArrayMap(f, thisArg) {
601 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); 613 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
602 614
603 var length = %_TypedArrayGetLength(this); 615 var length = %_TypedArrayGetLength(this);
604 var result = ConstructTypedArrayLike(this, length); 616 var result = TypedArraySpeciesCreate(this, length);
605 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f); 617 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
606 for (var i = 0; i < length; i++) { 618 for (var i = 0; i < length; i++) {
607 var element = this[i]; 619 var element = this[i];
608 result[i] = %_Call(f, thisArg, element, i, this); 620 result[i] = %_Call(f, thisArg, element, i, this);
609 } 621 }
610 return result; 622 return result;
611 } 623 }
612 %FunctionSetLength(TypedArrayMap, 1); 624 %FunctionSetLength(TypedArrayMap, 1);
613 625
614 626
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 } 704 }
693 705
694 var final; 706 var final;
695 if (relativeEnd < 0) { 707 if (relativeEnd < 0) {
696 final = MaxSimple(len + relativeEnd, 0); 708 final = MaxSimple(len + relativeEnd, 0);
697 } else { 709 } else {
698 final = MinSimple(relativeEnd, len); 710 final = MinSimple(relativeEnd, len);
699 } 711 }
700 712
701 var count = MaxSimple(final - k, 0); 713 var count = MaxSimple(final - k, 0);
702 var array = ConstructTypedArrayLike(this, count); 714 var array = TypedArraySpeciesCreate(this, count);
703 // The code below is the 'then' branch; the 'else' branch species 715 // The code below is the 'then' branch; the 'else' branch species
704 // a memcpy. Because V8 doesn't canonicalize NaN, the difference is 716 // a memcpy. Because V8 doesn't canonicalize NaN, the difference is
705 // unobservable. 717 // unobservable.
706 var n = 0; 718 var n = 0;
707 while (k < final) { 719 while (k < final) {
708 var kValue = this[k]; 720 var kValue = this[k];
709 // TODO(littledan): The spec says to throw on an error in setting;
710 // does this throw?
711 array[n] = kValue; 721 array[n] = kValue;
712 k++; 722 k++;
713 n++; 723 n++;
714 } 724 }
715 return array; 725 return array;
716 } 726 }
717 727
718 728
719 // ES2016 draft, section 22.2.3.14 729 // ES2016 draft, section 22.2.3.14
720 function TypedArrayIncludes(searchElement, fromIndex) { 730 function TypedArrayIncludes(searchElement, fromIndex) {
721 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); 731 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
722 732
723 var length = %_TypedArrayGetLength(this); 733 var length = %_TypedArrayGetLength(this);
724 734
725 return InnerArrayIncludes(searchElement, fromIndex, this, length); 735 return InnerArrayIncludes(searchElement, fromIndex, this, length);
726 } 736 }
727 %FunctionSetLength(TypedArrayIncludes, 1); 737 %FunctionSetLength(TypedArrayIncludes, 1);
728 738
729 739
730 // ES6 draft 08-24-14, section 22.2.2.2 740 // ES6 draft 08-24-14, section 22.2.2.2
731 function TypedArrayOf() { 741 function TypedArrayOf() {
732 var length = %_ArgumentsLength(); 742 var length = %_ArgumentsLength();
733 var array = new this(length); 743 var array = TypedArrayCreate(this, length);
734 for (var i = 0; i < length; i++) { 744 for (var i = 0; i < length; i++) {
735 array[i] = %_Arguments(i); 745 array[i] = %_Arguments(i);
736 } 746 }
737 return array; 747 return array;
738 } 748 }
739 749
740 750
741 function TypedArrayFrom(source, mapfn, thisArg) { 751 function TypedArrayFrom(source, mapfn, thisArg) {
742 // TODO(littledan): Investigate if there is a receiver which could be 752 // TODO(littledan): Investigate if there is a receiver which could be
743 // faster to accumulate on than Array, e.g., a TypedVector. 753 // faster to accumulate on than Array, e.g., a TypedVector.
754 // TODO(littledan): Rewrite this code to ensure that things happen
755 // in the write order, e.g., the constructor needs to be called before
756 // the mapping function on array-likes.
744 var array = %_Call(ArrayFrom, GlobalArray, source, mapfn, thisArg); 757 var array = %_Call(ArrayFrom, GlobalArray, source, mapfn, thisArg);
745 return ConstructTypedArray(this, array); 758 return TypedArrayCreate(this, array, UNDEFINED, UNDEFINED, true);
746 } 759 }
747 %FunctionSetLength(TypedArrayFrom, 1); 760 %FunctionSetLength(TypedArrayFrom, 1);
748 761
749 function TypedArray() { 762 function TypedArray() {
750 if (IS_UNDEFINED(new.target)) { 763 if (IS_UNDEFINED(new.target)) {
751 throw MakeTypeError(kConstructorNonCallable, "TypedArray"); 764 throw MakeTypeError(kConstructorNonCallable, "TypedArray");
752 } 765 }
753 if (new.target === TypedArray) { 766 if (new.target === TypedArray) {
754 throw MakeTypeError(kConstructAbstractClass, "TypedArray"); 767 throw MakeTypeError(kConstructAbstractClass, "TypedArray");
755 } 768 }
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 "setUint32", DataViewSetUint32JS, 957 "setUint32", DataViewSetUint32JS,
945 958
946 "getFloat32", DataViewGetFloat32JS, 959 "getFloat32", DataViewGetFloat32JS,
947 "setFloat32", DataViewSetFloat32JS, 960 "setFloat32", DataViewSetFloat32JS,
948 961
949 "getFloat64", DataViewGetFloat64JS, 962 "getFloat64", DataViewGetFloat64JS,
950 "setFloat64", DataViewSetFloat64JS 963 "setFloat64", DataViewSetFloat64JS
951 ]); 964 ]);
952 965
953 }) 966 })
OLDNEW
« no previous file with comments | « src/js/runtime.js ('k') | src/messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698