Skip to content
This repository has been archived by the owner on Dec 4, 2023. It is now read-only.

Allow registering Ruby callbacks for V8 objects. #387

Open
wants to merge 5 commits into
base: upgrade-to-v8-4.5
Choose a base branch
from

Conversation

cowboyd
Copy link
Collaborator

@cowboyd cowboyd commented Aug 28, 2015

This allows Ruby code to listen directly for when V8 object is garbage
collected. This is done with the SetWeak method which can
be invoked on any handle. This handle is now weak, and the object that it references can be garbage collected by V8 even if the Ruby object is still in scope. E.g.

  v8_object.SetWeak(method_that_generates_callable)

Later, once v8_object has been gc'd, the finalizer will be enqueued into an internal data structure that can
be accessed via the isolate's __EachV8Finalizer

  isolate.__EachV8Finalizer__ do |finalizer|
    finalizer.call()
  end

This also adds the ability to capture a new, persistent reference to an existing handle via the V8::C::Handle::New() method. For example, suppose we have the following:

object = V8::C::Object::New(isolate)

The object variable represents a persistent reference to this V8 object, and it cannot be garbage collected by V8 as long as this Ruby object is reachable. But we can add another reference:

second = V8::C::Handle::New(object)
second.class #=> V8::C::Object

Notice that even though we are using the handle api, the type of the returned object is the same as the original reference.

This V8 object cannot be garbage collected until both of the Ruby objects are either no longer reachable, or are set to be weak.

@cowboyd cowboyd force-pushed the 4.5/add-ruby-finalizers-to-v8-objects branch from b817b29 to 5cebcd4 Compare August 28, 2015 17:53
This allows Ruby code to listen directly for when V8 object is garbage
collected. This is done with the `__DefineFinalizer__` method which can
be invoked on any handle. E.g.

  v8_object.__DefineFinalizer__(method_that_generates_callable)

Just like in Ruby, care should be taken to ensure that the finalizer
does not reference the V8 object at all, otherwise, it might prevent it
from being garbage collected. The later, once v8_object has been gc'd,
the finalizer will be enqueued into an internal data structure that can
be accessed via the isolate's `__EachV8Finalizer`

  isolate.__EachV8Finalizer__ do |finalizer|
    finalizer.call()
  end

There was a question of whether to follow the strict V8 API for this,
and expose the `SetWeak` method, but this would mean actually making a
handle weak, which is fine, but then we would have to add a mechanism
to capture a strong reference from any reference which we don't have.

We may want to revisit this at some later date.
@cowboyd cowboyd force-pushed the 4.5/add-ruby-finalizers-to-v8-objects branch from 5cebcd4 to 750e6b4 Compare August 28, 2015 17:59
That will ensure that at least one object triggers finalization.
This implementation hues very closesly to the actual V8 API, so is more
desirable. It also adds the ability to capture a handle to an existing
object.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant