// 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 {
type LoadJoinElementFn = builtin(Context, JSReceiver, uintptr) => JSAny;

// Fast C call to write a fixed array (see Buffer.fixedArray) to a single
// string.
extern macro
ArrayBuiltinsAssembler::CallJSArrayArrayJoinConcatToSequentialString(
    FixedArray, intptr, String, String): String;

transitioning builtin LoadJoinElement<T : type extends ElementsKind>(
    context: Context, receiver: JSReceiver, k: uintptr): JSAny {
  return GetProperty(receiver, Convert<Number>(k));
}

transitioning LoadJoinElement<array::DictionaryElements>(
    context: Context, receiver: JSReceiver, k: uintptr): JSAny {
  const array: JSArray = UnsafeCast<JSArray>(receiver);
  const dict: NumberDictionary = UnsafeCast<NumberDictionary>(array.elements);
  try {
    return BasicLoadNumberDictionaryElement(dict, Signed(k))
        otherwise IfNoData, IfHole;
  } label IfNoData deferred {
    return GetProperty(receiver, Convert<Number>(k));
  } label IfHole {
    return kEmptyString;
  }
}

LoadJoinElement<array::FastSmiOrObjectElements>(
    context: Context, receiver: JSReceiver, k: uintptr): JSAny {
  const array: JSArray = UnsafeCast<JSArray>(receiver);
  const fixedArray: FixedArray = UnsafeCast<FixedArray>(array.elements);
  const element: Object = fixedArray.objects[k];
  return element == TheHole ? kEmptyString : UnsafeCast<JSAny>(element);
}

LoadJoinElement<array::FastDoubleElements>(
    context: Context, receiver: JSReceiver, k: uintptr): JSAny {
  const array: JSArray = UnsafeCast<JSArray>(receiver);
  const fixedDoubleArray: FixedDoubleArray =
      UnsafeCast<FixedDoubleArray>(array.elements);
  const element: float64 =
      fixedDoubleArray.floats[k].Value() otherwise return kEmptyString;
  return AllocateHeapNumberWithValue(element);
}

builtin LoadJoinTypedElement<T : type extends ElementsKind>(
    context: Context, receiver: JSReceiver, k: uintptr): JSAny {
  const typedArray: JSTypedArray = UnsafeCast<JSTypedArray>(receiver);
  assert(!IsDetachedBuffer(typedArray.buffer));
  return typed_array::LoadFixedTypedArrayElementAsTagged(
      typedArray.data_ptr, k, typed_array::KindForArrayType<T>());
}

transitioning builtin ConvertToLocaleString(
    context: Context, element: JSAny, locales: JSAny, options: JSAny): String {
  if (IsNullOrUndefined(element)) return kEmptyString;

  const prop: JSAny = GetProperty(element, 'toLocaleString');
  try {
    const callable: Callable = Cast<Callable>(prop) otherwise TypeError;
    let result: JSAny;
    if (IsNullOrUndefined(locales)) {
      result = Call(context, callable, element);
    } else if (IsNullOrUndefined(options)) {
      result = Call(context, callable, element, locales);
    } else {
      result = Call(context, callable, element, locales, options);
    }
    return ToString_Inline(result);
  } label TypeError {
    ThrowTypeError(MessageTemplate::kCalledNonCallable, prop);
  }
}

// Verifies the current element JSArray accessor can still be safely used
// (see LoadJoinElement<ElementsAccessor>).
macro CannotUseSameArrayAccessor<T: type>(implicit context: Context)(
    loadFn: LoadJoinElementFn, receiver: JSReceiver, originalMap: Map,
    originalLen: Number): bool;

CannotUseSameArrayAccessor<JSArray>(implicit context: Context)(
    loadFn: LoadJoinElementFn, receiver: JSReceiver, originalMap: Map,
    originalLen: Number): bool {
  if (loadFn == LoadJoinElement<array::GenericElementsAccessor>) return false;

  const array: JSArray = UnsafeCast<JSArray>(receiver);
  if (originalMap != array.map) return true;
  if (originalLen != array.length) return true;
  if (IsNoElementsProtectorCellInvalid()) return true;
  return false;
}

