| # Copyright 2019 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import web_idl |
| |
| from . import name_style |
| from .code_node import Likeliness |
| from .code_node import SymbolDefinitionNode |
| from .code_node import SymbolNode |
| from .code_node import TextNode |
| from .code_node_cxx import CxxIfElseNode |
| from .code_node_cxx import CxxLikelyIfNode |
| from .code_node_cxx import CxxUnlikelyIfNode |
| from .codegen_format import format_template as _format |
| |
| |
| def blink_class_name(idl_definition): |
| """ |
| Returns the class name of Blink implementation. |
| """ |
| class_name = idl_definition.code_generator_info.receiver_implemented_as |
| if class_name: |
| return class_name |
| |
| assert idl_definition.identifier[0].isupper() |
| # Do not apply |name_style.class_| in order to respect the original name |
| # (Web spec'ed name) as much as possible. For example, |interface EXTsRGB| |
| # is implemented as |class EXTsRGB|, not as |ExtSRgb| nor |ExtsRgb|. |
| if isinstance(idl_definition, |
| (web_idl.CallbackFunction, web_idl.CallbackInterface, |
| web_idl.Enumeration)): |
| return "V8{}".format(idl_definition.identifier) |
| elif isinstance(idl_definition, web_idl.NewUnion): |
| # Technically this name is not guaranteed to be unique because |
| # (X or sequence<Y or Z>) and (X or Y or sequence<Z>) have the same |
| # name, but it's highly unlikely to cause a conflict in the actual use |
| # cases. Plus, we prefer a simple naming rule conformant to the |
| # Chromium coding style. So, we go with this way. |
| return "V8Union{}".format("Or".join(idl_definition.member_tokens)) |
| else: |
| return idl_definition.identifier |
| |
| |
| def v8_bridge_class_name(idl_definition): |
| """ |
| Returns the name of V8-from/to-Blink bridge class. |
| """ |
| assert isinstance( |
| idl_definition, |
| (web_idl.CallbackInterface, web_idl.Interface, web_idl.Namespace)) |
| |
| assert idl_definition.identifier[0].isupper() |
| # Do not apply |name_style.class_| due to the same reason as |
| # |blink_class_name|. |
| return "V8{}".format(idl_definition.identifier) |
| |
| |
| def blink_type_info(idl_type, use_new_union=False): |
| """ |
| Returns the types of Blink implementation corresponding to the given IDL |
| type. The returned object has the following attributes. |
| |
| ref_t: The type of a local variable that references to an already-existing |
| value. E.g. String => String& |
| const_ref_t: A const-qualified reference type. |
| value_t: The type of a variable that behaves as a value. E.g. String => |
| String |
| member_t: The type of a member variable. E.g. T => Member<T> |
| member_ref_t: The type used for input to and output from a member |
| variable. E.g. T* for Member<T> and const String& for String. |
| has_null_value: True if the Blink implementation type can represent IDL |
| null value by itself without use of base::Optional<T>. |
| """ |
| assert isinstance(idl_type, web_idl.IdlType) |
| |
| class TypeInfo(object): |
| def __init__(self, |
| typename, |
| member_fmt="{}", |
| ref_fmt="{}", |
| const_ref_fmt="const {}", |
| value_fmt="{}", |
| has_null_value=False, |
| clear_member_var_fmt="{}.Clear()"): |
| self.typename = typename |
| self.is_gc_type = is_gc_type(idl_type) |
| self.ref_t = ref_fmt.format(typename) |
| self.const_ref_t = const_ref_fmt.format(typename) |
| self.value_t = value_fmt.format(typename) |
| self.member_t = member_fmt.format(typename) |
| self.member_ref_t = (self.ref_t |
| if self.is_gc_type else self.const_ref_t) |
| self.has_null_value = has_null_value |
| self._clear_member_var_fmt = clear_member_var_fmt |
| |
| def clear_member_var_expr(self, var_name): |
| """Returns an expression to reset the given member variable.""" |
| return self._clear_member_var_fmt.format(var_name) |
| |
| def is_gc_type(idl_type): |
| idl_type = idl_type.unwrap() |
| return bool( |
| idl_type.is_buffer_source_type or |
| (idl_type.type_definition_object and not idl_type.is_enumeration) |
| or (idl_type.new_union_definition_object and use_new_union)) |
| |
| def vector_element_type(idl_type): |
| # Use |Member<T>| explicitly so that the complete type definition of |
| # |T| will not be required. |
| type_info = blink_type_info(idl_type) |
| if type_info.is_gc_type: |
| return type_info.member_t |
| else: |
| return type_info.typename |
| |
| real_type = idl_type.unwrap(typedef=True) |
| |
| if real_type.is_boolean or real_type.is_numeric: |
| cxx_type = { |
| "boolean": "bool", |
| "byte": "int8_t", |
| "octet": "uint8_t", |
| "short": "int16_t", |
| "unsigned short": "uint16_t", |
| "long": "int32_t", |
| "unsigned long": "uint32_t", |
| "long long": "int64_t", |
| "unsigned long long": "uint64_t", |
| "float": "float", |
| "unrestricted float": "float", |
| "double": "double", |
| "unrestricted double": "double", |
| } |
| return TypeInfo(cxx_type[real_type.keyword_typename], |
| const_ref_fmt="{}", |
| clear_member_var_fmt="{} = 0") |
| |
| if real_type.is_string: |
| return TypeInfo("String", |
| ref_fmt="{}&", |
| const_ref_fmt="const {}&", |
| has_null_value=True, |
| clear_member_var_fmt="{} = String()") |
| |
| if real_type.is_array_buffer: |
| assert "AllowShared" not in real_type.extended_attributes |
| return TypeInfo( |
| 'DOM{}'.format(real_type.keyword_typename), |
| member_fmt="Member<{}>", |
| ref_fmt="{}*", |
| const_ref_fmt="const {}*", |
| value_fmt="{}*", |
| has_null_value=True) |
| |
| if real_type.is_buffer_source_type: |
| if "FlexibleArrayBufferView" in real_type.extended_attributes: |
| assert "AllowShared" in real_type.extended_attributes |
| return TypeInfo( |
| "Flexible{}".format(real_type.keyword_typename), |
| member_fmt="void", |
| ref_fmt="{}", |
| const_ref_fmt="const {}", |
| value_fmt="{}", |
| has_null_value=True) |
| elif "AllowShared" in real_type.extended_attributes: |
| return TypeInfo( |
| "MaybeShared<DOM{}>".format(real_type.keyword_typename), |
| has_null_value=True) |
| else: |
| return TypeInfo( |
| "NotShared<DOM{}>".format(real_type.keyword_typename), |
| has_null_value=True) |
| |
| if real_type.is_symbol: |
| assert False, "Blink does not support/accept IDL symbol type." |
| |
| if real_type.is_any or real_type.is_object: |
| return TypeInfo( |
| "ScriptValue", |
| ref_fmt="{}&", |
| const_ref_fmt="const {}&", |
| has_null_value=True) |
| |
| if real_type.is_void: |
| assert False, "Blink does not support/accept IDL void type." |
| |
| if real_type.type_definition_object: |
| blink_impl_type = blink_class_name(real_type.type_definition_object) |
| if real_type.is_enumeration: |
| return TypeInfo(blink_impl_type, clear_member_var_fmt="") |
| return TypeInfo( |
| blink_impl_type, |
| member_fmt="Member<{}>", |
| ref_fmt="{}*", |
| const_ref_fmt="const {}*", |
| value_fmt="{}*", |
| has_null_value=True) |
| |
| if (real_type.is_sequence or real_type.is_frozen_array |
| or real_type.is_variadic): |
| typename = "VectorOf<{}>".format( |
| vector_element_type(real_type.element_type)) |
| return TypeInfo(typename, |
| ref_fmt="{}&", |
| const_ref_fmt="const {}&", |
| clear_member_var_fmt="{}.clear()") |
| |
| if real_type.is_record: |
| typename = "VectorOfPairs<{}, {}>".format( |
| vector_element_type(real_type.key_type), |
| vector_element_type(real_type.value_type)) |
| return TypeInfo(typename, |
| ref_fmt="{}&", |
| const_ref_fmt="const {}&", |
| clear_member_var_fmt="{}.clear()") |
| |
| if real_type.is_promise: |
| return TypeInfo( |
| "ScriptPromise", ref_fmt="{}&", const_ref_fmt="const {}&") |
| |
| if real_type.is_union and use_new_union: |
| blink_impl_type = blink_class_name( |
| real_type.new_union_definition_object) |
| return TypeInfo(blink_impl_type, |
| member_fmt="Member<{}>", |
| ref_fmt="{}*", |
| const_ref_fmt="const {}*", |
| value_fmt="{}*", |
| has_null_value=False) |
| |
| if real_type.is_union: |
| blink_impl_type = blink_class_name(real_type.union_definition_object) |
| return TypeInfo( |
| blink_impl_type, |
| ref_fmt="{}&", |
| const_ref_fmt="const {}&", |
| has_null_value=True) |
| |
| if real_type.is_nullable: |
| inner_type = blink_type_info(real_type.inner_type) |
| if inner_type.has_null_value: |
| return inner_type |
| return TypeInfo("base::Optional<{}>".format(inner_type.value_t), |
| ref_fmt="{}&", |
| const_ref_fmt="const {}&", |
| clear_member_var_fmt="{}.reset()") |
| |
| assert False, "Unknown type: {}".format(idl_type.syntactic_form) |
| |
| |
| def native_value_tag(idl_type, argument=None, apply_optional_to_last_arg=True): |
| """Returns the tag type of NativeValueTraits.""" |
| assert isinstance(idl_type, web_idl.IdlType) |
| assert argument is None or isinstance(argument, web_idl.Argument) |
| |
| if (idl_type.is_optional and argument |
| and not (idl_type.is_nullable or argument.default_value) |
| and (apply_optional_to_last_arg |
| or argument != argument.owner.arguments[-1])): |
| return "IDLOptional<{}>".format(_native_value_tag_impl(idl_type)) |
| |
| return _native_value_tag_impl(idl_type) |
| |
| |
| def _native_value_tag_impl(idl_type): |
| """Returns the tag type of NativeValueTraits.""" |
| assert isinstance(idl_type, web_idl.IdlType) |
| |
| if idl_type.is_typedef: |
| if idl_type.identifier in ("EventHandler", |
| "OnBeforeUnloadEventHandler", |
| "OnErrorEventHandler"): |
| return "IDL{}".format(idl_type.identifier) |
| |
| real_type = idl_type.unwrap(typedef=True) |
| |
| if (real_type.is_boolean or real_type.is_numeric or real_type.is_any |
| or real_type.is_object): |
| return "IDL{}".format( |
| idl_type.type_name_with_extended_attribute_key_values) |
| |
| if real_type.is_string: |
| return "IDL{}V2".format( |
| idl_type.type_name_with_extended_attribute_key_values) |
| |
| if real_type.is_array_buffer: |
| return blink_type_info(real_type).typename |
| |
| if real_type.is_buffer_source_type: |
| return blink_type_info(real_type).value_t |
| |
| if real_type.is_symbol: |
| assert False, "Blink does not support/accept IDL symbol type." |
| |
| if real_type.is_void: |
| assert False, "Blink does not support/accept IDL void type." |
| |
| if real_type.type_definition_object: |
| return blink_class_name(real_type.type_definition_object) |
| |
| if real_type.is_sequence: |
| return "IDLSequence<{}>".format( |
| _native_value_tag_impl(real_type.element_type)) |
| |
| if real_type.is_frozen_array: |
| return "IDLArray<{}>".format( |
| _native_value_tag_impl(real_type.element_type)) |
| |
| if real_type.is_record: |
| return "IDLRecord<{}, {}>".format( |
| _native_value_tag_impl(real_type.key_type), |
| _native_value_tag_impl(real_type.value_type)) |
| |
| if real_type.is_promise: |
| return "IDLPromise" |
| |
| if real_type.is_union: |
| class_name = blink_class_name(real_type.union_definition_object) |
| if real_type.does_include_nullable_type: |
| return "IDLUnionINT<{}>".format(class_name) |
| return "IDLUnionNotINT<{}>".format(class_name) |
| |
| if real_type.is_nullable: |
| return "IDLNullable<{}>".format( |
| _native_value_tag_impl(real_type.inner_type)) |
| |
| assert False, "Unknown type: {}".format(idl_type.syntactic_form) |
| |
| |
| def make_blink_to_v8_value( |
| v8_var_name, |
| blink_value_expr, |
| idl_type, |
| argument=None, |
| error_exit_return_statement="return v8::MaybeLocal<v8::Value>();", |
| creation_context_script_state="${script_state}"): |
| """ |
| Returns a SymbolNode whose definition converts a Blink value to a v8::Value. |
| """ |
| assert isinstance(v8_var_name, str) |
| assert isinstance(blink_value_expr, str) |
| assert isinstance(idl_type, web_idl.IdlType) |
| assert argument is None or isinstance(argument, web_idl.Argument) |
| assert isinstance(error_exit_return_statement, str) |
| assert isinstance(creation_context_script_state, str) |
| |
| T = TextNode |
| F = lambda *args, **kwargs: T(_format(*args, **kwargs)) |
| |
| def create_definition(symbol_node): |
| binds = { |
| "blink_value_expr": blink_value_expr, |
| "creation_context_script_state": creation_context_script_state, |
| "native_value_tag": native_value_tag(idl_type, argument=argument), |
| "v8_var_name": v8_var_name, |
| } |
| pattern = ("!ToV8Traits<{native_value_tag}>::ToV8(" |
| "{creation_context_script_state}, {blink_value_expr})" |
| ".ToLocal(&{v8_var_name})") |
| nodes = [ |
| F("v8::Local<v8::Value> {v8_var_name};", **binds), |
| CxxUnlikelyIfNode(cond=F(pattern, **binds), |
| body=T(error_exit_return_statement)), |
| ] |
| return SymbolDefinitionNode(symbol_node, nodes) |
| |
| return SymbolNode(v8_var_name, definition_constructor=create_definition) |
| |
| |
| def make_default_value_expr(idl_type, default_value): |
| """ |
| Returns a set of C++ expressions to be used for initialization with default |
| values. The returned object has the following attributes. |
| |
| initializer_expr: Used as "Type var{|initializer_expr|};". This is None |
| if "Type var;" sets an appropriate default value. |
| initializer_deps: A list of symbol names that |initializer_expr| depends |
| on. |
| is_initialization_lightweight: True if a possibly-redundant initialization |
| will not be more expensive than assignment. See bellow for an |
| example. |
| assignment_value: Used as "var = |assignment_value|;". |
| assignment_deps: A list of symbol names that |assignment_value| depends |
| on. |
| |
| |
| |is_initialization_lightweight| is True if |
| |
| Type var{${initializer_expr}}; |
| if (value_is_given) |
| var = value; |
| |
| is not more expensive than |
| |
| Type var; |
| if (value_is_given) |
| var = value; |
| else |
| var = ${assignment_value}; |
| """ |
| assert isinstance(idl_type, web_idl.IdlType) |
| assert (default_value is None |
| or isinstance(default_value, web_idl.LiteralConstant)) |
| assert default_value.is_type_compatible_with(idl_type) |
| |
| class DefaultValueExpr(object): |
| _ALLOWED_SYMBOLS_IN_DEPS = ("isolate") |
| |
| def __init__(self, initializer_expr, initializer_deps, |
| is_initialization_lightweight, assignment_value, |
| assignment_deps): |
| assert initializer_expr is None or isinstance( |
| initializer_expr, str) |
| assert (isinstance(initializer_deps, (list, tuple)) and all( |
| dependency in DefaultValueExpr._ALLOWED_SYMBOLS_IN_DEPS |
| for dependency in initializer_deps)) |
| assert isinstance(is_initialization_lightweight, bool) |
| assert isinstance(assignment_value, str) |
| assert (isinstance(assignment_deps, (list, tuple)) and all( |
| dependency in DefaultValueExpr._ALLOWED_SYMBOLS_IN_DEPS |
| for dependency in assignment_deps)) |
| |
| self.initializer_expr = initializer_expr |
| self.initializer_deps = initializer_deps |
| self.is_initialization_lightweight = is_initialization_lightweight |
| self.assignment_value = assignment_value |
| self.assignment_deps = assignment_deps |
| |
| if idl_type.unwrap(typedef=True).is_union: |
| union_type = idl_type.unwrap(typedef=True) |
| member_type = None |
| for member_type in union_type.flattened_member_types: |
| if default_value.is_type_compatible_with(member_type): |
| member_type = member_type |
| break |
| assert member_type is not None |
| |
| union_class_name = blink_class_name(union_type.union_definition_object) |
| member_default_expr = make_default_value_expr(member_type, |
| default_value) |
| if default_value.idl_type.is_nullable: |
| initializer_expr = None |
| assignment_value = _format("{}()", union_class_name) |
| else: |
| func_name = name_style.func("From", member_type.type_name) |
| argument = member_default_expr.assignment_value |
| # TODO(peria): Remove this workaround when we support V8Enum types |
| # in Union. |
| if (member_type.is_sequence |
| and member_type.element_type.unwrap().is_enumeration): |
| argument = "{}" |
| initializer_expr = _format("{}::{}({})", union_class_name, |
| func_name, argument) |
| assignment_value = initializer_expr |
| return DefaultValueExpr( |
| initializer_expr=initializer_expr, |
| initializer_deps=member_default_expr.initializer_deps, |
| is_initialization_lightweight=False, |
| assignment_value=assignment_value, |
| assignment_deps=member_default_expr.assignment_deps) |
| |
| type_info = blink_type_info(idl_type) |
| |
| is_initialization_lightweight = False |
| initializer_deps = [] |
| assignment_deps = [] |
| if default_value.idl_type.is_nullable: |
| if not type_info.has_null_value: |
| initializer_expr = None # !base::Optional::has_value() by default |
| assignment_value = "base::nullopt" |
| elif idl_type.unwrap().type_definition_object is not None: |
| initializer_expr = "nullptr" |
| is_initialization_lightweight = True |
| assignment_value = "nullptr" |
| elif idl_type.unwrap().is_string: |
| initializer_expr = None # String::IsNull() by default |
| assignment_value = "String()" |
| elif idl_type.unwrap().is_buffer_source_type: |
| initializer_expr = "nullptr" |
| is_initialization_lightweight = True |
| assignment_value = "nullptr" |
| elif type_info.value_t == "ScriptValue": |
| initializer_expr = "${isolate}, v8::Null(${isolate})" |
| initializer_deps = ["isolate"] |
| assignment_value = "ScriptValue::CreateNull(${isolate})" |
| assignment_deps = ["isolate"] |
| elif idl_type.unwrap().is_union: |
| initializer_expr = None # <union_type>::IsNull() by default |
| assignment_value = "{}()".format(type_info.value_t) |
| else: |
| assert False |
| elif default_value.idl_type.is_sequence: |
| initializer_expr = None # VectorOf<T>::size() == 0 by default |
| assignment_value = "{}()".format(type_info.value_t) |
| elif default_value.idl_type.is_object: |
| dict_name = blink_class_name(idl_type.unwrap().type_definition_object) |
| value = _format("{}::Create(${isolate})", dict_name) |
| initializer_expr = value |
| initializer_deps = ["isolate"] |
| assignment_value = value |
| assignment_deps = ["isolate"] |
| elif default_value.idl_type.is_boolean: |
| value = "true" if default_value.value else "false" |
| initializer_expr = value |
| is_initialization_lightweight = True |
| assignment_value = value |
| elif default_value.idl_type.is_integer: |
| initializer_expr = default_value.literal |
| is_initialization_lightweight = True |
| assignment_value = default_value.literal |
| elif default_value.idl_type.is_floating_point_numeric: |
| if default_value.value == float("NaN"): |
| value_fmt = "std::numeric_limits<{type}>::quiet_NaN()" |
| elif default_value.value == float("Infinity"): |
| value_fmt = "std::numeric_limits<{type}>::infinity()" |
| elif default_value.value == float("-Infinity"): |
| value_fmt = "-std::numeric_limits<{type}>::infinity()" |
| else: |
| value_fmt = "{value}" |
| value = value_fmt.format( |
| type=type_info.value_t, value=default_value.literal) |
| initializer_expr = value |
| is_initialization_lightweight = True |
| assignment_value = value |
| elif default_value.idl_type.is_string: |
| if idl_type.unwrap().is_string: |
| value = "\"{}\"".format(default_value.value) |
| initializer_expr = value |
| assignment_value = value |
| elif idl_type.unwrap().is_enumeration: |
| enum_class_name = blink_class_name( |
| idl_type.unwrap().type_definition_object) |
| enum_value_name = name_style.constant(default_value.value) |
| initializer_expr = "{}::Enum::{}".format(enum_class_name, |
| enum_value_name) |
| is_initialization_lightweight = True |
| assignment_value = "{}({})".format(enum_class_name, |
| initializer_expr) |
| else: |
| assert False |
| else: |
| assert False |
| |
| return DefaultValueExpr( |
| initializer_expr=initializer_expr, |
| initializer_deps=initializer_deps, |
| is_initialization_lightweight=is_initialization_lightweight, |
| assignment_value=assignment_value, |
| assignment_deps=assignment_deps) |
| |
| |
| def make_v8_to_blink_value(blink_var_name, |
| v8_value_expr, |
| idl_type, |
| argument=None, |
| error_exit_return_statement="return;", |
| cg_context=None): |
| """ |
| Returns a SymbolNode whose definition converts a v8::Value to a Blink value. |
| """ |
| assert isinstance(blink_var_name, str) |
| assert isinstance(v8_value_expr, str) |
| assert isinstance(idl_type, web_idl.IdlType) |
| assert argument is None or isinstance(argument, web_idl.Argument) |
| assert isinstance(error_exit_return_statement, str) |
| |
| T = TextNode |
| F = lambda *args, **kwargs: T(_format(*args, **kwargs)) |
| |
| # Use of fast path is a trade-off between speed and binary size, so apply |
| # it only when it's effective. This hack is most significant on Android. |
| use_fast_path = ( |
| cg_context and cg_context.operation |
| and not (cg_context.is_return_type_promise_type or |
| "RaisesException" in cg_context.operation.extended_attributes) |
| and all((arg.idl_type.type_name == "String" or arg.idl_type.unwrap( |
| typedef=True).is_callback_function) |
| for arg in cg_context.operation.arguments)) |
| fast_path_cond = None |
| fast_path_body_text = None |
| if not use_fast_path: |
| pass |
| elif idl_type.type_name == "String": |
| # A key point of this fast path is that it doesn't require an |
| # ExceptionState. |
| fast_path_cond = "LIKELY({}->IsString())".format(v8_value_expr) |
| fast_path_body_text = "{}.Init({}.As<v8::String>());".format( |
| blink_var_name, v8_value_expr) |
| elif idl_type.unwrap(typedef=True).is_callback_function: |
| # A key point of this fast path is that it doesn't require an |
| # ExceptionState. |
| fast_path_cond = "LIKELY({}->IsFunction())".format(v8_value_expr) |
| fast_path_body_text = "{} = {}::Create({}.As<v8::Function>());".format( |
| blink_var_name, |
| blink_class_name(idl_type.unwrap().type_definition_object), |
| v8_value_expr) |
| |
| def create_definition(symbol_node): |
| if argument is None: |
| func_name = "NativeValue" |
| arguments = ["${isolate}", v8_value_expr, "${exception_state}"] |
| else: |
| func_name = "ArgumentValue" |
| arguments = [ |
| "${isolate}", |
| str(argument.index), |
| v8_value_expr, |
| "${exception_state}", |
| ] |
| if "StringContext" in idl_type.effective_annotations: |
| arguments.append("${execution_context_of_document_tree}") |
| blink_value_expr = _format("NativeValueTraits<{_1}>::{_2}({_3})", |
| _1=native_value_tag( |
| idl_type, |
| argument=argument, |
| apply_optional_to_last_arg=False), |
| _2=func_name, |
| _3=", ".join(arguments)) |
| if argument and argument.default_value: |
| default_expr = make_default_value_expr(idl_type, |
| argument.default_value) |
| else: |
| default_expr = None |
| exception_exit_node = CxxUnlikelyIfNode( |
| cond="${exception_state}.HadException()", |
| body=T(error_exit_return_statement)) |
| |
| if not (default_expr or fast_path_cond): |
| return SymbolDefinitionNode(symbol_node, [ |
| F("auto&& ${{{}}} = {};", blink_var_name, blink_value_expr), |
| exception_exit_node, |
| ]) |
| |
| blink_var_type = _format( |
| "decltype(NativeValueTraits<{}>::NativeValue(" |
| "std::declval<v8::Isolate*>(), " |
| "std::declval<v8::Local<v8::Value>>(), " |
| "std::declval<ExceptionState&>()))", |
| native_value_tag(idl_type, |
| argument=argument, |
| apply_optional_to_last_arg=False)) |
| if default_expr and default_expr.is_initialization_lightweight: |
| pattern = "{} ${{{}}}{{{}}};" |
| args = [ |
| blink_var_type, blink_var_name, default_expr.initializer_expr |
| ] |
| else: |
| pattern = "{} ${{{}}};" |
| args = [blink_var_type, blink_var_name] |
| blink_var_def_node = F(pattern, *args) |
| assignment = [ |
| F("${{{}}} = {};", blink_var_name, blink_value_expr), |
| exception_exit_node, |
| ] |
| if not default_expr: |
| pass |
| elif (default_expr.initializer_expr is None |
| or default_expr.is_initialization_lightweight): |
| assignment = CxxLikelyIfNode( |
| cond="!{}->IsUndefined()".format(v8_value_expr), |
| body=assignment) |
| else: |
| assignment = CxxIfElseNode( |
| cond="{}->IsUndefined()".format(v8_value_expr), |
| then=F("${{{}}} = {};", blink_var_name, |
| default_expr.assignment_value), |
| then_likeliness=Likeliness.LIKELY, |
| else_=assignment, |
| else_likeliness=Likeliness.LIKELY) |
| if fast_path_cond: |
| assignment = CxxIfElseNode(cond=fast_path_cond, |
| then=T(fast_path_body_text), |
| then_likeliness=Likeliness.LIKELY, |
| else_=assignment, |
| else_likeliness=Likeliness.UNLIKELY) |
| return SymbolDefinitionNode(symbol_node, [ |
| blink_var_def_node, |
| assignment, |
| ]) |
| |
| return SymbolNode(blink_var_name, definition_constructor=create_definition) |
| |
| |
| def make_v8_to_blink_value_variadic(blink_var_name, v8_array, |
| v8_array_start_index, idl_type): |
| """ |
| Returns a SymbolNode whose definition converts an array of v8::Value |
| (variadic arguments) to a Blink value. |
| """ |
| assert isinstance(blink_var_name, str) |
| assert isinstance(v8_array, str) |
| assert isinstance(v8_array_start_index, int) |
| assert isinstance(idl_type, web_idl.IdlType) |
| |
| pattern = ("auto&& ${{{_1}}} = " |
| "bindings::VariadicArgumentsToNativeValues<{_2}>({_3});") |
| arguments = [ |
| "${isolate}", v8_array, |
| str(v8_array_start_index), "${exception_state}" |
| ] |
| if "StringContext" in idl_type.element_type.effective_annotations: |
| arguments.append("${execution_context_of_document_tree}") |
| text = _format( |
| pattern, |
| _1=blink_var_name, |
| _2=native_value_tag(idl_type.element_type), |
| _3=", ".join(arguments)) |
| |
| def create_definition(symbol_node): |
| return SymbolDefinitionNode(symbol_node, [ |
| TextNode(text), |
| CxxUnlikelyIfNode( |
| cond="${exception_state}.HadException()", |
| body=TextNode("return;")), |
| ]) |
| |
| return SymbolNode(blink_var_name, definition_constructor=create_definition) |