blob: 9f56eb2fbd9dfc2ca0f62b837f13ef72a0805df6 [file] [log] [blame]
David Ghandehari9e5b5872016-07-28 09:50:04 -07001# Copyright (C) 2013 Google Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions are
5# met:
6#
7# * Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9# * Redistributions in binary form must reproduce the above
10# copyright notice, this list of conditions and the following disclaimer
11# in the documentation and/or other materials provided with the
12# distribution.
13# * Neither the name of Google Inc. nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
David Ghandeharic44f0032017-03-22 18:53:21 -070029# pylint: disable=relative-import
30
David Ghandehari9e5b5872016-07-28 09:50:04 -070031"""Generate template values for attributes.
32
33Extends IdlType with property |constructor_type_name|.
34
35Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
36"""
37
38import idl_types
39from idl_types import inherits_interface
David Ghandeharic44f0032017-03-22 18:53:21 -070040from v8_globals import includes
David Ghandehari9e5b5872016-07-28 09:50:04 -070041import v8_types
42import v8_utilities
43from v8_utilities import (cpp_name_or_partial, capitalize, cpp_name, has_extended_attribute,
44 has_extended_attribute_value, scoped_name, strip_suffix,
David Ghandeharic44f0032017-03-22 18:53:21 -070045 uncapitalize, extended_attribute_value_as_list, is_unforgeable,
46 is_legacy_interface_type_checking)
David Ghandehari9e5b5872016-07-28 09:50:04 -070047
48
David Ghandeharic44f0032017-03-22 18:53:21 -070049def attribute_context(interface, attribute, interfaces):
50 """Creates a Jinja template context for an attribute of an interface.
51
52 Args:
53 interface: An interface which |attribute| belongs to
54 attribute: An attribute to create the context for
55 interfaces: A dict which maps an interface name to the definition
56 which can be referred if needed
57
58 Returns:
59 A Jinja template context for |attribute|
60 """
61
David Ghandehari9e5b5872016-07-28 09:50:04 -070062 idl_type = attribute.idl_type
63 base_idl_type = idl_type.base_type
64 extended_attributes = attribute.extended_attributes
65
David Ghandeharic44f0032017-03-22 18:53:21 -070066 idl_type.add_includes_for_type(extended_attributes)
67 if idl_type.enum_values:
68 includes.add('core/inspector/ConsoleMessage.h')
David Ghandehari9e5b5872016-07-28 09:50:04 -070069
70 # [CheckSecurity]
David Ghandeharic44f0032017-03-22 18:53:21 -070071 is_cross_origin = 'CrossOrigin' in extended_attributes
72 is_check_security_for_receiver = (
73 has_extended_attribute_value(interface, 'CheckSecurity', 'Receiver') and
74 is_cross_origin)
75 is_check_security_for_return_value = (
76 has_extended_attribute_value(attribute, 'CheckSecurity', 'ReturnValue'))
77 if is_check_security_for_receiver or is_check_security_for_return_value:
David Ghandehari9e5b5872016-07-28 09:50:04 -070078 includes.add('bindings/core/v8/BindingSecurity.h')
David Ghandeharic44f0032017-03-22 18:53:21 -070079 # [CrossOrigin]
80 if has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'):
81 includes.add('bindings/core/v8/V8CrossOriginSetterInfo.h')
82 # [Constructor]
83 # TODO(yukishiino): Constructors are much like methods although constructors
84 # are not methods. Constructors must be data-type properties, and we can
85 # support them as a kind of methods.
86 constructor_type = idl_type.constructor_type_name if is_constructor_attribute(attribute) else None
87 # [CEReactions]
88 is_ce_reactions = 'CEReactions' in extended_attributes
89 if is_ce_reactions:
90 includes.add('core/dom/custom/CEReactionsScope.h')
David Ghandehari9e5b5872016-07-28 09:50:04 -070091 # [CustomElementCallbacks], [Reflect]
92 is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes
93 is_reflect = 'Reflect' in extended_attributes
94 if is_custom_element_callbacks or is_reflect:
David Ghandeharic44f0032017-03-22 18:53:21 -070095 includes.add('core/dom/custom/V0CustomElementProcessingStack.h')
David Ghandehari9e5b5872016-07-28 09:50:04 -070096 # [PerWorldBindings]
97 if 'PerWorldBindings' in extended_attributes:
98 assert idl_type.is_wrapper_type or 'LogActivity' in extended_attributes, '[PerWorldBindings] should only be used with wrapper types: %s.%s' % (interface.name, attribute.name)
David Ghandeharic44f0032017-03-22 18:53:21 -070099 # [SaveSameObject]
100 is_save_same_object = (
101 'SameObject' in attribute.extended_attributes and
102 'SaveSameObject' in attribute.extended_attributes)
103 if is_save_same_object:
104 includes.add('bindings/core/v8/V8PrivateProperty.h')
David Ghandehari9e5b5872016-07-28 09:50:04 -0700105
106 if (base_idl_type == 'EventHandler' and
David Ghandeharic44f0032017-03-22 18:53:21 -0700107 interface.name in ['Window', 'WorkerGlobalScope'] and
108 attribute.name == 'onerror'):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700109 includes.add('bindings/core/v8/V8ErrorHandler.h')
110
David Ghandeharic44f0032017-03-22 18:53:21 -0700111 cached_attribute_validation_method = extended_attributes.get('CachedAttribute')
112 keep_alive_for_gc = is_keep_alive_for_gc(interface, attribute)
113 if cached_attribute_validation_method or keep_alive_for_gc:
114 includes.add('bindings/core/v8/V8HiddenValue.h')
115
116 # [CachedAccessor]
117 is_cached_accessor = 'CachedAccessor' in extended_attributes
118 if is_cached_accessor:
119 includes.add('bindings/core/v8/V8PrivateProperty.h')
120
David Ghandehari9e5b5872016-07-28 09:50:04 -0700121 context = {
David Ghandehari9e5b5872016-07-28 09:50:04 -0700122 'activity_logging_world_list_for_getter': v8_utilities.activity_logging_world_list(attribute, 'Getter'), # [ActivityLogging]
123 'activity_logging_world_list_for_setter': v8_utilities.activity_logging_world_list(attribute, 'Setter'), # [ActivityLogging]
124 'activity_logging_world_check': v8_utilities.activity_logging_world_check(attribute), # [ActivityLogging]
David Ghandeharic44f0032017-03-22 18:53:21 -0700125 'cached_attribute_validation_method': cached_attribute_validation_method,
126 'constructor_type': constructor_type,
David Ghandehari9e5b5872016-07-28 09:50:04 -0700127 'cpp_name': cpp_name(attribute),
128 'cpp_type': idl_type.cpp_type,
129 'cpp_type_initializer': idl_type.cpp_type_initializer,
130 'deprecate_as': v8_utilities.deprecate_as(attribute), # [DeprecateAs]
David Ghandeharic44f0032017-03-22 18:53:21 -0700131 'enum_type': idl_type.enum_type,
132 'enum_values': idl_type.enum_values,
David Ghandehari9e5b5872016-07-28 09:50:04 -0700133 'exposed_test': v8_utilities.exposed(attribute, interface), # [Exposed]
David Ghandeharic44f0032017-03-22 18:53:21 -0700134 'has_cross_origin_getter':
135 has_extended_attribute_value(attribute, 'CrossOrigin', None) or
136 has_extended_attribute_value(attribute, 'CrossOrigin', 'Getter'),
137 'has_cross_origin_setter': has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'),
David Ghandehari9e5b5872016-07-28 09:50:04 -0700138 'has_custom_getter': has_custom_getter(attribute),
139 'has_custom_setter': has_custom_setter(attribute),
David Ghandeharic44f0032017-03-22 18:53:21 -0700140 'has_setter': has_setter(interface, attribute),
David Ghandehari9e5b5872016-07-28 09:50:04 -0700141 'idl_type': str(idl_type), # need trailing [] on array for Dictionary::ConversionContext::setConversionType
David Ghandeharic44f0032017-03-22 18:53:21 -0700142 'is_cached_accessor': is_cached_accessor,
143 'is_call_with_execution_context': has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'),
144 'is_call_with_script_state': has_extended_attribute_value(attribute, 'CallWith', 'ScriptState'),
145 'is_ce_reactions': is_ce_reactions,
146 'is_check_security_for_receiver': is_check_security_for_receiver,
147 'is_check_security_for_return_value': is_check_security_for_return_value,
David Ghandehari9e5b5872016-07-28 09:50:04 -0700148 'is_custom_element_callbacks': is_custom_element_callbacks,
David Ghandeharic44f0032017-03-22 18:53:21 -0700149 # TODO(yukishiino): Make all DOM attributes accessor-type properties.
150 'is_data_type_property': is_data_type_property(interface, attribute),
David Ghandehari9e5b5872016-07-28 09:50:04 -0700151 'is_getter_raises_exception': # [RaisesException]
152 'RaisesException' in extended_attributes and
153 extended_attributes['RaisesException'] in (None, 'Getter'),
David Ghandeharic44f0032017-03-22 18:53:21 -0700154 'is_keep_alive_for_gc': keep_alive_for_gc,
155 'is_lenient_this': 'LenientThis' in extended_attributes,
David Ghandehari9e5b5872016-07-28 09:50:04 -0700156 'is_nullable': idl_type.is_nullable,
157 'is_explicit_nullable': idl_type.is_explicit_nullable,
David Ghandeharic44f0032017-03-22 18:53:21 -0700158 'is_named_constructor': is_named_constructor_attribute(attribute),
David Ghandehari9e5b5872016-07-28 09:50:04 -0700159 'is_partial_interface_member':
160 'PartialInterfaceImplementedAs' in extended_attributes,
161 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes,
David Ghandeharic44f0032017-03-22 18:53:21 -0700162 'is_put_forwards': 'PutForwards' in extended_attributes,
David Ghandehari9e5b5872016-07-28 09:50:04 -0700163 'is_read_only': attribute.is_read_only,
164 'is_reflect': is_reflect,
165 'is_replaceable': 'Replaceable' in attribute.extended_attributes,
David Ghandeharic44f0032017-03-22 18:53:21 -0700166 'is_save_same_object': is_save_same_object,
David Ghandehari9e5b5872016-07-28 09:50:04 -0700167 'is_static': attribute.is_static,
168 'is_url': 'URL' in extended_attributes,
David Ghandeharic44f0032017-03-22 18:53:21 -0700169 'is_unforgeable': is_unforgeable(interface, attribute),
170 'on_instance': v8_utilities.on_instance(interface, attribute),
171 'on_interface': v8_utilities.on_interface(interface, attribute),
172 'on_prototype': v8_utilities.on_prototype(interface, attribute),
173 'origin_trial_enabled_function': v8_utilities.origin_trial_enabled_function_name(attribute), # [OriginTrialEnabled]
174 'origin_trial_feature_name': v8_utilities.origin_trial_feature_name(attribute), # [OriginTrialEnabled]
175 'use_output_parameter_for_result': idl_type.use_output_parameter_for_result,
176 'measure_as': v8_utilities.measure_as(attribute, interface), # [MeasureAs]
David Ghandehari9e5b5872016-07-28 09:50:04 -0700177 'name': attribute.name,
David Ghandeharic44f0032017-03-22 18:53:21 -0700178 'property_attributes': property_attributes(interface, attribute),
David Ghandehari9e5b5872016-07-28 09:50:04 -0700179 'reflect_empty': extended_attributes.get('ReflectEmpty'),
180 'reflect_invalid': extended_attributes.get('ReflectInvalid', ''),
181 'reflect_missing': extended_attributes.get('ReflectMissing'),
182 'reflect_only': extended_attribute_value_as_list(attribute, 'ReflectOnly'),
David Ghandeharic44f0032017-03-22 18:53:21 -0700183 'runtime_enabled_feature_name': v8_utilities.runtime_enabled_feature_name(attribute), # [RuntimeEnabled]
184 'secure_context_test': v8_utilities.secure_context(attribute, interface), # [SecureContext]
185 'cached_accessor_name': '%s%sCachedAccessor' % (interface.name, attribute.name.capitalize()),
186 'world_suffixes': (
187 ['', 'ForMainWorld']
188 if 'PerWorldBindings' in extended_attributes
189 else ['']), # [PerWorldBindings]
David Ghandehari9e5b5872016-07-28 09:50:04 -0700190 }
191
192 if is_constructor_attribute(attribute):
David Ghandeharic44f0032017-03-22 18:53:21 -0700193 update_constructor_attribute_context(interface, attribute, context)
David Ghandehari9e5b5872016-07-28 09:50:04 -0700194 if not has_custom_getter(attribute):
195 getter_context(interface, attribute, context)
David Ghandeharic44f0032017-03-22 18:53:21 -0700196 if not has_custom_setter(attribute) and has_setter(interface, attribute):
197 setter_context(interface, attribute, interfaces, context)
198
199 # [CrossOrigin] is incompatible with a number of other attributes, so check
200 # for them here.
201 if is_cross_origin:
202 if context['has_cross_origin_setter'] and context['has_custom_setter']:
203 raise Exception('[CrossOrigin] and [Custom] are incompatible on the same setter: %s.%s', interface.name, attribute.name)
204 if context['is_per_world_bindings']:
205 raise Exception('[CrossOrigin] and [PerWorldBindings] are incompatible: %s.%s', interface.name, attribute.name)
206 if context['constructor_type']:
207 raise Exception('[CrossOrigin] cannot be used for constructors: %s.%s', interface.name, attribute.name)
David Ghandehari9e5b5872016-07-28 09:50:04 -0700208
209 return context
210
211
David Ghandeharic44f0032017-03-22 18:53:21 -0700212def filter_accessors(attributes):
213 return [attribute for attribute in attributes if
214 not (attribute['exposed_test'] or
215 attribute['secure_context_test'] or
216 attribute['origin_trial_enabled_function'] or
217 attribute['runtime_enabled_feature_name']) and
218 not attribute['is_data_type_property']]
219
220
221def is_data_attribute(attribute):
222 return (not (attribute['exposed_test'] or
223 attribute['secure_context_test'] or
224 attribute['origin_trial_enabled_function'] or
225 attribute['runtime_enabled_feature_name']) and
226 attribute['is_data_type_property'])
227
228
229def is_lazy_data_attribute(attribute):
230 return ((attribute['constructor_type'] and not attribute['needs_constructor_getter_callback']) or
231 (attribute['idl_type'] == 'Window' and attribute['name'] == 'frames') or
232 (attribute['idl_type'] == 'Window' and attribute['name'] == 'self') or
233 (attribute['idl_type'] == 'Window' and attribute['name'] == 'window'))
234
235
236def filter_data_attributes(attributes):
237 return [attribute for attribute in attributes if is_data_attribute(attribute) and not is_lazy_data_attribute(attribute)]
238
239
240def filter_lazy_data_attributes(attributes):
241 return [attribute for attribute in attributes if is_data_attribute(attribute) and is_lazy_data_attribute(attribute)]
242
243
244def filter_origin_trial_enabled(attributes):
245 return [attribute for attribute in attributes if
246 attribute['origin_trial_feature_name'] and
247 not attribute['exposed_test']]
248
249
250def filter_runtime_enabled(attributes):
251 return [attribute for attribute in attributes if
252 not (attribute['exposed_test'] or
253 attribute['secure_context_test']) and
254 attribute['runtime_enabled_feature_name']]
255
256
David Ghandehari9e5b5872016-07-28 09:50:04 -0700257################################################################################
258# Getter
259################################################################################
260
261def getter_context(interface, attribute, context):
262 idl_type = attribute.idl_type
263 base_idl_type = idl_type.base_type
264 extended_attributes = attribute.extended_attributes
265
266 cpp_value = getter_expression(interface, attribute, context)
267 # Normally we can inline the function call into the return statement to
268 # avoid the overhead of using a Ref<> temporary, but for some cases
269 # (nullable types, EventHandler, [CachedAttribute], or if there are
270 # exceptions), we need to use a local variable.
271 # FIXME: check if compilers are smart enough to inline this, and if so,
272 # always use a local variable (for readability and CG simplicity).
David Ghandeharic44f0032017-03-22 18:53:21 -0700273 if (idl_type.is_explicit_nullable or
274 base_idl_type == 'EventHandler' or
275 'CachedAttribute' in extended_attributes or
276 'ReflectOnly' in extended_attributes or
277 context['is_keep_alive_for_gc'] or
278 context['is_getter_raises_exception']):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700279 context['cpp_value_original'] = cpp_value
280 cpp_value = 'cppValue'
David Ghandehari9e5b5872016-07-28 09:50:04 -0700281
282 def v8_set_return_value_statement(for_main_world=False):
David Ghandeharic44f0032017-03-22 18:53:21 -0700283 if context['is_keep_alive_for_gc'] or 'CachedAttribute' in extended_attributes:
284 return 'v8SetReturnValue(info, v8Value)'
285 return idl_type.v8_set_return_value(
286 cpp_value, extended_attributes=extended_attributes, script_wrappable='impl',
287 for_main_world=for_main_world, is_static=attribute.is_static)
David Ghandehari9e5b5872016-07-28 09:50:04 -0700288
289 context.update({
290 'cpp_value': cpp_value,
291 'cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(
David Ghandeharic44f0032017-03-22 18:53:21 -0700292 cpp_value=cpp_value, creation_context='holder',
David Ghandehari9e5b5872016-07-28 09:50:04 -0700293 extended_attributes=extended_attributes),
294 'v8_set_return_value_for_main_world': v8_set_return_value_statement(for_main_world=True),
295 'v8_set_return_value': v8_set_return_value_statement(),
296 })
297
David Ghandehari9e5b5872016-07-28 09:50:04 -0700298def getter_expression(interface, attribute, context):
299 arguments = []
300 this_getter_base_name = getter_base_name(interface, attribute, arguments)
301 getter_name = scoped_name(interface, attribute, this_getter_base_name)
302
David Ghandehari9e5b5872016-07-28 09:50:04 -0700303 arguments.extend(v8_utilities.call_with_arguments(
304 attribute.extended_attributes.get('CallWith')))
305 # Members of IDL partial interface definitions are implemented in C++ as
306 # static member functions, which for instance members (non-static members)
307 # take *impl as their first argument
308 if ('PartialInterfaceImplementedAs' in attribute.extended_attributes and
David Ghandeharic44f0032017-03-22 18:53:21 -0700309 not attribute.is_static):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700310 arguments.append('*impl')
311 if attribute.idl_type.is_explicit_nullable:
312 arguments.append('isNull')
313 if context['is_getter_raises_exception']:
314 arguments.append('exceptionState')
David Ghandeharic44f0032017-03-22 18:53:21 -0700315 if attribute.idl_type.use_output_parameter_for_result:
316 arguments.append('result')
317
318 expression = '%s(%s)' % (getter_name, ', '.join(arguments))
319 # Needed to handle getter expressions returning Type& as the
320 # use site for |expression| expects Type*.
321 if attribute.idl_type.is_interface_type and len(arguments) == 0:
322 return 'WTF::getPtr(%s)' % expression
323 return expression
David Ghandehari9e5b5872016-07-28 09:50:04 -0700324
325
326CONTENT_ATTRIBUTE_GETTER_NAMES = {
327 'boolean': 'fastHasAttribute',
328 'long': 'getIntegralAttribute',
329 'unsigned long': 'getUnsignedIntegralAttribute',
330}
331
332
333def getter_base_name(interface, attribute, arguments):
334 extended_attributes = attribute.extended_attributes
335
David Ghandehari9e5b5872016-07-28 09:50:04 -0700336 if 'Reflect' not in extended_attributes:
337 return uncapitalize(cpp_name(attribute))
338
339 content_attribute_name = extended_attributes['Reflect'] or attribute.name.lower()
340 if content_attribute_name in ['class', 'id', 'name']:
341 # Special-case for performance optimization.
342 return 'get%sAttribute' % content_attribute_name.capitalize()
343
344 arguments.append(scoped_content_attribute_name(interface, attribute))
345
346 base_idl_type = attribute.idl_type.base_type
347 if base_idl_type in CONTENT_ATTRIBUTE_GETTER_NAMES:
348 return CONTENT_ATTRIBUTE_GETTER_NAMES[base_idl_type]
349 if 'URL' in attribute.extended_attributes:
350 return 'getURLAttribute'
351 return 'fastGetAttribute'
352
353
354def is_keep_alive_for_gc(interface, attribute):
355 idl_type = attribute.idl_type
356 base_idl_type = idl_type.base_type
357 extended_attributes = attribute.extended_attributes
358 return (
359 # For readonly attributes, for performance reasons we keep the attribute
360 # wrapper alive while the owner wrapper is alive, because the attribute
361 # never changes.
362 (attribute.is_read_only and
363 idl_type.is_wrapper_type and
364 # There are some exceptions, however:
365 not(
366 # Node lifetime is managed by object grouping.
367 inherits_interface(interface.name, 'Node') or
368 inherits_interface(base_idl_type, 'Node') or
369 # A self-reference is unnecessary.
370 attribute.name == 'self' or
371 # FIXME: Remove these hard-coded hacks.
372 base_idl_type in ['EventTarget', 'Window'] or
373 base_idl_type.startswith(('HTML', 'SVG')))))
374
375
376################################################################################
377# Setter
378################################################################################
379
David Ghandeharic44f0032017-03-22 18:53:21 -0700380def setter_context(interface, attribute, interfaces, context):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700381 if 'PutForwards' in attribute.extended_attributes:
382 # Use target interface and attribute in place of original interface and
383 # attribute from this point onwards.
384 target_interface_name = attribute.idl_type.base_type
385 target_attribute_name = attribute.extended_attributes['PutForwards']
386 interface = interfaces[target_interface_name]
387 try:
388 attribute = next(candidate
389 for candidate in interface.attributes
390 if candidate.name == target_attribute_name)
391 except StopIteration:
392 raise Exception('[PutForward] target not found:\n'
393 'Attribute "%s" is not present in interface "%s"' %
394 (target_attribute_name, target_interface_name))
395
David Ghandeharic44f0032017-03-22 18:53:21 -0700396 if ('Replaceable' in attribute.extended_attributes):
397 context['cpp_setter'] = 'v8CallBoolean(info.Holder()->CreateDataProperty(info.GetIsolate()->GetCurrentContext(), propertyName, v8Value))'
398 return
399
David Ghandehari9e5b5872016-07-28 09:50:04 -0700400 extended_attributes = attribute.extended_attributes
401 idl_type = attribute.idl_type
402
403 # [RaisesException], [RaisesException=Setter]
404 is_setter_raises_exception = (
405 'RaisesException' in extended_attributes and
406 extended_attributes['RaisesException'] in [None, 'Setter'])
David Ghandeharic44f0032017-03-22 18:53:21 -0700407 # [LegacyInterfaceTypeChecking]
David Ghandehari9e5b5872016-07-28 09:50:04 -0700408 has_type_checking_interface = (
David Ghandeharic44f0032017-03-22 18:53:21 -0700409 not is_legacy_interface_type_checking(interface, attribute) and
David Ghandehari9e5b5872016-07-28 09:50:04 -0700410 idl_type.is_wrapper_type)
411
David Ghandehari9e5b5872016-07-28 09:50:04 -0700412 context.update({
413 'has_setter_exception_state':
414 is_setter_raises_exception or has_type_checking_interface or
David Ghandehari9e5b5872016-07-28 09:50:04 -0700415 idl_type.v8_conversion_needs_exception_state,
416 'has_type_checking_interface': has_type_checking_interface,
David Ghandeharic44f0032017-03-22 18:53:21 -0700417 'is_setter_call_with_execution_context': has_extended_attribute_value(
David Ghandehari9e5b5872016-07-28 09:50:04 -0700418 attribute, 'SetterCallWith', 'ExecutionContext'),
419 'is_setter_raises_exception': is_setter_raises_exception,
David Ghandehari9e5b5872016-07-28 09:50:04 -0700420 'v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value(
David Ghandeharic44f0032017-03-22 18:53:21 -0700421 extended_attributes, 'v8Value', 'cppValue'),
David Ghandehari9e5b5872016-07-28 09:50:04 -0700422 })
423
424 # setter_expression() depends on context values we set above.
425 context['cpp_setter'] = setter_expression(interface, attribute, context)
426
427
428def setter_expression(interface, attribute, context):
429 extended_attributes = attribute.extended_attributes
430 arguments = v8_utilities.call_with_arguments(
431 extended_attributes.get('SetterCallWith') or
432 extended_attributes.get('CallWith'))
433
434 this_setter_base_name = setter_base_name(interface, attribute, arguments)
435 setter_name = scoped_name(interface, attribute, this_setter_base_name)
436
437 # Members of IDL partial interface definitions are implemented in C++ as
438 # static member functions, which for instance members (non-static members)
439 # take *impl as their first argument
440 if ('PartialInterfaceImplementedAs' in extended_attributes and
David Ghandeharic44f0032017-03-22 18:53:21 -0700441 not attribute.is_static):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700442 arguments.append('*impl')
443 idl_type = attribute.idl_type
David Ghandeharic44f0032017-03-22 18:53:21 -0700444 if idl_type.base_type == 'EventHandler':
David Ghandehari9e5b5872016-07-28 09:50:04 -0700445 getter_name = scoped_name(interface, attribute, cpp_name(attribute))
446 context['event_handler_getter_expression'] = '%s(%s)' % (
447 getter_name, ', '.join(arguments))
448 if (interface.name in ['Window', 'WorkerGlobalScope'] and
David Ghandeharic44f0032017-03-22 18:53:21 -0700449 attribute.name == 'onerror'):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700450 includes.add('bindings/core/v8/V8ErrorHandler.h')
David Ghandeharic44f0032017-03-22 18:53:21 -0700451 arguments.append(
452 'V8EventListenerHelper::ensureEventListener<V8ErrorHandler>(' +
453 'v8Value, true, ScriptState::forReceiverObject(info))')
David Ghandehari9e5b5872016-07-28 09:50:04 -0700454 else:
David Ghandeharic44f0032017-03-22 18:53:21 -0700455 arguments.append(
456 'V8EventListenerHelper::getEventListener(' +
457 'ScriptState::forReceiverObject(info), v8Value, true, ' +
458 'ListenerFindOrCreate)')
David Ghandehari9e5b5872016-07-28 09:50:04 -0700459 else:
460 arguments.append('cppValue')
461 if context['is_setter_raises_exception']:
462 arguments.append('exceptionState')
463
464 return '%s(%s)' % (setter_name, ', '.join(arguments))
465
466
467CONTENT_ATTRIBUTE_SETTER_NAMES = {
468 'boolean': 'setBooleanAttribute',
469 'long': 'setIntegralAttribute',
470 'unsigned long': 'setUnsignedIntegralAttribute',
471}
472
473
474def setter_base_name(interface, attribute, arguments):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700475 if 'Reflect' not in attribute.extended_attributes:
476 return 'set%s' % capitalize(cpp_name(attribute))
477 arguments.append(scoped_content_attribute_name(interface, attribute))
478
479 base_idl_type = attribute.idl_type.base_type
480 if base_idl_type in CONTENT_ATTRIBUTE_SETTER_NAMES:
481 return CONTENT_ATTRIBUTE_SETTER_NAMES[base_idl_type]
482 return 'setAttribute'
483
484
485def scoped_content_attribute_name(interface, attribute):
486 content_attribute_name = attribute.extended_attributes['Reflect'] or attribute.name.lower()
487 if interface.name.startswith('SVG'):
David Ghandeharic44f0032017-03-22 18:53:21 -0700488 namespace = 'SVGNames'
David Ghandehari9e5b5872016-07-28 09:50:04 -0700489 else:
490 namespace = 'HTMLNames'
491 includes.add('core/%s.h' % namespace)
492 return '%s::%sAttr' % (namespace, content_attribute_name)
493
494
495################################################################################
496# Attribute configuration
497################################################################################
498
David Ghandeharic44f0032017-03-22 18:53:21 -0700499# Property descriptor's {writable: boolean}
500def is_writable(attribute):
501 return (not attribute.is_read_only or
502 'PutForwards' in attribute.extended_attributes or
503 'Replaceable' in attribute.extended_attributes)
David Ghandehari9e5b5872016-07-28 09:50:04 -0700504
505
David Ghandeharic44f0032017-03-22 18:53:21 -0700506def is_data_type_property(interface, attribute):
507 if 'CachedAccessor' in attribute.extended_attributes:
508 return False
509 return (is_constructor_attribute(attribute) or
510 'CrossOrigin' in attribute.extended_attributes)
511
512
513# [PutForwards], [Replaceable]
514def has_setter(interface, attribute):
515 if (is_data_type_property(interface, attribute) and
516 (is_constructor_attribute(attribute) or
517 'Replaceable' in attribute.extended_attributes)):
518 return False
519
520 return is_writable(attribute)
David Ghandehari9e5b5872016-07-28 09:50:04 -0700521
522
523# [NotEnumerable], [Unforgeable]
David Ghandeharic44f0032017-03-22 18:53:21 -0700524def property_attributes(interface, attribute):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700525 extended_attributes = attribute.extended_attributes
526 property_attributes_list = []
527 if ('NotEnumerable' in extended_attributes or
David Ghandeharic44f0032017-03-22 18:53:21 -0700528 is_constructor_attribute(attribute)):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700529 property_attributes_list.append('v8::DontEnum')
David Ghandeharic44f0032017-03-22 18:53:21 -0700530 if is_unforgeable(interface, attribute):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700531 property_attributes_list.append('v8::DontDelete')
David Ghandeharic44f0032017-03-22 18:53:21 -0700532 if not is_writable(attribute):
533 property_attributes_list.append('v8::ReadOnly')
David Ghandehari9e5b5872016-07-28 09:50:04 -0700534 return property_attributes_list or ['v8::None']
535
536
537# [Custom], [Custom=Getter]
538def has_custom_getter(attribute):
539 extended_attributes = attribute.extended_attributes
540 return ('Custom' in extended_attributes and
541 extended_attributes['Custom'] in [None, 'Getter'])
542
543
544# [Custom], [Custom=Setter]
545def has_custom_setter(attribute):
546 extended_attributes = attribute.extended_attributes
547 return (not attribute.is_read_only and
548 'Custom' in extended_attributes and
549 extended_attributes['Custom'] in [None, 'Setter'])
550
551
552################################################################################
553# Constructors
554################################################################################
555
556idl_types.IdlType.constructor_type_name = property(
David Ghandehari9e5b5872016-07-28 09:50:04 -0700557 lambda self: strip_suffix(self.base_type, 'Constructor'))
558
559
560def is_constructor_attribute(attribute):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700561 return attribute.idl_type.name.endswith('Constructor')
562
563
David Ghandeharic44f0032017-03-22 18:53:21 -0700564def is_named_constructor_attribute(attribute):
565 return attribute.idl_type.name.endswith('ConstructorConstructor')
566
567
568def update_constructor_attribute_context(interface, attribute, context):
David Ghandehari9e5b5872016-07-28 09:50:04 -0700569 context['needs_constructor_getter_callback'] = context['measure_as'] or context['deprecate_as']