Commit graph

485 commits

Author SHA1 Message Date
Andreas Kling
f10e850644 HashTable: Assert on iteration attempt over table during clear/rehash
It doesn't seem sane to try to iterate over a HashTable while it's in
the middle of being cleared. Since this might cause strange problems,
this patch adds an assertion if an iterator is constructed during
clear() or rehash() of a HashTable.
2019-07-31 10:23:24 +02:00
Robin Burchell
a82c60b22a Add Result<>, to use with/complement Error
An operation often has two pieces of underlying information:

* the data returned as a result from that operation
* an error that occurred while retrieving that data

Merely returning the data is not good enough. Result<> allows exposing
both the data, and the underlying error, and forces (via clang's
consumable attribute) you to check for the error before you try to
access the data.
2019-07-31 09:06:39 +02:00
Robin Burchell
7dd25141cd Add Error<>
Put simply, Error<> is a way of forcing error handling onto an API user.

Given a function like:

    bool might_work();

The following code might have been written previously:

    might_work(); // but what if it didn't?

The easy way to work around this is of course to [[nodiscard]] might_work.
But this doesn't work for more complex cases like, for instance, a
hypothetical read() function which might return one of _many_ errors
(typically signalled with an int, let's say).

    int might_read();

In such a case, the result is often _read_, but not properly handled. Like:

    return buffer.substr(0, might_read()); // but what if might_read returned an error?

This is where Error<> comes in:

    typedef Error<int, 0> ReadError;
    ReadError might_read();

    auto res = might_read();
    if (might_read.failed()) {
        switch (res.value()) {
        case EBADF:
            ...
        }
    }

Error<> uses clang's consumable attributes to force failed() to be
checked on an Error instance. If it's not checked, then you get smacked.
2019-07-31 09:06:39 +02:00
Robin Burchell
28362fcc57 Optional: Add consumable checks
These will, when building with clang, prevent using Optional::value
without first checking Optional::has_value() - at compile time.
2019-07-31 09:06:39 +02:00
rhin123
a175e76948 TextEditor: Include extension during SaveAs
When we save-as in the text editor we now auto-populate GFilePicker /w
the current name & extension.
2019-07-29 20:46:31 +02:00
Andreas Kling
57c29491a3 Kernel+AK: Remove AK/StdLibExtras.cpp, moving kernel stuff to Kernel/.
We had some kernel-specific gizmos in AK that should really just be in the
Kernel subdirectory instead. The only thing remaining after moving those
was mmx_memcpy() which I moved to the ARCH(i386)-specific section of
LibC/string.cpp.
2019-07-29 11:58:44 +02:00
Andreas Kling
66db6f4f92 AK: Add Queue::clear() to clear out a Queue. 2019-07-28 21:34:47 +02:00
Andreas Kling
6f397e23f1 ByteBuffer: Add slice_view(). Works like slice() but makes a wrapper only.
So we already have ByteBuffer::wrap() which is like a StringView for random
data. This might not be the best abstraction actually, but this will be
immediately useful so let's add it.
2019-07-27 15:26:51 +02:00
Andreas Kling
2f373a27a2 AK: Add RELEASE_ASSERT in non-Serenity builds. 2019-07-26 22:15:54 +02:00
Andreas Kling
fc9a1a1328 AK: Fix NonnullRefPtr<T>::operator=(NonnullRefPtr<U>). 2019-07-26 08:04:33 +02:00
Andreas Kling
6ae95945aa AK: Add ScopedValueRollback::set_override_rollback_value().
This can be used if you change your mind about what value we should roll
back to. :^)
2019-07-25 15:21:16 +02:00
Andreas Kling
9fb2a65716 AK: Rename ValueRestorer => ScopedValueRollback.
Qt had a pretty good name for this concept, so let's steal it. :^)
2019-07-25 15:15:46 +02:00
Andreas Kling
1bd3fca585 AK: Shim open_with_path_length() for non-Serenity builds.
This is pretty ugly but I don't want to *not* use open_with_path_length()
so let's just shim it.
2019-07-25 14:25:45 +02:00
Andreas Kling
7c8debfe46 AK: Don't compile mmx_memcpy() outside of ARCH(I386). 2019-07-25 14:25:33 +02:00
Andreas Kling
afc638c3ab AK: Allow NonnullRefPtr::ptr() when in "unknown" typestate.
Clang loses the typestate when passing NonnullRefPtr's via lambda captures.
This is unfortunate, but not much we can do about it. Allowing ptr() makes
it possible to use captured NonnullRefPtrs as you'd expect.
2019-07-25 11:51:24 +02:00
Andreas Kling
6a5446d6dd AK: Simplify NonnullPtrVector template a bit.
Add an "ElementType" typedef to NonnullOwnPtr and NonnullRefPtr to allow
clients to easily find the pointee type. Then use this to remove a template
argument from NonnullPtrVector. :^)
2019-07-25 11:10:28 +02:00
Andreas Kling
10d120dc85 AK: Share code between NonnullOwnPtrVector and NonnullRefPtrVector.
These can just inherit from a shared base template. Thanks to Robin for the
sweet idea :^)
2019-07-25 11:00:26 +02:00
Andreas Kling
0846986cac LogStream: Preserve errno for the lifetime of a LogStream object. 2019-07-25 07:00:33 +02:00
Andreas Kling
1d0b464618 AK: Make HashMap::get(Key) return an Optional<Value>.
This allows HashMap::get() to be used for value types that cannot be default
constructed (e.g NonnullOwnPtr.)
2019-07-24 10:25:43 +02:00
Andreas Kling
1686c4906b AK: Delete Vector::resize() from Nonnull{Own,Ref}PtrVector.
It's not possible to grow one of these vectors beyond what's already in them
since it's not possible to default-construct Nonnull{Own,Ref}Ptr.