CannotUseSameArrayAccessor<JSTypedArray>(implicit context: Context)(
    _loadFn: LoadJoinElementFn, receiver: JSReceiver, _initialMap: Map,
    _initialLen: Number): bool {
  const typedArray: JSTypedArray = UnsafeCast<JSTypedArray>(receiver);
  return IsDetachedBuffer(typedArray.buffer);
}

// Calculates the running total length of the resulting string.  If the
// calculated length exceeds the maximum string length (see
// String::kMaxLength), throws a range error.
macro AddStringLength(implicit context: Context)(
    lenA: intptr, lenB: intptr): intptr {
  try {
    const length: intptr = TryIntPtrAdd(lenA, lenB) otherwise IfOverflow;
    if (length > kStringMaxLength) goto IfOverflow;
    return length;
  } label IfOverflow deferred {
    ThrowInvalidStringLength(context);
  }
}

// Stores an element to a fixed array and return the fixed array. If the fixed
// array is not large enough, create and return a new, larger fixed array that
// contains all previously elements and the new element.
macro StoreAndGrowFixedArray<T: type>(
    fixedArray: FixedArray, index: intptr, element: T): FixedArray {
  const length: intptr = fixedArray.length_intptr;
  assert(index <= length);
  if (index < length) {
    fixedArray.objects[index] = element;
    return fixedArray;
  } else
    deferred {
      const newLength: intptr = CalculateNewElementsCapacity(length);
      assert(index < newLength);
      const newfixedArray: FixedArray =
          ExtractFixedArray(fixedArray, 0, length, newLength);
      newfixedArray.objects[index] = element;
      return newfixedArray;
    }
}

// Contains the information necessary to create a single, separator delimited,
// flattened one or two byte string.
// The buffer is maintained and updated by Buffer.constructor, Buffer.Add(),
// Buffer.AddSeparators().
struct Buffer {
  macro Add(implicit context: Context)(
      str: String, nofSeparators: intptr, separatorLength: intptr) {
    // Add separators if necessary (at the beginning or more than one)
    const writeSeparators: bool = this.index == 0 | nofSeparators > 1;
    this.AddSeparators(nofSeparators, separatorLength, writeSeparators);

    this.totalStringLength =
        AddStringLength(this.totalStringLength, str.length_intptr);
    this.fixedArray =
        StoreAndGrowFixedArray(this.fixedArray, this.index++, str);
    this.isOneByte =
        IsOneByteStringInstanceType(str.instanceType) & this.isOneByte;
  }

  macro AddSeparators(implicit context: Context)(
      nofSeparators: intptr, separatorLength: intptr, write: bool) {
    if (nofSeparators == 0 || separatorLength == 0) return;

    const nofSeparatorsInt: intptr = nofSeparators;
    const sepsLen: intptr = separatorLength * nofSeparatorsInt;
    // Detect integer overflow
    // TODO(tebbi): Replace with overflow-checked multiplication.
    if (sepsLen / separatorLength != nofSeparatorsInt) deferred {
        ThrowInvalidStringLength(context);
      }

    this.totalStringLength = AddStringLength(this.totalStringLength, sepsLen);
    if (write) deferred {
        this.fixedArray = StoreAndGrowFixedArray(
            this.fixedArray, this.index++, Convert<Smi>(nofSeparatorsInt));
      }
  }

  // Fixed array holding elements that are either:
  //   1) String result of `ToString(next)`.
  //   2) Smi representing the number of consecutive separators.
  // `BufferJoin()` will iterate and writes these entries to a flat string.
  //
  // To save space, reduce reads and writes, only separators at the beginning,
  // end, or more than one are written.
  //
  // No hole example
  //   receiver:   ['hello', 'world']
  //   fixedArray: ['hello', 'world']
  //
  // Hole example
  //   receiver:   [<hole>, 'hello', <hole>, 'world', <hole>]
  //   fixedArray: [1, 'hello', 2, 'world', 1]
  fixedArray: FixedArray;

  // Index to insert a new entry into `fixedArray`.
  index: intptr;

  // Running total of the resulting string length.
  totalStringLength: intptr;

