Skip to content

Commit

Permalink
bindings: Rename [NamedConstructor] to [LegacyFactoryFunction]
Browse files Browse the repository at this point in the history
Renames [NamedConstructor] to [LegacyFactoryFunction] following
a spec change. No behavioral change.

Bug: 1072773
Change-Id: Iaf49cd14668237f507f7536a077a4820d779ac4d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4578742
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1151787}
  • Loading branch information
yuki3 authored and Chromium LUCI CQ committed Jun 1, 2023
1 parent 074580d commit 2e9f0d5
Show file tree
Hide file tree
Showing 15 changed files with 176 additions and 170 deletions.
56 changes: 28 additions & 28 deletions third_party/blink/renderer/bindings/IDLExtendedAttributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,26 @@ Summary: HTML Elements have special constructor behavior. Interface object of gi

Usage: Must take no arguments, and must not appear on anything other than an interface. It must appear once on an interface, and the interface cannot be annotated with `[Constructor]` or `[LegacyNoInterfaceObject]` extended attributes. It must not be used on a callback interface.

### [LegacyFactoryFunction]

Standard: [LegacyFactoryFunction](https://webidl.spec.whatwg.org/#LegacyFactoryFunction)

Summary: If you want to allow JavaScript to create a DOM object of XXX using a different name constructor (i.e. allow JavaScript to create an XXX object using "new YYY()", where YYY != XXX), you can use `[LegacyFactoryFunction]`.

Usage: The possible usage is `[LegacyFactoryFunction=YYY(...)]`. Just as with constructors. `[LegacyFactoryFunction]` can be specified on interfaces. The spec allows multiple legacy factory functions, but the Blink IDL compiler currently only supports at most one.

```webidl
[
LegacyFactoryFunction=Audio(DOMString data),
] interface HTMLAudioElement {
...
};
```

The semantics are the same as constructors, except that the name changes: JavaScript can make a DOM object by `new Audio()` instead of by `new HTMLAudioElement()`.

Whether you should allow an interface to have a legacy factory function or not depends on the spec of each interface.

### [LegacyLenientSetter]

Standard: [LegacyLenientSetter](https://webidl.spec.whatwg.org/#LenientSetter)
Expand Down Expand Up @@ -376,26 +396,6 @@ By default, interface members are configurable (i.e. you can modify a property d

Standard: [LegacyWindowAlias](https://webidl.spec.whatwg.org/#LegacyWindowAlias)

### [NamedConstructor]

Standard: [NamedConstructor](https://webidl.spec.whatwg.org/#NamedConstructor)

Summary: If you want to allow JavaScript to create a DOM object of XXX using a different name constructor (i.e. allow JavaScript to create an XXX object using "new YYY()", where YYY != XXX), you can use `[NamedConstructor]`.

Usage: The possible usage is `[NamedConstructor=YYY(...)]`. Just as with constructors, an empty argument list can be omitted, as: `[NamedConstructor=YYY]`. `[NamedConstructor]` can be specified on interfaces. The spec allows multiple named constructors, but the Blink IDL compiler currently only supports at most one.

```webidl
[
NamedConstructor=Audio(DOMString data),
] interface HTMLAudioElement {
...
};
```

The semantics are the same as `[Constructor]`, except that the name changes: JavaScript can make a DOM object by `new Audio()` instead of by `new HTMLAudioElement()`.

Whether you should allow an interface to have a named constructor or not depends on the spec of each interface.

### [NewObject]

Standard: [NewObject](https://webidl.spec.whatwg.org/#NewObject)
Expand Down Expand Up @@ -1229,6 +1229,14 @@ interface TCPSocket {
};
```

### [LegacyFactoryFunction_CallWith]

Summary: The same as `[CallWith]` but applied to the legacy factory functions (aka the named constructors).

### [LegacyFactoryFunction_RaisesException]

Summary: The same as `[RaisesException]` but applied to the legacy factory functions (aka the named constructors).

### [LegacyWindowAlias_Measure]

Summary: The same as `[Measure]` but applied to the property exposed as `[LegacyWindowAlias]`.
Expand All @@ -1241,14 +1249,6 @@ Summary: The same as `[MeasureAs]` but applied to the property exposed as `[Lega

Summary: The same as `[RuntimeEnabled]` but applied to the property exposed as `[LegacyWindowAlias]`.

### [NamedConstructor_CallWith]

Summary: The same as `[CallWith]` but applied to the named constructors.

### [NamedConstructor_RaisesException]

Summary: The same as `[RaisesException]` but applied to the named constructors.

### [NoAllocDirectCall]

Summary: `[NoAllocDirectCall]` marks a given method as being usable with the fast API calls implemented in V8. They get their value conversions inlined in TurboFan, leading to overall better performance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ ExecutionContext* ExecutionContextFromV8Wrappable(const DOMParser* parser) {
return parser->GetWindow();
}

v8::MaybeLocal<v8::Value> CreateNamedConstructorFunction(
v8::MaybeLocal<v8::Value> CreateLegacyFactoryFunctionFunction(
ScriptState* script_state,
v8::FunctionCallback callback,
const char* func_name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable(
CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable(
const DOMParser* parser);

CORE_EXPORT v8::MaybeLocal<v8::Value> CreateNamedConstructorFunction(
CORE_EXPORT v8::MaybeLocal<v8::Value> CreateLegacyFactoryFunctionFunction(
ScriptState* script_state,
v8::FunctionCallback callback,
const char* func_name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def init(cls):
"constructor_group": None,
"dict_member": None,
"exposed_construct": None,
"is_named_constructor": False,
"is_legacy_factory_function": False,
"legacy_window_alias": None,
"operation": None,
"operation_group": None,
Expand Down
84 changes: 45 additions & 39 deletions third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def backward_compatible_api_func(cg_context):
if name:
pass
elif cg_context.constructor:
if cg_context.is_named_constructor:
if cg_context.is_legacy_factory_function:
name = "CreateForJSConstructor"
else:
name = "Create"
Expand Down Expand Up @@ -159,14 +159,14 @@ def _cxx_name(name):
elif cg_context.constant:
kind = "Constant"
elif cg_context.constructor_group:
if cg_context.is_named_constructor:
kind = "NamedConstructor"
if cg_context.is_legacy_factory_function:
kind = "LegacyFactoryFunction"
else:
property_name = ""
kind = "Constructor"
elif cg_context.exposed_construct:
if cg_context.is_named_constructor:
kind = "NamedConstructorProperty"
if cg_context.is_legacy_factory_function:
kind = "LegacyFactoryFunctionProperty"
elif cg_context.legacy_window_alias:
kind = "LegacyWindowAlias"
else:
Expand Down Expand Up @@ -437,7 +437,7 @@ def create_exception_state(symbol_node):
CodeGenAccumulator.require_include_headers([
"third_party/blink/renderer/platform/bindings/no_alloc_direct_call_exception_state.h"
]))
if cg_context.is_named_constructor:
if cg_context.is_legacy_factory_function:
init_args.append("\"{}\"".format(cg_context.property_.identifier))
else:
init_args.append("${class_like_name}")
Expand Down Expand Up @@ -876,7 +876,8 @@ def _make_bindings_logging_id(cg_context):
logging_id = "{}.{}".format(logging_id, "get")
elif cg_context.attribute_set:
logging_id = "{}.{}".format(logging_id, "set")
elif cg_context.constructor_group and not cg_context.is_named_constructor:
elif (cg_context.constructor_group
and not cg_context.is_legacy_factory_function):
logging_id = "{}.{}".format(cg_context.class_like.identifier,
"constructor")
return logging_id
Expand Down Expand Up @@ -945,7 +946,7 @@ def make_check_constructor_call(cg_context):
"ExceptionMessages::ConstructorCalledAsFunction());\n"
"return;")),
])
if not cg_context.is_named_constructor:
if not cg_context.is_legacy_factory_function:
node.append(
CxxLikelyIfNode(
cond=("ConstructorMode::Current(${isolate}) == "
Expand Down Expand Up @@ -2223,7 +2224,8 @@ def make_exposed_construct_callback_def(cg_context, function_name):
return func_def


def make_named_constructor_property_callback_def(cg_context, function_name):
def make_legacy_factory_function_property_callback_def(cg_context,
function_name):
assert isinstance(cg_context, CodeGenContext)
assert isinstance(function_name, str)

Expand All @@ -2243,32 +2245,34 @@ def make_named_constructor_property_callback_def(cg_context, function_name):
assert isinstance(constructor_group, web_idl.ConstructorGroup)
assert isinstance(constructor_group.owner, web_idl.Interface)
named_ctor_v8_bridge = v8_bridge_class_name(constructor_group.owner)
cgc = CodeGenContext(
interface=constructor_group.owner,
constructor_group=constructor_group,
is_named_constructor=True,
class_name=named_ctor_v8_bridge)
cgc = CodeGenContext(interface=constructor_group.owner,
constructor_group=constructor_group,
is_legacy_factory_function=True,
class_name=named_ctor_v8_bridge)
named_ctor_name = callback_function_name(cgc)
named_ctor_def = make_constructor_callback_def(cgc, named_ctor_name)

return_value_cache_return_early = """\
static const V8PrivateProperty::SymbolKey kPrivatePropertyNamedConstructor;
auto&& v8_private_named_constructor =
V8PrivateProperty::GetSymbol(${isolate}, kPrivatePropertyNamedConstructor);
v8::Local<v8::Value> v8_named_constructor;
if (!v8_private_named_constructor.GetOrUndefined(${v8_receiver})
.ToLocal(&v8_named_constructor)) {
static const V8PrivateProperty::SymbolKey
kPrivatePropertyLegacyFactoryFunction;
auto&& v8_private_legacy_factory_function =
V8PrivateProperty::GetSymbol(
${isolate},
kPrivatePropertyLegacyFactoryFunction);
v8::Local<v8::Value> v8_legacy_factory_function;
if (!v8_private_legacy_factory_function.GetOrUndefined(${v8_receiver})
.ToLocal(&v8_legacy_factory_function)) {
return;
}
if (!v8_named_constructor->IsUndefined()) {
bindings::V8SetReturnValue(${info}, v8_named_constructor);
if (!v8_legacy_factory_function->IsUndefined()) {
bindings::V8SetReturnValue(${info}, v8_legacy_factory_function);
return;
}
"""

pattern = """\
v8::Local<v8::Value> v8_value;
if (!bindings::CreateNamedConstructorFunction(
if (!bindings::CreateLegacyFactoryFunctionFunction(
${script_state},
{callback},
"{func_name}",
Expand All @@ -2279,20 +2283,20 @@ def make_named_constructor_property_callback_def(cg_context, function_name):
}
bindings::V8SetReturnValue(${info}, v8_value);
"""
create_named_constructor_function = _format(
create_legacy_factory_function_function = _format(
pattern,
callback=named_ctor_name,
func_name=constructor_group.identifier,
func_length=constructor_group.min_num_of_required_arguments,
v8_bridge=named_ctor_v8_bridge)

return_value_cache_update_value = """\
v8_private_named_constructor.Set(${v8_receiver}, v8_value);
v8_private_legacy_factory_function.Set(${v8_receiver}, v8_value);
"""

body.extend([
TextNode(return_value_cache_return_early),
TextNode(create_named_constructor_function),
TextNode(create_legacy_factory_function_function),
TextNode(return_value_cache_update_value),
])

Expand Down Expand Up @@ -5519,17 +5523,18 @@ def process_exposed_construct(exposed_construct, is_context_dependent,
exposed_construct=exposed_construct,
prop_callback_name=prop_callback_name))

def process_named_constructor_group(named_constructor_group,
is_context_dependent,
exposure_conditional, world):
def process_legacy_factory_function_group(legacy_factory_function_group,
is_context_dependent,
exposure_conditional, world):
cgc = cg_context.make_copy(
exposed_construct=named_constructor_group,
is_named_constructor=True,
exposed_construct=legacy_factory_function_group,
is_legacy_factory_function=True,
for_world=world,
v8_callback_type=CodeGenContext.V8_ACCESSOR_NAME_GETTER_CALLBACK)
prop_callback_name = callback_function_name(cgc)
prop_callback_node = make_named_constructor_property_callback_def(
cgc, prop_callback_name)
prop_callback_node = (
make_legacy_factory_function_property_callback_def(
cgc, prop_callback_name))

callback_def_nodes.extend([
prop_callback_node,
Expand All @@ -5541,7 +5546,7 @@ def process_named_constructor_group(named_constructor_group,
is_context_dependent=is_context_dependent,
exposure_conditional=exposure_conditional,
world=world,
exposed_construct=named_constructor_group,
exposed_construct=legacy_factory_function_group,
prop_callback_name=prop_callback_name))

def process_operation_group(operation_group, is_context_dependent,
Expand Down Expand Up @@ -5598,12 +5603,13 @@ def process_stringifier(_, is_context_dependent, exposure_conditional,
iterate(interface.constructor_groups, process_constructor_group)
iterate(interface.exposed_constructs, process_exposed_construct)
iterate(interface.legacy_window_aliases, process_exposed_construct)
named_constructor_groups = [
legacy_factory_function_groups = [
group for construct in interface.exposed_constructs
for group in construct.named_constructor_groups
if construct.named_constructor_groups
for group in construct.legacy_factory_function_groups
if construct.legacy_factory_function_groups
]
iterate(named_constructor_groups, process_named_constructor_group)
iterate(legacy_factory_function_groups,
process_legacy_factory_function_group)
if not class_like.is_callback_interface:
iterate(class_like.operation_groups, process_operation_group)
if interface and interface.stringifier:
Expand Down Expand Up @@ -7312,7 +7318,7 @@ def add_include_headers(idl_type):
if x:
operations.extend(x.operations)
for exposed_construct in class_like.exposed_constructs:
operations.extend(exposed_construct.named_constructors)
operations.extend(exposed_construct.legacy_factory_functions)
for operation in operations:
collect_from_idl_type(operation.return_type)
for argument in operation.arguments:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def _get_function_likes(target_store):
for interface in target_store.get(INTERFACES):
function_likes.extend(interface.operations)
function_likes.extend(interface.constructors)
function_likes.extend(interface.named_constructors)
function_likes.extend(interface.legacy_factory_functions)
if interface.iterable:
function_likes.extend(interface.iterable.operations)
if interface.maplike:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ def pv_readonly_attribute(assert_, target_object, ext_attr):
forms=F.IDENT),
E("IsCodeLike", applicable_to=[T.INTERFACE]),
E("IsolatedContext", applicable_to=T_EXPOSURE),
E("LegacyFactoryFunction",
applicable_to=[T.INTERFACE],
forms=F.NAMED_ARG_LIST),
E("LegacyFactoryFunction_CallWith",
applicable_to=[T.INTERFACE],
forms=[F.IDENT, F.IDENT_LIST],
values=V_CALL_WITH),
E("LegacyFactoryFunction_RaisesException",
applicable_to=[T.INTERFACE]),
E("LegacyLenientSetter", applicable_to=[T.ATTRIBUTE]),
E("LegacyLenientThis", applicable_to=[T.ATTRIBUTE]),
E("LegacyNoInterfaceObject", applicable_to=[T.INTERFACE]),
Expand Down Expand Up @@ -141,14 +150,6 @@ def pv_readonly_attribute(assert_, target_object, ext_attr):
T.LEGACY_WINDOW_ALIAS, T.OPERATION
],
forms=F.IDENT),
E("NamedConstructor",
applicable_to=[T.INTERFACE],
forms=F.NAMED_ARG_LIST),
E("NamedConstructor_CallWith",
applicable_to=[T.INTERFACE],
forms=[F.IDENT, F.IDENT_LIST],
values=V_CALL_WITH),
E("NamedConstructor_RaisesException", applicable_to=[T.INTERFACE]),
E("NewObject", applicable_to=[T.OPERATION]),
E("NoAllocDirectCall", applicable_to=[T.OPERATION]),
E("NotEnumerable", applicable_to=[T.ATTRIBUTE, T.OPERATION]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ def __init__(self,
self.constants = constants
self.constructors = []
self.constructor_groups = []
self.named_constructors = []
self.named_constructor_groups = []
self.legacy_factory_functions = []
self.legacy_factory_function_groups = []
self.operations = operations
self.operation_groups = []

Expand Down Expand Up @@ -120,13 +120,13 @@ def constructor_groups(self):
return ()

@property
def named_constructors(self):
"""Returns named constructors."""
def legacy_factory_functions(self):
"""Returns legacy factory functions."""
return ()

@property
def named_constructor_groups(self):
"""Returns groups of overloaded named constructors."""
def legacy_factory_function_groups(self):
"""Returns groups of overloaded legacy factory functions."""
return ()

@property
Expand Down

0 comments on commit 2e9f0d5

Please sign in to comment.