Add Vector::shrink() which can be used when you want to shrink the Vector
and delete resize() from the specialized Vectors.
2019-07-24 09:33:26 +02:00
Andreas Kling
a635e62e6a AK: Add NonnullOwnPtrVector.
This works just like NonnullRefPtr, except for NonnullOwnPtr's instead.
NonnullOwnPtrVector<T> inherits from Vector<NonnullOwnPtr<T>>, and adds some
comforts on top, like making accessors return T& so we can chase dots (.)
instead of arrows (->) :^)
2019-07-24 08:49:44 +02:00
Andreas Kling
28da5b002f AK: Add NonnullOwnPtr.
This is just like OwnPtr (also single-owner), except it cannot be null.

NonnullOwnPtr is perfect as the return type of functions that never need to
return nullptr.

It's also useful as an argument type to encode the fact that the argument
must not be nullptr.

The make<Foo>() helper is changed to return NonnullOwnPtr<Foo>.

Note: You can move() out of a NonnullOwnPtr, and after that the object is
in an invalid state. Internally it will be a nullptr at this point, so we'll
still catch misuse, but the only thing that should be done in this state
is running the destructor. I've used consumable annotations to generate some
warnings when using a NonnullOwnPtr after moving from it, but these only
work when compiling with clang, so be aware of that.
2019-07-24 08:32:11 +02:00
Andreas Kling
ecc35876af AK: Move clang-specific consumable annotation helpers to Platform.h 2019-07-24 08:16:59 +02:00
Andreas Kling
adb7b1bc4c AK: Add Optional::value_or(T).
This is like value() but with a fallback in case there's no value set.
2019-07-24 07:26:02 +02:00
Andreas Kling
facfaa50df AK: Remove unused Vector::shift_left().
I was using this for a makeshift queue, but now there is AK::Queue.
2019-07-21 21:46:03 +02:00
Andreas Kling
af81645a2a Kernel+LibC: Add a dbgputstr() syscall for sending strings to debug output.
This is very handy for the DebugLogStream implementation, among others. :^)
2019-07-21 21:43:37 +02:00
Robin Burchell
a3213659dd AK: Run host tests on make
Restructure the makefile a little so it only builds objects once, and
then run them on make clean.

