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) { ...@@ -248,6 +248,15 @@ ExecutionContext* ExecutionContextFromV8Wrappable(const DOMParser* parser) {
: nullptr; : 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 bindings
} // namespace blink } // namespace blink
...@@ -156,6 +156,10 @@ CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable( ...@@ -156,6 +156,10 @@ CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable(
CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable( CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable(
const DOMParser* parser); const DOMParser* parser);
CORE_EXPORT v8::Local<v8::Array> EnumerateIndexedProperties(
v8::Isolate* isolate,
uint32_t length);
} // namespace bindings } // namespace bindings
} // namespace blink } // namespace blink
......
...@@ -20,7 +20,7 @@ class CxxBlockNode(CompositeNode): ...@@ -20,7 +20,7 @@ class CxxBlockNode(CompositeNode):
def __init__(self, body): def __init__(self, body):
template_format = ( template_format = (
"{{\n" # "{{\n" #
" {body}\n" # " {body}\n"
"}}") "}}")
CompositeNode.__init__( CompositeNode.__init__(
...@@ -33,7 +33,7 @@ class CxxIfNode(CompositeNode): ...@@ -33,7 +33,7 @@ class CxxIfNode(CompositeNode):
def __init__(self, cond, body, likeliness): def __init__(self, cond, body, likeliness):
template_format = ( template_format = (
"if ({cond}) {{\n" # "if ({cond}) {{\n" #
" {body}\n" # " {body}\n"
"}}") "}}")
CompositeNode.__init__( CompositeNode.__init__(
...@@ -47,9 +47,9 @@ class CxxIfElseNode(CompositeNode): ...@@ -47,9 +47,9 @@ class CxxIfElseNode(CompositeNode):
def __init__(self, cond, then, then_likeliness, else_, else_likeliness): def __init__(self, cond, then, then_likeliness, else_, else_likeliness):
template_format = ( template_format = (
"if ({cond}) {{\n" # "if ({cond}) {{\n" #
" {then}\n" # " {then}\n"
"}} else {{\n" # "}} else {{\n"
" {else_}\n" # " {else_}\n"
"}}") "}}")
CompositeNode.__init__( CompositeNode.__init__(
......
...@@ -58,6 +58,11 @@ class CodeGenContext(object): ...@@ -58,6 +58,11 @@ class CodeGenContext(object):
"operation_group": None, "operation_group": None,
# Special member-ish definition # 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, "stringifier": None,
# The names of the class being generated and its base class. # The names of the class being generated and its base class.
...@@ -161,9 +166,19 @@ class CodeGenContext(object): ...@@ -161,9 +166,19 @@ class CodeGenContext(object):
return (self.callback_interface or self.dictionary or self.interface return (self.callback_interface or self.dictionary or self.interface
or self.namespace) 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 @property
def function_like(self): 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 @property
def idl_definition(self): def idl_definition(self):
...@@ -198,14 +213,16 @@ class CodeGenContext(object): ...@@ -198,14 +213,16 @@ class CodeGenContext(object):
@property @property
def is_return_by_argument(self): def is_return_by_argument(self):
if self.does_override_idl_return_type:
return False
if self.return_type is None: if self.return_type is None:
return None return False
return self.return_type.unwrap().is_union return self.return_type.unwrap().is_union
@property @property
def may_throw_exception(self): def may_throw_exception(self):
if not self.member_like: if not self.member_like:
return None return False
ext_attr = self.member_like.extended_attributes.get("RaisesException") ext_attr = self.member_like.extended_attributes.get("RaisesException")
if not ext_attr: if not ext_attr:
return False return False
...@@ -216,7 +233,8 @@ class CodeGenContext(object): ...@@ -216,7 +233,8 @@ class CodeGenContext(object):
@property @property
def member_like(self): def member_like(self):
return (self.attribute or self.constant or self.constructor 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 @property
def property_(self): def property_(self):
...@@ -225,20 +243,23 @@ class CodeGenContext(object): ...@@ -225,20 +243,23 @@ class CodeGenContext(object):
return (self.attribute or self.constant or self.constructor_group return (self.attribute or self.constant or self.constructor_group
or self.dict_member or self.exposed_construct or self.dict_member or self.exposed_construct
or self.operation_group) or self.operation_group or self._indexed_or_named_property)
@property @property
def return_type(self): def return_type(self):
if self.attribute_get: if self.attribute_get:
return self.attribute.idl_type return self.attribute.idl_type
if self.callback_function: function_like = self.function_like
return self.callback_function.return_type if function_like:
if self.constructor: return function_like.return_type
return self.constructor.return_type
if self.operation:
return self.operation.return_type
return None 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() CodeGenContext.init()
......
...@@ -414,6 +414,14 @@ class IndexedAndNamedProperties(WithOwner, WithDebugInfo): ...@@ -414,6 +414,14 @@ class IndexedAndNamedProperties(WithOwner, WithDebugInfo):
def has_named_properties(self): def has_named_properties(self):
return self.named_getter or self.named_setter or self.named_deleter 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 @property
def indexed_getter(self): def indexed_getter(self):
return self._find_accessor('own_indexed_getter') return self._find_accessor('own_indexed_getter')
......
...@@ -47,6 +47,15 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue { ...@@ -47,6 +47,15 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
StyleValueType GetType() const override { return kUnparsedType; } 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; CSSUnparsedSegment AnonymousIndexedGetter(unsigned, ExceptionState&) const;
IndexedPropertySetterResult AnonymousIndexedSetter(unsigned, IndexedPropertySetterResult AnonymousIndexedSetter(unsigned,
const CSSUnparsedSegment&, const CSSUnparsedSegment&,
......
...@@ -220,27 +220,27 @@ inline v8::Local<v8::Value> ToV8(const base::Optional<InnerType>& value, ...@@ -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() // Declare the function here but define it later so it can call the ToV8()
// overloads below. // overloads below.
template <typename Sequence> template <typename Sequence>
inline v8::Local<v8::Value> ToV8SequenceInternal( inline v8::Local<v8::Array> ToV8SequenceInternal(
const Sequence&, const Sequence&,
v8::Local<v8::Object> creation_context, v8::Local<v8::Object> creation_context,
v8::Isolate*); v8::Isolate*);
template <typename T, size_t Extent> 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::Local<v8::Object> creation_context,
v8::Isolate* isolate) { v8::Isolate* isolate) {
return ToV8SequenceInternal(value, creation_context, isolate); return ToV8SequenceInternal(value, creation_context, isolate);
} }
template <typename T, wtf_size_t inlineCapacity> 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::Local<v8::Object> creation_context,
v8::Isolate* isolate) { v8::Isolate* isolate) {
return ToV8SequenceInternal(value, creation_context, isolate); return ToV8SequenceInternal(value, creation_context, isolate);
} }
template <typename T, wtf_size_t inlineCapacity> 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::Local<v8::Object> creation_context,
v8::Isolate* isolate) { v8::Isolate* isolate) {
return ToV8SequenceInternal(value, creation_context, isolate); return ToV8SequenceInternal(value, creation_context, isolate);
...@@ -301,7 +301,7 @@ inline v8::Local<v8::Value> ToV8(const HeapVector<std::pair<String, T>>& value, ...@@ -301,7 +301,7 @@ inline v8::Local<v8::Value> ToV8(const HeapVector<std::pair<String, T>>& value,
} }
template <typename Sequence> template <typename Sequence>
inline v8::Local<v8::Value> ToV8SequenceInternal( inline v8::Local<v8::Array> ToV8SequenceInternal(
const Sequence& sequence, const Sequence& sequence,
v8::Local<v8::Object> creation_context, v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) { v8::Isolate* isolate) {
...@@ -324,7 +324,7 @@ inline v8::Local<v8::Value> ToV8SequenceInternal( ...@@ -324,7 +324,7 @@ inline v8::Local<v8::Value> ToV8SequenceInternal(
if (!array->CreateDataProperty(context, index++, value) if (!array->CreateDataProperty(context, index++, value)
.To(&created_property) || .To(&created_property) ||
!created_property) { !created_property) {
return v8::Local<v8::Value>(); return v8::Local<v8::Array>();
} }
} }
return array; return array;
......
...@@ -11,6 +11,38 @@ namespace blink { ...@@ -11,6 +11,38 @@ namespace blink {
namespace bindings { 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::Local<v8::Value> GetInterfaceObjectExposedOnGlobal(
v8::Isolate* isolate, v8::Isolate* isolate,
v8::Local<v8::Object> creation_context, v8::Local<v8::Object> creation_context,
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h" #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/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.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_per_isolate_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_value_cache.h" #include "third_party/blink/renderer/platform/bindings/v8_value_cache.h"
#include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/platform_export.h"
...@@ -49,6 +50,70 @@ void V8SetReturnValue(const CallbackInfo& info, const v8::Local<S> value) { ...@@ -49,6 +50,70 @@ void V8SetReturnValue(const CallbackInfo& info, const v8::Local<S> value) {
info.GetReturnValue().Set(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 // nullptr
template <typename CallbackInfo> template <typename CallbackInfo>
void V8SetReturnValue(const CallbackInfo& info, nullptr_t) { 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