blob: d324ffc50069406e38ec80396cbcddbfc01f258f [file] [log] [blame]
// 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 <memory>
#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_