Commit 27bd9c38 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

bind-gen: Fix indexed/named properties to pass WPTs

Bug: 839389
Change-Id: I77236487532a3776cd2a389d7e15a261f6489b48
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2137194
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#757008}
parent cc9758ba
...@@ -257,8 +257,6 @@ def bind_callback_local_vars(code_node, cg_context): ...@@ -257,8 +257,6 @@ def bind_callback_local_vars(code_node, cg_context):
"V8PerIsolateData::From(${isolate});")), "V8PerIsolateData::From(${isolate});")),
S("property_name", S("property_name",
"const char* const ${property_name} = \"${property.identifier}\";"), "const char* const ${property_name} = \"${property.identifier}\";"),
S("v8_receiver",
"v8::Local<v8::Object> ${v8_receiver} = ${info}.This();"),
S("receiver_context", ("v8::Local<v8::Context> ${receiver_context} = " S("receiver_context", ("v8::Local<v8::Context> ${receiver_context} = "
"${v8_receiver}->CreationContext();")), "${v8_receiver}->CreationContext();")),
S("receiver_script_state", S("receiver_script_state",
...@@ -373,6 +371,19 @@ def bind_callback_local_vars(code_node, cg_context): ...@@ -373,6 +371,19 @@ def bind_callback_local_vars(code_node, cg_context):
S("v8_property_value", S("v8_property_value",
"v8::Local<v8::Value> ${v8_property_value} = ${info}[0];")) "v8::Local<v8::Value> ${v8_property_value} = ${info}[0];"))
# v8_receiver
if cg_context.v8_callback_type == CodeGenContext.V8_FUNCTION_CALLBACK:
# In case of v8::FunctionCallbackInfo, This() is the receiver object.
local_vars.append(
S("v8_receiver",
"v8::Local<v8::Object> ${v8_receiver} = ${info}.This();"))
else:
# In case of v8::PropertyCallbackInfo, Holder() is the object that has
# the property being processed.
local_vars.append(
S("v8_receiver",
"v8::Local<v8::Object> ${v8_receiver} = ${info}.Holder();"))
code_node.register_code_symbols(local_vars) code_node.register_code_symbols(local_vars)
code_node.add_template_vars(template_vars) code_node.add_template_vars(template_vars)
...@@ -1928,6 +1939,14 @@ def make_indexed_property_getter_callback(cg_context, function_name): ...@@ -1928,6 +1939,14 @@ def make_indexed_property_getter_callback(cg_context, function_name):
body.extend([ body.extend([
make_runtime_call_timer_scope(cg_context, "IndexedPropertyGetter"), make_runtime_call_timer_scope(cg_context, "IndexedPropertyGetter"),
EmptyNode(), EmptyNode(),
TextNode("""\
// LegacyPlatformObjectGetOwnProperty
// https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
// step 1.2. If index is a supported property index, then:
// step 3. Return OrdinaryGetOwnProperty(O, P).
if (${index} >= ${blink_receiver}->length())
return; // Do not intercept. Fallback to OrdinaryGetOwnProperty.\
"""),
make_v8_set_return_value(cg_context), make_v8_set_return_value(cg_context),
]) ])
...@@ -1938,12 +1957,9 @@ def make_indexed_property_setter_callback(cg_context, function_name): ...@@ -1938,12 +1957,9 @@ def make_indexed_property_setter_callback(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext) assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str) assert isinstance(function_name, str)
if cg_context.indexed_property_setter is None:
return None, None
arg_decls = [ arg_decls = [
"uint32_t index", "uint32_t index",
"v8::Local<v8::Value> v8_value", "v8::Local<v8::Value> v8_property_value",
"const v8::PropertyCallbackInfo<v8::Value>& info", "const v8::PropertyCallbackInfo<v8::Value>& info",
] ]
return_type = "void" return_type = "void"
...@@ -1962,24 +1978,126 @@ def make_indexed_property_setter_callback(cg_context, function_name): ...@@ -1962,24 +1978,126 @@ def make_indexed_property_setter_callback(cg_context, function_name):
func_def.set_base_template_vars(cg_context.template_bindings()) func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body body = func_def.body
body.add_template_var("index", "index") body.add_template_var("index", "index")
body.add_template_var("v8_value", "v8_value") body.add_template_var("v8_property_value", "v8_property_value")
body.add_template_var("info", "info") body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context) bind_callback_local_vars(body, cg_context)
body.extend([
make_runtime_call_timer_scope(cg_context, "IndexedPropertySetter"),
EmptyNode(),
])
if not cg_context.indexed_property_setter:
body.append(
TextNode("""\
// 3.8.2. [[Set]]
// https://heycam.github.io/webidl/#legacy-platform-object-set
// step 1. If O and Receiver are the same object, then:
if (${info}.Holder() == ${info}.This()) {
// OrdinarySetWithOwnDescriptor will end up calling DefineOwnProperty,
// which will fail when the receiver object is this legacy platform
// object.
bindings::V8SetReturnValue(${info}, nullptr);
if (${info}.ShouldThrowOnError()) {
ExceptionState exception_state(${info}.GetIsolate(),
ExceptionState::kIndexedSetterContext,
"${interface.identifier}");
exception_state.ThrowTypeError(
"Indexed property setter is not supported.");
}
return;
}
// step 2. Let ownDesc be LegacyPlatformObjectGetOwnProperty(O, P, true).
// step 3. Perform ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver,
// ownDesc).
//
// Do not intercept. Fallback to OrdinarySetWithOwnDescriptor.\
"""))
return func_decl, func_def
bind_return_value( bind_return_value(
body, cg_context, overriding_args=["${index}", "${blink_value}"]) body,
cg_context,
overriding_args=["${index}", "${blink_property_value}"])
body.register_code_symbol( body.register_code_symbol(
make_v8_to_blink_value( make_v8_to_blink_value(
"blink_value", "blink_property_value",
"${v8_value}", "${v8_property_value}",
cg_context.indexed_property_setter.arguments[1].idl_type, cg_context.indexed_property_setter.arguments[1].idl_type,
argument_index=2)) argument_index=2))
body.extend([ body.extend([
make_runtime_call_timer_scope(cg_context, "IndexedPropertySetter"), TextNode("""\
// 3.8.2. [[Set]]
// https://heycam.github.io/webidl/#legacy-platform-object-set
// step 1. If O and Receiver are the same object, then:\
"""),
CxxLikelyIfNode(
cond="${info}.Holder() == ${info}.This()",
body=[
TextNode("""\
// step 1.1.1. Invoke the indexed property setter with P and V.\
"""),
make_steps_of_ce_reactions(cg_context),
EmptyNode(),
make_v8_set_return_value(cg_context),
TextNode("""\
bindings::V8SetReturnValue(${info}, nullptr);
return;"""),
]),
EmptyNode(), EmptyNode(),
make_steps_of_ce_reactions(cg_context), TextNode("""\
// Do not intercept. Fallback to OrdinarySetWithOwnDescriptor.\
"""),
])
return func_decl, func_def
def make_indexed_property_deleter_callback(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str)
arg_decls = [
"uint32_t index",
"const v8::PropertyCallbackInfo<v8::Boolean>& info",
]
return_type = "void"
func_decl = CxxFuncDeclNode(
name=function_name,
arg_decls=arg_decls,
return_type=return_type,
static=True)
func_def = CxxFuncDefNode(
name=function_name,
arg_decls=arg_decls,
return_type=return_type,
class_name=cg_context.class_name)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
body.add_template_var("index", "index")
body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context)
body.extend([
make_runtime_call_timer_scope(cg_context, "IndexedPropertyDeleter"),
EmptyNode(), EmptyNode(),
make_v8_set_return_value(cg_context), TextNode("""\
// 3.8.4. [[Delete]]
// https://heycam.github.io/webidl/#legacy-platform-object-delete
// step 1.2. If index is not a supported property index, then return true.
// step 1.3. Return false.
const bool is_supported = ${index} < ${blink_receiver}->length();
bindings::V8SetReturnValue(${info}, !is_supported);
if (is_supported and ${info}.ShouldThrowOnError()) {
ExceptionState exception_state(${info}.GetIsolate(),
ExceptionState::kIndexedDeletionContext,
"${interface.identifier}");
exception_state.ThrowTypeError("Index property deleter is not supported.");
}"""),
]) ])
return func_decl, func_def return func_decl, func_def
...@@ -1991,7 +2109,7 @@ def make_indexed_property_definer_callback(cg_context, function_name): ...@@ -1991,7 +2109,7 @@ def make_indexed_property_definer_callback(cg_context, function_name):
arg_decls = [ arg_decls = [
"uint32_t index", "uint32_t index",
"const v8::PropertyDescriptor& desc", "const v8::PropertyDescriptor& v8_property_desc",
"const v8::PropertyCallbackInfo<v8::Value>& info", "const v8::PropertyCallbackInfo<v8::Value>& info",
] ]
return_type = "void" return_type = "void"
...@@ -2010,17 +2128,19 @@ def make_indexed_property_definer_callback(cg_context, function_name): ...@@ -2010,17 +2128,19 @@ def make_indexed_property_definer_callback(cg_context, function_name):
func_def.set_base_template_vars(cg_context.template_bindings()) func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body body = func_def.body
body.add_template_var("index", "index") body.add_template_var("index", "index")
body.add_template_var("desc", "desc") body.add_template_var("v8_property_desc", "v8_property_desc")
body.add_template_var("info", "info") body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context) bind_callback_local_vars(body, cg_context)
body.append( body.extend([
make_runtime_call_timer_scope(cg_context, "IndexedPropertyDefiner"),
EmptyNode(),
TextNode("""\ TextNode("""\
// https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
// 3.8.3. [[DefineOwnProperty]] // 3.8.3. [[DefineOwnProperty]]
// https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
// step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then
// return false. // return false.
if (desc.has_get() || desc.has_set()) { if (v8_property_desc.has_get() || v8_property_desc.has_set()) {
bindings::V8SetReturnValue(${info}, nullptr); bindings::V8SetReturnValue(${info}, nullptr);
if (${info}.ShouldThrowOnError()) { if (${info}.ShouldThrowOnError()) {
ExceptionState exception_state(${info}.GetIsolate(), ExceptionState exception_state(${info}.GetIsolate(),
...@@ -2030,18 +2150,10 @@ if (desc.has_get() || desc.has_set()) { ...@@ -2030,18 +2150,10 @@ if (desc.has_get() || desc.has_set()) {
} }
return; return;
} }
""")) """),
])
writable = bool( if not cg_context.interface.indexed_and_named_properties.indexed_setter:
cg_context.interface.indexed_and_named_properties.indexed_setter)
if writable:
body.append(
TextNode("""\
// step 1.3. Invoke the indexed property setter with P and Desc.[[Value]].
//
// Return nothing and fall back to
// ${class_name}::IndexedPropertySetterCallback."""))
else:
body.append( body.append(
TextNode("""\ TextNode("""\
// step 1.2. If O does not implement an interface with an indexed property // step 1.2. If O does not implement an interface with an indexed property
...@@ -2052,8 +2164,15 @@ if (${info}.ShouldThrowOnError()) { ...@@ -2052,8 +2164,15 @@ if (${info}.ShouldThrowOnError()) {
ExceptionState::kIndexedSetterContext, ExceptionState::kIndexedSetterContext,
"${interface.identifier}"); "${interface.identifier}");
exception_state.ThrowTypeError("Index property setter is not supported."); exception_state.ThrowTypeError("Index property setter is not supported.");
return;
}""")) }"""))
else:
body.append(
TextNode("""\
// step 1.3. Invoke the indexed property setter with P and Desc.[[Value]].
${class_name}::IndexedPropertySetterCallback(
${index}, ${v8_property_desc}.value(), ${info});
bindings::V8SetReturnValue(${info}, nullptr);\
"""))
return func_decl, func_def return func_decl, func_def
...@@ -2085,27 +2204,36 @@ def make_indexed_property_descriptor_callback(cg_context, function_name): ...@@ -2085,27 +2204,36 @@ def make_indexed_property_descriptor_callback(cg_context, function_name):
body.add_template_var("info", "info") body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context) bind_callback_local_vars(body, cg_context)
body.extend([
make_runtime_call_timer_scope(cg_context, "IndexedPropertyDescriptor"),
EmptyNode(),
])
pattern = """\ pattern = """\
// LegacyPlatformObjectGetOwnProperty
// https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
// Steps 1.1. to 1.2. are covered here: we rely on // step 1.2.3. If operation was defined without an identifier, then set
// IndexedPropertyGetterCallback() to call the getter function and check // value to the result of performing the steps listed in the interface
// that |index| is a valid property index, in which case it will have set // description to determine the value of an indexed property with index
// info.GetReturnValue() to something other than undefined. // as the index.
// step 1.2.4. Otherwise, operation was defined with an identifier. Set
// value to the result of performing the steps listed in the description
// of operation with index as the only argument value.
${class_name}::IndexedPropertyGetterCallback(${index}, ${info}); ${class_name}::IndexedPropertyGetterCallback(${index}, ${info});
v8::Local<v8::Value> v8_value = ${info}.GetReturnValue().Get(); v8::Local<v8::Value> v8_value = ${info}.GetReturnValue().Get();
// step 1.2. If index is a supported property index, then:
// step 3. Return OrdinaryGetOwnProperty(O, P).
if (v8_value->IsUndefined()) if (v8_value->IsUndefined())
return; return; // Do not intercept. Fallback to OrdinaryGetOwnProperty.
// 1.2.5. Let |desc| be a newly created Property Descriptor with no fields. // step 1.2.6. Set desc.[[Value]] to the result of converting value to an
// 1.2.6. Set desc.[[Value]] to the result of converting value to an
// ECMAScript value. // ECMAScript value.
// 1.2.7. If O implements an interface with an indexed property setter, // step 1.2.7. If O implements an interface with an indexed property setter,
// then set desc.[[Writable]] to true, otherwise set it to false. // then set desc.[[Writable]] to true, otherwise set it to false.
// step 1.2.8. Set desc.[[Enumerable]] and desc.[[Configurable]] to true.
v8::PropertyDescriptor desc(v8_value, /*writable=*/{cxx_writable}); v8::PropertyDescriptor desc(v8_value, /*writable=*/{cxx_writable});
// 1.2.8. Set desc.[[Enumerable]] and desc.[[Configurable]] to true.
desc.set_enumerable(true); desc.set_enumerable(true);
desc.set_configurable(true); desc.set_configurable(true);
// 1.2.9. Return |desc|.
bindings::V8SetReturnValue(${info}, desc);""" bindings::V8SetReturnValue(${info}, desc);"""
writable = bool( writable = bool(
cg_context.interface.indexed_and_named_properties.indexed_setter) cg_context.interface.indexed_and_named_properties.indexed_setter)
...@@ -2138,12 +2266,20 @@ def make_indexed_property_enumerator_callback(cg_context, function_name): ...@@ -2138,12 +2266,20 @@ def make_indexed_property_enumerator_callback(cg_context, function_name):
body.add_template_var("info", "info") body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context) bind_callback_local_vars(body, cg_context)
body.append( body.extend([
make_runtime_call_timer_scope(cg_context, "IndexedPropertyEnumerator"),
EmptyNode(),
TextNode("""\ TextNode("""\
// 3.8.6. [[OwnPropertyKeys]]
// https://heycam.github.io/webidl/#legacy-platform-object-ownpropertykeys
// step 2. If O supports indexed properties, then for each index of O's
// supported property indices, in ascending numerical order, append
// ! ToString(index) to keys.
uint32_t length = ${blink_receiver}->length(); uint32_t length = ${blink_receiver}->length();
v8::Local<v8::Array> array = v8::Local<v8::Array> array =
bindings::EnumerateIndexedProperties(${isolate}, length); bindings::EnumerateIndexedProperties(${isolate}, length);
bindings::V8SetReturnValue(${info}, array);""")) bindings::V8SetReturnValue(${info}, array);"""),
])
return func_decl, func_def return func_decl, func_def
...@@ -2186,8 +2322,47 @@ def make_named_property_getter_callback(cg_context, function_name): ...@@ -2186,8 +2322,47 @@ def make_named_property_getter_callback(cg_context, function_name):
text = _format("${class_name}::{}(${blink_property_name}, ${info});", text = _format("${class_name}::{}(${blink_property_name}, ${info});",
custom_function_name(cg_context)) custom_function_name(cg_context))
body.append(TextNode(text)) body.append(TextNode(text))
return func_decl, func_def
# The named property getter's implementation of Blink is not designed to
# represent the property existence, and we have to determine the property
# existence by heuristics.
type = cg_context.return_type.unwrap()
if type.is_any or type.is_object:
not_found_expr = "${return_value}.IsEmpty()"
elif type.is_string:
not_found_expr = "${return_value}.IsNull()"
elif type.is_interface:
not_found_expr = "!${return_value}"
elif type.is_union:
not_found_expr = "${return_value}.IsNull()"
else: else:
body.append(make_v8_set_return_value(cg_context)) assert False
body.extend([
TextNode("""\
// LegacyPlatformObjectGetOwnProperty
// https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
// step 2.1. If the result of running the named property visibility
// algorithm with property name P and object O is true, then:\
"""),
CxxUnlikelyIfNode(
cond=not_found_expr,
body=[
TextNode("// step 3. Return OrdinaryGetOwnProperty(O, P)."),
TextNode("return; // Do not intercept."),
]),
TextNode("""\
// step 2.1.3. If operation was defined without an identifier, then set
// value to the result of performing the steps listed in the interface
// description to determine the value of a named property with P as the
// name.
// step 2.1.4. Otherwise, operation was defined with an identifier. Set
// value to the result of performing the steps listed in the description
// of operation with P as the only argument value.\
"""),
make_v8_set_return_value(cg_context),
])
return func_decl, func_def return func_decl, func_def
...@@ -2196,9 +2371,6 @@ def make_named_property_setter_callback(cg_context, function_name): ...@@ -2196,9 +2371,6 @@ def make_named_property_setter_callback(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext) assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str) assert isinstance(function_name, str)
if cg_context.named_property_setter is None:
return None, None
arg_decls = [ arg_decls = [
"v8::Local<v8::Name> v8_property_name", "v8::Local<v8::Name> v8_property_name",
"v8::Local<v8::Value> v8_property_value", "v8::Local<v8::Value> v8_property_value",
...@@ -2223,34 +2395,92 @@ def make_named_property_setter_callback(cg_context, function_name): ...@@ -2223,34 +2395,92 @@ def make_named_property_setter_callback(cg_context, function_name):
body.add_template_var("v8_property_value", "v8_property_value") body.add_template_var("v8_property_value", "v8_property_value")
body.add_template_var("info", "info") body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context) bind_callback_local_vars(body, cg_context)
body.extend([
make_runtime_call_timer_scope(cg_context, "NamedPropertySetter"),
EmptyNode(),
])
if not cg_context.named_property_setter:
body.append(
TextNode("""\
// 3.8.2. [[Set]]
// https://heycam.github.io/webidl/#legacy-platform-object-set
// step 1. If O and Receiver are the same object, then:
if (${info}.Holder() == ${info}.This()) {
// OrdinarySetWithOwnDescriptor will end up calling DefineOwnProperty.
// 3.8.3. [[DefineOwnProperty]]
// https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
// step 2.1. Let creating be true if P is not a supported property name,
// and false otherwise.
// step 2.2.1. If creating is false and O does not implement an interface
// with a named property setter, then return false.
${class_name}::NamedPropertyGetterCallback(${v8_property_name}, ${info});
const bool is_creating = ${info}.GetReturnValue().Get()->IsUndefined();
if (!is_creating) {
bindings::V8SetReturnValue(${info}, nullptr);
if (${info}.ShouldThrowOnError()) {
ExceptionState exception_state(${info}.GetIsolate(),
ExceptionState::kSetterContext,
"${interface.identifier}");
exception_state.ThrowTypeError(
"Named property setter is not supported.");
}
return;
}
}
// step 2. Let ownDesc be LegacyPlatformObjectGetOwnProperty(O, P, true).
// step 3. Perform ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver,
// ownDesc).
//
// Do not intercept. Fallback to OrdinarySetWithOwnDescriptor.\
"""))
return func_decl, func_def
bind_return_value( bind_return_value(
body, body,
cg_context, cg_context,
overriding_args=["${blink_property_name}", "${blink_value}"]) overriding_args=["${blink_property_name}", "${blink_property_value}"])
body.register_code_symbol( body.register_code_symbol(
make_v8_to_blink_value( make_v8_to_blink_value(
"blink_value", "blink_property_value",
"${v8_property_value}", "${v8_property_value}",
cg_context.named_property_setter.arguments[1].idl_type, cg_context.named_property_setter.arguments[1].idl_type,
argument_index=2)) argument_index=2))
body.extend([
make_runtime_call_timer_scope(cg_context, "NamedPropertySetter"),
EmptyNode(),
])
if "Custom" in cg_context.named_property_setter.extended_attributes: if "Custom" in cg_context.named_property_setter.extended_attributes:
text = _format( text = _format(
"${class_name}::{}" "${class_name}::{}"
"(${blink_property_name}, ${v8_property_value}, ${info});", "(${blink_property_name}, ${v8_property_value}, ${info});",
custom_function_name(cg_context)) custom_function_name(cg_context))
body.append(TextNode(text)) body.append(TextNode(text))
else: return func_decl, func_def
body.extend([
make_steps_of_ce_reactions(cg_context), body.extend([
EmptyNode(), TextNode("""\
make_v8_set_return_value(cg_context), // 3.8.2. [[Set]]
]) // https://heycam.github.io/webidl/#legacy-platform-object-set
// step 1. If O and Receiver are the same object, then:\
"""),
CxxLikelyIfNode(
cond="${info}.Holder() == ${info}.This()",
body=[
TextNode("""\
// step 1.2.1. Invoke the named property setter with P and V.\
"""),
make_steps_of_ce_reactions(cg_context),
EmptyNode(),
make_v8_set_return_value(cg_context),
TextNode("""\
bindings::V8SetReturnValue(${info}, nullptr);
return;"""),
]),
EmptyNode(),
TextNode("""\
// Do not intercept. Fallback to OrdinarySetWithOwnDescriptor.\
"""),
])
return func_decl, func_def return func_decl, func_def
...@@ -2259,9 +2489,6 @@ def make_named_property_deleter_callback(cg_context, function_name): ...@@ -2259,9 +2489,6 @@ def make_named_property_deleter_callback(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext) assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str) assert isinstance(function_name, str)
if cg_context.named_property_deleter is None:
return None, None
arg_decls = [ arg_decls = [
"v8::Local<v8::Name> v8_property_name", "v8::Local<v8::Name> v8_property_name",
"const v8::PropertyCallbackInfo<v8::Boolean>& info", "const v8::PropertyCallbackInfo<v8::Boolean>& info",
...@@ -2284,24 +2511,88 @@ def make_named_property_deleter_callback(cg_context, function_name): ...@@ -2284,24 +2511,88 @@ def make_named_property_deleter_callback(cg_context, function_name):
body.add_template_var("v8_property_name", "v8_property_name") body.add_template_var("v8_property_name", "v8_property_name")
body.add_template_var("info", "info") body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context) bind_callback_local_vars(body, cg_context)
bind_return_value(
body, cg_context, overriding_args=["${blink_property_name}"])
body.extend([ body.extend([
make_runtime_call_timer_scope(cg_context), make_runtime_call_timer_scope(cg_context, "NamedPropertyDeleter"),
EmptyNode(), EmptyNode(),
]) ])
props = cg_context.interface.indexed_and_named_properties
if (not cg_context.named_property_deleter
and "NotEnumerable" in props.named_getter.extended_attributes):
body.append(
TextNode("""\
// 3.8.4. [[Delete]]
// https://heycam.github.io/webidl/#legacy-platform-object-delete
// step 2. If O supports named properties, O does not implement an interface
// with the [Global] extended attribute and the result of calling the
// named property visibility algorithm with property name P and object O
// is true, then:
//
// There is no easy way to determine whether the named property is visible
// or not. Just do not intercept and fallback to the default behavior.\
"""))
return func_decl, func_def
if not cg_context.named_property_deleter:
body.append(
TextNode("""\
// 3.8.4. [[Delete]]
// https://heycam.github.io/webidl/#legacy-platform-object-delete
// step 2. If O supports named properties, O does not implement an interface
// with the [Global] extended attribute and the result of calling the
// named property visibility algorithm with property name P and object O
// is true, then:
// step 2.1. If O does not implement an interface with a named property
// deleter, then return false.
ExceptionState exception_state(${info}.GetIsolate(),
ExceptionState::kDeletionContext,
"${interface.identifier}");
bool does_exist = ${blink_receiver}->NamedPropertyQuery(
${blink_property_name}, exception_state);
if (exception_state.HadException())
return;
if (does_exist) {
bindings::V8SetReturnValue(${info}, false);
if (${info}.ShouldThrowOnError()) {
exception_state.ThrowTypeError(
"Named property deleter is not supported.");
}
return;
}
// Do not intercept.\
"""))
return func_decl, func_def
bind_return_value(
body, cg_context, overriding_args=["${blink_property_name}"])
if "Custom" in cg_context.named_property_deleter.extended_attributes: if "Custom" in cg_context.named_property_deleter.extended_attributes:
text = _format("${class_name}::{}(${blink_property_name}, ${info});", text = _format("${class_name}::{}(${blink_property_name}, ${info});",
custom_function_name(cg_context)) custom_function_name(cg_context))
body.append(TextNode(text)) body.append(TextNode(text))
else: return func_decl, func_def
body.extend([
make_steps_of_ce_reactions(cg_context), body.extend([
EmptyNode(), TextNode("""\
make_v8_set_return_value(cg_context), // 3.8.4. [[Delete]]
]) // https://heycam.github.io/webidl/#legacy-platform-object-delete\
"""),
make_steps_of_ce_reactions(cg_context),
EmptyNode(),
make_v8_set_return_value(cg_context),
TextNode("""\
if (${return_value} == NamedPropertyDeleterResult::kDidNotDelete) {
if (${info}.ShouldThrowOnError()) {
ExceptionState exception_state(${info}.GetIsolate(),
ExceptionState::kDeletionContext,
"${interface.identifier}");
exception_state.ThrowTypeError("Failed to delete a property.");
}
return;
}"""),
])
return func_decl, func_def return func_decl, func_def
...@@ -2312,7 +2603,7 @@ def make_named_property_definer_callback(cg_context, function_name): ...@@ -2312,7 +2603,7 @@ def make_named_property_definer_callback(cg_context, function_name):
arg_decls = [ arg_decls = [
"v8::Local<v8::Name> v8_property_name", "v8::Local<v8::Name> v8_property_name",
"const v8::PropertyDescriptor& desc", "const v8::PropertyDescriptor& v8_property_desc",
"const v8::PropertyCallbackInfo<v8::Value>& info", "const v8::PropertyCallbackInfo<v8::Value>& info",
] ]
return_type = "void" return_type = "void"
...@@ -2331,50 +2622,62 @@ def make_named_property_definer_callback(cg_context, function_name): ...@@ -2331,50 +2622,62 @@ def make_named_property_definer_callback(cg_context, function_name):
func_def.set_base_template_vars(cg_context.template_bindings()) func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body body = func_def.body
body.add_template_var("v8_property_name", "v8_property_name") body.add_template_var("v8_property_name", "v8_property_name")
body.add_template_var("desc", "desc") body.add_template_var("v8_property_desc", "v8_property_desc")
body.add_template_var("info", "info") body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context) bind_callback_local_vars(body, cg_context)
body.append( body.extend([
make_runtime_call_timer_scope(cg_context, "NamedPropertyDefiner"),
EmptyNode(),
TextNode("""\ TextNode("""\
// https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
// 3.8.3. [[DefineOwnProperty]] // 3.8.3. [[DefineOwnProperty]]
// step 2.2.2.1. If the result of calling IsDataDescriptor(Desc) is false, // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty\
// then return false. """),
if (desc.has_get() || desc.has_set()) { ])
if not cg_context.interface.indexed_and_named_properties.named_setter:
body.append(
TextNode("""\
// step 2.1. Let creating be true if P is not a supported property name, and
// false otherwise.
// step 2.2.1. If creating is false and O does not implement an interface
// with a named property setter, then return false.
${class_name}::NamedPropertyGetterCallback(${v8_property_name}, ${info});
const bool is_creating = ${info}.GetReturnValue().Get()->IsUndefined();
if (!is_creating) {
bindings::V8SetReturnValue(${info}, nullptr); bindings::V8SetReturnValue(${info}, nullptr);
if (${info}.ShouldThrowOnError()) { if (${info}.ShouldThrowOnError()) {
ExceptionState exception_state(${info}.GetIsolate(), ExceptionState exception_state(${info}.GetIsolate(),
ExceptionState::kSetterContext, ExceptionState::kSetterContext,
"${interface.identifier}"); "${interface.identifier}");
exception_state.ThrowTypeError("Accessor properties are not allowed."); exception_state.ThrowTypeError("Named property setter is not supported.");
} }
return; return;
} }
"""))
writable = bool( // Do not intercept. Fallback to OrdinaryDefineOwnProperty.\
cg_context.interface.indexed_and_named_properties.named_setter) """))
if writable:
body.append(
TextNode("""\
// step 2.2.2. Invoke the named property setter with P and Desc.[[Value]].
//
// Return nothing and fall back to
// ${class_name}::NamedPropertySetterCallback."""))
else: else:
body.append( body.append(
TextNode("""\ TextNode("""\
// step 2.2.1. If creating is false and O does not implement an interface // step 2.2.2. If O implements an interface with a named property setter,
// with a named property setter, then return false. // then:
bindings::V8SetReturnValue(${info}, nullptr); // step 2.2.2.1. If the result of calling IsDataDescriptor(Desc) is false,
if (${info}.ShouldThrowOnError()) { // then return false.
ExceptionState exception_state(${info}.GetIsolate(), if (v8_property_desc.has_get() || v8_property_desc.has_set()) {
ExceptionState::kSetterContext, bindings::V8SetReturnValue(${info}, nullptr);
"${interface.identifier}"); if (${info}.ShouldThrowOnError()) {
exception_state.ThrowTypeError("Named property setter is not supported."); ExceptionState exception_state(${info}.GetIsolate(),
ExceptionState::kSetterContext,
"${interface.identifier}");
exception_state.ThrowTypeError("Accessor properties are not allowed.");
}
return; return;
}""")) }
// step 2.2.2.2. Invoke the named property setter with P and Desc.[[Value]].
${class_name}::NamedPropertySetterCallback(
${v8_property_name}, ${v8_property_desc}.value(), ${info});
bindings::V8SetReturnValue(${info}, nullptr);\
"""))
return func_decl, func_def return func_decl, func_def
...@@ -2406,30 +2709,40 @@ def make_named_property_descriptor_callback(cg_context, function_name): ...@@ -2406,30 +2709,40 @@ def make_named_property_descriptor_callback(cg_context, function_name):
body.add_template_var("info", "info") body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context) bind_callback_local_vars(body, cg_context)
body.extend([
make_runtime_call_timer_scope(cg_context, "NamedPropertyDescriptor"),
EmptyNode(),
])
pattern = """\ pattern = """\
// LegacyPlatformObjectGetOwnProperty
// https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty
// Steps 2.1. is covered here: we rely on // step 2.1.3. If operation was defined without an identifier, then set
// NamedPropertyGetterCallback() to call the getter function and check // value to the result of performing the steps listed in the interface
// that |v8_property_name| is a valid property name, in which case it will // description to determine the value of a named property with P as the
// have set info.GetReturnValue() to something other than undefined. // name.
// step 2.1.4. Otherwise, operation was defined with an identifier. Set
// value to the result of performing the steps listed in the description
// of operation with P as the only argument value.
${class_name}::NamedPropertyGetterCallback(${v8_property_name}, ${info}); ${class_name}::NamedPropertyGetterCallback(${v8_property_name}, ${info});
v8::Local<v8::Value> v8_value = ${info}.GetReturnValue().Get(); v8::Local<v8::Value> v8_value = ${info}.GetReturnValue().Get();
// step 2.1. If the result of running the named property visibility
// algorithm with property name P and object O is true, then:
// step 3. Return OrdinaryGetOwnProperty(O, P).
if (v8_value->IsUndefined()) if (v8_value->IsUndefined())
return; return; // Do not intercept. Fallback to OrdinaryGetOwnProperty.
// 2.1.5. Let |desc| be a newly created Property Descriptor with no fields. // step 2.1.6. Set desc.[[Value]] to the result of converting value to an
// 2.1.6. Set desc.[[Value]] to the result of converting value to an
// ECMAScript value. // ECMAScript value.
// 2.1.7. If O implements an interface with a named property setter, then // step 2.1.7. If O implements an interface with a named property setter,
// set desc.[[Writable]] to true, otherwise set it to false. // then set desc.[[Writable]] to true, otherwise set it to false.
v8::PropertyDescriptor desc(v8_value, /*writable=*/{cxx_writable}); // step 2.1.8. If O implements an interface with the
// 2.1.8. If O implements an interface with the
// [LegacyUnenumerableNamedProperties] extended attribute, then set // [LegacyUnenumerableNamedProperties] extended attribute, then set
// desc.[[Enumerable]] to false, otherwise set it to true. // desc.[[Enumerable]] to false, otherwise set it to true.
// step 2.1.9. Set desc.[[Configurable]] to true.
v8::PropertyDescriptor desc(v8_value, /*writable=*/{cxx_writable});
desc.set_enumerable({cxx_enumerable}); desc.set_enumerable({cxx_enumerable});
// 2.1.9. Set desc.[[Configurable]] to true.
desc.set_configurable(true); desc.set_configurable(true);
// 1.2.9. Return |desc|.
bindings::V8SetReturnValue(${info}, desc);""" bindings::V8SetReturnValue(${info}, desc);"""
props = cg_context.interface.indexed_and_named_properties props = cg_context.interface.indexed_and_named_properties
writable = bool(props.named_setter) writable = bool(props.named_setter)
...@@ -2446,12 +2759,77 @@ bindings::V8SetReturnValue(${info}, desc);""" ...@@ -2446,12 +2759,77 @@ bindings::V8SetReturnValue(${info}, desc);"""
return func_decl, func_def return func_decl, func_def
def make_named_property_query_callback(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str)
props = cg_context.interface.indexed_and_named_properties
if "NotEnumerable" in props.named_getter.extended_attributes:
return None, None
arg_decls = [
"v8::Local<v8::Name> v8_property_name",
"const v8::PropertyCallbackInfo<v8::Integer>& info",
]
return_type = "void"
func_decl = CxxFuncDeclNode(
name=function_name,
arg_decls=arg_decls,
return_type=return_type,
static=True)
func_def = CxxFuncDefNode(
name=function_name,
arg_decls=arg_decls,
return_type=return_type,
class_name=cg_context.class_name)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
body.add_template_var("v8_property_name", "v8_property_name")
body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context)
flags = []
if not props.named_setter:
flags.append("v8::ReadOnly")
if not props.is_named_property_enumerable:
flags.append("v8::DontEnum")
if not flags:
flags.append("v8::None")
if len(flags) == 1:
property_attribute = flags[0]
else:
property_attribute = " | ".join(flags)
body.extend([
make_runtime_call_timer_scope(cg_context, "NamedPropertyQuery"),
EmptyNode(),
TextNode("""\
ExceptionState exception_state(${isolate},
ExceptionState::kQueryContext,
"${interface.identifier}");
bool does_exist = ${blink_receiver}->NamedPropertyQuery(
${blink_property_name}, exception_state);
if (!does_exist)
return; // Do not intercept.
"""),
TextNode(
_format(
"bindings::V8SetReturnValue"
"(${info}, uint32_t({property_attribute}));",
property_attribute=property_attribute)),
])
return func_decl, func_def
def make_named_property_enumerator_callback(cg_context, function_name): def make_named_property_enumerator_callback(cg_context, function_name):
assert isinstance(cg_context, CodeGenContext) assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str) assert isinstance(function_name, str)
if not (cg_context.interface.indexed_and_named_properties. props = cg_context.interface.indexed_and_named_properties
is_named_property_enumerable): if "NotEnumerable" in props.named_getter.extended_attributes:
return None, None return None, None
arg_decls = ["const v8::PropertyCallbackInfo<v8::Array>& info"] arg_decls = ["const v8::PropertyCallbackInfo<v8::Array>& info"]
...@@ -2473,8 +2851,15 @@ def make_named_property_enumerator_callback(cg_context, function_name): ...@@ -2473,8 +2851,15 @@ def make_named_property_enumerator_callback(cg_context, function_name):
body.add_template_var("info", "info") body.add_template_var("info", "info")
bind_callback_local_vars(body, cg_context) bind_callback_local_vars(body, cg_context)
body.append( body.extend([
make_runtime_call_timer_scope(cg_context, "NamedPropertyEnumerator"),
EmptyNode(),
TextNode("""\ TextNode("""\
// 3.8.6. [[OwnPropertyKeys]]
// https://heycam.github.io/webidl/#legacy-platform-object-ownpropertykeys
// step 3. If O supports named properties, then for each P of O's supported
// property names that is visible according to the named property
// visibility algorithm, append P to keys.
Vector<String> blink_property_names; Vector<String> blink_property_names;
${blink_receiver}->NamedPropertyEnumerator( ${blink_receiver}->NamedPropertyEnumerator(
blink_property_names, ${exception_state}); blink_property_names, ${exception_state});
...@@ -2482,8 +2867,9 @@ if (${exception_state}.HadException()) ...@@ -2482,8 +2867,9 @@ if (${exception_state}.HadException())
return; return;
bindings::V8SetReturnValue( bindings::V8SetReturnValue(
${info}, ${info},
ToV8(blink_property_names, ${creation_context_object}, ${isolate})); ToV8(blink_property_names, ${creation_context_object}, ${isolate}));\
""")) """),
])
return func_decl, func_def return func_decl, func_def
...@@ -3614,6 +4000,23 @@ def make_install_interface_template( ...@@ -3614,6 +4000,23 @@ def make_install_interface_template(
${instance_template}->SetCallAsFunctionHandler( ${instance_template}->SetCallAsFunctionHandler(
${class_name}::LegacyCallCustom); ${class_name}::LegacyCallCustom);
${instance_template}->MarkAsUndetectable(); ${instance_template}->MarkAsUndetectable();
"""))
if cg_context.class_like.identifier == "Iterator":
body.append(
T("""\
// Iterator-specific settings
// https://heycam.github.io/webidl/#es-iterator-prototype-object
{
v8::Local<v8::FunctionTemplate>
intrinsic_iterator_prototype_interface_template =
v8::FunctionTemplate::New(${isolate});
intrinsic_iterator_prototype_interface_template->RemovePrototype();
intrinsic_iterator_prototype_interface_template->SetIntrinsicDataProperty(
V8AtomicString(${isolate}, "prototype"), v8::kIteratorPrototype);
${interface_template}->Inherit(
intrinsic_iterator_prototype_interface_template);
}
""")) """))
if cg_context.class_like.identifier == "Location": if cg_context.class_like.identifier == "Location":
...@@ -3631,7 +4034,7 @@ ${instance_template}->SetIntrinsicDataProperty( ...@@ -3631,7 +4034,7 @@ ${instance_template}->SetIntrinsicDataProperty(
V8AtomicString(${isolate}, "valueOf"), V8AtomicString(${isolate}, "valueOf"),
v8::kObjProto_valueOf, v8::kObjProto_valueOf,
static_cast<v8::PropertyAttribute>( static_cast<v8::PropertyAttribute>(
int(v8::ReadOnly) | int(v8::DontEnum) | int(v8::DontDelete))); v8::ReadOnly | v8::DontEnum | v8::DontDelete));
// step 4. Perform ! location.[[DefineOwnProperty]](@@toPrimitive, // step 4. Perform ! location.[[DefineOwnProperty]](@@toPrimitive,
// { [[Value]]: undefined, [[Writable]]: false, [[Enumerable]]: false, // { [[Value]]: undefined, [[Writable]]: false, [[Enumerable]]: false,
// [[Configurable]]: false }). // [[Configurable]]: false }).
...@@ -3639,7 +4042,7 @@ ${instance_template}->Set( ...@@ -3639,7 +4042,7 @@ ${instance_template}->Set(
v8::Symbol::GetToPrimitive(${isolate}), v8::Symbol::GetToPrimitive(${isolate}),
v8::Undefined(${isolate}), v8::Undefined(${isolate}),
static_cast<v8::PropertyAttribute>( static_cast<v8::PropertyAttribute>(
int(v8::ReadOnly) | int(v8::DontEnum) | int(v8::DontDelete))); v8::ReadOnly | v8::DontEnum | v8::DontDelete));
""")) """))
if indexed_and_named_property_install_nodes: if indexed_and_named_property_install_nodes:
...@@ -3648,6 +4051,31 @@ ${instance_template}->Set( ...@@ -3648,6 +4051,31 @@ ${instance_template}->Set(
EmptyNode(), EmptyNode(),
]) ])
if (cg_context.interface
and cg_context.interface.indexed_and_named_properties and
cg_context.interface.indexed_and_named_properties.indexed_getter
and "Global" not in cg_context.interface.extended_attributes):
body.append(
T("""\
// @@iterator for indexed properties
${prototype_template}->SetIntrinsicDataProperty(
v8::Symbol::GetIterator(${isolate}), v8::kArrayProto_values, v8::DontEnum);
"""))
if (cg_context.interface.iterable
and cg_context.interface.iterable.key_type is None):
body.append(
T("""\
// Value iterator for indexed properties
${prototype_template}->SetIntrinsicDataProperty(
V8AtomicString(${isolate}, "entries"), v8::kArrayProto_entries, v8::None);
${prototype_template}->SetIntrinsicDataProperty(
V8AtomicString(${isolate}, "keys"), v8::kArrayProto_keys, v8::None);
${prototype_template}->SetIntrinsicDataProperty(
V8AtomicString(${isolate}, "values"), v8::kArrayProto_values, v8::None);
${prototype_template}->SetIntrinsicDataProperty(
V8AtomicString(${isolate}, "forEach"), v8::kArrayProto_forEach, v8::None);
"""))
if ("Global" in cg_context.class_like.extended_attributes if ("Global" in cg_context.class_like.extended_attributes
or cg_context.class_like.identifier == "Location"): or cg_context.class_like.identifier == "Location"):
if "Global" in cg_context.class_like.extended_attributes: if "Global" in cg_context.class_like.extended_attributes:
...@@ -3936,6 +4364,8 @@ def make_indexed_and_named_property_callbacks_and_install_nodes(cg_context): ...@@ -3936,6 +4364,8 @@ def make_indexed_and_named_property_callbacks_and_install_nodes(cg_context):
add_callback(*make_indexed_property_setter_callback( add_callback(*make_indexed_property_setter_callback(
cg_context.make_copy(indexed_property_setter=props.indexed_setter), cg_context.make_copy(indexed_property_setter=props.indexed_setter),
"IndexedPropertySetterCallback")) "IndexedPropertySetterCallback"))
add_callback(*make_indexed_property_deleter_callback(
cg_context, "IndexedPropertyDeleterCallback"))
add_callback(*make_indexed_property_definer_callback( add_callback(*make_indexed_property_definer_callback(
cg_context, "IndexedPropertyDefinerCallback")) cg_context, "IndexedPropertyDefinerCallback"))
add_callback(*make_indexed_property_descriptor_callback( add_callback(*make_indexed_property_descriptor_callback(
...@@ -3961,15 +4391,12 @@ def make_indexed_and_named_property_callbacks_and_install_nodes(cg_context): ...@@ -3961,15 +4391,12 @@ def make_indexed_and_named_property_callbacks_and_install_nodes(cg_context):
${instance_template}->SetHandler( ${instance_template}->SetHandler(
v8::IndexedPropertyHandlerConfiguration( v8::IndexedPropertyHandlerConfiguration(
{impl_bridge}::IndexedPropertyGetterCallback, {impl_bridge}::IndexedPropertyGetterCallback,
% if interface.indexed_and_named_properties.indexed_setter:
{impl_bridge}::IndexedPropertySetterCallback, {impl_bridge}::IndexedPropertySetterCallback,
% else: nullptr, // query
nullptr, // setter {impl_bridge}::IndexedPropertyDeleterCallback,
% endif
{impl_bridge}::IndexedPropertyDescriptorCallback,
nullptr, // deleter
{impl_bridge}::IndexedPropertyEnumeratorCallback, {impl_bridge}::IndexedPropertyEnumeratorCallback,
{impl_bridge}::IndexedPropertyDefinerCallback, {impl_bridge}::IndexedPropertyDefinerCallback,
{impl_bridge}::IndexedPropertyDescriptorCallback,
v8::Local<v8::Value>(), v8::Local<v8::Value>(),
{property_handler_flags}));""" {property_handler_flags}));"""
install_nodes.append( install_nodes.append(
...@@ -3994,6 +4421,8 @@ ${instance_template}->SetHandler( ...@@ -3994,6 +4421,8 @@ ${instance_template}->SetHandler(
cg_context, "NamedPropertyDefinerCallback")) cg_context, "NamedPropertyDefinerCallback"))
add_callback(*make_named_property_descriptor_callback( add_callback(*make_named_property_descriptor_callback(
cg_context, "NamedPropertyDescriptorCallback")) cg_context, "NamedPropertyDescriptorCallback"))
add_callback(*make_named_property_query_callback(
cg_context, "NamedPropertyQueryCallback"))
add_callback(*make_named_property_enumerator_callback( add_callback(*make_named_property_enumerator_callback(
cg_context, "NamedPropertyEnumeratorCallback")) cg_context, "NamedPropertyEnumeratorCallback"))
...@@ -4012,7 +4441,7 @@ ${instance_template}->SetHandler( ...@@ -4012,7 +4441,7 @@ ${instance_template}->SetHandler(
flags.append("v8::PropertyHandlerFlags::kHasNoSideEffect") flags.append("v8::PropertyHandlerFlags::kHasNoSideEffect")
property_handler_flags = ( property_handler_flags = (
"static_cast<v8::PropertyHandlerFlags>({})".format(" | ".join( "static_cast<v8::PropertyHandlerFlags>({})".format(" | ".join(
map(lambda flag: "int({})".format(flag), flags)))) map(lambda flag: "int32_t({})".format(flag), flags))))
pattern = """\ pattern = """\
// Named properties // Named properties
% if "Global" in interface.extended_attributes: % if "Global" in interface.extended_attributes:
...@@ -4023,23 +4452,22 @@ ${instance_template} ...@@ -4023,23 +4452,22 @@ ${instance_template}
->SetHandler( ->SetHandler(
v8::NamedPropertyHandlerConfiguration( v8::NamedPropertyHandlerConfiguration(
{impl_bridge}::NamedPropertyGetterCallback, {impl_bridge}::NamedPropertyGetterCallback,
% if interface.indexed_and_named_properties.named_setter:
{impl_bridge}::NamedPropertySetterCallback, {impl_bridge}::NamedPropertySetterCallback,
% if "NotEnumerable" not in \
interface.indexed_and_named_properties.named_getter.extended_attributes:
{impl_bridge}::NamedPropertyQueryCallback,
% else: % else:
nullptr, // setter nullptr, // query
% endif % endif
{impl_bridge}::NamedPropertyDescriptorCallback,
% if interface.indexed_and_named_properties.named_deleter:
{impl_bridge}::NamedPropertyDeleterCallback, {impl_bridge}::NamedPropertyDeleterCallback,
% else: % if "NotEnumerable" not in \
nullptr, // deleter interface.indexed_and_named_properties.named_getter.extended_attributes:
% endif
% if interface.indexed_and_named_properties.is_named_property_enumerable:
{impl_bridge}::NamedPropertyEnumeratorCallback, {impl_bridge}::NamedPropertyEnumeratorCallback,
% else: % else:
nullptr, // enumerator nullptr, // enumerator
% endif % endif
{impl_bridge}::NamedPropertyDefinerCallback, {impl_bridge}::NamedPropertyDefinerCallback,
{impl_bridge}::NamedPropertyDescriptorCallback,
v8::Local<v8::Value>(), v8::Local<v8::Value>(),
{property_handler_flags}));""" {property_handler_flags}));"""
install_nodes.append( install_nodes.append(
......
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