  // `true` if the separator and all strings in the buffer are one-byte,
  // otherwise `false`.
  isOneByte: bool;
}

macro NewBuffer(len: uintptr, sep: String): Buffer {
  const cappedBufferSize: intptr = len > kMaxNewSpaceFixedArrayElements ?
      kMaxNewSpaceFixedArrayElements :
      Signed(len);
  assert(cappedBufferSize > 0);
  return Buffer{
    fixedArray: AllocateZeroedFixedArray(cappedBufferSize),
    index: 0,
    totalStringLength: 0,
    isOneByte: IsOneByteStringInstanceType(sep.instanceType)
  };
}

macro BufferJoin(implicit context: Context)(
    buffer: Buffer, sep: String): String {
  assert(IsValidPositiveSmi(buffer.totalStringLength));
  if (buffer.totalStringLength == 0) return kEmptyString;

  // Fast path when there's only one buffer element.
  if (buffer.index == 1) {
    const fixedArray: FixedArray = buffer.fixedArray;
    typeswitch (fixedArray.objects[0]) {
      // When the element is a string, just return it and completely avoid
      // allocating another string.
      case (str: String): {
        return str;
      }

      // When the element is a smi, use StringRepeat to quickly build a memory
      // efficient separator repeated string.
      case (nofSeparators: Number): {
        return StringRepeat(context, sep, nofSeparators);
      }
      case (Object): {
        unreachable;
      }
    }
  }

  const length: uint32 = Convert<uint32>(Unsigned(buffer.totalStringLength));
  const r: String = buffer.isOneByte ? AllocateSeqOneByteString(length) :
                                       AllocateSeqTwoByteString(length);
  return CallJSArrayArrayJoinConcatToSequentialString(
      buffer.fixedArray, buffer.index, sep, r);
}

transitioning macro ArrayJoinImpl<T: type>(implicit context: Context)(
    receiver: JSReceiver, sep: String, lengthNumber: Number,
    useToLocaleString: constexpr bool, locales: JSAny, options: JSAny,
    initialLoadFn: LoadJoinElementFn): String {
  const initialMap: Map = receiver.map;
  const len: uintptr = Convert<uintptr>(lengthNumber);
  const separatorLength: intptr = sep.length_intptr;
  let nofSeparators: intptr = 0;
  let loadFn: LoadJoinElementFn = initialLoadFn;
  let buffer: Buffer = NewBuffer(len, sep);

  // 6. Let k be 0.
  let k: uintptr = 0;

  // 7. Repeat, while k < len
  while (k < len) {
    if (CannotUseSameArrayAccessor<T>(
            loadFn, receiver, initialMap, lengthNumber))
      deferred {
        loadFn = LoadJoinElement<array::GenericElementsAccessor>;
      }

    if (k > 0) {
      // a. If k > 0, let R be the string-concatenation of R and sep.
      nofSeparators = nofSeparators + 1;
    }

    // b. Let element be ? Get(O, ! ToString(k)).
    const element: JSAny = loadFn(context, receiver, k++);

    // c. If element is undefined or null, let next be the empty String;
    //    otherwise, let next be ? ToString(element).
    let next: String;
    if constexpr (useToLocaleString) {
      next = ConvertToLocaleString(context, element, locales, options);
      if (next == kEmptyString) continue;
    } else {
      typeswitch (element) {
        case (str: String): {
          if (str == kEmptyString) continue;
          next = str;
        }
        case (num: Number): {
          next = NumberToString(num);
        }
        case (obj: JSAny): {
          if (IsNullOrUndefined(obj)) continue;
          next = string::ToString(context, obj);
        }
      }
    }

    // d. Set R to the string-concatenation of R and next.
    buffer.Add(next, nofSeparators, separatorLength);
    nofSeparators = 0;
  }

  // Add any separators at the end.
  buffer.AddSeparators(nofSeparators, separatorLength, true);

  // 8. Return R.
  return BufferJoin(buffer, sep);
}

transitioning macro ArrayJoin<T: type>(implicit context: Context)(
    useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String,
    lenNumber: Number, locales: JSAny, options: JSAny): JSAny;

