| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| namespace array { |
| extern builtin ArrayUnshift(Context, JSFunction, JSAny, int32): JSAny; |
| |
| transitioning macro GenericArrayUnshift( |
| context: Context, receiver: JSAny, arguments: Arguments): Number { |
| // 1. Let O be ? ToObject(this value). |
| const object: JSReceiver = ToObject_Inline(context, receiver); |
| |
| // 2. Let len be ? ToLength(? Get(O, "length")). |
| const length: Number = GetLengthProperty(object); |
| |
| // 3. Let argCount be the number of actual arguments. |
| const argCount: Smi = Convert<Smi>(arguments.length); |
| |
| // 4. If argCount > 0, then. |
| if (argCount > 0) { |
| // a. If len + argCount > 2**53 - 1, throw a TypeError exception. |
| if (length + argCount > kMaxSafeInteger) { |
| ThrowTypeError(MessageTemplate::kInvalidArrayLength); |
| } |
| |
| // b. Let k be len. |
| let k: Number = length; |
| |
| // c. Repeat, while k > 0. |
| while (k > 0) { |
| // i. Let from be ! ToString(k - 1). |
| const from: Number = k - 1; |
| |
| // ii. Let to be ! ToString(k + argCount - 1). |
| const to: Number = k + argCount - 1; |
| |
| // iii. Let fromPresent be ? HasProperty(O, from). |
| const fromPresent: Boolean = HasProperty(object, from); |
| |
| // iv. If fromPresent is true, then |
| if (fromPresent == True) { |
| // 1. Let fromValue be ? Get(O, from). |
| const fromValue: JSAny = GetProperty(object, from); |
| |
| // 2. Perform ? Set(O, to, fromValue, true). |
| SetProperty(object, to, fromValue); |
| } else { |
| // 1. Perform ? DeletePropertyOrThrow(O, to). |
| DeleteProperty(object, to, LanguageMode::kStrict); |
| } |
| |
| // vi. Decrease k by 1. |
| --k; |
| } |
| |
| // d. Let j be 0. |
| let j: Smi = 0; |
| |
| // e. Let items be a List whose elements are, in left to right order, |
| // the arguments that were passed to this function invocation. |
| // f. Repeat, while items is not empty |
| while (j < argCount) { |
| // ii .Perform ? Set(O, ! ToString(j), E, true). |
| SetProperty(object, j, arguments[Convert<intptr>(j)]); |
| |
| // iii. Increase j by 1. |
| ++j; |
| } |
| } |
| |
| // 5. Perform ? Set(O, "length", len + argCount, true). |
| const newLength: Number = length + argCount; |
| SetProperty(object, kLengthString, newLength); |
| |
| // 6. Return length + argCount. |
| return newLength; |
| } |
| |
| // https://tc39.github.io/ecma262/#sec-array.prototype.unshift |
| transitioning javascript builtin ArrayPrototypeUnshift( |
| js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { |
| try { |
| const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow; |
| array::EnsureWriteableFastElements(array); |
| |
| const map: Map = array.map; |
| if (!IsExtensibleMap(map)) goto Slow; |
| EnsureArrayLengthWritable(map) otherwise Slow; |
| |
| tail ArrayUnshift( |
| context, LoadTargetFromFrame(), Undefined, |
| Convert<int32>(arguments.length)); |
| } label Slow { |
| return GenericArrayUnshift(context, receiver, arguments); |
| } |
| } |
| } |