This is a little slower (since we're relinking tests each makeall), but
it also ensures that it will work.
2019-07-21 18:48:44 +02:00
Andreas Kling
29a62558c4 AK: Fix off-by-one in Vector::prepend(Vector&&).
Caught by valgrind's uninitialized access checks on the Vector unit test.
Yay for finding bugs with valgrind on the unit tests! :^)
2019-07-21 12:55:39 +02:00
Andreas Kling
20c6edc976 AK: Make NonnullRefPtr::operator=(NonnullRefPtr<U>&&) cast incoming pointer.
Same as the RefPtr issue I just fixed. This makes it possible to assign a
NonnullRefPtr<Derived>&& to a NonnullRefPtr<Base>.
2019-07-21 12:55:39 +02:00
Robin Burchell
a9db382f0e TestSuite: Don't leak the suite instance
Makes checking for leaks more straightforward
2019-07-21 11:51:10 +02:00
Robin Burchell
fc479d1e20 TestSuite: instance() -> the(), and return a reference
To be more consistent with the rest of the codebase
2019-07-21 11:51:10 +02:00
Andreas Kling
fa6f601170 AK: RefPtr::operator=(RefPtr<U>&&) needs to cast the incoming pointer.
Otherwise it's not possible to assign a RefPtr<Derived>&& to a RefPtr<Base>.
2019-07-21 11:37:24 +02:00
Andreas Kling
aeae1cb5e2 AK: Add a unit test for Vector::prepend(Vector&&) with complex T.
It's good to verify that complex objects can be moved nicely by Vector.
2019-07-21 11:35:41 +02:00
Andreas Kling
4179283562 AK: Add some basic unit tests for WeakPtr. 2019-07-21 11:34:31 +02:00
Andreas Kling
2fedf36276 TestSuite: Make tests actually run (oops!)
We were not actually running any of the unit tests, only getting a pointer
to them. Thankfully they all pass, even after we start running them. :^)
2019-07-21 11:27:55 +02:00
Andreas Kling
67654ec529 AK: Add Vector::prepend(Vector&&).
Also included a good boy unit test.
2019-07-20 16:10:52 +02:00
Robin Burchell
53262cd08b AK: Introduce IntrusiveList
And use it in the scheduler.

IntrusiveList is similar to InlineLinkedList, except that rather than
making assertions about the type (and requiring inheritance), it
provides an IntrusiveListNode type that can be used to put an instance
into many different lists at once.

As a proof of concept, port the scheduler over to use it. The only
downside here is that the "list" global needs to know the position of
the IntrusiveListNode member, so we have to position things a little
awkwardly to make that happen. We also move the runnable lists to
Thread, to avoid having to publicize the node.
2019-07-19 15:42:30 +02:00
Robin Burchell
7de79d3bbb ELFImage: Sprinkle some constification love 2019-07-18 13:22:51 +02:00
Andreas Kling
f60d7e5d1f JsonValue: Add to_uint(), to_int() and as_double().
The to_foo() functions are for converting when you might not be sure of the
underlying value type. The as_foo() family assumes that you know exactly
what the underlying value type is.
2019-07-18 08:18:39 +02:00
Robin Burchell
41d2c674d7 AK: Add a new TestSuite.h from my own work, adapted to match the existing one a bit
This gives a few new features:

* benchmarks
* the ability to run individual testcases easily
* timing of tests
2019-07-16 11:03:38 +02:00
Robin Burchell
6e90f00925 BufferStream: Add a function to fully reset state
This will allow us to reuse the same buffer with the same stream instance.
Needed in AudioServer.
2019-07-16 09:36:38 +02:00
Robin Burchell
2c929c3aa1 BufferStream: Add signed int overloads for read/write
This will be required in AudioServer
2019-07-16 09:36:38 +02:00
Andreas Kling
8075ba5064 LogStream: Add a simple-ish mechanism for colorizing and styling output.
Meet TStyle. It allows you to write things like this:

    dbg() << TStyle(TStyle::Red, TStyle::Bold) << "Hello, friends!";

Any style used will be reset along with the newline emitted when the dbg()
temporary goes out of scope. :^)

This can definitely be improved, but I think it's a decent place to start.
2019-07-15 20:22:30 +02:00
Andreas Kling
954a0b8efe AK: Add a canonicalized_path() convenience function.
This is the same as calling FileSystemPath(foo).string(). The majority of
clients only care about canonicalizing a path, so let's have an easy way
to express that.
2019-07-15 06:50:32 +02:00
Robin Burchell
7b75632e5c AK/LibAudio: Add stream read operators to AK::BufferStream, and use it in AWavLoader
At the same time, we allow chaining of streaming operators, and add a
way to check for partial reads (also used in WAV parsing).
2019-07-14 15:29:59 +02:00
Robin Burchell
3792883219 AK: Remove some superstition from BufferStream :) 2019-07-14 15:29:59 +02:00
Andreas Kling
f712ead1fb AK: Add Queue::enqueue(const T&). 2019-07-13 17:00:30 +02:00
Andreas Kling
d9d13f2445 AK: Support case-insensitive HashMap<String, T>.
We achieve this by allowing you to specify custom traits for the key type.
For convenience, we also provide a CaseInsensitiveStringTraits for String.
2019-07-13 11:00:29 +02:00
Andreas Kling
25e3d46502 AK: Delete bad pointer assignment operators and constructors.
We shouldn't allow constructing e.g an OwnPtr from a RefPtr, and similar
conversions. Instead just delete those functions so the compiler whines
loudly if you try to use them.