transitioning ArrayJoin<JSArray>(implicit context: Context)(
    useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String,
    lenNumber: Number, locales: JSAny, options: JSAny): JSAny {
  const map: Map = receiver.map;
  const kind: ElementsKind = map.elements_kind;
  let loadFn: LoadJoinElementFn;

  try {
    const array: JSArray = Cast<JSArray>(receiver) otherwise IfSlowPath;
    if (array.length != lenNumber) goto IfSlowPath;
    if (!IsPrototypeInitialArrayPrototype(map)) goto IfSlowPath;
    if (IsNoElementsProtectorCellInvalid()) goto IfSlowPath;

    if (IsElementsKindLessThanOrEqual(kind, ElementsKind::HOLEY_ELEMENTS)) {
      loadFn = LoadJoinElement<array::FastSmiOrObjectElements>;
    } else if (IsElementsKindLessThanOrEqual(
                   kind, ElementsKind::HOLEY_DOUBLE_ELEMENTS)) {
      loadFn = LoadJoinElement<array::FastDoubleElements>;
    } else if (kind == ElementsKind::DICTIONARY_ELEMENTS)
      deferred {
        const dict: NumberDictionary =
            UnsafeCast<NumberDictionary>(array.elements);
        const nofElements: Smi = GetNumberDictionaryNumberOfElements(dict);
        if (nofElements == 0) {
          if (sep == kEmptyString) return kEmptyString;
          try {
            const nofSeparators: Smi =
                Cast<Smi>(lenNumber - 1) otherwise IfNotSmi;
            return StringRepeat(context, sep, nofSeparators);
          } label IfNotSmi {
            ThrowInvalidStringLength(context);
          }
        } else {
          loadFn = LoadJoinElement<array::DictionaryElements>;
        }
      }
    else {
      goto IfSlowPath;
    }
  } label IfSlowPath {
    loadFn = LoadJoinElement<array::GenericElementsAccessor>;
  }
  return ArrayJoinImpl<JSArray>(
      receiver, sep, lenNumber, useToLocaleString, locales, options, loadFn);
}

transitioning ArrayJoin<JSTypedArray>(implicit context: Context)(
    useToLocaleString: constexpr bool, receiver: JSReceiver, sep: String,
    lenNumber: Number, locales: JSAny, options: JSAny): JSAny {
  const map: Map = receiver.map;
  const kind: ElementsKind = map.elements_kind;
  let loadFn: LoadJoinElementFn;

  if (IsElementsKindGreaterThan(kind, ElementsKind::UINT32_ELEMENTS)) {
    if (kind == ElementsKind::INT32_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::Int32Elements>;
    } else if (kind == ElementsKind::FLOAT32_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::Float32Elements>;
    } else if (kind == ElementsKind::FLOAT64_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::Float64Elements>;
    } else if (kind == ElementsKind::UINT8_CLAMPED_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::Uint8ClampedElements>;
    } else if (kind == ElementsKind::BIGUINT64_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::BigUint64Elements>;
    } else if (kind == ElementsKind::BIGINT64_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::BigInt64Elements>;
    } else {
      unreachable;
    }
  } else {
    if (kind == ElementsKind::UINT8_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::Uint8Elements>;
    } else if (kind == ElementsKind::INT8_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::Int8Elements>;
    } else if (kind == ElementsKind::UINT16_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::Uint16Elements>;
    } else if (kind == ElementsKind::INT16_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::Int16Elements>;
    } else if (kind == ElementsKind::UINT32_ELEMENTS) {
      loadFn = LoadJoinTypedElement<typed_array::Uint32Elements>;
    } else {
      unreachable;
    }
  }
  return ArrayJoinImpl<JSTypedArray>(
      receiver, sep, lenNumber, useToLocaleString, locales, options, loadFn);
}

// The Join Stack detects cyclical calls to Array Join builtins
// (Array.p.join(), Array.p.toString(), Array.p.toLocaleString()). This
// FixedArray holds a stack of receivers to the current call.
// CycleProtectedArrayJoin() is responsible for calling JoinStackPush and
// JoinStackPop when visiting and leaving a receiver, respectively.
const kMinJoinStackSize:
    constexpr int31 generates 'JSArray::kMinJoinStackSize';
