Currently, when a finalizer callback is registered, it is not
guaranteed to be called if there is a global reference to the
corresponding object that survives the isolate. This is because the
finalizer callback takes a `&mut Isolate`, and so it must be called
before the isolate is fully destroyed, but all existing globals
(including possibly the one being currently finalized) are still
usable while there still exists a mutable reference to the isolate.
However, there are still use cases for having finalizers that are
guaranteed to run regardless of any remaining globals, but that don't
require any interaction with the isolate. This change adds them.
This change also changes the context annex to use a guaranteed
finalizer, fixing a bug with context slots not being freed if there
were any globals to the context at the time the isolate is dropped.
property_attribute previously had an addition operator overload which
doesn't make much sense in comparison to the corresponding V8
enumeration. This changes that to a bitor overload.
Signed-off-by: Darshan Sen <raisinten@gmail.com>
This change allows the customization of the behavior of
v8::Object::GetOwnPropertyNames() and v8::Object::GetPropertyNames() by
accepting all the options that the raw V8 API supports.
Signed-off-by: Darshan Sen <raisinten@gmail.com>
This change adds support for weak handles that don't prevent GC of the
referenced objects, through the `v8::Weak<T>` API. A weak handle can
be empty (if it was created empty or its object was GC'd) or
non-empty, and if non-empty it allows getting its object as a global
or local.
When creating a `v8::Weak` you can also set a finalizer that will be
called at some point after the object is GC'd, as long as the weak
handle is still alive at that point. This finalization corresponds to
the second-pass callback in `kParameter` mode in the C++ API, so it
will only be called after the object is GC'd. The finalizer function
is a `FnOnce` that may close over data, and which takes a
`&mut Isolate` as an argument.
The C++ finalization API doesn't guarantee _when_ or even _if_ the
finalizer will ever be called, but in order to prevent memory leaks,
the rusty_v8 wrapper ensures that it will be called at some point,
even if it's just before the isolate gets dropped.
`v8::Weak<T>` implements `Clone`, but a finalizer is tied to a single
weak handle, so its clones won't be able to keep the finalizer alive.
And in fact, cloning will create a new weak handle that isn't tied to
a finalizer at all. `v8::Weak::clone_with_finalizer` can be used to
make a clone of a weak handle which has a finalizer tied to it.
Note that `v8::Weak<T>` doesn't implement `Hash`, because the hash
would have to change once the handle's object is GC'd, which is a big
gotcha and would break some of the algorithms that rely on hashes,
such as the Rust std's `HashMap`.