Commit 1d02dd83 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

bind-gen: Implement indexed properties and named properties

This patch implements indexed / named properties in the new
bindings generator (not yet shipped).  No change in prod.

Bug: 839389
Change-Id: I4ebda31736eb0da9f2df2d3fbc70381677d7a56c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2105653Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#753182}
parent c259a59f
......@@ -248,6 +248,15 @@ ExecutionContext* ExecutionContextFromV8Wrappable(const DOMParser* parser) {
: nullptr;
}
v8::Local<v8::Array> EnumerateIndexedProperties(v8::Isolate* isolate,
uint32_t length) {
Vector<v8::Local<v8::Value>> elements;
elements.ReserveCapacity(length);
for (uint32_t i = 0; i < length; ++i)
elements.UncheckedAppend(v8::Integer::New(isolate, i));
return v8::Array::New(isolate, elements.data(), elements.size());
}
} // namespace bindings
} // namespace blink
......@@ -156,6 +156,10 @@ CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable(
CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable(
const DOMParser* parser);
CORE_EXPORT v8::Local<v8::Array> EnumerateIndexedProperties(
v8::Isolate* isolate,
uint32_t length);
} // namespace bindings
} // namespace blink
......
......@@ -20,7 +20,7 @@ class CxxBlockNode(CompositeNode):
def __init__(self, body):
template_format = (
"{{\n" #
" {body}\n" #
" {body}\n"
"}}")
CompositeNode.__init__(
......@@ -33,7 +33,7 @@ class CxxIfNode(CompositeNode):
def __init__(self, cond, body, likeliness):
template_format = (
"if ({cond}) {{\n" #
" {body}\n" #
" {body}\n"
"}}")
CompositeNode.__init__(
......@@ -47,9 +47,9 @@ class CxxIfElseNode(CompositeNode):
def __init__(self, cond, then, then_likeliness, else_, else_likeliness):
template_format = (
"if ({cond}) {{\n" #
" {then}\n" #
"}} else {{\n" #
" {else_}\n" #
" {then}\n"
"}} else {{\n"
" {else_}\n"
"}}")
CompositeNode.__init__(
......
......@@ -58,6 +58,11 @@ class CodeGenContext(object):
"operation_group": None,
# Special member-ish definition
"indexed_property_getter": None,
"indexed_property_setter": None,
"named_property_getter": None,
"named_property_setter": None,
"named_property_deleter": None,
"stringifier": None,
# The names of the class being generated and its base class.
......@@ -161,9 +166,19 @@ class CodeGenContext(object):
return (self.callback_interface or self.dictionary or self.interface
or self.namespace)
@property
def does_override_idl_return_type(self):
# Blink implementation returns in a type different from the IDL type.
# Namely, IndexedPropertySetterResult, NamedPropertySetterResult, and
# NamedPropertyDeleterResult are returned ignoring the operation's
# return type.
return (self.indexed_property_setter or self.named_property_setter
or self.named_property_deleter)
@property
def function_like(self):
return (self.callback_function or self.constructor or self.operation)
return (self.callback_function or self.constructor or self.operation
or self._indexed_or_named_property)
@property
def idl_definition(self):
......@@ -198,14 +213,16 @@ class CodeGenContext(object):
@property
def is_return_by_argument(self):
if self.does_override_idl_return_type:
return False
if self.return_type is None:
return None
return False
return self.return_type.unwrap().is_union
@property
def may_throw_exception(self):
if not self.member_like:
return None
return False
ext_attr = self.member_like.extended_attributes.get("RaisesException")
if not ext_attr:
return False
......@@ -216,7 +233,8 @@ class CodeGenContext(object):
@property
def member_like(self):
return (self.attribute or self.constant or self.constructor
or self.dict_member or self.operation)
or self.dict_member or self.operation
or self._indexed_or_named_property)
@property
def property_(self):
......@@ -225,20 +243,23 @@ class CodeGenContext(object):
return (self.attribute or self.constant or self.constructor_group
or self.dict_member or self.exposed_construct
or self.operation_group)
or self.operation_group or self._indexed_or_named_property)
@property
def return_type(self):
if self.attribute_get:
return self.attribute.idl_type
if self.callback_function:
return self.callback_function.return_type
if self.constructor:
return self.constructor.return_type
if self.operation:
return self.operation.return_type
function_like = self.function_like
if function_like:
return function_like.return_type
return None
@property
def _indexed_or_named_property(self):
return (self.indexed_property_getter or self.indexed_property_setter
or self.named_property_getter or self.named_property_setter
or self.named_property_deleter)
CodeGenContext.init()
......
......@@ -414,6 +414,14 @@ class IndexedAndNamedProperties(WithOwner, WithDebugInfo):
def has_named_properties(self):
return self.named_getter or self.named_setter or self.named_deleter
@property
def is_named_property_enumerable(self):
named_getter = self.named_getter
return bool(named_getter
and 'NotEnumerable' not in named_getter.extended_attributes
and 'LegacyUnenumerableNamedProperties' not in self.owner.
extended_attributes)
@property
def indexed_getter(self):
return self._find_accessor('own_indexed_getter')
......
......@@ -47,6 +47,15 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
StyleValueType GetType() const override { return kUnparsedType; }
void AnonymousIndexedGetter(uint32_t index,
CSSUnparsedSegment& return_value,
ExceptionState& exception_state) const {
return_value = AnonymousIndexedGetter(index, exception_state);
}
// TODO(crbug.com/1050474): Remove the following 2-arguments version once the
// migration to the new bindings generator is done. The current policy is
// that return value of IDL union type is returned by argument. This policy
// may change when we implement IDL union types with GarbageCollected classes.
CSSUnparsedSegment AnonymousIndexedGetter(unsigned, ExceptionState&) const;
IndexedPropertySetterResult AnonymousIndexedSetter(unsigned,
const CSSUnparsedSegment&,
......
......@@ -220,27 +220,27 @@ inline v8::Local<v8::Value> ToV8(const base::Optional<InnerType>& value,
// Declare the function here but define it later so it can call the ToV8()
// overloads below.
template <typename Sequence>
inline v8::Local<v8::Value> ToV8SequenceInternal(
inline v8::Local<v8::Array> ToV8SequenceInternal(
const Sequence&,
v8::Local<v8::Object> creation_context,
v8::Isolate*);
template <typename T, size_t Extent>
inline v8::Local<v8::Value> ToV8(base::span<T, Extent> value,
inline v8::Local<v8::Array> ToV8(base::span<T, Extent> value,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
return ToV8SequenceInternal(value, creation_context, isolate);
}
template <typename T, wtf_size_t inlineCapacity>
inline v8::Local<v8::Value> ToV8(const Vector<T, inlineCapacity>& value,
inline v8::Local<v8::Array> ToV8(const Vector<T, inlineCapacity>& value,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
return ToV8SequenceInternal(value, creation_context, isolate);
}
template <typename T, wtf_size_t inlineCapacity>
inline v8::Local<v8::Value> ToV8(const HeapVector<T, inlineCapacity>& value,
inline v8::Local<v8::Array> ToV8(const HeapVector<T, inlineCapacity>& value,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
return ToV8SequenceInternal(value, creation_context, isolate);
......@@ -301,7 +301,7 @@ inline v8::Local<v8::Value> ToV8(const HeapVector<std::pair<String, T>>& value,
}
template <typename Sequence>
inline v8::Local<v8::Value> ToV8SequenceInternal(
inline v8::Local<v8::Array> ToV8SequenceInternal(
const Sequence& sequence,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
......@@ -324,7 +324,7 @@ inline v8::Local<v8::Value> ToV8SequenceInternal(
if (!array->CreateDataProperty(context, index++, value)
.To(&created_property) ||
!created_property) {
return v8::Local<v8::Value>();
return v8::Local<v8::Array>();
}
}
return array;
......
......@@ -11,6 +11,38 @@ namespace blink {
namespace bindings {
v8::Local<v8::Object> CreatePropertyDescriptorObject(
v8::Isolate* isolate,
const v8::PropertyDescriptor& desc) {
// https://tc39.es/ecma262/#sec-frompropertydescriptor
v8::Local<v8::Context> current_context = isolate->GetCurrentContext();
v8::Local<v8::Object> object = v8::Object::New(isolate);
auto add_property = [&](const char* name, v8::Local<v8::Value> value) {
return object->CreateDataProperty(current_context, V8String(isolate, name),
value);
};
auto add_property_bool = [&](const char* name, bool value) {
return add_property(name, value ? v8::True(isolate) : v8::False(isolate));
};
bool result;
if (desc.has_value()) {
if (!(add_property("value", desc.value()).To(&result) &&
add_property_bool("writable", desc.writable()).To(&result)))
return v8::Local<v8::Object>();
} else {
if (!(add_property("get", desc.get()).To(&result) &&
add_property("set", desc.set()).To(&result)))
return v8::Local<v8::Object>();
}
if (!(add_property_bool("enumerable", desc.enumerable()).To(&result) &&
add_property_bool("configurable", desc.configurable()).To(&result)))
return v8::Local<v8::Object>();
return object;
}
v8::Local<v8::Value> GetInterfaceObjectExposedOnGlobal(
v8::Isolate* isolate,
v8::Local<v8::Object> creation_context,
......
......@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/platform/bindings/dom_data_store.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/v8_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_value_cache.h"
#include "third_party/blink/renderer/platform/platform_export.h"
......@@ -49,6 +50,70 @@ void V8SetReturnValue(const CallbackInfo& info, const v8::Local<S> value) {
info.GetReturnValue().Set(value);
}
// Property descriptor
PLATFORM_EXPORT v8::Local<v8::Object> CreatePropertyDescriptorObject(
v8::Isolate* isolate,
const v8::PropertyDescriptor& desc);
template <typename CallbackInfo>
void V8SetReturnValue(const CallbackInfo& info,
const v8::PropertyDescriptor& value) {
info.GetReturnValue().Set(
CreatePropertyDescriptorObject(info.GetIsolate(), value));
}
// Indexed properties and named properties
PLATFORM_EXPORT inline void V8SetReturnValue(
const v8::FunctionCallbackInfo<v8::Value>& info,
IndexedPropertySetterResult value) {
// If an operation implementing indexed property setter is invoked as a
// regular operation, and the return type is not type void (V8SetReturnValue
// won't be called in case of type void), then return the given value as is.
info.GetReturnValue().Set(info[1]);
}
PLATFORM_EXPORT inline void V8SetReturnValue(
const v8::PropertyCallbackInfo<v8::Value>& info,
IndexedPropertySetterResult value) {
if (value == IndexedPropertySetterResult::kDidNotIntercept) {
// Do not set the return value to indicate that the request was not
// intercepted.
return;
}
info.GetReturnValue().SetNull();
}
PLATFORM_EXPORT inline void V8SetReturnValue(
const v8::FunctionCallbackInfo<v8::Value>& info,
NamedPropertySetterResult value) {
// If an operation implementing named property setter is invoked as a
// regular operation, and the return type is not type void (V8SetReturnValue
// won't be called in case of type void), then return the given value as is.
info.GetReturnValue().Set(info[1]);
}
PLATFORM_EXPORT inline void V8SetReturnValue(
const v8::PropertyCallbackInfo<v8::Value>& info,
NamedPropertySetterResult value) {
if (value == NamedPropertySetterResult::kDidNotIntercept) {
// Do not set the return value to indicate that the request was not
// intercepted.
return;
}
info.GetReturnValue().SetNull();
}
template <typename CallbackInfo>
void V8SetReturnValue(const CallbackInfo& info,
NamedPropertyDeleterResult value) {
if (value == NamedPropertyDeleterResult::kDidNotIntercept) {
// Do not set the return value to indicate that the request was not
// intercepted.
return;
}
info.GetReturnValue().Set(value == NamedPropertyDeleterResult::kDeleted);
}
// nullptr
template <typename CallbackInfo>
void V8SetReturnValue(const CallbackInfo& info, nullptr_t) {
......
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