Commit b525aaf6 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

Reland "[bindings] Replace JSFunction backlink with GC-aware wrapper link"

Replaces the custom backlink from V8->Blink that was using a v8::External with a
GC-aware backpointer that is encapsulated in the CustomWrappableAdapter
interface.

CustomWrappableAdapter establishes a link from a given JavaScript object to the
Blink object inheriting from CustomWrappableAdapter. The link is known to
garbage collectors and thus the Blink object will be kept alive as long as the
JavaScript object is alive. The adapter can be used to model liveness across V8
and Blink component boundaries. In contrast to ScriptWrappable, there is no IDL
definitions required and the JavaScript object must not escape to user-visible
JavaScript.

This reverts commit c1d0a59d.

Bug: chromium:843903
Change-Id: I8763cdf56ff3cbeff5fa7ae508bc1be8a5deb1c3
Reviewed-on: https://chromium-review.googlesource.com/1154926Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#579039}
parent e9e9833d
......@@ -30,6 +30,8 @@ bindings_core_v8_files =
"core/v8/binding_security.cc",
"core/v8/binding_security.h",
"core/v8/callback_promise_adapter.h",
"core/v8/custom_wrappable_adapter.cc",
"core/v8/custom_wrappable_adapter.h",
"core/v8/dictionary.cc",
"core/v8/dictionary.h",
"core/v8/dictionary_helper_for_core.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
namespace blink {
namespace {
v8::Local<v8::FunctionTemplate> CreateCustomWrappableTemplate(
v8::Isolate* isolate,
const DOMWrapperWorld& world);
const WrapperTypeInfo custom_wrappable_info = {
gin::kEmbedderBlink,
CreateCustomWrappableTemplate,
nullptr,
"CustomWrappableAdapter",
nullptr,
WrapperTypeInfo::kWrapperTypeNoPrototype,
WrapperTypeInfo::kCustomWrappableId,
WrapperTypeInfo::kNotInheritFromActiveScriptWrappable,
};
void InstallCustomWrappableTemplate(
v8::Isolate* isolate,
const DOMWrapperWorld& world,
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
V8DOMConfiguration::InitializeDOMInterfaceTemplate(
isolate, interfaceTemplate, custom_wrappable_info.interface_name,
v8::Local<v8::FunctionTemplate>(), kV8DefaultWrapperInternalFieldCount);
}
v8::Local<v8::FunctionTemplate> CreateCustomWrappableTemplate(
v8::Isolate* isolate,
const DOMWrapperWorld& world) {
return V8DOMConfiguration::DomClassTemplate(
isolate, world, const_cast<WrapperTypeInfo*>(&custom_wrappable_info),
InstallCustomWrappableTemplate);
}
} // namespace
CustomWrappableAdapter* CustomWrappableAdapter::LookupInternal(
v8::Local<v8::Object> object,
const V8PrivateProperty::Symbol& property) {
v8::Local<v8::Value> custom_wrappable_adapter_value;
if (!property.GetOrUndefined(object).ToLocal(&custom_wrappable_adapter_value))
return nullptr;
if (!custom_wrappable_adapter_value->IsUndefined()) {
return static_cast<CustomWrappableAdapter*>(
ToCustomWrappable(custom_wrappable_adapter_value.As<v8::Object>()));
}
return nullptr;
}
void CustomWrappableAdapter::Attach(ScriptState* script_state,
v8::Local<v8::Object> object,
const V8PrivateProperty::Symbol& property,
CustomWrappableAdapter* adapter) {
DCHECK(wrapper_.IsEmpty());
v8::Isolate* isolate = script_state->GetIsolate();
v8::Local<v8::Object> wrapper_object = V8DOMWrapper::CreateWrapper(
isolate, script_state->GetContext()->Global(), &custom_wrappable_info);
V8DOMWrapper::AssociateObjectWithWrapper(
isolate, adapter, &custom_wrappable_info, wrapper_object);
property.Set(object, wrapper_object);
wrapper_.Set(isolate, wrapper_object);
custom_wrappable_info.ConfigureWrapper(&wrapper_.Get());
}
} // namespace blink
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_CUSTOM_WRAPPABLE_ADAPTER_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_CUSTOM_WRAPPABLE_ADAPTER_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/custom_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "v8/include/v8.h"
namespace blink {
class ScriptState;
// CustomWrappableAdapter establishes a link from a given JavaScript object to
// the Blink object inheriting from CustomWrappableAdapter. The link is known to
// garbage collectors and the lifetime of the V8 and Blink objects will be tied
// together. The adapter can be used to model liveness across V8 and Blink
// component boundaries. In contrast to ScriptWrappable, no IDL definitions are
// required.
//
// The intended use case is binding the lifetime of a Blink object to a
// user-provided JavaScript object.
class CORE_EXPORT CustomWrappableAdapter : public CustomWrappable {
public:
// Lookup the CustomWrappableAdapter implementation on a given |object|'s
// |property|. Returns nullptr if no adapter has been attached. See Attach.
template <typename T>
static T* Lookup(v8::Local<v8::Object> object,
const V8PrivateProperty::Symbol& property) {
return static_cast<T*>(LookupInternal(object, property));
}
// Attaches a given |adapter| to |object|'s |property|.
void Attach(ScriptState*,
v8::Local<v8::Object> object,
const V8PrivateProperty::Symbol& property,
CustomWrappableAdapter* adapter);
~CustomWrappableAdapter() override = default;
void Trace(Visitor* visitor) override {
visitor->Trace(wrapper_);
CustomWrappable::Trace(visitor);
}
private:
static CustomWrappableAdapter* LookupInternal(
v8::Local<v8::Object>,
const V8PrivateProperty::Symbol&);
// Internal wrapper reference is needed as Oilpan looks up its roots from V8
// by following all configured wrapper references.
TraceWrapperV8Reference<v8::Object> wrapper_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_CUSTOM_WRAPPABLE_ADAPTER_H_
......@@ -34,7 +34,6 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/self_keep_alive.h"
#include "v8/include/v8.h"
......
......@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_event_listener_helper.h"
#include "third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_error_handler.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_event_listener.h"
......@@ -42,27 +43,21 @@ namespace {
template <typename ListenerType, typename ListenerFactory>
ListenerType* GetEventListenerInternal(
v8::Isolate* isolate,
ScriptState* script_state,
v8::Local<v8::Object> object,
const V8PrivateProperty::Symbol& listener_property,
ListenerLookupType lookup,
const ListenerFactory& listener_factory) {
DCHECK(isolate->InContext());
v8::Local<v8::Value> listener_value;
if (!listener_property.GetOrUndefined(object).ToLocal(&listener_value))
return nullptr;
DCHECK(script_state->GetIsolate()->InContext());
ListenerType* listener =
listener_value->IsUndefined()
? nullptr
: static_cast<ListenerType*>(
listener_value.As<v8::External>()->Value());
CustomWrappableAdapter::Lookup<ListenerType>(object, listener_property);
if (listener || lookup == kListenerFindOnly)
return listener;
listener = listener_factory();
if (listener)
listener_property.Set(object, v8::External::New(isolate, listener));
if (listener) {
listener->Attach(script_state, object, listener_property, listener);
}
return listener;
}
......@@ -87,7 +82,7 @@ V8EventListener* V8EventListenerHelper::GetEventListener(
: V8PrivateProperty::GetV8EventListenerListener(isolate);
return GetEventListenerInternal<V8EventListener>(
isolate, object, listener_property, lookup,
script_state, object, listener_property, lookup,
[object, is_attribute, script_state]() {
return script_state->World().IsWorkerWorld()
? V8WorkerOrWorkletEventListener::Create(
......@@ -109,7 +104,7 @@ V8ErrorHandler* V8EventListenerHelper::EnsureErrorHandler(
V8PrivateProperty::GetV8ErrorHandlerErrorHandler(isolate);
return GetEventListenerInternal<V8ErrorHandler>(
isolate, object, listener_property, kListenerFindOrCreate,
script_state, object, listener_property, kListenerFindOrCreate,
[object, script_state]() {
const bool is_attribute = true;
return V8ErrorHandler::Create(object, is_attribute, script_state);
......
......@@ -75,6 +75,12 @@ Node* V8GCController::OpaqueRootForGC(v8::Isolate*, Node* node) {
return node;
}
bool IsDOMWrapperClassId(uint16_t class_id) {
return class_id == WrapperTypeInfo::kNodeClassId ||
class_id == WrapperTypeInfo::kObjectClassId ||
class_id == WrapperTypeInfo::kCustomWrappableId;
}
class MinorGCUnmodifiedWrapperVisitor : public v8::PersistentHandleVisitor {
public:
explicit MinorGCUnmodifiedWrapperVisitor(v8::Isolate* isolate)
......@@ -82,8 +88,11 @@ class MinorGCUnmodifiedWrapperVisitor : public v8::PersistentHandleVisitor {
void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
uint16_t class_id) override {
if (class_id != WrapperTypeInfo::kNodeClassId &&
class_id != WrapperTypeInfo::kObjectClassId) {
if (!IsDOMWrapperClassId(class_id))
return;
if (class_id == WrapperTypeInfo::kCustomWrappableId) {
v8::Persistent<v8::Object>::Cast(*value).MarkActive();
return;
}
......@@ -331,12 +340,19 @@ class DOMWrapperTracer final : public v8::PersistentHandleVisitor {
void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
uint16_t class_id) final {
if (class_id != WrapperTypeInfo::kNodeClassId &&
class_id != WrapperTypeInfo::kObjectClassId)
if (!IsDOMWrapperClassId(class_id))
return;
WrapperTypeInfo* wrapper_type_info = const_cast<WrapperTypeInfo*>(
ToWrapperTypeInfo(v8::Persistent<v8::Object>::Cast(*value)));
// WrapperTypeInfo pointer may have been cleared before termination GCs on
// worker threads.
if (!wrapper_type_info)
return;
visitor_->Trace(
ToScriptWrappable(v8::Persistent<v8::Object>::Cast(*value)));
wrapper_type_info->Trace(
visitor_, ToUntypedWrappable(v8::Persistent<v8::Object>::Cast(*value)));
}
private:
......@@ -351,8 +367,7 @@ class DOMWrapperPurger final : public v8::PersistentHandleVisitor {
void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
uint16_t class_id) final {
if (class_id != WrapperTypeInfo::kNodeClassId &&
class_id != WrapperTypeInfo::kObjectClassId)
if (!IsDOMWrapperClassId(class_id))
return;
// Clear out wrapper type information, essentially disconnecting the Blink
......@@ -364,7 +379,6 @@ class DOMWrapperPurger final : public v8::PersistentHandleVisitor {
isolate_, v8::Persistent<v8::Object>::Cast(*value));
wrapper->SetAlignedPointerInInternalFields(base::size(indices), indices,
values);
value->Reset();
}
private:
......
......@@ -21,6 +21,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_LISTENER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_LISTENER_H_
#include "third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
......@@ -31,9 +32,7 @@ namespace blink {
class Event;
class ExecutionContext;
class CORE_EXPORT EventListener
: public GarbageCollectedFinalized<EventListener>,
public NameClient {
class CORE_EXPORT EventListener : public CustomWrappableAdapter {
public:
enum ListenerType {
kJSEventListenerType,
......@@ -42,7 +41,7 @@ class CORE_EXPORT EventListener
kConditionEventListenerType,
};
virtual ~EventListener() = default;
~EventListener() override = default;
virtual bool operator==(const EventListener&) const = 0;
virtual void handleEvent(ExecutionContext*, Event*) = 0;
virtual const String& Code() const { return g_empty_string; }
......@@ -54,7 +53,6 @@ class CORE_EXPORT EventListener
ListenerType GetType() const { return type_; }
virtual void Trace(blink::Visitor* visitor) {}
const char* NameInHeapSnapshot() const override { return "EventListener"; }
protected:
......
......@@ -423,6 +423,7 @@ jumbo_component("platform") {
"bindings/callback_function_base.h",
"bindings/callback_interface_base.cc",
"bindings/callback_interface_base.h",
"bindings/custom_wrappable.h",
"bindings/dom_data_store.h",
"bindings/dom_wrapper_map.h",
"bindings/dom_wrapper_world.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CUSTOM_WRAPPABLE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CUSTOM_WRAPPABLE_H_
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
namespace blink {
// See the comment on CustomWrappableAdaptor.
class PLATFORM_EXPORT CustomWrappable
: public GarbageCollectedFinalized<CustomWrappable>,
public NameClient {
WTF_MAKE_NONCOPYABLE(CustomWrappable);
public:
virtual ~CustomWrappable() = default;
virtual void Trace(Visitor*) {}
const char* NameInHeapSnapshot() const override { return "CustomWrappable"; }
protected:
CustomWrappable() = default;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CUSTOM_WRAPPABLE_H_
......@@ -7,6 +7,7 @@
#include "base/auto_reset.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h"
#include "third_party/blink/renderer/platform/bindings/custom_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_map.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
......@@ -165,13 +166,8 @@ void ScriptWrappableMarkingVisitor::RegisterV8Reference(
if (wrapper_type_info->gin_embedder != gin::GinEmbedder::kEmbedderBlink) {
return;
}
DCHECK(wrapper_type_info->wrapper_class_id == WrapperTypeInfo::kNodeClassId ||
wrapper_type_info->wrapper_class_id ==
WrapperTypeInfo::kObjectClassId);
ScriptWrappable* script_wrappable =
reinterpret_cast<ScriptWrappable*>(internal_fields.second);
TraceWithWrappers(script_wrappable);
wrapper_type_info->TraceWithWrappers(this, internal_fields.second);
}
void ScriptWrappableMarkingVisitor::RegisterV8References(
......
......@@ -94,10 +94,11 @@ bool V8DOMWrapper::HasInternalFieldsSet(v8::Local<v8::Value> value) {
if (object->InternalFieldCount() < kV8DefaultWrapperInternalFieldCount)
return false;
const ScriptWrappable* untrusted_script_wrappable = ToScriptWrappable(object);
// The untrusted wrappable can either be ScriptWrappable or CustomWrappable.
const void* untrused_wrappable = ToUntypedWrappable(object);
const WrapperTypeInfo* untrusted_wrapper_type_info =
ToWrapperTypeInfo(object);
return untrusted_script_wrappable && untrusted_wrapper_type_info &&
return untrused_wrappable && untrusted_wrapper_type_info &&
untrusted_wrapper_type_info->gin_embedder == gin::kEmbedderBlink;
}
......
......@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_DOM_WRAPPER_H_
#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/bindings/custom_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
......@@ -67,10 +68,24 @@ class V8DOMWrapper {
ScriptWrappable*,
const WrapperTypeInfo*,
v8::Local<v8::Object> wrapper);
static void SetNativeInfo(v8::Isolate*,
v8::Local<v8::Object>,
const WrapperTypeInfo*,
ScriptWrappable*);
static void AssociateObjectWithWrapper(v8::Isolate*,
CustomWrappable*,
const WrapperTypeInfo*,
v8::Local<v8::Object> wrapper);
static void SetNativeInfo(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const WrapperTypeInfo* wrapper_type_info,
ScriptWrappable* script_wrappable) {
SetNativeInfoInternal(isolate, wrapper, wrapper_type_info,
script_wrappable);
}
static void SetNativeInfo(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const WrapperTypeInfo* wrapper_type_info,
CustomWrappable* custom_wrappable) {
SetNativeInfoInternal(isolate, wrapper, wrapper_type_info,
custom_wrappable);
}
static void ClearNativeInfo(v8::Isolate*, v8::Local<v8::Object>);
// hasInternalFieldsSet only checks if the value has the internal fields for
......@@ -78,19 +93,24 @@ class V8DOMWrapper {
// value may not be a Blink's wrapper object. In order to make sure of it,
// Use isWrapper function instead.
PLATFORM_EXPORT static bool HasInternalFieldsSet(v8::Local<v8::Value>);
private:
static void SetNativeInfoInternal(v8::Isolate*,
v8::Local<v8::Object>,
const WrapperTypeInfo*,
void*);
};
inline void V8DOMWrapper::SetNativeInfo(
inline void V8DOMWrapper::SetNativeInfoInternal(
v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const WrapperTypeInfo* wrapper_type_info,
ScriptWrappable* script_wrappable) {
void* wrappable) {
DCHECK_GE(wrapper->InternalFieldCount(), 2);
DCHECK(script_wrappable);
DCHECK(wrappable);
DCHECK(wrapper_type_info);
int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex};
void* values[] = {script_wrappable,
const_cast<WrapperTypeInfo*>(wrapper_type_info)};
void* values[] = {wrappable, const_cast<WrapperTypeInfo*>(wrapper_type_info)};
wrapper->SetAlignedPointerInInternalFields(base::size(indices), indices,
values);
auto* per_isolate_data = V8PerIsolateData::From(isolate);
......@@ -100,7 +120,7 @@ inline void V8DOMWrapper::SetNativeInfo(
// necessarily detect wrappers created during its incremental marking.
per_isolate_data->GetScriptWrappableMarkingVisitor()->RegisterV8Reference(
std::make_pair(const_cast<WrapperTypeInfo*>(wrapper_type_info),
script_wrappable));
wrappable));
}
inline void V8DOMWrapper::ClearNativeInfo(v8::Isolate* isolate,
......@@ -127,6 +147,19 @@ inline v8::Local<v8::Object> V8DOMWrapper::AssociateObjectWithWrapper(
return wrapper;
}
inline void V8DOMWrapper::AssociateObjectWithWrapper(
v8::Isolate* isolate,
CustomWrappable* impl,
const WrapperTypeInfo* wrapper_type_info,
v8::Local<v8::Object> wrapper) {
RUNTIME_CALL_TIMER_SCOPE(
isolate, RuntimeCallStats::CounterId::kAssociateObjectWithWrapper);
WrapperTypeInfo::WrapperCreated();
SetNativeInfo(isolate, wrapper, wrapper_type_info, impl);
DCHECK(HasInternalFieldsSet(wrapper));
SECURITY_CHECK(ToCustomWrappable(wrapper) == impl);
}
class V8WrapperInstantiationScope {
STACK_ALLOCATED();
......
......@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
#include "third_party/blink/renderer/platform/bindings/custom_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
......@@ -25,4 +27,32 @@ void WrapperTypeInfo::WrapperDestroyed() {
stats_collector->IncreaseCollectedWrapperCount(1);
}
void WrapperTypeInfo::Trace(Visitor* visitor, void* impl) {
switch (wrapper_class_id) {
case WrapperTypeInfo::kNodeClassId:
case WrapperTypeInfo::kObjectClassId:
visitor->Trace(reinterpret_cast<ScriptWrappable*>(impl));
break;
case WrapperTypeInfo::kCustomWrappableId:
visitor->Trace(reinterpret_cast<CustomWrappable*>(impl));
break;
default:
NOTREACHED();
}
}
void WrapperTypeInfo::TraceWithWrappers(Visitor* visitor, void* impl) {
switch (wrapper_class_id) {
case WrapperTypeInfo::kNodeClassId:
case WrapperTypeInfo::kObjectClassId:
visitor->TraceWithWrappers(reinterpret_cast<ScriptWrappable*>(impl));
break;
case WrapperTypeInfo::kCustomWrappableId:
visitor->TraceWithWrappers(reinterpret_cast<CustomWrappable*>(impl));
break;
default:
NOTREACHED();
}
}
} // namespace blink
......@@ -40,8 +40,10 @@
namespace blink {
class ActiveScriptWrappableBase;
class CustomWrappable;
class DOMWrapperWorld;
class ScriptWrappable;
class Visitor;
ScriptWrappable* ToScriptWrappable(
const v8::PersistentBase<v8::Object>& wrapper);
......@@ -87,6 +89,7 @@ struct WrapperTypeInfo {
enum WrapperClassId {
kNodeClassId = 1, // NodeClassId must be smaller than ObjectClassId.
kObjectClassId,
kCustomWrappableId,
};
enum ActiveScriptWrappableInheritance {
......@@ -143,6 +146,11 @@ struct WrapperTypeInfo {
kInheritFromActiveScriptWrappable;
}
// Garbage collection support for when the type depends the WrapperTypeInfo
// object.
PLATFORM_EXPORT void Trace(Visitor*, void*);
PLATFORM_EXPORT void TraceWithWrappers(Visitor*, void*);
// This field must be the first member of the struct WrapperTypeInfo.
// See also static_assert() in .cpp file.
const gin::GinEmbedder gin_embedder;
......@@ -182,6 +190,23 @@ inline ScriptWrappable* ToScriptWrappable(v8::Local<v8::Object> wrapper) {
return GetInternalField<ScriptWrappable, kV8DOMWrapperObjectIndex>(wrapper);
}
inline CustomWrappable* ToCustomWrappable(
const v8::PersistentBase<v8::Object>& wrapper) {
return GetInternalField<CustomWrappable, kV8DOMWrapperObjectIndex>(wrapper);
}
inline CustomWrappable* ToCustomWrappable(v8::Local<v8::Object> wrapper) {
return GetInternalField<CustomWrappable, kV8DOMWrapperObjectIndex>(wrapper);
}
inline void* ToUntypedWrappable(const v8::PersistentBase<v8::Object>& wrapper) {
return GetInternalField<void, kV8DOMWrapperObjectIndex>(wrapper);
}
inline void* ToUntypedWrappable(v8::Local<v8::Object> wrapper) {
return GetInternalField<void, kV8DOMWrapperObjectIndex>(wrapper);
}
inline const WrapperTypeInfo* ToWrapperTypeInfo(
const v8::PersistentBase<v8::Object>& wrapper) {
return GetInternalField<WrapperTypeInfo, kV8DOMWrapperTypeIndex>(wrapper);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment