blob: 1d72ec5830f13516af3f79f3162b8da3fb9125bb [file] [log] [blame]
# 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 os.path
import web_idl
from . import name_style
from .blink_v8_bridge import blink_class_name
from .blink_v8_bridge import blink_type_info
from .blink_v8_bridge import make_default_value_expr
from .blink_v8_bridge import make_v8_to_blink_value
from .code_node import CodeNode
from .code_node import Likeliness
from .code_node import ListNode
from .code_node import SequenceNode
from .code_node import SymbolNode
from .code_node import SymbolScopeNode
from .code_node import TextNode
from .code_node_cxx import CxxClassDefNode
from .code_node_cxx import CxxFuncDeclNode
from .code_node_cxx import CxxFuncDefNode
from .code_node_cxx import CxxIfElseNode
from .code_node_cxx import CxxLikelyIfNode
from .code_node_cxx import CxxNamespaceNode
from .codegen_accumulator import CodeGenAccumulator
from .codegen_context import CodeGenContext
from .codegen_expr import expr_from_exposure
from .codegen_format import format_template as _format
from .codegen_utils import collect_include_headers_of_idl_types
from .codegen_utils import component_export
from .codegen_utils import component_export_header
from .codegen_utils import enclose_with_header_guard
from .codegen_utils import make_copyright_header
from .codegen_utils import make_forward_declarations
from .codegen_utils import make_header_include_directives
from .codegen_utils import write_code_node_to_file
from .mako_renderer import MakoRenderer
from .path_manager import PathManager
_DICT_MEMBER_PRESENCE_PREDICATES = {
"ScriptValue": "{}.IsEmpty()",
"ScriptPromise": "{}.IsEmpty()",
}
def _blink_member_name(member):
assert isinstance(member, web_idl.DictionaryMember)
class BlinkMemberName(object):
def __init__(self, member):
blink_name = (member.code_generator_info.property_implemented_as
or member.identifier)
self.get_api = name_style.api_func(blink_name)
self.set_api = name_style.api_func("set", blink_name)
self.has_api = name_style.api_func("has", blink_name)
# C++ data member that shows the presence of the IDL member.
self.presence_var = name_style.member_var("has", blink_name)
# C++ data member that holds the value of the IDL member.
self.value_var = name_style.member_var(blink_name)
return BlinkMemberName(member)
def _is_member_always_present(member):
assert isinstance(member, web_idl.DictionaryMember)
return member.is_required or member.default_value is not None
def _does_use_presence_flag(member):
assert isinstance(member, web_idl.DictionaryMember)
return (not _is_member_always_present(member) and blink_type_info(
member.idl_type).member_t not in _DICT_MEMBER_PRESENCE_PREDICATES)
def _member_presence_expr(member):
assert isinstance(member, web_idl.DictionaryMember)
if _is_member_always_present(member):
return "true"
if _does_use_presence_flag(member):
return _blink_member_name(member).presence_var
blink_type = blink_type_info(member.idl_type).member_t
assert blink_type in _DICT_MEMBER_PRESENCE_PREDICATES
_1 = _blink_member_name(member).value_var
return _format(_DICT_MEMBER_PRESENCE_PREDICATES[blink_type], _1)
def bind_member_iteration_local_vars(code_node):
local_vars = [
SymbolNode(
"current_context", "v8::Local<v8::Context> ${current_context} = "
"${isolate}->GetCurrentContext();"),
SymbolNode(
"member_names", "const auto* ${member_names} = "
"GetV8MemberNames(${isolate}).data();"),
]
# Execution context
node = SymbolNode(
"execution_context", "ExecutionContext* ${execution_context} = "
"ToExecutionContext(${current_context});")
node.accumulate(
CodeGenAccumulator.require_include_headers([
"third_party/blink/renderer/core/execution_context/execution_context.h"
]))
local_vars.append(node)
code_node.register_code_symbols(local_vars)
def make_dict_member_get_def(cg_context):
assert isinstance(cg_context, CodeGenContext)
member = cg_context.dict_member
blink_member_name = _blink_member_name(member)
name = blink_member_name.get_api
blink_type = blink_type_info(member.idl_type)
if blink_type.ref_t != blink_type.const_ref_t:
func_def = CxxFuncDefNode(
name=name, arg_decls=[], return_type=blink_type.ref_t)
func_def.set_base_template_vars(cg_context.template_bindings())
func_def.body.extend([
TextNode(_format("DCHECK({}());", blink_member_name.has_api)),
TextNode(_format("return {};", blink_member_name.value_var)),
])
else:
func_def = None
const_func_def = CxxFuncDefNode(
name=name,
arg_decls=[],
return_type=blink_type.const_ref_t,
const=True)
const_func_def.set_base_template_vars(cg_context.template_bindings())
const_func_def.body.extend([
TextNode(_format("DCHECK({}());", blink_member_name.has_api)),
TextNode(_format("return {};", blink_member_name.value_var)),
])
return ListNode([func_def, const_func_def])
def make_dict_member_has_def(cg_context):
assert isinstance(cg_context, CodeGenContext)
member = cg_context.dict_member
func_def = CxxFuncDefNode(
name=_blink_member_name(member).has_api,
arg_decls=[],
return_type="bool",
const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
_1 = _member_presence_expr(member)
body.append(TextNode(_format("return {_1};", _1=_1)))
return func_def
def make_dict_member_set_def(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
member = cg_context.dict_member
blink_member_name = _blink_member_name(member)
real_type = member.idl_type.unwrap(typedef=True)
type_info = blink_type_info(real_type)
decls = ListNode() # Includes inline definitions.
defs = ListNode()
template_func_def = CxxFuncDefNode(
name=blink_member_name.set_api,
arg_decls=["T&& value"],
return_type="void",
template_params=["typename T"])
decls.append(template_func_def)
# This setter with the explicit type declaration makes it possible to set
# the dictionary member with uniform initialization (especially aggregate
# initialization), e.g. setIntVector({3, 1, 4, 1, 5}).
move_func_decl = CxxFuncDeclNode(
name=blink_member_name.set_api,
arg_decls=[_format("{}&&", type_info.member_t)],
return_type="void")
decls.append(move_func_decl)
move_func_def = CxxFuncDefNode(
name=blink_member_name.set_api,
arg_decls=[_format("{}&& value", type_info.member_t)],
return_type="void",
class_name=cg_context.class_name)
defs.append(move_func_def)
_1 = blink_member_name.value_var
template_func_def.body.append(
T(_format("{_1} = std::forward<T>(value);", _1=_1)))
move_func_def.body.append(T(_format("{_1} = value;", _1=_1)))
if _does_use_presence_flag(member):
set_presense_expr = _format("{} = true;",
blink_member_name.presence_var)
template_func_def.body.append(T(set_presense_expr))
move_func_def.body.append(T(set_presense_expr))
# Migration Adapter
if (real_type.is_nullable and
blink_type_info(real_type).typename.startswith("base::Optional")):
to_null_func_def = CxxFuncDefNode(
name=_format("{}ToNull", blink_member_name.set_api),
arg_decls=[],
return_type="void")
decls.append(to_null_func_def)
to_null_func_def.set_base_template_vars(cg_context.template_bindings())
to_null_func_def.body.append(
T(_format("{}(base::nullopt);", blink_member_name.set_api)))
return decls, defs
def make_dict_member_defs(cg_context):
assert isinstance(cg_context, CodeGenContext)
member = cg_context.dict_member
get_def = make_dict_member_get_def(cg_context)
has_def = make_dict_member_has_def(cg_context)
set_decls, set_defs = make_dict_member_set_def(cg_context)
default_value_initializer = ""
if member.default_value:
default_expr = make_default_value_expr(member.idl_type,
member.default_value)
if default_expr.initializer is not None:
default_value_initializer = _format("{{{}}}",
default_expr.initializer)
_1 = blink_type_info(member.idl_type).member_t
_2 = _blink_member_name(member).value_var
_3 = default_value_initializer
value_var_def = TextNode(_format("{_1} {_2}{_3};", _1=_1, _2=_2, _3=_3))
if _does_use_presence_flag(member):
_1 = _blink_member_name(member).presence_var
presense_var_def = TextNode(_format("bool {_1} = false;", _1=_1))
else:
presense_var_def = None
return (get_def, has_def, set_decls, set_defs, value_var_def,
presense_var_def)
def make_get_v8_dict_member_names_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
dictionary = cg_context.dictionary
name = "GetV8MemberNames"
arg_decls = ["v8::Isolate* isolate"]
return_type = "const base::span<const v8::Eternal<v8::Name>>"
func_decl = CxxFuncDeclNode(
name=name, arg_decls=arg_decls, return_type=return_type, static=True)
func_def = CxxFuncDefNode(
name=name,
class_name=cg_context.class_name,
arg_decls=arg_decls,
return_type=return_type)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
if dictionary.own_members:
pattern = "static const char* kKeyStrings[] = {{{_1}}};"
_1 = ", ".join(
_format("\"{}\"", member.identifier)
for member in dictionary.own_members)
body.extend([
TextNode(_format(pattern, _1=_1)),
TextNode("return V8PerIsolateData::From(isolate)"
"->FindOrCreateEternalNameCache(kKeyStrings, "
"kKeyStrings);"),
])
else:
body.append(TextNode("return {};"))
return func_decl, func_def
def make_fill_with_dict_members_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
dictionary = cg_context.dictionary
name = "FillWithMembers"
arg_decls = [
"v8::Isolate* isolate",
"v8::Local<v8::Object> creation_context",
"v8::Local<v8::Object> v8_dictionary",
]
return_type = "bool"
func_decl = CxxFuncDeclNode(
name=name,
arg_decls=arg_decls,
return_type=return_type,
const=True,
override=True)
func_def = CxxFuncDefNode(
name=name,
class_name=cg_context.class_name,
arg_decls=arg_decls,
return_type=return_type,
const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
if dictionary.inherited:
text = """\
if (!BaseClass::FillWithMembers(isolate, creation_context, v8_dictionary)) {
return false;
}"""
body.append(TextNode(text))
body.append(
TextNode("return FillWithOwnMembers("
"isolate, creation_context, v8_dictionary);"))
return func_decl, func_def
def make_fill_with_own_dict_members_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
dictionary = cg_context.dictionary
own_members = dictionary.own_members
name = "FillWithOwnMembers"
arg_decls = [
"v8::Isolate* isolate",
"v8::Local<v8::Object> creation_context",
"v8::Local<v8::Object> v8_dictionary",
]
return_type = "bool"
func_decl = CxxFuncDeclNode(
name=name, arg_decls=arg_decls, return_type=return_type, const=True)
func_def = CxxFuncDefNode(
name=name,
class_name=cg_context.class_name,
arg_decls=arg_decls,
return_type=return_type,
const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
body.add_template_var("isolate", "isolate")
bind_member_iteration_local_vars(body)
for key_index, member in enumerate(own_members):
_1 = _blink_member_name(member).has_api
_2 = key_index
_3 = _blink_member_name(member).get_api
pattern = ("""\
if ({_1}()) {{
if (!v8_dictionary
->CreateDataProperty(
${current_context},
${member_names}[{_2}].Get(isolate),
ToV8({_3}(), creation_context, isolate))
.ToChecked()) {{
return false;
}}
}}\
""")
node = T(_format(pattern, _1=_1, _2=_2, _3=_3))
conditional = expr_from_exposure(member.exposure)
if not conditional.is_always_true:
node = CxxLikelyIfNode(cond=conditional, body=node)
body.append(node)
body.append(T("return true;"))
return func_decl, func_def
def make_dict_create_funcs(cg_context):
assert isinstance(cg_context, CodeGenContext)
name = "Create"
arg_decls = [
"v8::Isolate* isolate",
"v8::Local<v8::Value> v8_value",
"ExceptionState& exception_state",
]
return_type = "${class_name}*"
default_create_def = CxxFuncDefNode(
name=name, arg_decls=[], return_type=return_type, static=True)
default_create_def.set_base_template_vars(cg_context.template_bindings())
default_create_def.body.append(
TextNode("return MakeGarbageCollected<${class_name}>();"))
create_decl = CxxFuncDeclNode(
name=name, arg_decls=arg_decls, return_type=return_type, static=True)
create_def = CxxFuncDefNode(
name=name,
class_name=cg_context.class_name,
arg_decls=arg_decls,
return_type=return_type)
create_def.set_base_template_vars(cg_context.template_bindings())
create_def.body.append(
TextNode("""\
DCHECK(!v8_value.IsEmpty());
${class_name}* dictionary = MakeGarbageCollected<${class_name}>();
dictionary->FillMembers(isolate, v8_value, exception_state);
if (exception_state.HadException()) {
return nullptr;
}
return dictionary;"""))
decls = ListNode([
default_create_def,
create_decl,
])
defs = ListNode([
create_def,
])
return decls, defs
def make_fill_dict_members_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
dictionary = cg_context.dictionary
own_members = dictionary.own_members
required_own_members = list(
member for member in own_members if member.is_required)
name = "FillMembers"
arg_decls = [
"v8::Isolate* isolate",
"v8::Local<v8::Value> v8_value",
"ExceptionState& exception_state",
]
return_type = "void"
func_decl = CxxFuncDeclNode(
name=name, arg_decls=arg_decls, return_type=return_type)
func_def = CxxFuncDefNode(
name=name,
class_name=cg_context.class_name,
arg_decls=arg_decls,
return_type=return_type)
func_def.set_base_template_vars(cg_context.template_bindings())
if required_own_members:
check_required_members_node = T("""\
if (v8_value->IsNullOrUndefined()) {
exception_state.ThrowTypeError(ExceptionMessages::FailedToConstruct(
"${dictionary.identifier}",
"has required members, but null/undefined was passed."));
return;
}""")
else:
check_required_members_node = T("""\
if (v8_value->IsNullOrUndefined()) {
return;
}""")
# [PermissiveDictionaryConversion]
if "PermissiveDictionaryConversion" in dictionary.extended_attributes:
permissive_conversion_node = T("""\
if (!v8_value->IsObject()) {
// [PermissiveDictionaryConversion]
return;
}""")
else:
permissive_conversion_node = T("""\
if (!v8_value->IsObject()) {
exception_state.ThrowTypeError(
ExceptionMessages::FailedToConstruct(
"${dictionary.identifier}", "The value is not of type Object"));
return;
}""")
call_internal_func_node = T("""\
FillMembersInternal(isolate, v8_value.As<v8::Object>(), exception_state);""")
func_def.body.extend([
check_required_members_node,
permissive_conversion_node,
call_internal_func_node,
])
return func_decl, func_def
def make_fill_dict_members_internal_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
dictionary = cg_context.dictionary
own_members = dictionary.own_members
name = "FillMembersInternal"
arg_decls = [
"v8::Isolate* isolate",
"v8::Local<v8::Object> v8_dictionary",
"ExceptionState& exception_state",
]
return_type = "void"
func_decl = CxxFuncDeclNode(
name=name, arg_decls=arg_decls, return_type=return_type)
func_def = CxxFuncDefNode(
name=name,
class_name=cg_context.class_name,
arg_decls=arg_decls,
return_type=return_type)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
body.add_template_var("isolate", "isolate")
body.add_template_var("exception_state", "exception_state")
bind_member_iteration_local_vars(body)
body.register_code_symbols([
SymbolNode("try_block", "v8::TryCatch ${try_block}(${isolate});"),
SymbolNode("v8_value", "v8::Local<v8::Value> ${v8_value};"),
])
if dictionary.inherited:
text = """\
BaseClass::FillMembersInternal(${isolate}, v8_dictionary, ${exception_state});
if (${exception_state}.HadException()) {
return;
}
"""
body.append(T(text))
for key_index, member in enumerate(own_members):
body.append(make_fill_own_dict_member(key_index, member))
return func_decl, func_def
def make_fill_own_dict_member(key_index, member):
assert isinstance(key_index, int)
assert isinstance(member, web_idl.DictionaryMember)
T = TextNode
pattern = """
if (!<% try_block %>v8_dictionary->Get(${current_context}, ${member_names}[{_1}].Get(${isolate}))
.ToLocal(&${v8_value})) {{
${exception_state}.RethrowV8Exception(${try_block}.Exception());
return;
}}"""
get_v8_value_node = T(_format(pattern, _1=key_index))
api_call_node = SymbolScopeNode()
api_call_node.register_code_symbol(
make_v8_to_blink_value("blink_value", "${v8_value}", member.idl_type))
_1 = _blink_member_name(member).set_api
api_call_node.append(T(_format("{_1}(${blink_value});", _1=_1)))
if member.is_required:
exception_pattern = """\
${exception_state}.ThrowTypeError(
ExceptionMessages::FailedToGet(
"{}", "${{dictionary.identifier}}",
"Required member is undefined."));
"""
check_and_fill_node = CxxIfElseNode(
cond="!${v8_value}->IsUndefined()",
then=api_call_node,
then_likeliness=Likeliness.LIKELY,
else_=T(_format(exception_pattern, member.identifier)),
else_likeliness=Likeliness.UNLIKELY)
else:
check_and_fill_node = CxxLikelyIfNode(
cond="!${v8_value}->IsUndefined()", body=api_call_node)
node = SequenceNode([
get_v8_value_node,
check_and_fill_node,
])
conditional = expr_from_exposure(member.exposure)
if not conditional.is_always_true:
node = CxxLikelyIfNode(cond=conditional, body=node)
return node
def make_dict_trace_func(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
dictionary = cg_context.dictionary
own_members = dictionary.own_members
name = "Trace"
arg_decls = ["Visitor* visitor"]
return_type = "void"
func_decl = CxxFuncDeclNode(
name=name, arg_decls=arg_decls, return_type=return_type, override=True)
func_def = CxxFuncDefNode(
name=name,
class_name=cg_context.class_name,
arg_decls=arg_decls,
return_type=return_type)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
def make_trace_member_node(member):
pattern = "TraceIfNeeded<{_1}>::Trace(visitor, {_2});"
_1 = blink_type_info(member.idl_type).member_t
_2 = _blink_member_name(member).value_var
return TextNode(_format(pattern, _1=_1, _2=_2))
body.extend(map(make_trace_member_node, own_members))
body.append(TextNode("BaseClass::Trace(visitor);"))
return func_decl, func_def
def generate_dictionary(dictionary):
assert len(dictionary.components) == 1, (
"We don't support partial dictionaries across components yet.")
component = dictionary.components[0]
path_manager = PathManager(dictionary)
class_name = name_style.class_(blink_class_name(dictionary))
if dictionary.inherited:
base_class_name = blink_class_name(dictionary.inherited)
else:
base_class_name = "bindings::DictionaryBase"
cg_context = CodeGenContext(
dictionary=dictionary,
class_name=class_name,
base_class_name=base_class_name)
# Filepaths
basename = "dictionary_example"
header_path = path_manager.api_path(filename=basename, ext="h")
source_path = path_manager.api_path(filename=basename, ext="cc")
# Root nodes
header_node = ListNode(tail="\n")
header_node.set_accumulator(CodeGenAccumulator())
header_node.set_renderer(MakoRenderer())
source_node = ListNode(tail="\n")
source_node.set_accumulator(CodeGenAccumulator())
source_node.set_renderer(MakoRenderer())
# Namespaces
header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
# Class definitions
class_def = CxxClassDefNode(
cg_context.class_name,
base_class_names=[cg_context.base_class_name],
export=component_export(component))
class_def.set_base_template_vars(cg_context.template_bindings())
class_def.top_section.append(
TextNode("using BaseClass = ${base_class_name};"))
# Create functions
create_decl, create_def = make_dict_create_funcs(cg_context)
# Constructor and destructor
constructor_decl = CxxFuncDeclNode(
name=cg_context.class_name, arg_decls=[], return_type="", default=True)
destructor_decl = CxxFuncDeclNode(
name="~${class_name}", arg_decls=[], return_type="", default=True)
# Fill with members (Blink -> V8 conversion)
(fill_with_members_decl,
fill_with_members_def) = make_fill_with_dict_members_func(cg_context)
(fill_with_own_members_decl, fill_with_own_members_def
) = make_fill_with_own_dict_members_func(cg_context)
# Fill members (V8 -> Blink conversion)
(fill_members_decl,
fill_members_def) = make_fill_dict_members_func(cg_context)
(fill_members_internal_decl, fill_members_internal_def
) = make_fill_dict_members_internal_func(cg_context)
# Misc. functions
(get_v8_member_names_decl,
get_v8_member_names_def) = make_get_v8_dict_member_names_func(cg_context)
trace_decl, trace_def = make_dict_trace_func(cg_context)
member_accessor_decls = ListNode()
member_accessor_defs = ListNode()
member_value_var_defs = ListNode()
member_presense_var_defs = ListNode()
for member in cg_context.dictionary.own_members:
(member_get_decls, member_has_decls, member_set_decls, member_set_defs,
member_value_var, member_presense_var) = make_dict_member_defs(
cg_context.make_copy(dict_member=member))
member_accessor_decls.extend([
TextNode(""),
member_get_decls,
member_has_decls,
member_set_decls,
])
member_accessor_defs.extend([
TextNode(""),
member_set_defs,
])
member_value_var_defs.append(member_value_var)
member_presense_var_defs.append(member_presense_var)
# Header part (copyright, include directives, and forward declarations)
if dictionary.inherited:
base_class_header = PathManager(dictionary.inherited).api_path(ext="h")
else:
base_class_header = (
"third_party/blink/renderer/platform/bindings/dictionary_base.h")
header_node.accumulator.add_include_headers(
collect_include_headers_of_idl_types(
[member.idl_type for member in dictionary.own_members]))
header_node.accumulator.add_include_headers([
base_class_header,
component_export_header(component),
"v8/include/v8.h",
])
header_node.accumulator.add_class_decls([
"ExceptionState",
"Visitor",
])
source_node.accumulator.add_include_headers([
"third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h",
"third_party/blink/renderer/platform/bindings/exception_messages.h",
"third_party/blink/renderer/platform/bindings/exception_state.h",
"third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h",
"third_party/blink/renderer/platform/heap/visitor.h",
])
header_node.extend([
make_copyright_header(),
TextNode(""),
enclose_with_header_guard(
ListNode([
make_header_include_directives(header_node.accumulator),
TextNode(""),
header_blink_ns,
]), name_style.header_guard(header_path)),
])
header_blink_ns.body.extend([
make_forward_declarations(header_node.accumulator),
TextNode(""),
])
source_node.extend([
make_copyright_header(),
TextNode(""),
TextNode("#include \"{}\"".format(header_path)),
TextNode(""),
make_header_include_directives(source_node.accumulator),
TextNode(""),
source_blink_ns,
])
source_blink_ns.body.extend([
make_forward_declarations(source_node.accumulator),
TextNode(""),
])
# Assemble the parts.
header_blink_ns.body.append(class_def)
class_def.public_section.extend([
create_decl,
constructor_decl,
destructor_decl,
TextNode(""),
trace_decl,
TextNode(""),
member_accessor_decls,
])
class_def.protected_section.extend([
fill_with_members_decl,
TextNode(""),
fill_members_internal_decl,
])
class_def.private_section.extend([
get_v8_member_names_decl,
TextNode(""),
fill_with_own_members_decl,
TextNode(""),
fill_members_decl,
TextNode(""),
member_value_var_defs,
TextNode(""),
member_presense_var_defs,
])
source_blink_ns.body.extend([
get_v8_member_names_def,
TextNode(""),
create_def,
TextNode(""),
fill_with_members_def,
TextNode(""),
fill_with_own_members_def,
TextNode(""),
fill_members_def,
TextNode(""),
fill_members_internal_def,
TextNode(""),
member_accessor_defs,
TextNode(""),
trace_def,
])
# Write down to the files.
write_code_node_to_file(header_node, path_manager.gen_path_to(header_path))
write_code_node_to_file(source_node, path_manager.gen_path_to(source_path))
def generate_dictionaries(web_idl_database):
dictionary = web_idl_database.find("RTCQuicStreamWriteParameters")
generate_dictionary(dictionary)