Commit b8f1bac1 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

v8binding: Support [CSSProperty]

Supports [CSSProperty] IDL extended attribute in order to
support CSS properties.

There are 1,215 CSS properties, so it's worth optimizing
the property installation of CSS properties to reduce the
APK size.  CSS properties are currently implemented as
named properties, but they will soon be implemented as
IDL attributes conforming to the spec.  Then, the APK size
increase will be ~9KB with this patch (~300KB without this
patch).

Bug: 1075980, 1075981
Change-Id: Id0410d57737ae106ead95d01a89661a6942fc0b7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2391180
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Reviewed-by: default avatarAnders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804746}
parent bf35d432
......@@ -789,6 +789,12 @@ When applied to an interface, the generated code for the relevant global object
Note that `[ContextEnabled]` is not mututally exclusive to `[RuntimeEnabled]`, and a feature which may be enabled by either mechanism will be enabled if the appropriate `[RuntimeEnabled]` feature is enabled; _or_ if the appropriate `[ContextEnabled]` feature is enabled; _or_ if both are enabled.
### [CSSProperty] _(a)_
Summary: `[CSSProperty]` indicates that the attribute implements a CSS property and Blink optimizes the property installation accordingly.
`[CSSProperty]` must be applied only at `CSSStyleDeclaration`'s IDL attributes implementing CSS properties ([camel-cased attributes](https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-camel_cased_attribute), [webkit-cased attributes](https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-camel_cased_attribute), [dashed attributes](https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-dashed_attribute)).
### [Custom] _(i, m, s, a, f)_
Summary: They allow you to write bindings code manually as you like: full bindings for methods and attributes, certain functions for interfaces.
......
......@@ -35,6 +35,7 @@ ActiveScriptWrappable
Affects=Nothing
AllowShared
CEReactions
CSSProperty
CachedAccessor=*
CachedAttribute=*
CallWith=ExecutionContext|Isolate|ScriptState|ThisValue
......
......@@ -6,7 +6,9 @@
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_css_style_declaration.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_set_return_value_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
......@@ -15,6 +17,7 @@
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_processing_stack.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/xml/dom_parser.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
namespace blink {
......@@ -349,6 +352,81 @@ v8::Local<v8::Array> EnumerateIndexedProperties(v8::Isolate* isolate,
#if defined(USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE)
void InstallCSSPropertyAttributes(
v8::Isolate* isolate,
const DOMWrapperWorld& world,
v8::Local<v8::ObjectTemplate> instance_template,
v8::Local<v8::ObjectTemplate> prototype_template,
v8::Local<v8::FunctionTemplate> interface_template,
v8::Local<v8::Signature> signature,
base::span<const char* const> css_property_names) {
const String kGetPrefix = "get ";
const String kSetPrefix = "set ";
for (const char* const property_name : css_property_names) {
v8::Local<v8::Value> v8_property_name = v8::External::New(
isolate,
const_cast<void*>(reinterpret_cast<const void*>(property_name)));
v8::Local<v8::FunctionTemplate> get_func = v8::FunctionTemplate::New(
isolate, CSSPropertyAttributeGet, v8_property_name, signature, 0,
v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasNoSideEffect);
v8::Local<v8::FunctionTemplate> set_func = v8::FunctionTemplate::New(
isolate, CSSPropertyAttributeSet, v8_property_name, signature, 1,
v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasSideEffect);
get_func->RemovePrototype();
set_func->RemovePrototype();
get_func->SetAcceptAnyReceiver(false);
set_func->SetAcceptAnyReceiver(false);
get_func->SetClassName(
V8AtomicString(isolate, String(kGetPrefix + property_name)));
set_func->SetClassName(
V8AtomicString(isolate, String(kSetPrefix + property_name)));
prototype_template->SetAccessorProperty(
V8AtomicString(isolate, property_name), get_func, set_func);
}
}
void CSSPropertyAttributeGet(const v8::FunctionCallbackInfo<v8::Value>& info) {
CSSStyleDeclaration* blink_receiver =
V8CSSStyleDeclaration::ToWrappableUnsafe(info.This());
const char* property_name =
reinterpret_cast<const char*>(info.Data().As<v8::External>()->Value());
// TODO(andruud): AnonymousNamedGetter is not the best function. Change the
// function to a more appropriate one.
auto&& return_value = blink_receiver->AnonymousNamedGetter(property_name);
bindings::V8SetReturnValue(info, return_value, info.GetIsolate(),
bindings::V8ReturnValue::kNonNullable);
}
void CSSPropertyAttributeSet(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
const char* const class_like_name = "CSSStyleDeclaration";
const char* property_name =
reinterpret_cast<const char*>(info.Data().As<v8::External>()->Value());
ExceptionState exception_state(isolate, ExceptionState::kSetterContext,
class_like_name, property_name);
// [CEReactions]
CEReactionsScope ce_reactions_scope;
v8::Local<v8::Object> v8_receiver = info.This();
CSSStyleDeclaration* blink_receiver =
V8CSSStyleDeclaration::ToWrappableUnsafe(v8_receiver);
v8::Local<v8::Value> v8_property_value = info[0];
auto&& arg1_value =
NativeValueTraits<IDLStringTreatNullAsEmptyStringV2>::NativeValue(
isolate, v8_property_value, exception_state);
if (exception_state.HadException()) {
return;
}
v8::Local<v8::Context> receiver_context = v8_receiver->CreationContext();
ScriptState* receiver_script_state = ScriptState::From(receiver_context);
// TODO(andruud): AnonymousNamedSetter is not the best function. Change the
// function to a more appropriate one. It's better to pass |exception_state|
// as the implementation of AnonymousNamedSetter needs it.
blink_receiver->AnonymousNamedSetter(receiver_script_state, property_name,
arg1_value);
}
template <typename IDLType,
typename ArgType,
void (Element::*MemFunc)(const QualifiedName&, ArgType)>
......
......@@ -228,6 +228,20 @@ bool ConvertDictionaryMember(v8::Isolate* isolate,
return true;
}
// [CSSProperty]
CORE_EXPORT void InstallCSSPropertyAttributes(
v8::Isolate* isolate,
const DOMWrapperWorld& world,
v8::Local<v8::ObjectTemplate> instance_template,
v8::Local<v8::ObjectTemplate> prototype_template,
v8::Local<v8::FunctionTemplate> interface_template,
v8::Local<v8::Signature> signature,
base::span<const char* const> css_property_names);
CORE_EXPORT void CSSPropertyAttributeGet(
const v8::FunctionCallbackInfo<v8::Value>& info);
CORE_EXPORT void CSSPropertyAttributeSet(
const v8::FunctionCallbackInfo<v8::Value>& info);
// Common implementation to reduce the binary size of attribute set callbacks.
CORE_EXPORT void PerformAttributeSetCEReactionsReflectTypeBoolean(
const v8::FunctionCallbackInfo<v8::Value>& info,
......
......@@ -4792,6 +4792,9 @@ def _make_property_entries_and_callback_defs(
def process_attribute(attribute, is_context_dependent,
exposure_conditional, world):
if "CSSProperty" in attribute.extended_attributes:
return # [CSSProperty] will be installed in a special manner.
cgc_attr = cg_context.make_copy(attribute=attribute, for_world=world)
cgc = cgc_attr.make_copy(attribute_get=True)
attr_get_callback_name = callback_function_name(cgc)
......@@ -5226,6 +5229,29 @@ def make_install_interface_template(cg_context, function_name, class_name,
EmptyNode(),
])
if class_like.identifier == "CSSStyleDeclaration":
css_properties = filter(
lambda attr: "CSSProperty" in attr.extended_attributes,
class_like.attributes)
if css_properties:
prop_name_list = "".join(
map(lambda attr: "\"{}\", ".format(attr.identifier),
css_properties))
body.append(
T("""\
// CSSStyleDeclaration-specific settings
// [CSSProperty]
{
static constexpr const char* kCssProperties[] = {
""" + prop_name_list + """
};
bindings::InstallCSSPropertyAttributes(
${isolate}, ${world},
${instance_template}, ${prototype_template}, ${interface_template},
${signature}, kCssProperties);
}
"""))
if class_like.identifier == "DOMException":
body.append(
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