ladybird/Meta/Generators/libweb_bindings/to_js_value.py
Shannon Booth dba62aefc0 LibWeb/Bindings: Port IDL bindings generator to Python
Replace the Lagom C++ bindings generator invocation with the new Python
generator under Meta/Generators/libweb_bindings.

Fold the exposed-interface generation into the same generator entry
point, and keep generated overload metadata using the existing LibIDL
types for now.
2026-06-08 01:11:40 +02:00

626 lines
27 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Copyright (c) 2026-present, the Ladybird developers.
#
# SPDX-License-Identifier: BSD-2-Clause
from typing import TextIO
from Generators.libweb_bindings.context import GenerationContext
from Generators.libweb_bindings.cpp_types import add_binding_include_for_type
from Generators.libweb_bindings.cpp_types import add_buffer_source_type_include
from Generators.libweb_bindings.cpp_types import cpp_name
from Generators.libweb_bindings.cpp_types import cpp_type_details
from Generators.libweb_bindings.cpp_types import cpp_type_for_idl_type
from Generators.libweb_bindings.cpp_types import cpp_type_for_idl_type_details
from Generators.libweb_bindings.cpp_types import implementation_header_for_interface
from Generators.libweb_bindings.cpp_types import interface_like_type_for_idl_type
from Generators.libweb_bindings.cpp_types import is_buffer_source_type
from Generators.libweb_bindings.cpp_types import is_optional_without_default
from Generators.libweb_bindings.cpp_types import is_string_type
from Generators.libweb_bindings.includes import GeneratedIncludes
from Utils.utils import make_name_acceptable_cpp
from Utils.utils import string_to_cpp_enum_name
from Utils.utils import title_case_to_snake_case
from Utils.webidl_parser import Dictionary
from Utils.webidl_parser import DictionaryMember
from Utils.webidl_parser import Enumeration
from Utils.webidl_parser import IDLParameterizedType
from Utils.webidl_parser import IDLType
from Utils.webidl_parser import IDLUnionType
def unsupported_to_javascript_value(idl_type: IDLType) -> str:
raise RuntimeError(f"Unsupported IDL value conversion for '{idl_type.name}'")
def to_value_function_name(dictionary: Dictionary) -> str:
return f"{make_name_acceptable_cpp(title_case_to_snake_case(dictionary.name))}_to_value"
def write_enumeration_to_javascript_value_declaration(
out: TextIO,
enumeration: Enumeration,
includes: GeneratedIncludes,
) -> None:
includes.add("AK/String.h")
out.write(f"String idl_enum_to_string({enumeration.name});\n\n")
def write_dictionary_to_javascript_value_declaration(out: TextIO, dictionary: Dictionary) -> None:
if "GenerateToValue" not in dictionary.extended_attributes:
return
out.write(f"JS::Value {to_value_function_name(dictionary)}(JS::Realm&, {dictionary.name} const&);\n\n")
def write_enumeration_to_javascript_value_conversion(out: TextIO, enumeration: Enumeration) -> None:
out.write(
f"""// https://webidl.spec.whatwg.org/#idl-enumeration
String idl_enum_to_string({enumeration.name} value)
{{
// The result of converting an IDL enumeration type value to a JavaScript value is the String value that represents the same sequence of code units as the enumeration value.
switch (value) {{
"""
)
for value in enumeration.values:
out.write(f" case {enumeration.name}::{string_to_cpp_enum_name(value)}:\n")
out.write(f' return "{value}"_string;\n')
out.write(
""" }
VERIFY_NOT_REACHED();
}
"""
)
def write_dictionary_to_javascript_value_conversion(
out: TextIO,
dictionary: Dictionary,
includes: GeneratedIncludes,
context: GenerationContext,
) -> None:
if "GenerateToValue" not in dictionary.extended_attributes:
return
includes.add("LibJS/Runtime/Object.h")
out.write(
f"""JS::Value {to_value_function_name(dictionary)}(JS::Realm& realm, {dictionary.name} const& dictionary)
{{
auto& vm = realm.vm();
return {to_javascript_value(IDLType(dictionary.name), "dictionary", includes, context)};
}}
"""
)
def integer_to_javascript_value(cpp_type_name: str, value: str, includes: GeneratedIncludes) -> str:
includes.add("LibWeb/WebIDL/Types.h")
return f"JS::Value(static_cast<{cpp_type_name}>({value}))"
# 3.2.1. any, https://webidl.spec.whatwg.org/#js-any
def any_to_javascript_value(value: str) -> str:
# An IDL any value is converted to a JavaScript value according to the rules for converting the specific type of the
# NB: We're getting passed a JS::Value - which is already our JS representation, so we can just return it as-is.
return value
# 3.2.2. undefined, https://webidl.spec.whatwg.org/#js-undefined
def undefined_to_javascript_value() -> str:
# The unique IDL undefined value is converted to the JavaScript undefined value.
return "JS::js_undefined()"
# 3.2.3. boolean, https://webidl.spec.whatwg.org/#js-boolean
def boolean_to_javascript_value(value: str) -> str:
# The IDL boolean value true is converted to the JavaScript true value and the IDL boolean value false is converted
# to the JavaScript false value.
return f"JS::Value({value})"
# 3.2.4.1. byte, https://webidl.spec.whatwg.org/#js-byte
def byte_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
# The result of converting an IDL byte value to a JavaScript value is a Number that represents the same numeric value
# as the IDL byte value. The Number value will be an integer in the range [128, 127].
return integer_to_javascript_value("WebIDL::Byte", value, includes)
# 3.2.4.2. octet, https://webidl.spec.whatwg.org/#js-octet
def octet_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
# The result of converting an IDL octet value to a JavaScript value is a Number that represents the same numeric value
# as the IDL octet value. The Number value will be an integer in the range [0, 255].
return integer_to_javascript_value("WebIDL::Octet", value, includes)
# 3.2.4.3. short, https://webidl.spec.whatwg.org/#js-short
def short_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
# The result of converting an IDL short value to a JavaScript value is a Number that represents the same numeric value
# as the IDL short value. The Number value will be an integer in the range [32768, 32767].
return integer_to_javascript_value("WebIDL::Short", value, includes)
# 3.2.4.4. unsigned short, https://webidl.spec.whatwg.org/#js-unsigned-short
def unsigned_short_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
# The result of converting an IDL unsigned short value to a JavaScript value is a Number that represents the same numeric
# value as the IDL unsigned short value. The Number value will be an integer in the range [0, 65535].
return integer_to_javascript_value("WebIDL::UnsignedShort", value, includes)
# 3.2.4.5. long, https://webidl.spec.whatwg.org/#js-long
def long_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
# The result of converting an IDL long value to a JavaScript value is a Number that represents the same numeric value as
# the IDL long value. The Number value will be an integer in the range [2147483648, 2147483647].
return integer_to_javascript_value("WebIDL::Long", value, includes)
# 3.2.4.6. unsigned long, https://webidl.spec.whatwg.org/#js-unsigned-long
def unsigned_long_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
# The result of converting an IDL unsigned long value to a JavaScript value is a Number that represents the same numeric
# value as the IDL unsigned long value. The Number value will be an integer in the range [0, 4294967295].
return integer_to_javascript_value("WebIDL::UnsignedLong", value, includes)
# 3.2.4.7. long long,
def long_long_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
# The result of converting an IDL long long value to a JavaScript value is a Number value that represents the closest
# numeric value to the long long, choosing the numeric value with an even significand if there are two equally close
# values. If the long long is in the range [2^53 + 1, 2^53 1], then the Number will be able to represent exactly
# the same value as the long long.
return integer_to_javascript_value("double", value, includes)
# 3.2.4.8. unsigned long long, https://webidl.spec.whatwg.org/#js-unsigned-long-long
def unsigned_long_long_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
# The result of converting an IDL unsigned long long value to a JavaScript value is a Number value that represents
# the closest numeric value to the unsigned long long, choosing the numeric value with an even significand if there
# are two equally close values. If the unsigned long long is less than or equal to 253 1, then the Number will be
# able to represent exactly the same value as the unsigned long long.
return integer_to_javascript_value("double", value, includes)
# 3.2.5. float, https://webidl.spec.whatwg.org/#js-float
def float_to_javascript_value(value: str) -> str:
# The result of converting an IDL float value to a JavaScript value is the Number value that represents the same
# numeric value as the IDL float value.
return f"JS::Value({value})"
# 3.2.6. unrestricted float, https://webidl.spec.whatwg.org/#js-unrestricted-float
def unrestricted_float_to_javascript_value(value: str) -> str:
# 1. If the IDL unrestricted float value is a NaN, then the Number value is NaN.
# 2. Otherwise, the Number value is the one that represents the same numeric value as the IDL unrestricted float value.
return f"JS::Value({value})"
# 3.2.7. double, https://webidl.spec.whatwg.org/#js-double
def double_to_javascript_value(value: str) -> str:
# The result of converting an IDL double value to a JavaScript value is the Number value that represents the same
# numeric value as the IDL double value.
return f"JS::Value({value})"
# 3.2.8. unrestricted double, https://webidl.spec.whatwg.org/#js-unrestricted-double
def unrestricted_double_to_javascript_value(value: str) -> str:
# 1. If the IDL unrestricted double value is a NaN, then the Number value is NaN.
# 2. Otherwise, the Number value is the one that represents the same numeric value as the IDL unrestricted double value.
return f"JS::Value({value})"
# 3.2.10. DOMString, https://webidl.spec.whatwg.org/#js-DOMString
def domstring_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
includes.add("LibJS/Runtime/PrimitiveString.h")
return f"JS::PrimitiveString::create(vm, {value})"
# 3.2.11. ByteString, https://webidl.spec.whatwg.org/#js-ByteString
def bytestring_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
includes.add("LibJS/Runtime/PrimitiveString.h")
# The result of converting an IDL ByteString value to a JavaScript value is a String value whose length is the length
# of the ByteString, and the value of each element of which is the value of the corresponding element of the ByteString.
return f"JS::PrimitiveString::create(vm, {value})"
# 3.2.12. USVString, https://webidl.spec.whatwg.org/#js-USVString
def usvstring_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
includes.add("LibJS/Runtime/PrimitiveString.h")
# The result of converting an IDL USVString value S to a JavaScript value is S.
return f"JS::PrimitiveString::create(vm, {value})"
# 3.2.13. object, https://webidl.spec.whatwg.org/#js-object
def object_to_javascript_value(value: str) -> str:
# The result of converting an IDL object value to a JavaScript value is the Object value that represents a reference to
# the same object that the IDL object represents.
return f"JS::Value({value})"
# 3.2.15. Interface types, https://webidl.spec.whatwg.org/#js-interface
def interface_to_javascript_value(value: str, includes: GeneratedIncludes, interface_like_type) -> str:
includes.add(interface_like_type.implementation_header)
# FIXME: Do we need this const cast?
# The result of converting an IDL interface type value to a JavaScript value is the Object value that represents a
# reference to the same object that the IDL interface type value represents.
return f"JS::Value({value})"
# 3.2.16. Callback interface types, https://webidl.spec.whatwg.org/#js-callback-interface
def callback_interface_to_javascript_value(value: str, includes: GeneratedIncludes, interface) -> str:
# The result of converting an IDL callback interface type value to a JavaScript value is the Object value that represents
# a reference to the same object that the IDL callback interface type value represents.
includes.add(implementation_header_for_interface(interface))
return f"{value}->callback().callback"
def dictionary_member_to_javascript_conversion(
member: DictionaryMember,
dictionary_value: str,
includes: GeneratedIncludes,
context: GenerationContext,
) -> tuple[str, str]:
member_value = f"{dictionary_value}.{cpp_name(member)}"
member_type = member.type
member_exists = ""
if is_optional_without_default(member):
cpp_type = cpp_type_details(member, context)
if cpp_type.gc_ref_target_type and not member.type.nullable:
member_exists = member_value
else:
member_exists = f"{member_value}.has_value()"
member_value = f"{member_value}.value()"
if member.type.nullable and not isinstance(member.type, IDLUnionType) and not cpp_type.is_optional_presence:
member_type = member.type.without_nullable()
return member_exists, to_javascript_value(member_type, member_value, includes, context)
# 3.2.17. Dictionary types, https://webidl.spec.whatwg.org/#js-dictionary
def dictionary_to_javascript_value(
idl_type: IDLType,
value: str,
includes: GeneratedIncludes,
context: GenerationContext,
) -> str:
dictionary = context.dictionary(idl_type)
if dictionary is None:
raise RuntimeError(f"Unknown dictionary '{idl_type.name}'")
add_binding_include_for_type(idl_type, includes, context)
includes.add("LibJS/Runtime/Object.h")
generated_conversion = """[&]() -> JS::Value {
// 1. Let O be OrdinaryObjectCreate(%Object.prototype%).
auto dictionary_object = JS::Object::create(realm, realm.intrinsics().object_prototype());
"""
# 2. Let dictionaries be a list consisting of D and all of D's inherited dictionaries, in order from least to most derived.
# 3. For each dictionary dictionary in dictionaries, in order:
for dictionary_in_stack in reversed(context.dictionary_inheritance_stack(dictionary)):
# 1. For each dictionary member member declared on dictionary, in lexicographical order:
for member in dictionary_in_stack.members:
member_exists, converted_member_value = dictionary_member_to_javascript_conversion(
member, value, includes, context
)
generated_conversion += """
// 1. Let key be the identifier of member.
// 2. If V[key] exists, then:
"""
if member_exists:
generated_conversion += f" if ({member_exists}) {{\n"
generated_conversion += f"""
// 1. Let idlValue be V[key].
// 2. Let value be the result of converting idlValue to a JavaScript value.
// 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
MUST(dictionary_object->create_data_property("{member.name}"_utf16_fly_string, {converted_member_value}));
"""
if member_exists:
generated_conversion += " }\n"
generated_conversion += """
// 4. Return O.
return dictionary_object;
}()"""
return generated_conversion
# 3.2.18. Enumeration types, https://webidl.spec.whatwg.org/#js-enumeration
def enumeration_to_javascript_value(
idl_type: IDLType,
value: str,
includes: GeneratedIncludes,
context: GenerationContext,
) -> str:
add_binding_include_for_type(idl_type, includes, context)
includes.add("LibJS/Runtime/PrimitiveString.h")
# The result of converting an IDL enumeration type value to a JavaScript value is the String value that represents the
# same sequence of code units as the enumeration value.
return f"JS::PrimitiveString::create(vm, idl_enum_to_string({value}))"
# 3.2.19. Callback function types, https://webidl.spec.whatwg.org/#js-callback-function
def callback_function_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
includes.add("LibWeb/WebIDL/CallbackType.h")
# The result of converting an IDL callback function type value to a JavaScript value is a reference to the same object
# that the IDL callback function type value represents.
return f"{value}->callback"
# 3.2.20. Nullable types — T?, https://webidl.spec.whatwg.org/#js-nullable-type
def nullable_to_javascript_value(
idl_type: IDLType,
value: str,
includes: GeneratedIncludes,
context: GenerationContext,
) -> str:
inner_type = idl_type.clone_with_nullable(False)
value_is_nullable_pointer = bool(cpp_type_for_idl_type_details(idl_type, context).gc_ref_target_type)
inner_value = value if value_is_nullable_pointer else f"{value}.value()"
has_value = value if value_is_nullable_pointer else f"{value}.has_value()"
return f"""[&]() -> JS::Value {{
// 1. If the IDL nullable type T? value is null, then the JavaScript value is null.
if (!{has_value})
return JS::js_null();
// 2. Otherwise, the JavaScript value is the result of converting the IDL nullable type value to the inner IDL type T.
return JS::Value({to_javascript_value(inner_type, inner_value, includes, context)});
}}()"""
# 3.2.21. Sequences — sequence<T>, https://webidl.spec.whatwg.org/#js-sequence
def sequence_to_javascript_value(
sequence_type: IDLParameterizedType,
value: str,
includes: GeneratedIncludes,
context: GenerationContext,
freeze: bool = False,
) -> str:
includes.add("LibJS/Runtime/Array.h")
element_type = sequence_type.parameters[0]
length_name = "sequence_length"
array_name = "sequence_array"
index_name = "sequence_index"
element_name = "sequence_element"
js_element_name = "js_sequence_element"
converted_element = to_javascript_value(element_type, element_name, includes, context)
freeze_array = ""
if freeze:
freeze_array = f"""
MUST({array_name}->set_integrity_level(JS::Object::IntegrityLevel::Frozen));
"""
return f"""[&]() -> JS::Value {{
// An IDL sequence<T> value S is converted to a JavaScript value as follows:
// 1. Let n be the length of S.
auto {length_name} = {value}.size();
// 2. Let A be a new Array object created as if by the expression [].
auto {array_name} = MUST(JS::Array::create(realm, {length_name}));
// 3. Initialize i to be 0.
// 4. While i < n:
for (size_t {index_name} = 0; {index_name} < {length_name}; ++{index_name}) {{
// 1. Let V be the value in S at index i.
auto& {element_name} = {value}.at({index_name});
// 2. Let E be the result of converting V to a JavaScript value.
JS::Value {js_element_name} = {converted_element};
// 3. Let P be the result of calling ! ToString(i).
// 4. Perform ! CreateDataPropertyOrThrow(A, P, E).
MUST({array_name}->create_data_property(JS::PropertyKey {{ {index_name} }}, {js_element_name}));
// 5. Set i to i + 1.
}}
{freeze_array}
// 5. Return A.
return {array_name};
}}()"""
# 3.2.23. Records — record<K, V>, https://webidl.spec.whatwg.org/#js-record
def record_to_javascript_value(
record_type: IDLParameterizedType,
value: str,
includes: GeneratedIncludes,
context: GenerationContext,
) -> str:
if len(record_type.parameters) != 2:
raise RuntimeError("Record type must have two parameters")
key_type = record_type.parameters[0]
if not is_string_type(key_type.name):
raise RuntimeError(f"Unsupported record key type '{key_type.name}'")
includes.add("AK/Utf16FlyString.h")
includes.add("LibJS/Runtime/Object.h")
value_type = record_type.parameters[1]
object_name = "record_object"
key_name = "record_key"
value_name = "record_value"
converted_value = to_javascript_value(value_type, value_name, includes, context)
return f"""[&]() -> JS::Value {{
// 1. Let result be OrdinaryObjectCreate(%Object.prototype%).
auto {object_name} = JS::Object::create(realm, realm.intrinsics().object_prototype());
// 2. For each key → value of D:
for (auto const& [{key_name}, {value_name}] : {value}) {{
// 1. Let jsKey be key converted to a JavaScript value.
// 2. Let jsValue be value converted to a JavaScript value.
// 3. Let created be ! CreateDataProperty(result, jsKey, jsValue).
// 4. Assert: created is true.
MUST({object_name}->create_data_property(Utf16FlyString::from_utf8({key_name}), {converted_value}));
}}
// 3. Return result.
return {object_name};
}}()"""
# 3.2.24. Promise types — Promise<T>, https://webidl.spec.whatwg.org/#js-promise
def promise_to_javascript_value(value: str, includes: GeneratedIncludes) -> str:
includes.add("AK/TypeCasts.h")
includes.add("LibJS/Runtime/Promise.h")
includes.add("LibWeb/WebIDL/Promise.h")
# The result of converting an IDL promise type value to a JavaScript value is the value of the [[Promise]] field of the
# record that IDL promise type represents.
return f"GC::Ref {{ as<JS::Promise>(*{value}->promise()) }}"
# 3.2.25. Union types, https://webidl.spec.whatwg.org/#js-union
def union_to_javascript_value(
union_type: IDLUnionType,
value: str,
includes: GeneratedIncludes,
context: GenerationContext,
) -> str:
includes.add("AK/Variant.h")
# An IDL union type value is converted to a JavaScript value according to the rules for converting the specific type of the
# IDL union type value as described in this section (§3.2 JavaScript type mapping).
conversions = []
for index, member_type in enumerate(union_type.flattened_member_types()):
if member_type.name == "undefined":
continue
inner_type = member_type.clone_with_nullable(False)
visited_value = f"visited_union_value{index}"
visited_cpp_type = cpp_type_for_idl_type(inner_type, context)
converted_value = to_javascript_value(inner_type, visited_value, includes, context)
conversions.append(
f""" [&]({visited_cpp_type} const& {visited_value}) -> JS::Value
{{
return {converted_value};
}}"""
)
if union_type.includes_nullable_type():
conversions.append(
""" [](Empty) -> JS::Value
{
return JS::js_null();
}"""
)
elif union_type.includes_undefined():
conversions.append(
""" [](Empty) -> JS::Value
{
return JS::js_undefined();
}"""
)
joined_conversions = ",\n".join(conversions)
return f"""{value}.visit(
{joined_conversions}
)"""
# 3.2.26. Buffer source types, https://webidl.spec.whatwg.org/#js-buffer-source-types
def buffer_source_to_javascript_value(idl_type: IDLType, value: str, includes: GeneratedIncludes) -> str:
add_buffer_source_type_include(idl_type, includes)
# The result of converting an IDL value of any buffer source type to a JavaScript value is the Object value that
# represents a reference to the same object that the IDL value represents.
return f"JS::Value({value})"
# 3.2.27. Frozen arrays — FrozenArray<T>, https://webidl.spec.whatwg.org/#js-frozen-array
def frozen_array_to_javascript_value(
frozen_array_type: IDLParameterizedType,
value: str,
includes: GeneratedIncludes,
context: GenerationContext,
) -> str:
# The result of converting an IDL FrozenArray<T> value to a JavaScript value is the Object value that represents a
# reference to the same object that the IDL FrozenArray<T> represents.
return sequence_to_javascript_value(frozen_array_type, value, includes, context, freeze=True)
def to_javascript_value(
idl_type: IDLType,
value: str,
includes: GeneratedIncludes,
context: GenerationContext,
) -> str:
includes.add("LibJS/Runtime/Value.h")
type_name = idl_type.name
if isinstance(idl_type, IDLUnionType):
return union_to_javascript_value(idl_type, value, includes, context)
if idl_type.nullable:
return nullable_to_javascript_value(idl_type, value, includes, context)
if type_name == "undefined":
return undefined_to_javascript_value()
if type_name == "any":
return any_to_javascript_value(value)
if type_name == "object":
return object_to_javascript_value(value)
if is_buffer_source_type(idl_type):
return buffer_source_to_javascript_value(idl_type, value, includes)
if type_name == "boolean":
return boolean_to_javascript_value(value)
if type_name == "byte":
return byte_to_javascript_value(value, includes)
if type_name == "octet":
return octet_to_javascript_value(value, includes)
if type_name == "short":
return short_to_javascript_value(value, includes)
if type_name == "unsigned short":
return unsigned_short_to_javascript_value(value, includes)
if type_name == "long":
return long_to_javascript_value(value, includes)
if type_name == "unsigned long":
return unsigned_long_to_javascript_value(value, includes)
if type_name == "long long":
return long_long_to_javascript_value(value, includes)
if type_name == "unsigned long long":
return unsigned_long_long_to_javascript_value(value, includes)
if type_name == "float":
return float_to_javascript_value(value)
if type_name == "unrestricted float":
return unrestricted_float_to_javascript_value(value)
if type_name == "double":
return double_to_javascript_value(value)
if type_name == "unrestricted double":
return unrestricted_double_to_javascript_value(value)
if type_name in ("DOMString", "Utf16DOMString"):
return domstring_to_javascript_value(value, includes)
if type_name in ("ByteString",):
return bytestring_to_javascript_value(value, includes)
if type_name in ("USVString", "Utf16USVString"):
return usvstring_to_javascript_value(value, includes)
if context.enumeration(idl_type) is not None:
return enumeration_to_javascript_value(idl_type, value, includes, context)
if context.dictionary(idl_type) is not None:
return dictionary_to_javascript_value(idl_type, value, includes, context)
if type_name == "Promise":
return promise_to_javascript_value(value, includes)
interface_like_type = interface_like_type_for_idl_type(idl_type, context)
if interface_like_type is not None:
return interface_to_javascript_value(value, includes, interface_like_type)
interface = context.interface(idl_type)
if interface is not None and interface.is_callback_interface:
return callback_interface_to_javascript_value(value, includes, interface)
if context.callback_function(idl_type) is not None:
return callback_function_to_javascript_value(value, includes)
if isinstance(idl_type, IDLParameterizedType) and type_name == "sequence":
return sequence_to_javascript_value(idl_type, value, includes, context)
if isinstance(idl_type, IDLParameterizedType) and type_name == "record":
return record_to_javascript_value(idl_type, value, includes, context)
if isinstance(idl_type, IDLParameterizedType) and type_name == "FrozenArray":
return frozen_array_to_javascript_value(idl_type, value, includes, context)
return unsupported_to_javascript_value(idl_type)