macro LoadJoinStack(implicit context: Context)(): FixedArray
    labels IfUninitialized {
  typeswitch (*NativeContextSlot(ContextSlot::ARRAY_JOIN_STACK_INDEX)) {
    case (Undefined): {
      goto IfUninitialized;
    }
    case (stack: FixedArray): {
      return stack;
    }
  }
}

macro SetJoinStack(implicit context: Context)(stack: FixedArray): void {
  *NativeContextSlot(ContextSlot::ARRAY_JOIN_STACK_INDEX) = stack;
}

// Adds a receiver to the stack. The FixedArray will automatically grow to
// accommodate the receiver. If the receiver already exists on the stack,
// this indicates a cyclical call and False is returned.
builtin JoinStackPush(implicit context: Context)(
    stack: FixedArray, receiver: JSReceiver): Boolean {
  const capacity: intptr = stack.length_intptr;
  for (let i: intptr = 0; i < capacity; i++) {
    const previouslyVisited: Object = stack.objects[i];

    // Add `receiver` to the first open slot
    if (previouslyVisited == TheHole) {
      stack.objects[i] = receiver;
      return True;
    }

    // Detect cycles
    if (receiver == previouslyVisited) return False;
  }

  // If no open slots were found, grow the stack and add receiver to the end.
  const newStack: FixedArray =
      StoreAndGrowFixedArray(stack, capacity, receiver);
  SetJoinStack(newStack);
  return True;
}

// Fast path the common non-nested calls. If the receiver is not already on
// the stack, add it to the stack and return true. Otherwise return false.
macro JoinStackPushInline(implicit context: Context)(receiver: JSReceiver):
    bool {
  try {
    const stack: FixedArray = LoadJoinStack()
        otherwise IfUninitialized;
    if (stack.objects[0] == TheHole) {
      stack.objects[0] = receiver;
    } else if (JoinStackPush(stack, receiver) == False)
      deferred {
        return false;
      }
  } label IfUninitialized {
    const stack: FixedArray =
        AllocateFixedArrayWithHoles(kMinJoinStackSize, AllocationFlag::kNone);
    stack.objects[0] = receiver;
    SetJoinStack(stack);
  }
  return true;
}

// Removes a receiver from the stack. The FixedArray will automatically shrink
// to Heap::kMinJoinStackSize once the stack becomes empty.
builtin JoinStackPop(implicit context: Context)(
    stack: FixedArray, receiver: JSReceiver): JSAny {
  const len: intptr = stack.length_intptr;
  for (let i: intptr = 0; i < len; i++) {
    if (stack.objects[i] == receiver) {
      // Shrink the Join Stack if the stack will be empty and is larger than
      // the minimum size.
      if (i == 0 && len > kMinJoinStackSize) deferred {
          const newStack: FixedArray = AllocateFixedArrayWithHoles(
              kMinJoinStackSize, AllocationFlag::kNone);
          SetJoinStack(newStack);
        }
      else {
        stack.objects[i] = TheHole;
      }
      return Undefined;
    }
  }
  unreachable;
}

// Fast path the common non-nested calls.
macro JoinStackPopInline(implicit context: Context)(receiver: JSReceiver) {
  const stack: FixedArray = LoadJoinStack()
      otherwise unreachable;
  const len: intptr = stack.length_intptr;

  // Builtin call was not nested (receiver is the first entry) and
  // did not contain other nested arrays that expanded the stack.
  if (stack.objects[0] == receiver && len == kMinJoinStackSize) {
    StoreFixedArrayElement(stack, 0, TheHole, SKIP_WRITE_BARRIER);
  } else
    deferred {
      JoinStackPop(stack, receiver);
    }
}

