blob: 1aadee1bba3add0f32efe39d7b9507c3ea31d213 [file] [log] [blame]
// 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.
module array {
extern builtin ArrayUnshift(Context, JSFunction, Object, int32);
macro TryFastArrayUnshift(
context: Context, receiver: Object, arguments: constexpr Arguments): never
labels Slow {
EnsureFastJSArray(context, receiver) otherwise Slow;
const array: JSArray = unsafe_cast<JSArray>(receiver);
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));
}
macro GenericArrayUnshift(
context: Context, receiver: Object,
arguments: constexpr 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(context, object);
// 3. Let argCount be the number of actual arguments.
const arg_count: Smi = convert<Smi>(arguments.length);
// 4. If argCount > 0, then.
if (arg_count > 0) {
// a. If len + argCount > 2**53 - 1, throw a TypeError exception.
if (length + arg_count > kMaxSafeInteger) {
ThrowTypeError(context, 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 + arg_count - 1;
// iii. Let fromPresent be ? HasProperty(O, from).
const from_present: Boolean = HasProperty(context, object, from);
// iv. If fromPresent is true, then
if (from_present == True) {
// 1. Let fromValue be ? Get(O, from).
const from_value: Object = GetProperty(context, object, from);
// 2. Perform ? Set(O, to, fromValue, true).
SetProperty(context, object, to, from_value);
} else {
// 1. Perform ? DeletePropertyOrThrow(O, to).
DeleteProperty(context, object, to, 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 < arg_count) {
// ii .Perform ? Set(O, ! ToString(j), E, true).
SetProperty(context, object, j, arguments[convert<intptr>(j)]);
// iii. Increase j by 1.
++j;
}
}
// 5. Perform ? Set(O, "length", len + argCount, true).
const new_length: Number = length + arg_count;
SetProperty(context, object, kLengthString, new_length);
// 6. Return length + arg_count.
return new_length;
}
// https://tc39.github.io/ecma262/#sec-array.prototype.unshift
javascript builtin ArrayPrototypeUnshift(
context: Context, receiver: Object, ...arguments): Object {
try {
TryFastArrayUnshift(context, receiver, arguments) otherwise Baseline;
}
label Baseline {
return GenericArrayUnshift(context, receiver, arguments);
}
}
}