summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
blob: 4f86ee390bfc0639f7dc9482b3df7e025520afc8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2017 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_CALLBACK_INTERFACE_BASE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CALLBACK_INTERFACE_BASE_H_

#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"

namespace blink {

class V8PersistentCallbackInterfaceBase;

// CallbackInterfaceBase is the common base class of all the callback interface
// classes. Most importantly this class provides a way of type dispatching (e.g.
// overload resolutions, SFINAE technique, etc.) so that it's possible to
// distinguish callback interfaces from anything else. Also it provides a common
// implementation of callback interfaces.
//
// As the signatures of callback interface's operations vary, this class does
// not implement any operation. Subclasses will implement it.
class PLATFORM_EXPORT CallbackInterfaceBase
    : public GarbageCollectedFinalized<CallbackInterfaceBase>,
      public NameClient {
 public:
  // Whether the callback interface is a "single operation callback interface"
  // or not.
  // https://heycam.github.io/webidl/#dfn-single-operation-callback-interface
  enum SingleOperationOrNot {
    kNotSingleOperation,
    kSingleOperation,
  };

  virtual ~CallbackInterfaceBase() = default;

  virtual void Trace(blink::Visitor*);

  v8::Isolate* GetIsolate() {
    return callback_relevant_script_state_->GetIsolate();
  }
  ScriptState* CallbackRelevantScriptState() {
    return callback_relevant_script_state_;
  }

  // NodeIteratorBase counts the invocation of those which are callable and
  // those which are not.
  bool IsCallbackObjectCallableForNodeIteratorBase() const {
    return IsCallbackObjectCallable();
  }

 protected:
  CallbackInterfaceBase(v8::Local<v8::Object> callback_object,
                        SingleOperationOrNot);

  v8::Local<v8::Object> CallbackObject() {
    return callback_object_.NewLocal(GetIsolate());
  }
  // Returns true iff the callback interface is a single operation callback
  // interface and the callback interface type value is callable.
  bool IsCallbackObjectCallable() const { return is_callback_object_callable_; }
  ScriptState* IncumbentScriptState() { return incumbent_script_state_; }

 private:
  // The "callback interface type" value.
  TraceWrapperV8Reference<v8::Object> callback_object_;
  bool is_callback_object_callable_ = false;
  // The associated Realm of the callback interface type value. Note that the
  // callback interface type value can be different from the function object
  // to be invoked.
  Member<ScriptState> callback_relevant_script_state_;
  // The callback context, i.e. the incumbent Realm when an ECMAScript value is
  // converted to an IDL value.
  // https://heycam.github.io/webidl/#dfn-callback-context
  Member<ScriptState> incumbent_script_state_;

  friend class V8PersistentCallbackInterfaceBase;
  // ToV8 needs to call |CallbackObject| member function.
  friend v8::Local<v8::Value> ToV8(CallbackInterfaceBase* callback,
                                   v8::Local<v8::Object> creation_context,
                                   v8::Isolate*);
};

// V8PersistentCallbackInterfaceBase retains the underlying v8::Object of a
// CallbackInterfaceBase without wrapper-tracing. This class is necessary and
// useful where wrapper-tracing is not suitable. Remember that, as a nature of
// v8::Persistent, abuse of V8PersistentCallbackInterfaceBase would result in
// memory leak, so the use of V8PersistentCallbackInterfaceBase should be
// limited to those which are guaranteed to release the persistents in a finite
// time period.
class PLATFORM_EXPORT V8PersistentCallbackInterfaceBase
    : public GarbageCollectedFinalized<V8PersistentCallbackInterfaceBase> {
 public:
  virtual ~V8PersistentCallbackInterfaceBase() { v8_object_.Reset(); }

  virtual void Trace(blink::Visitor*);

  v8::Isolate* GetIsolate() { return callback_interface_->GetIsolate(); }

 protected:
  explicit V8PersistentCallbackInterfaceBase(CallbackInterfaceBase*);

  template <typename V8CallbackInterface>
  V8CallbackInterface* As() {
    static_assert(
        std::is_base_of<CallbackInterfaceBase, V8CallbackInterface>::value,
        "V8CallbackInterface must be a subclass of CallbackInterfaceBase.");
    return static_cast<V8CallbackInterface*>(callback_interface_.Get());
  }

 private:
  Member<CallbackInterfaceBase> callback_interface_;
  v8::Persistent<v8::Object> v8_object_;
};

// V8PersistentCallbackInterface<V8CallbackInterface> is a counter-part of
// V8CallbackInterface. While V8CallbackInterface uses wrapper-tracing,
// V8PersistentCallbackInterface<V8CallbackInterface> uses v8::Persistent to
// make the underlying v8::Object alive.
//
// Since the signatures of the operations vary depending on the IDL definition,
// the class definition is specialized and generated by the bindings code
// generator.
template <typename V8CallbackInterface>
class V8PersistentCallbackInterface;

// Converts the wrapper-tracing version of a callback interface to the
// v8::Persistent version of it.
template <typename V8CallbackInterface>
inline V8PersistentCallbackInterface<V8CallbackInterface>*
ToV8PersistentCallbackInterface(V8CallbackInterface* callback_interface) {
  static_assert(
      std::is_base_of<CallbackInterfaceBase, V8CallbackInterface>::value,
      "V8CallbackInterface must be a subclass of CallbackInterfaceBase.");
  return callback_interface
             ? new V8PersistentCallbackInterface<V8CallbackInterface>(
                   callback_interface)
             : nullptr;
}

// CallbackInterfaceBase is designed to be used with wrapper-tracing. As
// blink::Persistent does not perform wrapper-tracing, use of |WrapPersistent|
// for callback interfaces is likely (if not always) misuse. Thus, this code
// prohibits such a use case. The call sites should explicitly use
// WrapPersistent(V8PersistentCallbackInterface<T>*).
Persistent<CallbackInterfaceBase> WrapPersistent(CallbackInterfaceBase*) =
    delete;

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CALLBACK_INTERFACE_BASE_H_