// Main entry point for all builtins using Array Join functionality.
transitioning macro CycleProtectedArrayJoin<T: type>(
    implicit context: Context)(
    useToLocaleString: constexpr bool, o: JSReceiver, len: Number,
    sepObj: JSAny, locales: JSAny, options: JSAny): JSAny {
  // 3. If separator is undefined, let sep be the single-element String ",".
  // 4. Else, let sep be ? ToString(separator).
  const sep: String = sepObj == Undefined ? ',' : ToString_Inline(sepObj);

  // If the receiver is not empty and not already being joined, continue with
  // the normal join algorithm.
  if (len > 0 && JoinStackPushInline(o)) {
    try {
      const result: JSAny =
          ArrayJoin<T>(useToLocaleString, o, sep, len, locales, options);
      JoinStackPopInline(o);
      return result;
    } catch (e) deferred {
      JoinStackPopInline(o);
      ReThrow(context, e);
    }
  } else {
    return kEmptyString;
  }
}

// https://tc39.github.io/ecma262/#sec-array.prototype.join
transitioning javascript builtin
ArrayPrototypeJoin(
    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
  const separator: JSAny = arguments[0];

  // 1. Let O be ? ToObject(this value).
  const o: JSReceiver = ToObject_Inline(context, receiver);

  // 2. Let len be ? ToLength(? Get(O, "length")).
  const len: Number = GetLengthProperty(o);

  // Only handle valid array lengths. Although the spec allows larger
  // values, this matches historical V8 behavior.
  if (len > kMaxArrayIndex + 1)
    ThrowTypeError(MessageTemplate::kInvalidArrayLength);

  return CycleProtectedArrayJoin<JSArray>(
      false, o, len, separator, Undefined, Undefined);
}

// https://tc39.github.io/ecma262/#sec-array.prototype.tolocalestring
transitioning javascript builtin ArrayPrototypeToLocaleString(
    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
  const locales: JSAny = arguments[0];
  const options: JSAny = arguments[1];

  // 1. Let O be ? ToObject(this value).
  const o: JSReceiver = ToObject_Inline(context, receiver);

  // 2. Let len be ? ToLength(? Get(O, "length")).
  const len: Number = GetLengthProperty(o);

  // Only handle valid array lengths. Although the spec allows larger
  // values, this matches historical V8 behavior.
  if (len > kMaxArrayIndex + 1)
    ThrowTypeError(MessageTemplate::kInvalidArrayLength);

  return CycleProtectedArrayJoin<JSArray>(true, o, len, ',', locales, options);
}

// https://tc39.github.io/ecma262/#sec-array.prototype.tostring
transitioning javascript builtin ArrayPrototypeToString(
    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
  // 1. Let array be ? ToObject(this value).
  const array: JSReceiver = ToObject_Inline(context, receiver);

  // 2. Let func be ? Get(array, "join").
  const prop: JSAny = GetProperty(array, 'join');
  try {
    // 3. If IsCallable(func) is false, let func be the intrinsic function
    //    %ObjProto_toString%.
    const func: Callable = Cast<Callable>(prop) otherwise NotCallable;

    // 4. Return ? Call(func, array).
    return Call(context, func, array);
  } label NotCallable {
    return ObjectToString(context, array);
  }
}

// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.join
transitioning javascript builtin TypedArrayPrototypeJoin(
    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
  const separator: JSAny = arguments[0];

  // Spec: ValidateTypedArray is applied to the this value prior to evaluating
  // the algorithm.
  const typedArray: JSTypedArray = typed_array::ValidateTypedArray(
      context, receiver, '%TypedArray%.prototype.join');
  const length = Convert<Number>(typedArray.length);

  return CycleProtectedArrayJoin<JSTypedArray>(
      false, typedArray, length, separator, Undefined, Undefined);
}

// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.tolocalestring
transitioning javascript builtin TypedArrayPrototypeToLocaleString(
    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
  const locales: JSAny = arguments[0];
  const options: JSAny = arguments[1];

  // Spec: ValidateTypedArray is applied to the this value prior to evaluating
  // the algorithm.
  const typedArray: JSTypedArray = typed_array::ValidateTypedArray(
      context, receiver, '%TypedArray%.prototype.toLocaleString');
  const length = Convert<Number>(typedArray.length);

  return CycleProtectedArrayJoin<JSTypedArray>(
      true, typedArray, length, ',', locales, options);
}
}
