summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
blob: bfe5d2bc82f45645db83c86be6b1e3837dfb18ec (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
// Copyright 2016 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_V8_PRIVATE_PROPERTY_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_PRIVATE_PROPERTY_H_

#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "v8/include/v8.h"

namespace blink {

class ScriptWrappable;

// Provides access to V8's private properties with a symbol key.
//
//   static const V8PrivateProperty::SymbolKey kPrivateProperty;
//   auto private_property = V8PrivateProperty::GetSymbol(
//       isolate, kPrivateProperty);
//   v8::Local<v8::Object> object = ...;
//   v8::Local<v8::Value> value;
//   if (!private_property.GetOrUndefined(object).ToLocal(&value)) return;
//   value = ...;
//   private_property.Set(object, value);
//   ...
class PLATFORM_EXPORT V8PrivateProperty {
  USING_FAST_MALLOC(V8PrivateProperty);

 public:
  // Private properties used to implement [CachedAccessor].
  enum class CachedAccessor : unsigned {
    kNone = 0,
    kWindowProxy,
    kWindowDocument,
  };

  V8PrivateProperty() = default;

  // Provides fast access to V8's private properties.
  //
  // Retrieving/creating a global private symbol from a string is very
  // expensive compared to get or set a private property.  This class
  // provides a way to cache a private symbol and re-use it.
  class PLATFORM_EXPORT Symbol {
    STACK_ALLOCATED();

   public:
    bool HasValue(v8::Local<v8::Object> object) const {
      return object->HasPrivate(GetContext(), private_symbol_).ToChecked();
    }

    // Returns the value of the private property if set, or undefined.
    WARN_UNUSED_RESULT v8::MaybeLocal<v8::Value> GetOrUndefined(
        v8::Local<v8::Object> object) const {
      return object->GetPrivate(GetContext(), private_symbol_);
    }

    bool Set(v8::Local<v8::Object> object, v8::Local<v8::Value> value) const {
      return object->SetPrivate(GetContext(), private_symbol_, value)
          .ToChecked();
    }

    bool DeleteProperty(v8::Local<v8::Object> object) const {
      return object->DeletePrivate(GetContext(), private_symbol_).ToChecked();
    }

    v8::Local<v8::Private> GetPrivate() const { return private_symbol_; }

   private:
    friend class V8PrivateProperty;
    // The following classes are exceptionally allowed to call to
    // getFromMainWorld.
    friend class V8ExtendableMessageEvent;

    Symbol(v8::Isolate* isolate, v8::Local<v8::Private> private_symbol)
        : private_symbol_(private_symbol), isolate_(isolate) {}

    // To get/set private property, we should use the current context.
    v8::Local<v8::Context> GetContext() const {
      return isolate_->GetCurrentContext();
    }

    // Only friend classes are allowed to use this API.
    WARN_UNUSED_RESULT v8::MaybeLocal<v8::Value> GetFromMainWorld(
        ScriptWrappable*);

    v8::Local<v8::Private> private_symbol_;
    v8::Isolate* isolate_;
  };

  // This class is used for a key to get Symbol.
  //
  // We can improve ability of tracking private properties by using an instance
  // of this class.
  class PLATFORM_EXPORT SymbolKey final {
   public:
    SymbolKey() = default;

   private:
    SymbolKey(const SymbolKey&) = delete;
    SymbolKey& operator=(const SymbolKey&) = delete;
  };

  // TODO(peria): Do not use this specialized hack. See a TODO comment
  // on m_symbolWindowDocumentCachedAccessor.
  static Symbol GetWindowDocumentCachedAccessor(v8::Isolate* isolate);

  static Symbol GetCachedAccessor(v8::Isolate* isolate,
                                  CachedAccessor symbol_id);

  // Returns a Symbol to access a private property. Symbol instances from same
  // |key| are guaranteed to access the same property.
  static Symbol GetSymbol(v8::Isolate* isolate, const SymbolKey& key);

  // This function is always called after NOTREACHED(). The Symbol returned from
  // this function must not be used.
  static Symbol GetEmptySymbol() {
    return Symbol(nullptr, v8::Local<v8::Private>());
  }

 private:
  static v8::Local<v8::Private> CreateV8Private(v8::Isolate*,
                                                const char* symbol);

  // TODO(peria): Do not use this specialized hack for
  // Window#DocumentCachedAccessor. This is required to put v8::Private key in
  // a snapshot, and it cannot be a v8::Eternal<> due to V8 serializer's
  // requirement.
  ScopedPersistent<v8::Private> symbol_window_document_cached_accessor_;

  WTF::HashMap<const void*, v8::Eternal<v8::Private>> symbol_map_;

  DISALLOW_COPY_AND_ASSIGN(V8PrivateProperty);
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_PRIVATE_PROPERTY_H_