blob: 18e0f936fb8e0a385b80891dd073d13a7dd038bd [file] [log] [blame]
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
import 'dart:js_interop';
/// `_JSList` acts as a wrapper around a JS list object providing an interface to
/// access the list items and list length while also allowing us to specify the
/// list item type from outside.
extension type _JSList<T extends JSObject>(JSObject _) implements JSObject {
/// The **`item()`** method returns the [JSObject]
/// at the specified index in the list.
external T item(int index);
/// The **`length`** read-only property indicates the number of
/// items in a given list.
external int get length;
}
/// A wrapper to present a JS immutable list of type `T` and list item type `U` as
/// a `List<U>`.
class JSImmutableListWrapper<T extends JSObject, U extends JSObject>
with ListMixin<U> {
final _JSList<U> _jsList;
JSImmutableListWrapper(T original) : _jsList = _JSList<U>(original);
@override
int get length => _jsList.length;
@override
U operator [](int index) {
if (index > length) {
throw IndexError.withLength(index, length, indexable: this);
}
return _jsList.item(index);
}
@override
void operator []=(int index, U value) {
throw UnsupportedError('Cannot assign element of immutable List.');
}
@override
set length(int value) {
throw UnsupportedError('Cannot resize immutable List.');
}
@override
U get first {
if (length > 0) return _jsList.item(0);
throw StateError('No elements');
}
@override
U get last {
final len = length;
if (len > 0) return _jsList.item(len - 1);
throw StateError('No elements');
}
@override
U get single {
if (length > 1) throw StateError('More than one element');
return first;
}
@override
U elementAt(int index) => this[index];
}