{% endif %}
{% if method.number_of_required_arguments %}
if (UNLIKELY(info.Length() < {{method.number_of_required_arguments}})) {
- {{throw_type_error(method,
- 'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
- method.number_of_required_arguments) | indent(8)}}
+ {{throw_arity_type_error(method, method.number_of_required_arguments)}};
return;
}
{% endif %}
return;
}
{% endif %}
-{% if method.is_strict_type_checking and argument.is_wrapper_type %}
+{% if argument.has_type_checking_interface %}
{# Type checking for wrapper interface types (if interface not implemented,
- throw TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
+ throw a TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
if (info.Length() > {{argument.index}} && {% if argument.is_nullable %}!isUndefinedOrNull(info[{{argument.index}}]) && {% endif %}!V8{{argument.idl_type}}::hasInstance(info[{{argument.index}}], info.GetIsolate())) {
{{throw_type_error(method, '"parameter %s is not of type \'%s\'."' %
(argument.index + 1, argument.idl_type)) | indent}}
RefPtr<{{argument.idl_type}}> {{argument.name}} = V8EventListenerList::getEventListener(info[1], false, ListenerFindOrCreate);
{% endif %}{# method.name #}
{% else %}
+{# Callback functions must be functions:
+ http://www.w3.org/TR/WebIDL/#es-callback-function #}
{% if argument.is_optional %}
OwnPtr<{{argument.idl_type}}> {{argument.name}};
if (info.Length() > {{argument.index}} && !isUndefinedOrNull(info[{{argument.index}}])) {
{% elif argument.is_clamp %}{# argument.is_callback_interface #}
{# NaN is treated as 0: http://www.w3.org/TR/WebIDL/#es-type-mapping #}
{{argument.cpp_type}} {{argument.name}} = 0;
-V8TRYCATCH_VOID(double, {{argument.name}}NativeValue, info[{{argument.index}}]->NumberValue());
+TONATIVE_VOID(double, {{argument.name}}NativeValue, info[{{argument.index}}]->NumberValue());
if (!std::isnan({{argument.name}}NativeValue))
{# IDL type is used for clamping, for the right bounds, since different
IDL integer types have same internal C++ type (int or unsigned) #}
{% else %}
{{argument.v8_value_to_local_cpp_value}};
{% endif %}
-{% if argument.enum_validation_expression %}
-{# Methods throw on invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
+{# Type checking, possibly throw a TypeError, per:
+ http://www.w3.org/TR/WebIDL/#es-type-mapping #}
+{% if argument.has_type_checking_unrestricted %}
+{# Non-finite floating point values (NaN, +Infinity or −Infinity), per:
+ http://heycam.github.io/webidl/#es-float
+ http://heycam.github.io/webidl/#es-double #}
+if (!std::isfinite({{argument.name}})) {
+ {{throw_type_error(method, '"%s parameter %s is non-finite."' %
+ (argument.idl_type, argument.index + 1)) | indent}}
+ return;
+}
+{% elif argument.enum_validation_expression %}
+{# Invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
String string = {{argument.name}};
if (!({{argument.enum_validation_expression}})) {
{{throw_type_error(method,
(argument.index + 1)) | indent}}
return;
}
-{% endif %}
-{% if argument.idl_type in ['Dictionary', 'Promise'] %}
+{% elif argument.idl_type in ['Dictionary', 'Promise'] %}
+{# Dictionaries must have type Undefined, Null or Object:
+http://heycam.github.io/webidl/#es-dictionary
+We also require this for our implementation of promises, though not in spec:
+http://heycam.github.io/webidl/#es-promise #}
if (!{{argument.name}}.isUndefinedOrNull() && !{{argument.name}}.isObject()) {
{{throw_type_error(method, '"parameter %s (\'%s\') is not an object."' %
(argument.index + 1, argument.name)) | indent}}
{######################################}
{% macro cpp_method_call(method, v8_set_return_value, cpp_value) %}
{# Local variables #}
-{% if method.is_implemented_by and not method.is_static %}
+{% if method.is_partial_interface_member and not method.is_static %}
+{# instance members (non-static members) in partial interface take |impl| #}
ASSERT(impl);
{% endif %}
{% if method.is_call_with_script_state %}
-ScriptState* currentState = ScriptState::current();
-if (!currentState)
- return;
-ScriptState& state = *currentState;
+ScriptState* state = ScriptState::current(info.GetIsolate());
{% endif %}
{% if method.is_call_with_execution_context %}
ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
{# Call #}
{% if method.idl_type == 'void' %}
{{cpp_value}};
+{% elif method.is_constructor %}
+{{method.cpp_type}} impl = {{cpp_value}};
{% elif method.is_call_with_script_state or method.is_raises_exception %}
{# FIXME: consider always using a local variable #}
{{method.cpp_type}} result = {{cpp_value}};
if (exceptionState.throwIfNeeded())
return;
{% endif %}
-{% if method.is_call_with_script_state %}
-if (state.hadException()) {
- v8::Local<v8::Value> exception = state.exception();
- state.clearException();
- throwError(exception, info.GetIsolate());
- return;
-}
-{% endif %}
{# Set return value #}
-{% if method.union_arguments %}
+{% if method.is_constructor %}
+{{generate_constructor_wrapper(method)}}{% elif method.union_arguments %}
{{union_type_method_call_and_set_return_value(method)}}
{% elif v8_set_return_value %}{{v8_set_return_value}};{% endif %}{# None for void #}
{% endmacro %}
{% endmacro %}
+{######################################}
+{% macro throw_arity_type_error(method, number_of_required_arguments) %}
+{% if method.has_exception_state %}
+throwArityTypeError(exceptionState, {{number_of_required_arguments}}, info.Length())
+{%- elif method.is_constructor %}
+throwArityTypeErrorForConstructor("{{interface_name}}", {{number_of_required_arguments}}, info.Length(), info.GetIsolate())
+{%- else %}
+throwArityTypeErrorForMethod("{{method.name}}", "{{interface_name}}", {{number_of_required_arguments}}, info.Length(), info.GetIsolate())
+{%- endif %}
+{% endmacro %}
+
+
{##############################################################################}
{% macro overload_resolution_method(overloads, world_suffix) %}
static void {{overloads.name}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
{
+ {% if overloads.measure_all_as %}
+ UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{overloads.measure_all_as}});
+ {% endif %}
+ {% if overloads.deprecate_all_as %}
+ UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{overloads.deprecate_all_as}});
+ {% endif %}
{% for method in overloads.methods %}
if ({{method.overload_resolution_expression}}) {
+ {% if method.measure_as and not overloads.measure_all_as %}
+ UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{method.measure_as}});
+ {% endif %}
+ {% if method.deprecate_as and not overloads.deprecate_all_as %}
+ UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{method.deprecate_as}});
+ {% endif %}
{{method.name}}{{method.overload_index}}Method{{world_suffix}}(info);
return;
}
{% if overloads.minimum_number_of_required_arguments %}
ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{overloads.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
if (UNLIKELY(info.Length() < {{overloads.minimum_number_of_required_arguments}})) {
- {{throw_type_error(overloads,
- 'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
- overloads.minimum_number_of_required_arguments) | indent(8)}}
+ {{throw_arity_type_error(overloads, overloads.minimum_number_of_required_arguments)}};
return;
}
{% endif %}
static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
{
TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMMethod");
+ {% if not method.overloads %}{# Overloaded methods are measured in overload_resolution_method() #}
{% if method.measure_as %}
UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{method.measure_as}});
{% endif %}
{% if method.deprecate_as %}
UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{method.deprecate_as}});
{% endif %}
+ {% endif %}{# not method.overloads #}
{% if world_suffix in method.activity_logging_world_list %}
- V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
- if (contextData && contextData->activityLogger()) {
+ DOMWrapperWorld& world = DOMWrapperWorld::current(info.GetIsolate());
+ if (world.activityLogger()) {
{# FIXME: replace toVectorOfArguments with toNativeArguments(info, 0)
and delete toVectorOfArguments #}
Vector<v8::Handle<v8::Value> > loggerArgs = toNativeArguments<v8::Handle<v8::Value> >(info, 0);
- contextData->activityLogger()->log("{{interface_name}}.{{method.name}}", info.Length(), loggerArgs.data(), "Method");
+ world.activityLogger()->logMethod("{{interface_name}}.{{method.name}}", info.Length(), loggerArgs.data());
}
{% endif %}
{% if method.is_custom %}
return;
}
- v8::Local<v8::Value> hiddenValue = info.This()->GetHiddenValue(v8AtomicString(isolate, "{{method.name}}"));
+ {# The findInstanceInPrototypeChain() call above only returns a non-empty handle if info.This() is an Object. #}
+ v8::Local<v8::Value> hiddenValue = v8::Handle<v8::Object>::Cast(info.This())->GetHiddenValue(v8AtomicString(isolate, "{{method.name}}"));
if (!hiddenValue.IsEmpty()) {
v8SetReturnValue(info, hiddenValue);
return;
{% if interface_length and not constructor.overload_index %}
{# FIXME: remove UNLIKELY: constructors are expensive, so no difference. #}
if (UNLIKELY(info.Length() < {{interface_length}})) {
- {{throw_type_error(constructor,
- 'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
- interface_length) | indent(8)}}
+ {{throw_arity_type_error(constructor, interface_length)}};
return;
}
{% endif %}
{% if is_constructor_call_with_document %}
Document& document = *toDocument(currentExecutionContext(isolate));
{% endif %}
- {{ref_ptr}}<{{cpp_class}}> impl = {{cpp_class}}::create({{constructor.argument_list | join(', ')}});
+ {{constructor.cpp_type}} impl = {{cpp_class}}::create({{constructor.argument_list | join(', ')}});
{% if is_constructor_raises_exception %}
if (exceptionState.throwIfNeeded())
return;
{% endif %}
- {% if has_custom_wrap %}
- v8::Handle<v8::Object> wrapper = wrap(impl.get(), info.Holder(), isolate);
- {% else %}
- v8::Handle<v8::Object> wrapper = info.Holder();
- V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}::wrapperTypeInfo, wrapper, isolate, {{wrapper_configuration}});
- {% endif %}
- v8SetReturnValue(info, wrapper);
+ {{generate_constructor_wrapper(constructor) | indent}}
}
{% endmacro %}
{##############################################################################}
+{% macro generate_constructor_wrapper(constructor) %}
+{% if has_custom_wrap %}
+v8::Handle<v8::Object> wrapper = wrap(impl.get(), info.Holder(), isolate);
+{% else %}
+{% set constructor_class = v8_class + ('Constructor'
+ if constructor.is_named_constructor else
+ '') %}
+v8::Handle<v8::Object> wrapper = info.Holder();
+V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{constructor_class}}::wrapperTypeInfo, wrapper, isolate, {{wrapper_configuration}});
+{% endif %}
+v8SetReturnValue(info, wrapper);
+{% endmacro %}
+
+
+{##############################################################################}
{% macro named_constructor_callback(constructor) %}
static void {{v8_class}}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{
+ v8::Isolate* isolate = info.GetIsolate();
if (!info.IsConstructCall()) {
- throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("{{constructor.name}}"), info.GetIsolate());
+ throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("{{constructor.name}}"), isolate);
return;
}
- if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
+ if (ConstructorMode::current(isolate) == ConstructorMode::WrapExistingObject) {
v8SetReturnValue(info, info.Holder());
return;
}
- Document* document = currentDOMWindow(info.GetIsolate())->document();
+ Document* document = currentDOMWindow(isolate)->document();
ASSERT(document);
// Make sure the document is added to the DOM Node map. Otherwise, the {{cpp_class}} instance
// may end up being the only node in the map and get garbage-collected prematurely.
- toV8(document, info.Holder(), info.GetIsolate());
+ toV8(document, info.Holder(), isolate);
{% if constructor.has_exception_state %}
- ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate());
+ ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), isolate);
{% endif %}
{% if constructor.number_of_required_arguments %}
if (UNLIKELY(info.Length() < {{constructor.number_of_required_arguments}})) {
- {{throw_type_error(constructor,
- 'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
- constructor.number_of_required_arguments) | indent(8)}}
+ {{throw_arity_type_error(constructor, constructor.number_of_required_arguments)}};
return;
}
{% endif %}
{% for argument in constructor.arguments %}
{{generate_argument(constructor, argument) | indent}}
{% endfor %}
- RefPtr<{{cpp_class}}> impl = {{cpp_class}}::createForJSConstructor({{constructor.argument_list | join(', ')}});
+ {{constructor.cpp_type}} impl = {{cpp_class}}::createForJSConstructor({{constructor.argument_list | join(', ')}});
{% if is_constructor_raises_exception %}
if (exceptionState.throwIfNeeded())
return;
{% endif %}
- {% if has_custom_wrap %}
- v8::Handle<v8::Object> wrapper = wrap(impl.get(), info.Holder(), info.GetIsolate());
- {% else %}
- v8::Handle<v8::Object> wrapper = info.Holder();
- V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}Constructor::wrapperTypeInfo, wrapper, info.GetIsolate(), {{wrapper_configuration}});
- {% endif %}
- v8SetReturnValue(info, wrapper);
+ {{generate_constructor_wrapper(constructor) | indent}}
}
{% endmacro %}