This patch also deletes constructing OwnPtr from a WeakPtr, even though
that *may* be a valid thing to do, it's sufficiently weird that we can
make the client jump through some hoops if he really wants it. :^)
2019-07-11 16:50:30 +02:00
Andreas Kling
eb64a4ca60 AK: Remove copy_ref().
This patch removes copy_ref() from RefPtr and NonnullRefPtr. This means that
it's now okay to simply copy these smart pointers instead:

- RefPtr = RefPtr // Okay!
- RefPtr = NonnullRefPtr // Okay!
- NonnullRefPtr = NonnullRefPtr // Okay!
- NonnullRefPtr = RefPtr // Not okay, since RefPtr can be null.
2019-07-11 16:05:51 +02:00
Andreas Kling
b0372883ff AK: Remove use of copy_ref(). 2019-07-11 15:45:11 +02:00
Andreas Kling
560d037c41 AK: Make it more more pleasant to copy RefPtr's.
I had a silly ambition that we would avoid unnecessary ref count churn by
forcing explicit use of "copy_ref()" wherever a copy was actually needed.
This was making RefPtr a bit clunky to work with, for no real benefit.

This patch adds the missing copy construction/assignment stuff to RefPtr.
2019-07-11 15:38:38 +02:00
Andreas Kling
32fb7ecef4 AK: Remove weird RefPtr(RefPtr&) constructor. 2019-07-11 15:19:16 +02:00
Andreas Kling
3d9f783e31 AK: Make MappedFile non-copyable. 2019-07-11 15:14:30 +02:00
Andreas Kling
6534f5f083 AK: Remove weird NonnullRefPtr(NonnullRefPtr&) constructor. 2019-07-11 14:28:29 +02:00
Robin Burchell
bee39d8524 AK: Use operator== for comparison in Vector::contains_slow 2019-07-11 14:17:37 +02:00
Robin Burchell
2c4af740c7 AK: Add operator== & operator!= to Vector 2019-07-11 14:17:37 +02:00
Lawrence Manning
c3ecf753b2 AKString: add missing comparison operators
And some trivial tests.
2019-07-11 14:13:30 +02:00
Andreas Kling
c452aa891f AK: Add Platform.h with an ARCH() macro.
You can currently use this to detect the CPU architecture like so:

    #if ARCH(I386)
        ...
    #elif ARCH(X86_64)
        ...
    #else
        ...
    #endif

