blob: 67f6d8724666c0fed9b2f99b842835e341ae216a [file] [log] [blame]
{% from 'callback_invoke.cc.tmpl' import callback_invoke %}
{% filter format_blink_cpp_source_code %}
{% include 'copyright_block.txt' %}
#include "{{this_include_header_path}}"
{% for filename in cpp_includes %}
#include "{{filename}}"
{% endfor %}
namespace blink {
{% if is_legacy_callback_interface %}
// Support of "legacy callback interface"
// Suppress warning: global constructors, because struct WrapperTypeInfo is
// trivial and does not depend on another global objects.
#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
#endif
const WrapperTypeInfo {{v8_class}}::wrapperTypeInfo = {
gin::kEmbedderBlink,
{{v8_class}}::DomTemplate,
nullptr,
"{{interface_name}}",
nullptr,
WrapperTypeInfo::kWrapperTypeNoPrototype,
WrapperTypeInfo::kObjectClassId,
WrapperTypeInfo::kNotInheritFromActiveScriptWrappable,
};
#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__)
#pragma clang diagnostic pop
#endif
{% from 'constants.cc.tmpl' import install_constants with context %}
static void Install{{v8_class}}Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interface_template) {
// Legacy callback interface must not have a prototype object.
interface_template->RemovePrototype();
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(
isolate, interface_template,
{{v8_class}}::wrapperTypeInfo.interface_name,
v8::Local<v8::FunctionTemplate>(),
kV8DefaultWrapperInternalFieldCount);
interface_template->SetLength(0);
// Register IDL constants.
{# |install_constants| requires |interfaceTemplate| and |prototypeTemplate|. #}
v8::Local<v8::FunctionTemplate> interfaceTemplate = interface_template;
v8::Local<v8::ObjectTemplate> prototypeTemplate =
interface_template->PrototypeTemplate();
{{install_constants() | trim | indent(2)}}
}
// static
v8::Local<v8::FunctionTemplate> {{v8_class}}::DomTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world) {
return V8DOMConfiguration::DomClassTemplate(
isolate,
world,
const_cast<WrapperTypeInfo*>(&wrapperTypeInfo),
Install{{v8_class}}Template);
}
{% endif %}{# is_legacy_callback_interface #}
const char* {{v8_class}}::NameInHeapSnapshot() const {
return "{{v8_class}}";
}
// static
{{v8_class}}* {{v8_class}}::CreateOrNull(v8::Local<v8::Object> callback_object) {
v8::Local<v8::Context> creation_context = callback_object->CreationContext();
// When |callback_object| is an object in RemoteContext (i.e. RemoteInstance),
// the object has no creation context, and no way to proceed.
// TODO(crbug.com/886588): Make CreateOrNull into Create removing the early
// return with nullptr.
if (creation_context.IsEmpty())
return nullptr;
return MakeGarbageCollected<{{v8_class}}>(callback_object, creation_context);
}
{% for method in methods %}
v8::Maybe<{{method.cpp_type}}> {{v8_class}}::{{method.name}}({{method.argument_declarations | join(', ')}}) {
{{callback_invoke(
'callback interface', None,
method.cpp_type, method.native_value_traits_tag, method.arguments,
False, False,
interface_name, method.name)}}
}
{% endfor %}
{% if methods|length == 1 and methods[0].idl_type == 'void' %}
void {{v8_class}}::InvokeAndReportException({{methods[0].argument_declarations | join(', ')}}) {
v8::TryCatch try_catch(GetIsolate());
try_catch.SetVerbose(true);
v8::Maybe<void> maybe_result =
{{methods[0].name}}({{
(['callback_this_value'] +
(methods[0].arguments|map(attribute='name')|list)
)|join(', ')
}});
// An exception if any is killed with the v8::TryCatch above.
ALLOW_UNUSED_LOCAL(maybe_result);
}
{% endif %}
{% if interface_name == 'EventListener' %}
bool {{v8_class}}::IsRunnableOrThrowException(IgnorePause ignore_pause) {
bool is_runnable =
ignore_pause == IgnorePause::kIgnore ?
IsCallbackFunctionRunnableIgnoringPause(
CallbackRelevantScriptState(), IncumbentScriptState()) :
IsCallbackFunctionRunnable(
CallbackRelevantScriptState(), IncumbentScriptState());
if (is_runnable)
return true;
// Wrapper-tracing for the callback function makes the function object and
// its creation context alive. Thus it's safe to use the creation context
// of the callback function here.
v8::HandleScope handle_scope(GetIsolate());
v8::Local<v8::Object> callback_object = CallbackObject();
CHECK(!callback_object.IsEmpty());
v8::Context::Scope context_scope(callback_object->CreationContext());
V8ThrowException::ThrowError(
GetIsolate(),
ExceptionMessages::FailedToExecute(
"{{methods[0].name}}",
"{{interface_name}}",
"The provided callback is no longer runnable."));
return false;
}
v8::Maybe<{{methods[0].cpp_type}}> {{v8_class}}::InvokeWithoutRunnabilityCheck({{methods[0].argument_declarations | join(', ')}}) {
{{callback_invoke(
'callback interface', None,
methods[0].cpp_type, methods[0].native_value_traits_tag, methods[0].arguments,
False, True,
interface_name, methods[0].name)}}
}
{% endif %}
{% for method in methods %}
v8::Maybe<{{method.cpp_type}}> V8PersistentCallbackInterface<{{v8_class}}>::{{method.name}}({{method.argument_declarations | join(', ')}}) {
return Proxy()->{{method.name}}(
{{
(['callback_this_value'] +
(method.arguments|map(attribute='name')|list)
)|join(', ')
}});
}
{% endfor %}
{% if methods|length == 1 and methods[0].idl_type == 'void' %}
void V8PersistentCallbackInterface<{{v8_class}}>::InvokeAndReportException({{methods[0].argument_declarations | join(', ')}}) {
Proxy()->InvokeAndReportException(
{{
(['callback_this_value'] +
(methods[0].arguments|map(attribute='name')|list)
)|join(', ')
}});
}
{% endif %}
} // namespace blink
{% endfilter %}{# format_blink_cpp_source_code #}