Make @Array(size) a bytecode intrinsic
[WebKit-https.git] / Source / JavaScriptCore / builtins / ArrayConstructor.js
1 /*
2  * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 function of(/* items... */)
27 {
28     "use strict";
29
30     var length = arguments.length;
31     var array = @isConstructor(this) ? new this(length) : @newArrayWithSize(length);
32     for (var k = 0; k < length; ++k)
33         @putByValDirect(array, k, arguments[k]);
34     array.length = length;
35     return array;
36 }
37
38 function from(items /*, mapFn, thisArg */)
39 {
40     "use strict";
41
42     var thisObj = this;
43
44     var mapFn = arguments.length > 1 ? arguments[1] : @undefined;
45
46     var thisArg;
47
48     if (mapFn !== @undefined) {
49         if (typeof mapFn !== "function")
50             throw new @TypeError("Array.from requires that the second argument, when provided, be a function");
51
52         if (arguments.length > 2)
53             thisArg = arguments[2];
54     }
55
56     if (items == null)
57         throw new @TypeError("Array.from requires an array-like object - not null or undefined");
58
59     var iteratorMethod = items.@iteratorSymbol;
60     if (iteratorMethod != null) {
61         if (typeof iteratorMethod !== "function")
62             throw new @TypeError("Array.from requires that the property of the first argument, items[Symbol.iterator], when exists, be a function");
63
64         var result = @isConstructor(thisObj) ? new thisObj() : [];
65
66         var k = 0;
67         var iterator = iteratorMethod.@call(items);
68
69         // Since for-of loop once more looks up the @@iterator property of a given iterable,
70         // it could be observable if the user defines a getter for @@iterator.
71         // To avoid this situation, we define a wrapper object that @@iterator just returns a given iterator.
72         var wrapper = {}
73         wrapper.@iteratorSymbol = function() { return iterator; };
74
75         for (var value of wrapper) {
76             if (mapFn)
77                 @putByValDirect(result, k, thisArg === @undefined ? mapFn(value, k) : mapFn.@call(thisArg, value, k));
78             else
79                 @putByValDirect(result, k, value);
80             k += 1;
81         }
82
83         result.length = k;
84         return result;
85     }
86
87     var arrayLike = @Object(items);
88     var arrayLikeLength = @toLength(arrayLike.length);
89
90     var result = @isConstructor(thisObj) ? new thisObj(arrayLikeLength) : @newArrayWithSize(arrayLikeLength);
91
92     var k = 0;
93     while (k < arrayLikeLength) {
94         var value = arrayLike[k];
95         if (mapFn)
96             @putByValDirect(result, k, thisArg === @undefined ? mapFn(value, k) : mapFn.@call(thisArg, value, k));
97         else
98             @putByValDirect(result, k, value);
99         k += 1;
100     }
101
102     result.length = arrayLikeLength;
103     return result;
104 }