This will be helpful for separating out architecture-specific code blocks.
2019-07-09 15:48:04 +02:00
Andreas Kling
eca5c2bdf8 Kernel: Move VirtualAddress.h into VM/ 2019-07-09 15:04:45 +02:00
Andreas Kling
c110cf193d Kernel: Have the open() syscall take an explicit path length parameter.
Instead of computing the path length inside the syscall handler, let the
caller do that work. This allows us to implement to new variants of open()
and creat(), called open_with_path_length() and creat_with_path_length().
These are suitable for use with e.g StringView.
2019-07-08 20:01:49 +02:00
Andreas Kling
2caec95d30 StringBuilder: Reset the internal builder length after building.
This puts the StringBuilder back into a pristine state, allowing you
to use it to build more strings after you've built one.
2019-07-08 15:57:25 +02:00
Andreas Kling
0e75aba7c3 StringView: Rename characters() to characters_without_null_termination().
This should make you think twice before trying to use the const char* from
a StringView as if it's a null-terminated string.
2019-07-08 15:38:44 +02:00
Andreas Kling
567551bc12 AK: Add some missing includes in SinglyLinkedList. 2019-07-08 14:06:22 +02:00
Andreas Kling
5b19911025 AK: Add JsonValue::to_bool(). 2019-07-08 14:06:03 +02:00
Andreas Kling
c79b048198 MappedFile: Fix misuse of StringView::characters().
This makes me wonder if the open() syscall should take characters+length
and we'd compute the length at the LibC layer instead. That way we could
also provide an optional non-POSIX open() that takes the length directly..
2019-07-08 13:59:10 +02:00
Andreas Kling
a8aadf73e9 AK: Add JsonObject::set(key, &&value) overload.
This dodges a whole bunch of value copying in JsonParser.
2019-07-08 13:08:21 +02:00
Andreas Kling
7bb1e465c6 AK: Make it easy to convert between JsonValue and IPv4Address.
They still use string storage, but this change makes it nice and easy to
work with IPv4 addresses in JSON data.
2019-07-08 13:03:55 +02:00
Andreas Kling
d8f1a7e046 AK: Add LogStream operator<< for IPv4Address. 2019-07-08 11:43:42 +02:00
Andreas Kling
dddcedfd11 AK: Add IPv4Address::from_string(StringView).
This attempts to parse an IPv4Address from a string, and gives us an excuse
to try out the new Optional<T> for the return value. :^)
2019-07-08 11:38:58 +02:00
Andreas Kling
7b2a4c02e7 AK: Add a simple Optional<T> template.
This can be used to store any type, with a flag that says if any value
is present or not.
2019-07-08 11:29:38 +02:00
Andreas Kling
a0ee2bad72 String: String::to_int() should fail for any empty string, not just null. 2019-07-08 10:51:45 +02:00
Andreas Kling
f9089da2bc LogStream: Uninline some public functions so the linker can find them. 2019-07-08 09:22:22 +02:00
Andreas Kling
55a5c46253 AK: Add Vector::insert_before_matching(T&&, callback);
This allows you to do things like:

vector.insert_before_matching(value, [](auto& entry) {
    return value < entry;
});

Basically it scans until it finds an element that matches the condition
callback and then inserts the new value before the matching element.
2019-07-04 14:20:48 +02:00
Andreas Kling
57da8792fd Vector: Simplify functions that take both T&& and const T&.
We can implement foo(const T&) by invoking foo(T&&) with a temporary T.
2019-07-04 13:54:37 +02:00
Andreas Kling
1b013ba699 AK: Move some of LogStream out of line & add overloads for smart pointers. 2019-07-04 07:05:58 +02:00
Andreas Kling
05cc59921a AK: Start fleshing out LogStream, a type-aware logging mechanism.
The first implementation class is DebugLogStream, which can be used like so:

    dbg() << "Hello friends, I am " << m_years << " years old!";

Note that it will automatically print a newline when the object created by
dbg() goes out of scope.

This API will grow and evolve, so let's see what we end up with :^)
2019-07-04 06:43:30 +02:00
Andreas Kling
27f699ef0c AK: Rename the common integer typedefs to make it obvious what they are.
These types can be picked up by including <AK/Types.h>:

* u8, u16, u32, u64 (unsigned)
* i8, i16, i32, i64 (signed)
2019-07-03 21:20:13 +02:00
Andreas Kling
b79112e6d6 AK: Add String::number() for creating a String from a number.
Instead of manually doing String::format("%d"/"%u") everywhere, let's have
a String API for this. It's just a wrapper around format() for now, but it
could be made more efficient in the future.
2019-07-03 14:56:27 +02:00
Andreas Kling
a190f67450 AK: Add u8/u16/u32/u64 and i8/i16/i32/i64 typedefs.
These are more explicit and will be immediately understandable unlike the
old types which assume that you're in an IA-32 headspace. :^)
2019-07-01 15:58:21 +02:00
VAN BOSSUYT Nicolas
802d4dcb6b Meta: Removed all gitignore in the source tree only keeping the root one 2019-06-30 10:41:26 +02:00
Andreas Kling
6e95b11395 AK: Allow HashMap to be used with non-default-constructible values.
Solve this by adding find() overloads to HashTable and SinglyLinkedList
that take a templated functor for comparing the values.

