Summary
V8 exposes the following public methods on
V8InspectorSession:
wrapObject
unwrapObject
releaseObjectGroup
These methods are not currently exposed by rusty_v8.
Without them, a Rust embedder cannot use the Inspector's own remote-object
identity system from an embedder-provided Inspector command:
- A
Local<Value> cannot be converted into a Runtime.RemoteObject with an
Inspector-generated objectId.
- An
objectId received from the frontend cannot be resolved back to its V8
value and context.
- An embedder cannot directly release an object group that it created.
Impact
The built-in Runtime and Debugger domains continue to work because V8 uses
these mechanisms internally.
The missing bindings affect embedder-provided Inspector functionality that
needs to exchange object references with the frontend. Without them, an
embedder would have to invent a separate object-ID registry instead of using
the Inspector's injected-script and object-group state.
That produces object IDs which are not naturally interoperable with standard
CDP operations such as Runtime.getProperties, and duplicates lifecycle
management already implemented by V8.
Proposed API
Expose an opaque owned representation of the Inspector RemoteObject:
pub struct RemoteObject {
// Owns a protocol::Runtime::API::RemoteObject.
}
impl RemoteObject {
/// Serialize using the Inspector's CRDTP/CBOR representation.
pub fn to_bytes(&self) -> Vec<u8>;
}
Add the corresponding session operations:
impl V8InspectorSession {
pub fn wrap_object<'s>(
&self,
scope: &mut PinScope<'s, '_>,
context: Local<'s, Context>,
value: Local<'s, Value>,
object_group: StringView,
generate_preview: bool,
) -> Option<RemoteObject>;
pub fn unwrap_object<'s>(
&self,
scope: &mut PinScope<'s, '_>,
object_id: StringView,
) -> Result<UnwrappedObject<'s>, String>;
pub fn release_object_group(
&self,
object_group: StringView,
);
}
The unwrap result would contain all values returned by V8:
pub struct UnwrappedObject<'s> {
pub value: Local<'s, Value>,
pub context: Local<'s, Context>,
pub object_group: Option<String>,
}
wrap_object returns None when V8 cannot find an injected script for the
context or otherwise cannot create the RemoteObject.
unwrap_object returns V8's error message for an invalid or stale object ID.
The returned Local handles are tied to the caller's scope.
RemoteObject representation
The proposal uses an opaque owned RemoteObject rather than returning a JSON
string directly.
Its to_bytes method would use the generated RemoteObject's
AppendSerialized implementation, producing the same CBOR representation used
by the existing CRDTP APIs. Callers that need JSON can use the existing
crdtp::cbor_to_json conversion.
This avoids:
- forcing every caller through JSON;
- exposing generated protocol classes directly;
- making raw CRDTP pointer types public;
- treating protocol data as an unvalidated UTF-8 string.
If maintainers prefer a smaller API surface, an alternative is for
wrap_object to return Option<Vec<u8>> containing the serialized CBOR
directly.
Ownership and safety
- The C++ shim receives the
std::unique_ptr<RemoteObject> from V8 and
transfers it to an owning Rust wrapper.
- Destruction of the protocol object remains on the C++ side.
- No generated C++ object layout is exposed to Rust.
unwrap_object copies the small error and object-group strings into owned
Rust strings.
- Returned V8 handles remain bounded by the supplied scope.
- Only public V8 Inspector APIs are used.
Tests
The binding should include tests verifying that:
- Wrapping an object returns a serializable
Runtime.RemoteObject.
- The result contains a non-empty Inspector-generated
objectId.
- Unwrapping that ID returns the original value and context.
- The original object group is returned.
- An invalid object ID produces an error.
- Releasing the object group makes its previous IDs invalid.
- Wrapping fails cleanly when the context has no usable injected script.
- Repeated wrapping and releasing does not leak protocol objects or V8
handles.
Open questions
- Should
wrap_object return an opaque owned RemoteObject, as proposed, or
serialized CBOR bytes?
- Should unwrap errors and object-group names be copied into Rust
String
values, or should the API preserve V8's owned StringBuffer types?
- Is one PR for all three lifecycle operations preferred, or should the
implementation be delivered as:
wrap_object and RemoteObject serialization first;
unwrap_object and release_object_group second?
Summary
V8 exposes the following public methods on
V8InspectorSession:wrapObjectunwrapObjectreleaseObjectGroupThese methods are not currently exposed by
rusty_v8.Without them, a Rust embedder cannot use the Inspector's own remote-object
identity system from an embedder-provided Inspector command:
Local<Value>cannot be converted into aRuntime.RemoteObjectwith anInspector-generated
objectId.objectIdreceived from the frontend cannot be resolved back to its V8value and context.
Impact
The built-in Runtime and Debugger domains continue to work because V8 uses
these mechanisms internally.
The missing bindings affect embedder-provided Inspector functionality that
needs to exchange object references with the frontend. Without them, an
embedder would have to invent a separate object-ID registry instead of using
the Inspector's injected-script and object-group state.
That produces object IDs which are not naturally interoperable with standard
CDP operations such as
Runtime.getProperties, and duplicates lifecyclemanagement already implemented by V8.
Proposed API
Expose an opaque owned representation of the Inspector RemoteObject:
Add the corresponding session operations:
The unwrap result would contain all values returned by V8:
wrap_objectreturnsNonewhen V8 cannot find an injected script for thecontext or otherwise cannot create the RemoteObject.
unwrap_objectreturns V8's error message for an invalid or stale object ID.The returned
Localhandles are tied to the caller's scope.RemoteObject representation
The proposal uses an opaque owned
RemoteObjectrather than returning a JSONstring directly.
Its
to_bytesmethod would use the generated RemoteObject'sAppendSerializedimplementation, producing the same CBOR representation usedby the existing CRDTP APIs. Callers that need JSON can use the existing
crdtp::cbor_to_jsonconversion.This avoids:
If maintainers prefer a smaller API surface, an alternative is for
wrap_objectto returnOption<Vec<u8>>containing the serialized CBORdirectly.
Ownership and safety
std::unique_ptr<RemoteObject>from V8 andtransfers it to an owning Rust wrapper.
unwrap_objectcopies the small error and object-group strings into ownedRust strings.
Tests
The binding should include tests verifying that:
Runtime.RemoteObject.objectId.handles.
Open questions
wrap_objectreturn an opaque ownedRemoteObject, as proposed, orserialized CBOR bytes?
Stringvalues, or should the API preserve V8's owned
StringBuffertypes?implementation be delivered as:
wrap_objectand RemoteObject serialization first;unwrap_objectandrelease_object_groupsecond?