1 {##############################################################################}
2 {% macro generate_method(method, world_suffix) %}
3 {% filter conditional(method.conditional_string) %}
4 static void {{method.name}}{{method.overload_index}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
6 {% if method.has_exception_state %}
7 ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{method.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
9 {% if method.name in ['addEventListener', 'removeEventListener',
11 {{add_event_listener_remove_event_listener_dispatch_event() | indent}}
13 {% if method.name in ['addEventListener', 'removeEventListener'] %}
14 {{add_event_listener_remove_event_listener_method(method.name) | indent}}
16 {% if method.number_of_required_arguments %}
17 if (UNLIKELY(info.Length() < {{method.number_of_required_arguments}})) {
18 {{throw_type_error(method,
19 'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
20 method.number_of_required_arguments) | indent(8)}}
24 {% if not method.is_static %}
25 {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
27 {% if method.is_custom_element_callbacks %}
28 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
30 {% if method.is_check_security_for_frame %}
31 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), exceptionState)) {
32 exceptionState.throwIfNeeded();
36 {% if method.is_check_security_for_node %}
37 if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), imp->{{method.name}}(exceptionState), exceptionState)) {
38 v8SetReturnValueNull(info);
39 exceptionState.throwIfNeeded();
43 {% for argument in method.arguments %}
44 {{generate_argument(method, argument, world_suffix) | indent}}
47 {{cpp_method_call(method, method.v8_set_return_value_for_main_world, method.cpp_value) | indent}}
49 {{cpp_method_call(method, method.v8_set_return_value, method.cpp_value) | indent}}
51 {% endif %}{# addEventListener, removeEventListener #}
57 {######################################}
58 {% macro add_event_listener_remove_event_listener_dispatch_event() %}
59 {# FIXME: Clean up: use the normal |imp| above,
60 use the existing shouldAllowAccessToFrame check if possible. #}
61 EventTarget* impl = {{v8_class}}::toNative(info.Holder());
62 if (DOMWindow* window = impl->toDOMWindow()) {
63 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), window->frame(), exceptionState)) {
64 exceptionState.throwIfNeeded();
67 if (!window->document())
73 {######################################}
74 {% macro add_event_listener_remove_event_listener_method(method_name) %}
75 {# Set template values for addEventListener vs. removeEventListener #}
76 {% set listener_lookup_type, listener, hidden_dependency_action =
77 ('ListenerFindOrCreate', 'listener', 'addHiddenValueToArray')
78 if method_name == 'addEventListener' else
79 ('ListenerFindOnly', 'listener.get()', 'removeHiddenValueFromArray')
81 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(info[1], false, {{listener_lookup_type}});
83 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, eventName, info[0]);
84 impl->{{method_name}}(eventName, {{listener}}, info[2]->BooleanValue());
86 {{hidden_dependency_action}}(info.Holder(), info[1], {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
91 {######################################}
92 {% macro generate_argument(method, argument, world_suffix) %}
93 {% if argument.is_optional and not argument.has_default and
94 argument.idl_type != 'Dictionary' and
95 not argument.is_callback_interface %}
96 {# Optional arguments without a default value generate an early call with
97 fewer arguments if they are omitted.
98 Optional Dictionary arguments default to empty dictionary. #}
99 if (UNLIKELY(info.Length() <= {{argument.index}})) {
100 {% if world_suffix %}
101 {{cpp_method_call(method, argument.v8_set_return_value_for_main_world, argument.cpp_value) | indent}}
103 {{cpp_method_call(method, argument.v8_set_return_value, argument.cpp_value) | indent}}
108 {% if method.is_strict_type_checking and argument.is_wrapper_type %}
109 {# Type checking for wrapper interface types (if interface not implemented,
110 throw TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
111 if (info.Length() > {{argument.index}} && {% if argument.is_nullable %}!isUndefinedOrNull(info[{{argument.index}}]) && {% endif %}!V8{{argument.idl_type}}::hasInstance(info[{{argument.index}}], info.GetIsolate())) {
112 {{throw_type_error(method, '"parameter %s is not of type \'%s\'."' %
113 (argument.index + 1, argument.idl_type)) | indent}}
117 {% if argument.is_callback_interface %}
118 {% if argument.is_optional %}
119 OwnPtr<{{argument.idl_type}}> {{argument.name}};
120 if (info.Length() > {{argument.index}} && !isUndefinedOrNull(info[{{argument.index}}])) {
121 if (!info[{{argument.index}}]->IsFunction()) {
122 {{throw_type_error(method,
123 '"The callback provided as parameter %s is not a function."' %
124 (argument.index + 1)) | indent(8)}}
127 {{argument.name}} = V8{{argument.idl_type}}::create(v8::Handle<v8::Function>::Cast(info[{{argument.index}}]), currentExecutionContext(info.GetIsolate()));
130 if (info.Length() <= {{argument.index}} || !{% if argument.is_nullable %}(info[{{argument.index}}]->IsFunction() || info[{{argument.index}}]->IsNull()){% else %}info[{{argument.index}}]->IsFunction(){% endif %}) {
131 {{throw_type_error(method,
132 '"The callback provided as parameter %s is not a function."' %
133 (argument.index + 1)) | indent }}
136 OwnPtr<{{argument.idl_type}}> {{argument.name}} = {% if argument.is_nullable %}info[{{argument.index}}]->IsNull() ? nullptr : {% endif %}V8{{argument.idl_type}}::create(v8::Handle<v8::Function>::Cast(info[{{argument.index}}]), currentExecutionContext(info.GetIsolate()));
137 {% endif %}{# argument.is_optional #}
138 {% elif argument.is_clamp %}{# argument.is_callback_interface #}
139 {# NaN is treated as 0: http://www.w3.org/TR/WebIDL/#es-type-mapping #}
140 {{argument.cpp_type}} {{argument.name}} = 0;
141 V8TRYCATCH_VOID(double, {{argument.name}}NativeValue, info[{{argument.index}}]->NumberValue());
142 if (!std::isnan({{argument.name}}NativeValue))
143 {# IDL type is used for clamping, for the right bounds, since different
144 IDL integer types have same internal C++ type (int or unsigned) #}
145 {{argument.name}} = clampTo<{{argument.idl_type}}>({{argument.name}}NativeValue);
146 {% elif argument.idl_type == 'SerializedScriptValue' %}
147 {{argument.cpp_type}} {{argument.name}} = SerializedScriptValue::create(info[{{argument.index}}], 0, 0, exceptionState, info.GetIsolate());
148 if (exceptionState.throwIfNeeded())
150 {% elif argument.is_variadic_wrapper_type %}
151 Vector<{{argument.cpp_type}} > {{argument.name}};
152 for (int i = {{argument.index}}; i < info.Length(); ++i) {
153 if (!V8{{argument.idl_type}}::hasInstance(info[i], info.GetIsolate())) {
154 {{throw_type_error(method, '"parameter %s is not of type \'%s\'."' %
155 (argument.index + 1, argument.idl_type)) | indent(8)}}
158 {{argument.name}}.append(V8{{argument.idl_type}}::toNative(v8::Handle<v8::Object>::Cast(info[i])));
161 {{argument.v8_value_to_local_cpp_value}};
163 {% if argument.enum_validation_expression %}
164 {# Methods throw on invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
165 String string = {{argument.name}};
166 if (!({{argument.enum_validation_expression}})) {
167 {{throw_type_error(method,
168 '"parameter %s (\'" + string + "\') is not a valid enum value."' %
169 (argument.index + 1)) | indent}}
173 {% if argument.idl_type in ['Dictionary', 'Promise'] %}
174 if (!{{argument.name}}.isUndefinedOrNull() && !{{argument.name}}.isObject()) {
175 {{throw_type_error(method, '"parameter %s (\'%s\') is not an object."' %
176 (argument.index + 1, argument.name)) | indent}}
183 {######################################}
184 {% macro cpp_method_call(method, v8_set_return_value, cpp_value) %}
185 {% if method.is_call_with_script_state %}
186 ScriptState* currentState = ScriptState::current();
189 ScriptState& state = *currentState;
191 {% if method.is_call_with_execution_context %}
192 ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
194 {% if method.is_call_with_script_arguments %}
195 RefPtr<ScriptArguments> scriptArguments(createScriptArguments(info, {{method.number_of_arguments}}));
197 {% if method.idl_type == 'void' %}
199 {% elif method.is_call_with_script_state or method.is_raises_exception %}
200 {# FIXME: consider always using a local variable #}
201 {{method.cpp_type}} result = {{cpp_value}};
203 {% if method.is_raises_exception %}
204 if (exceptionState.throwIfNeeded())
207 {% if method.is_call_with_script_state %}
208 if (state.hadException()) {
209 v8::Local<v8::Value> exception = state.exception();
210 state.clearException();
211 throwError(exception, info.GetIsolate());
215 {% if method.union_arguments %}
216 {{union_type_method_call(method)}}
217 {% elif v8_set_return_value %}{{v8_set_return_value}};{% endif %}{# None for void #}
220 {######################################}
221 {% macro union_type_method_call(method) %}
222 {% for cpp_type in method.cpp_type %}
223 bool result{{loop.index0}}Enabled = false;
224 {{cpp_type}} result{{loop.index0}};
226 {{method.cpp_value}};
227 {% if method.is_null_expression %}{# used by getters #}
228 if ({{method.is_null_expression}})
231 {% for v8_set_return_value in method.v8_set_return_value %}
232 if (result{{loop.index0}}Enabled) {
233 {{v8_set_return_value}};
237 {# Fall back to null if none of the union members results are returned #}
238 v8SetReturnValueNull(info);
242 {######################################}
243 {% macro throw_type_error(method, error_message) %}
244 {% if method.has_exception_state %}
245 exceptionState.throwTypeError({{error_message}});
246 exceptionState.throwIfNeeded();
247 {%- elif method.is_constructor %}
248 throwTypeError(ExceptionMessages::failedToConstruct("{{interface_name}}", {{error_message}}), info.GetIsolate());
250 throwTypeError(ExceptionMessages::failedToExecute("{{method.name}}", "{{interface_name}}", {{error_message}}), info.GetIsolate());
255 {##############################################################################}
256 {% macro overload_resolution_method(overloads, world_suffix) %}
257 static void {{overloads.name}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
259 {% for method in overloads.methods %}
260 if ({{method.overload_resolution_expression}}) {
261 {{method.name}}{{method.overload_index}}Method{{world_suffix}}(info);
265 {% if overloads.minimum_number_of_required_arguments %}
266 ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{overloads.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
267 if (UNLIKELY(info.Length() < {{overloads.minimum_number_of_required_arguments}})) {
268 {{throw_type_error(overloads,
269 'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
270 overloads.minimum_number_of_required_arguments) | indent(8)}}
274 {{throw_type_error(overloads, '"No function was found that matched the signature provided."') | indent}}
279 {##############################################################################}
280 {% macro method_callback(method, world_suffix) %}
281 {% filter conditional(method.conditional_string) %}
282 static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
284 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMMethod");
285 {% if method.measure_as %}
286 UseCounter::count(activeExecutionContext(info.GetIsolate()), UseCounter::{{method.measure_as}});
288 {% if method.deprecate_as %}
289 UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::{{method.deprecate_as}});
291 {% if world_suffix in method.activity_logging_world_list %}
292 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
293 if (contextData && contextData->activityLogger()) {
294 {# FIXME: replace toVectorOfArguments with toNativeArguments(info, 0)
295 and delete toVectorOfArguments #}
296 Vector<v8::Handle<v8::Value> > loggerArgs = toNativeArguments<v8::Handle<v8::Value> >(info, 0);
297 contextData->activityLogger()->log("{{interface_name}}.{{method.name}}", info.Length(), loggerArgs.data(), "Method");
300 {% if method.is_custom %}
301 {{v8_class}}::{{method.name}}MethodCustom(info);
303 {{cpp_class}}V8Internal::{{method.name}}Method{{world_suffix}}(info);
305 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
311 {##############################################################################}
312 {% macro origin_safe_method_getter(method, world_suffix) %}
313 static void {{method.name}}OriginSafeMethodGetter{{world_suffix}}(const v8::PropertyCallbackInfo<v8::Value>& info)
315 {% set signature = 'v8::Local<v8::Signature>()'
316 if method.is_do_not_check_signature else
317 'v8::Signature::New(info.GetIsolate(), %s::domTemplate(info.GetIsolate(), currentWorldType))' % v8_class %}
318 {# FIXME: don't call GetIsolate() so often #}
319 // This is only for getting a unique pointer which we can pass to privateTemplate.
320 static int privateTemplateUniqueKey;
321 WrapperWorldType currentWorldType = worldType(info.GetIsolate());
322 V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate());
323 {# FIXME: 1 case of [DoNotCheckSignature] in Window.idl may differ #}
324 v8::Handle<v8::FunctionTemplate> privateTemplate = data->privateTemplate(currentWorldType, &privateTemplateUniqueKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), {{signature}}, {{method.number_of_required_or_variadic_arguments}});
326 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain({{v8_class}}::domTemplate(info.GetIsolate(), currentWorldType));
327 if (holder.IsEmpty()) {
328 // This is only reachable via |object.__proto__.func|, in which case it
329 // has already passed the same origin security check
330 v8SetReturnValue(info, privateTemplate->GetFunction());
333 {{cpp_class}}* imp = {{v8_class}}::toNative(holder);
334 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), DoNotReportSecurityError)) {
335 static int sharedTemplateUniqueKey;
336 v8::Handle<v8::FunctionTemplate> sharedTemplate = data->privateTemplate(currentWorldType, &sharedTemplateUniqueKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), {{signature}}, {{method.number_of_required_or_variadic_arguments}});
337 v8SetReturnValue(info, sharedTemplate->GetFunction());
341 v8::Local<v8::Value> hiddenValue = getHiddenValue(info.GetIsolate(), info.This(), "{{method.name}}");
342 if (!hiddenValue.IsEmpty()) {
343 v8SetReturnValue(info, hiddenValue);
347 v8SetReturnValue(info, privateTemplate->GetFunction());
350 static void {{method.name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)
352 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
353 {{cpp_class}}V8Internal::{{method.name}}OriginSafeMethodGetter{{world_suffix}}(info);
354 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
359 {##############################################################################}
360 {% macro generate_constructor(constructor) %}
361 static void constructor{{constructor.overload_index}}(const v8::FunctionCallbackInfo<v8::Value>& info)
363 {% if constructor.has_exception_state %}
364 ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate());
366 {% if interface_length and not constructor.overload_index %}
367 {# FIXME: remove this UNLIKELY: constructors are heavy, so no difference. #}
368 if (UNLIKELY(info.Length() < {{interface_length}})) {
369 {{throw_type_error(constructor,
370 'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
371 interface_length) | indent(8)}}
375 {% for argument in constructor.arguments %}
376 {{generate_argument(constructor, argument) | indent}}
378 {% if is_constructor_call_with_execution_context %}
379 ExecutionContext* context = currentExecutionContext(info.GetIsolate());
381 {% if is_constructor_call_with_document %}
382 Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
384 {{ref_ptr}}<{{cpp_class}}> impl = {{cpp_class}}::create({{constructor.argument_list | join(', ')}});
385 v8::Handle<v8::Object> wrapper = info.Holder();
386 {% if is_constructor_raises_exception %}
387 if (exceptionState.throwIfNeeded())
391 {# FIXME: Should probably be Independent unless [ActiveDOMObject]
392 or [DependentLifetime]. #}
393 V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent);
394 v8SetReturnValue(info, wrapper);
399 {##############################################################################}
400 {% macro named_constructor_callback(constructor) %}
401 static void {{v8_class}}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
403 if (!info.IsConstructCall()) {
404 throwTypeError(ExceptionMessages::failedToConstruct("{{constructor.name}}", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate());
408 if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
409 v8SetReturnValue(info, info.Holder());
413 Document* document = currentDocument(info.GetIsolate());
416 // Make sure the document is added to the DOM Node map. Otherwise, the {{cpp_class}} instance
417 // may end up being the only node in the map and get garbage-collected prematurely.
418 toV8(document, info.Holder(), info.GetIsolate());
420 {% if constructor.has_exception_state %}
421 ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate());
423 {% if constructor.number_of_required_arguments %}
424 if (UNLIKELY(info.Length() < {{constructor.number_of_required_arguments}})) {
425 {{throw_type_error(constructor,
426 'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
427 constructor.number_of_required_arguments) | indent(8)}}
431 {% for argument in constructor.arguments %}
432 {{generate_argument(constructor, argument) | indent}}
434 RefPtr<{{cpp_class}}> impl = {{cpp_class}}::createForJSConstructor({{constructor.argument_list | join(', ')}});
435 v8::Handle<v8::Object> wrapper = info.Holder();
436 {% if is_constructor_raises_exception %}
437 if (exceptionState.throwIfNeeded())
441 V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}Constructor::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent);
442 v8SetReturnValue(info, wrapper);