This allows HashMap to call HashTable::find() without having to create
a temporary Entry for use as the table key. :^)
2019-06-29 21:09:40 +02:00
Andreas Kling
d5bb98acbc AK: Defer to Traits<T> for equality comparison in container templates.
This is prep work for supporting HashMap with NonnullRefPtr<T> as values.
It's currently not possible because many HashTable functions require being
able to default-construct the value type.
2019-06-29 19:14:03 +02:00
Andreas Kling
293946c960 JsonValue: Add is_bool() and various as_foo() helpers. 2019-06-29 12:07:46 +02:00
Andreas Kling
7f224ade60 JsonValue: No need to null-check StringImpls if type is Type::String.
If you try to create a JsonValue from a null String(), it will become a
null JsonValue anyway.
2019-06-29 12:07:46 +02:00
Andreas Kling
50677a58d4 StringView: Make it easy to construct from a ByteBuffer. 2019-06-29 12:07:46 +02:00
Andreas Kling
53479f9356 HashTable: Don't use move assignment in set(const T&). 2019-06-29 12:07:46 +02:00
Andreas Kling
b1d113e32a AK: Make a tiny JSON unit test based on a saved VisualBuilder form. 2019-06-29 12:07:42 +02:00
Andreas Kling
2bd8118843 Kernel: Change the format of /proc/all to JSON.
Update ProcessManager, top and WSCPUMonitor to handle the new format.

Since the kernel is not allowed to use floating-point math, we now compile
the JSON classes in AK without JsonValue::Type::Double support.
To accomodate large unsigned ints, I added a JsonValue::Type::UnsignedInt.
2019-06-29 09:04:45 +02:00
Andreas Kling
3af59dfed1 AK: We can't use std::initializer_list in LibC builds.
The LibC build is a bit complicated, since the toolchain depends on it.
During the toolchain bootstrap, after we've built parts of GCC, we have
to stop and build Serenity's LibC, so that the rest of GCC can use it.

This means that during that specific LibC build, we don't yet have access
to things like std::initializer_list.

For now we solve this by defining SERENITY_LIBC_BUILD during the LibC
build and excluding the Vector/initializer_list support inside LibC.
2019-06-28 20:58:41 +02:00
Andreas Kling
4c285f9e1a AK: Add Vector(std::initializer_list<T>) constructor.
This allows us to construct a Vector from an initializer list like so:

Vector<Object> objects = { object1, object2, object3 };
2019-06-28 20:21:23 +02:00
Andreas Kling
2282e89d3f AK: Use a SinglyLinkedList<T> as HashTable's bucket chain storage.
We were using a DoublyLinkedList<T> simply because it supported remove().
This patch consolidates the SinglyLinkedList iterators and adds remove().
2019-06-27 16:36:31 +02:00
Andreas Kling
7f613c79cd AK: Oops, fix typo in RemoveVolatile<T> helper. 2019-06-27 16:01:24 +02:00
Andreas Kling
516d736afe AK: Consolidate iterators for HashTable and DoublyLinkedList respectively.
Get rid of the ConstIterator classes for these containers and use templated
FooIterator<T, ...> and FooIterator<const T, ...> helpers.

This makes the HashTable class a lot easier to read.
2019-06-27 15:57:49 +02:00
Andreas Kling
50700c107f AK: Get rid of ConstVectorIterator.
We can achieve the same with just a VectorIterator<const Vector, const T>.
2019-06-27 14:52:12 +02:00
Andreas Kling
ebe108efa6 AK: Simplify HashMap a bit. 2019-06-27 14:27:26 +02:00
Andreas Kling
3bd47a2e09 AK: NonnullRefPtrVector should use Vector<T, inline_capacity> as its base.
We were forgetting to plumb through the inline capacity in the Base typedef.
2019-06-27 13:39:09 +02:00
Andreas Kling
9ab3718266 AK: Allow constructing an empty NonnullRefPtrVector. 2019-06-27 13:23:10 +02:00
Andreas Kling
48108ec474 AK: Support range-for iteration over a NonnullRefPtrVector<T>.
This means you can now do this:

void harmonize(NonnullRefPtrVector<Voice>& voices)
{
    for (auto& voice : voices) {
        voice.sing(); // Look, no "->"!
    }
}

Pretty dang cool :^)
2019-06-27 12:11:58 +02:00
Andreas Kling
25a1bf0c90 AK: Add NonnullRefPtrVector<T>.
This is a slot-in convenience replacement for Vector<NonnullRefPtr<T>> that
makes accessors return T& instead of NonnullRefPtr<T>&.
Since NonnullRefPtr guarantees non-nullness, this allows you to access these
vector elements using dot (.) rather than arrow (->). :^)
2019-06-27 12:04:27 +02:00