Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / templates / methods.cpp
index c6eb5cf..1a34416 100644 (file)
 {% filter conditional(method.conditional_string) %}
 static void {{method.name}}{{method.overload_index}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
+    {# Local variables #}
     {% if method.has_exception_state %}
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{method.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
     {% endif %}
-    {% if method.name in ['addEventListener', 'removeEventListener',
-                          'dispatchEvent'] %}
-    {{add_event_listener_remove_event_listener_dispatch_event() | indent}}
-    {% endif %}
-    {% if method.name in ['addEventListener', 'removeEventListener'] %}
-    {{add_event_listener_remove_event_listener_method(method.name) | indent}}
-    {% else %}
-    {% if method.number_of_required_arguments %}
+    {# Overloaded methods have length checked during overload resolution #}
+    {% if method.number_of_required_arguments and not method.overload_index %}
     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_minimum_arity_type_error(method, method.number_of_required_arguments) | indent(8)}}
         return;
     }
     {% endif %}
     {% if not method.is_static %}
-    {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
+    {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder());
     {% endif %}
     {% if method.is_custom_element_callbacks %}
     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
     {% endif %}
-    {% if method.is_check_security_for_frame %}
-    if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), exceptionState)) {
-        exceptionState.throwIfNeeded();
+    {# Security checks #}
+    {# FIXME: change to method.is_check_security_for_window #}
+    {% if interface_name == 'EventTarget' %}
+    if (LocalDOMWindow* window = impl->toDOMWindow()) {
+        if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), window->frame(), exceptionState)) {
+            {{throw_from_exception_state(method)}};
+            return;
+        }
+        if (!window->document())
+            return;
+    }
+    {% elif method.is_check_security_for_frame %}
+    if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) {
+        {{throw_from_exception_state(method)}};
         return;
     }
     {% endif %}
     {% if method.is_check_security_for_node %}
-    if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), imp->{{method.name}}(exceptionState), exceptionState)) {
+    if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), impl->{{method.name}}(exceptionState), exceptionState)) {
         v8SetReturnValueNull(info);
-        exceptionState.throwIfNeeded();
+        {{throw_from_exception_state(method)}};
         return;
     }
     {% endif %}
-    {% for argument in method.arguments %}
-    {{generate_argument(method, argument, world_suffix) | indent}}
-    {% endfor %}
+    {# Call method #}
+    {% if method.arguments %}
+    {{generate_arguments(method, world_suffix) | indent}}
+    {% endif %}
     {% if world_suffix %}
     {{cpp_method_call(method, method.v8_set_return_value_for_main_world, method.cpp_value) | indent}}
     {% else %}
     {{cpp_method_call(method, method.v8_set_return_value, method.cpp_value) | indent}}
     {% endif %}
-    {% endif %}{# addEventListener, removeEventListener #}
 }
 {% endfilter %}
 {% endmacro %}
 
 
 {######################################}
-{% macro add_event_listener_remove_event_listener_dispatch_event() %}
-{# FIXME: Clean up: use the normal |imp| above,
-          use the existing shouldAllowAccessToFrame check if possible. #}
-EventTarget* impl = {{v8_class}}::toNative(info.Holder());
-if (DOMWindow* window = impl->toDOMWindow()) {
-    if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), window->frame(), exceptionState)) {
-        exceptionState.throwIfNeeded();
-        return;
+{% macro generate_arguments(method, world_suffix) %}
+{% for argument in method.arguments %}
+{{generate_argument_var_declaration(argument)}};
+{% endfor %}
+{
+    {% if method.arguments_need_try_catch %}
+    v8::TryCatch block;
+    V8RethrowTryCatchScope rethrow(block);
+    {% endif %}
+    {% for argument in method.arguments %}
+    {% if argument.default_value %}
+    if (!info[{{argument.index}}]->IsUndefined()) {
+        {{generate_argument(method, argument, world_suffix) | indent(8)}}
+    } else {
+        {{argument.name}} = {{argument.default_value}};
     }
-    if (!window->document())
-        return;
+    {% else %}
+    {{generate_argument(method, argument, world_suffix) | indent}}
+    {% endif %}
+    {% endfor %}
 }
 {% endmacro %}
 
 
 {######################################}
-{% macro add_event_listener_remove_event_listener_method(method_name) %}
-{# Set template values for addEventListener vs. removeEventListener #}
-{% set listener_lookup_type, listener, hidden_dependency_action =
-    ('ListenerFindOrCreate', 'listener', 'addHiddenValueToArray')
-    if method_name == 'addEventListener' else
-    ('ListenerFindOnly', 'listener.get()', 'removeHiddenValueFromArray')
-%}
-RefPtr<EventListener> listener = V8EventListenerList::getEventListener(info[1], false, {{listener_lookup_type}});
-if (listener) {
-    V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, eventName, info[0]);
-    impl->{{method_name}}(eventName, {{listener}}, info[2]->BooleanValue());
-    if (!impl->toNode())
-        {{hidden_dependency_action}}(info.Holder(), info[1], {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
-}
+{% macro generate_argument_var_declaration(argument) %}
+{% if argument.is_callback_interface %}
+{# FIXME: remove EventListener special case #}
+{% if argument.idl_type == 'EventListener' %}
+RefPtr<{{argument.idl_type}}> {{argument.name}}
+{%- else %}
+OwnPtr<{{argument.idl_type}}> {{argument.name}}
+{%- endif %}{# argument.idl_type == 'EventListener' #}
+{%- 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
+{%- else %}
+{{argument.cpp_type}} {{argument.name}}
+{%- endif %}
 {% endmacro %}
 
 
@@ -102,21 +115,35 @@ if (UNLIKELY(info.Length() <= {{argument.index}})) {
     {% else %}
     {{cpp_method_call(method, argument.v8_set_return_value, argument.cpp_value) | indent}}
     {% endif %}
+    {% if argument.has_event_listener_argument %}
+    {{hidden_dependency_action(method.name) | indent}}
+    {% endif %}
     return;
 }
 {% endif %}
-{% if method.is_strict_type_checking and argument.is_wrapper_type %}
+{% if argument.has_type_checking_interface and not argument.is_variadic_wrapper_type %}
 {# 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
+   Note: for variadic arguments, the type checking is done for each matched
+   argument instead; see argument.is_variadic_wrapper_type code-path below. #}
 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}}
     return;
 }
-{% endif %}
+{% endif %}{# argument.has_type_checking_interface #}
 {% if argument.is_callback_interface %}
+{# FIXME: remove EventListener special case #}
+{% if argument.idl_type == 'EventListener' %}
+{% if method.name == 'removeEventListener' %}
+{{argument.name}} = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[{{argument.index}}], false, ListenerFindOnly);
+{% else %}{# method.name == 'addEventListener' #}
+{{argument.name}} = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[{{argument.index}}], false, ListenerFindOrCreate);
+{% endif %}{# method.name #}
+{% else %}{# argument.idl_type == 'EventListener' #}
+{# 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}}])) {
     if (!info[{{argument.index}}]->IsFunction()) {
         {{throw_type_error(method,
@@ -124,31 +151,37 @@ if (info.Length() > {{argument.index}} && !isUndefinedOrNull(info[{{argument.ind
                   (argument.index + 1)) | indent(8)}}
         return;
     }
-    {{argument.name}} = V8{{argument.idl_type}}::create(v8::Handle<v8::Function>::Cast(info[{{argument.index}}]), currentExecutionContext(info.GetIsolate()));
+    {{argument.name}} = V8{{argument.idl_type}}::create(v8::Handle<v8::Function>::Cast(info[{{argument.index}}]), ScriptState::current(info.GetIsolate()));
 }
-{% else %}
+{% else %}{# argument.is_optional #}
 if (info.Length() <= {{argument.index}} || !{% if argument.is_nullable %}(info[{{argument.index}}]->IsFunction() || info[{{argument.index}}]->IsNull()){% else %}info[{{argument.index}}]->IsFunction(){% endif %}) {
     {{throw_type_error(method,
           '"The callback provided as parameter %s is not a function."' %
               (argument.index + 1)) | indent }}
     return;
 }
-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()));
+{{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}}]), ScriptState::current(info.GetIsolate()));
 {% endif %}{# argument.is_optional #}
+{% endif %}{# argument.idl_type == 'EventListener' #}
 {% 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());
+double {{argument.name}}NativeValue;
+{% if method.idl_type == 'Promise' %}
+TONATIVE_VOID_PROMISE_INTERNAL({{argument.name}}NativeValue, info[{{argument.index}}]->NumberValue(), info);
+{% else %}
+TONATIVE_VOID_INTERNAL({{argument.name}}NativeValue, info[{{argument.index}}]->NumberValue());
+{% endif %}
 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) #}
     {{argument.name}} = clampTo<{{argument.idl_type}}>({{argument.name}}NativeValue);
 {% elif argument.idl_type == 'SerializedScriptValue' %}
-{{argument.cpp_type}} {{argument.name}} = SerializedScriptValue::create(info[{{argument.index}}], 0, 0, exceptionState, info.GetIsolate());
-if (exceptionState.throwIfNeeded())
+{{argument.name}} = SerializedScriptValue::create(info[{{argument.index}}], 0, 0, exceptionState, info.GetIsolate());
+if (exceptionState.hadException()) {
+    {{throw_from_exception_state(method)}};
     return;
+}
 {% elif argument.is_variadic_wrapper_type %}
-Vector<{{argument.cpp_type}} > {{argument.name}};
 for (int i = {{argument.index}}; i < info.Length(); ++i) {
     if (!V8{{argument.idl_type}}::hasInstance(info[i], info.GetIsolate())) {
         {{throw_type_error(method, '"parameter %s is not of type \'%s\'."' %
@@ -157,11 +190,22 @@ for (int i = {{argument.index}}; i < info.Length(); ++i) {
     }
     {{argument.name}}.append(V8{{argument.idl_type}}::toNative(v8::Handle<v8::Object>::Cast(info[i])));
 }
-{% else %}
+{% else %}{# argument.is_nullable #}
 {{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 #}
+{% endif %}{# argument.is_nullable #}
+{# 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,
@@ -169,8 +213,11 @@ if (!({{argument.enum_validation_expression}})) {
               (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}}
@@ -182,96 +229,209 @@ if (!{{argument.name}}.isUndefinedOrNull() && !{{argument.name}}.isObject()) {
 
 {######################################}
 {% macro cpp_method_call(method, v8_set_return_value, cpp_value) %}
+{# Local variables #}
 {% if method.is_call_with_script_state %}
-ScriptState* currentState = ScriptState::current();
-if (!currentState)
-    return;
-ScriptState& state = *currentState;
+{# [CallWith=ScriptState] #}
+ScriptState* scriptState = ScriptState::current(info.GetIsolate());
 {% endif %}
 {% if method.is_call_with_execution_context %}
-ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
+{# [ConstructorCallWith=ExecutionContext] #}
+{# [CallWith=ExecutionContext] #}
+ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
 {% endif %}
 {% if method.is_call_with_script_arguments %}
-RefPtr<ScriptArguments> scriptArguments(createScriptArguments(info, {{method.number_of_arguments}}));
+{# [CallWith=ScriptArguments] #}
+RefPtrWillBeRawPtr<ScriptArguments> scriptArguments(createScriptArguments(scriptState, info, {{method.number_of_arguments}}));
 {% endif %}
+{% if method.is_call_with_document %}
+{# [ConstructorCallWith=Document] #}
+Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
+{% endif %}
+{# Call #}
 {% if method.idl_type == 'void' %}
 {{cpp_value}};
-{% elif method.is_call_with_script_state or method.is_raises_exception %}
-{# FIXME: consider always using a local variable #}
+{% elif method.is_implemented_in_private_script %}
+{{method.cpp_type}} result{{method.cpp_type_initializer}};
+if (!{{method.cpp_value}})
+    return;
+{% elif method.is_constructor %}
+{{method.cpp_type}} impl = {{cpp_value}};
+{% elif method.use_local_result and not method.union_arguments %}
 {{method.cpp_type}} result = {{cpp_value}};
 {% endif %}
+{# Post-call #}
 {% if method.is_raises_exception %}
-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());
+if (exceptionState.hadException()) {
+    {{throw_from_exception_state(method)}};
     return;
 }
 {% endif %}
-{% if method.union_arguments %}
-{{union_type_method_call(method)}}
-{% elif v8_set_return_value %}{{v8_set_return_value}};{% endif %}{# None for void #}
+{# Set return value #}
+{% 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 %}
+{% if method.is_explicit_nullable %}
+if (result.isNull())
+    v8SetReturnValueNull(info);
+else
+    {{v8_set_return_value}};
+{% else %}
+{{v8_set_return_value}};
+{% endif %}
+{%- endif %}{# None for void #}
+{# Post-set #}
+{% if interface_name == 'EventTarget' and method.name in ('addEventListener',
+                                                          'removeEventListener') %}
+{% set hidden_dependency_action = 'addHiddenValueToArray'
+       if method.name == 'addEventListener' else 'removeHiddenValueFromArray' %}
+{# Length check needed to skip action on legacy calls without enough arguments.
+   http://crbug.com/353484 #}
+if (info.Length() >= 2 && listener && !impl->toNode())
+    {{hidden_dependency_action}}(info.Holder(), info[1], {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
+{% endif %}
 {% endmacro %}
 
+
 {######################################}
-{% macro union_type_method_call(method) %}
-{% for cpp_type in method.cpp_type %}
-bool result{{loop.index0}}Enabled = false;
-{{cpp_type}} result{{loop.index0}};
+{% macro union_type_method_call_and_set_return_value(method) %}
+{% for argument in method.union_arguments %}
+{{argument.cpp_type}} {{argument.cpp_value}};
 {% endfor %}
 {{method.cpp_value}};
 {% if method.is_null_expression %}{# used by getters #}
 if ({{method.is_null_expression}})
     return;
 {% endif %}
-{% for v8_set_return_value in method.v8_set_return_value %}
-if (result{{loop.index0}}Enabled) {
-    {{v8_set_return_value}};
+{% for argument in method.union_arguments %}
+if ({{argument.null_check_value}}) {
+    {{argument.v8_set_return_value}};
     return;
 }
 {% endfor %}
 {# Fall back to null if none of the union members results are returned #}
+{% if method.is_null_expression %}
+ASSERT_NOT_REACHED();
+{% else %}
 v8SetReturnValueNull(info);
-{%- endmacro %}
+{% endif %}
+{% endmacro %}
 
 
 {######################################}
 {% macro throw_type_error(method, error_message) %}
 {% if method.has_exception_state %}
 exceptionState.throwTypeError({{error_message}});
-exceptionState.throwIfNeeded();
-{%- elif method.is_constructor %}
-throwTypeError(ExceptionMessages::failedToConstruct("{{interface_name}}", {{error_message}}), info.GetIsolate());
+{{throw_from_exception_state(method)}};
+{% elif method.idl_type == 'Promise' %}
+v8SetReturnValue(info, ScriptPromise::rejectRaw(info.GetIsolate(), V8ThrowException::createTypeError({{type_error_message(method, error_message)}}, info.GetIsolate())));
+{% else %}
+V8ThrowException::throwTypeError({{type_error_message(method, error_message)}}, info.GetIsolate());
+{% endif %}{# method.has_exception_state #}
+{% endmacro %}
+
+
+{######################################}
+{% macro type_error_message(method, error_message) %}
+{% if method.is_constructor %}
+ExceptionMessages::failedToConstruct("{{interface_name}}", {{error_message}})
 {%- else %}
-throwTypeError(ExceptionMessages::failedToExecute("{{method.name}}", "{{interface_name}}", {{error_message}}), info.GetIsolate());
+ExceptionMessages::failedToExecute("{{method.name}}", "{{interface_name}}", {{error_message}})
 {%- endif %}
-{% endmacro %}
+{%- endmacro %}
+
+
+{######################################}
+{% macro throw_from_exception_state(method) %}
+{% if method.idl_type == 'Promise' %}
+v8SetReturnValue(info, exceptionState.reject(ScriptState::current(info.GetIsolate())).v8Value())
+{%- else %}
+exceptionState.throwIfNeeded()
+{%- endif %}
+{%- endmacro %}
+
+
+{######################################}
+{% macro throw_minimum_arity_type_error(method, number_of_required_arguments) %}
+{% if method.has_exception_state %}
+setMinimumArityTypeError(exceptionState, {{number_of_required_arguments}}, info.Length());
+{{throw_from_exception_state(method)}};
+{%- elif method.idl_type == 'Promise' %}
+v8SetReturnValue(info, ScriptPromise::rejectRaw(info.GetIsolate(), {{create_minimum_arity_type_error_without_exception_state(method, number_of_required_arguments)}}));
+{%- else %}
+V8ThrowException::throwException({{create_minimum_arity_type_error_without_exception_state(method, number_of_required_arguments)}}, info.GetIsolate());
+{%- endif %}
+{%- endmacro %}
+
+
+{######################################}
+{% macro create_minimum_arity_type_error_without_exception_state(method, number_of_required_arguments) %}
+{% if method.is_constructor %}
+createMinimumArityTypeErrorForConstructor("{{interface_name}}", {{number_of_required_arguments}}, info.Length(), info.GetIsolate())
+{%- else %}
+createMinimumArityTypeErrorForMethod("{{method.name}}", "{{interface_name}}", {{number_of_required_arguments}}, info.Length(), info.GetIsolate())
+{%- endif %}
+{%- endmacro %}
 
 
 {##############################################################################}
+{# FIXME: We should return a rejected Promise if an error occurs in this
+function when ALL methods in this overload return Promise. In order to do so,
+we must ensure either ALL or NO methods in this overload return Promise #}
 {% macro overload_resolution_method(overloads, world_suffix) %}
 static void {{overloads.name}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    {% for method in overloads.methods %}
-    if ({{method.overload_resolution_expression}}) {
-        {{method.name}}{{method.overload_index}}Method{{world_suffix}}(info);
-        return;
-    }
-    {% endfor %}
-    {% 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)}}
+    {% 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 %}
+    {# First resolve by length #}
+    {# 2. Initialize argcount to be min(maxarg, n). #}
+    switch (std::min({{overloads.maxarg}}, info.Length())) {
+    {# 3. Remove from S all entries whose type list is not of length argcount. #}
+    {% for length, tests_methods in overloads.length_tests_methods %}
+    {# 10. If i = d, then: #}
+    case {{length}}:
+        {# Then resolve by testing argument #}
+        {% for test, method in tests_methods %}
+        {% filter runtime_enabled(not overloads.runtime_enabled_function_all and
+                                  method.runtime_enabled_function) %}
+        if ({{test}}) {
+            {% 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;
+        }
+        {% endfilter %}
+        {% endfor %}
+        break;
+    {% endfor %}
+    default:
+        {# Invalid arity, throw error #}
+        {# Report full list of valid arities if gaps and above minimum #}
+        {% if overloads.valid_arities %}
+        if (info.Length() >= {{overloads.minarg}}) {
+            setArityTypeError(exceptionState, "{{overloads.valid_arities}}", info.Length());
+            exceptionState.throwIfNeeded();
+            return;
+        }
+        {% endif %}
+        {# Otherwise just report "not enough arguments" #}
+        exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments({{overloads.minarg}}, info.Length()));
+        exceptionState.throwIfNeeded();
         return;
     }
-    {% endif %}
-    {{throw_type_error(overloads, '"No function was found that matched the signature provided."') | indent}}
+    {# No match, throw error #}
+    exceptionState.throwTypeError("No function was found that matched the signature provided.");
+    exceptionState.throwIfNeeded();
 }
 {% endmacro %}
 
@@ -281,20 +441,25 @@ static void {{overloads.name}}Method{{world_suffix}}(const v8::FunctionCallbackI
 {% filter conditional(method.conditional_string) %}
 static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMMethod");
+    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(activeExecutionContext(info.GetIsolate()), UseCounter::{{method.measure_as}});
+    UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{method.measure_as}});
     {% endif %}
     {% if method.deprecate_as %}
-    UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::{{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());
+    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    V8PerContextData* contextData = scriptState->perContextData();
+    {% if method.activity_logging_world_check %}
+    if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger())
+    {% else %}
     if (contextData && contextData->activityLogger()) {
-        {# FIXME: replace toVectorOfArguments with toNativeArguments(info, 0)
-           and delete toVectorOfArguments #}
+    {% endif %}
         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");
+        contextData->activityLogger()->logMethod("{{interface_name}}.{{method.name}}", info.Length(), loggerArgs.data());
     }
     {% endif %}
     {% if method.is_custom %}
@@ -302,7 +467,7 @@ static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCall
     {% else %}
     {{cpp_class}}V8Internal::{{method.name}}Method{{world_suffix}}(info);
     {% endif %}
-    TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
+    TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
 }
 {% endfilter %}
 {% endmacro %}
@@ -314,31 +479,29 @@ static void {{method.name}}OriginSafeMethodGetter{{world_suffix}}(const v8::Prop
 {
     {% set signature = 'v8::Local<v8::Signature>()'
                        if method.is_do_not_check_signature else
-                       'v8::Signature::New(info.GetIsolate(), %s::domTemplate(info.GetIsolate(), currentWorldType))' % v8_class %}
-    {# FIXME: don't call GetIsolate() so often #}
-    // This is only for getting a unique pointer which we can pass to privateTemplate.
-    static int privateTemplateUniqueKey;
-    WrapperWorldType currentWorldType = worldType(info.GetIsolate());
+                       'v8::Signature::New(info.GetIsolate(), %s::domTemplate(info.GetIsolate()))' % v8_class %}
+    static int domTemplateKey; // This address is used for a key to look up the dom template.
     V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate());
     {# FIXME: 1 case of [DoNotCheckSignature] in Window.idl may differ #}
-    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}});
+    v8::Handle<v8::FunctionTemplate> privateTemplate = data->domTemplate(&domTemplateKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), {{signature}}, {{method.length}});
 
-    v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain({{v8_class}}::domTemplate(info.GetIsolate(), currentWorldType));
+    v8::Handle<v8::Object> holder = {{v8_class}}::findInstanceInPrototypeChain(info.This(), info.GetIsolate());
     if (holder.IsEmpty()) {
         // This is only reachable via |object.__proto__.func|, in which case it
         // has already passed the same origin security check
         v8SetReturnValue(info, privateTemplate->GetFunction());
         return;
     }
-    {{cpp_class}}* imp = {{v8_class}}::toNative(holder);
-    if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), DoNotReportSecurityError)) {
-        static int sharedTemplateUniqueKey;
-        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}});
+    {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
+    if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), DoNotReportSecurityError)) {
+        static int sharedTemplateKey; // This address is used for a key to look up the dom template.
+        v8::Handle<v8::FunctionTemplate> sharedTemplate = data->domTemplate(&sharedTemplateKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), {{signature}}, {{method.length}});
         v8SetReturnValue(info, sharedTemplate->GetFunction());
         return;
     }
 
-    v8::Local<v8::Value> hiddenValue = getHiddenValue(info.GetIsolate(), info.This(), "{{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(info.GetIsolate(), "{{method.name}}"));
     if (!hiddenValue.IsEmpty()) {
         v8SetReturnValue(info, hiddenValue);
         return;
@@ -349,96 +512,117 @@ static void {{method.name}}OriginSafeMethodGetter{{world_suffix}}(const v8::Prop
 
 static void {{method.name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)
 {
-    TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
+    TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter");
     {{cpp_class}}V8Internal::{{method.name}}OriginSafeMethodGetter{{world_suffix}}(info);
-    TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
+    TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
 }
 {% endmacro %}
 
 
 {##############################################################################}
-{% macro generate_constructor(constructor) %}
-static void constructor{{constructor.overload_index}}(const v8::FunctionCallbackInfo<v8::Value>& info)
+{% macro method_implemented_in_private_script(method) %}
+bool {{v8_class}}::PrivateScript::{{method.name}}Method({{method.argument_declarations_for_private_script | join(', ')}})
 {
-    {% if constructor.has_exception_state %}
-    ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate());
-    {% endif %}
-    {% if interface_length and not constructor.overload_index %}
-    {# FIXME: remove this UNLIKELY: constructors are heavy, so no difference. #}
-    if (UNLIKELY(info.Length() < {{interface_length}})) {
-        {{throw_type_error(constructor,
-            'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
-                interface_length) | indent(8)}}
-        return;
-    }
-    {% endif %}
-    {% for argument in constructor.arguments %}
-    {{generate_argument(constructor, argument) | indent}}
+    if (!frame)
+        return false;
+    v8::HandleScope handleScope(toIsolate(frame));
+    ScriptForbiddenScope::AllowUserAgentScript script;
+    v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld());
+    if (context.IsEmpty())
+        return false;
+    ScriptState* scriptState = ScriptState::from(context);
+    if (!scriptState->executionContext())
+        return false;
+
+    ScriptState::Scope scope(scriptState);
+    v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Global(), scriptState->isolate());
+
+    {% for argument in method.arguments %}
+    v8::Handle<v8::Value> {{argument.handle}} = {{argument.private_script_cpp_value_to_v8_value}};
     {% endfor %}
-    {% if is_constructor_call_with_execution_context %}
-    ExecutionContext* context = currentExecutionContext(info.GetIsolate());
-    {% endif %}
-    {% if is_constructor_call_with_document %}
-    Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
+    {% if method.arguments %}
+    v8::Handle<v8::Value> argv[] = { {{method.arguments | join(', ', 'handle')}} };
+    {% else %}
+    {# Empty array initializers are illegal, and don\'t compile in MSVC. #}
+    v8::Handle<v8::Value> *argv = 0;
     {% endif %}
-    {{ref_ptr}}<{{cpp_class}}> impl = {{cpp_class}}::create({{constructor.argument_list | join(', ')}});
-    v8::Handle<v8::Object> wrapper = info.Holder();
-    {% if is_constructor_raises_exception %}
-    if (exceptionState.throwIfNeeded())
-        return;
+    ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{method.name}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate());
+    v8::TryCatch block;
+    {% if method.idl_type == 'void' %}
+    PrivateScriptRunner::runDOMMethod(scriptState, "{{cpp_class}}", "{{method.name}}", holder, {{method.arguments | length}}, argv);
+    if (block.HasCaught()) {
+        if (!PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolate(), exceptionState, block)) {
+            // FIXME: We should support more exceptions.
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+        block.ReThrow();
+        return false;
+    }
+    {% else %}
+    v8::Handle<v8::Value> v8Value = PrivateScriptRunner::runDOMMethod(scriptState, "{{cpp_class}}", "{{method.name}}", holder, {{method.arguments | length}}, argv);
+    if (block.HasCaught()) {
+        if (!PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolate(), exceptionState, block)) {
+            // FIXME: We should support more exceptions.
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+        block.ReThrow();
+        return false;
+    }
+    {{method.private_script_v8_value_to_local_cpp_value}};
+    RELEASE_ASSERT(!exceptionState.hadException());
+    *result = cppValue;
     {% endif %}
-
-    {# FIXME: Should probably be Independent unless [ActiveDOMObject]
-              or [DependentLifetime]. #}
-    V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent);
-    v8SetReturnValue(info, wrapper);
+    return true;
 }
 {% endmacro %}
 
 
 {##############################################################################}
-{% macro named_constructor_callback(constructor) %}
-static void {{v8_class}}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{% macro generate_constructor(constructor) %}
+{% set name = '%sConstructorCallback' % v8_class
+              if constructor.is_named_constructor else
+              'constructor%s' % (constructor.overload_index or '') %}
+static void {{name}}(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
+    {% if constructor.is_named_constructor %}
     if (!info.IsConstructCall()) {
-        throwTypeError(ExceptionMessages::failedToConstruct("{{constructor.name}}", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate());
+        V8ThrowException::throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("{{constructor.name}}"), info.GetIsolate());
         return;
     }
 
-    if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
+    if (ConstructorMode::current(info.GetIsolate()) == ConstructorMode::WrapExistingObject) {
         v8SetReturnValue(info, info.Holder());
         return;
     }
-
-    Document* document = currentDocument(info.GetIsolate());
-    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());
-
+    {% endif %}
     {% if constructor.has_exception_state %}
     ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate());
     {% endif %}
-    {% if constructor.number_of_required_arguments %}
+    {# Overloaded constructors have length checked during overload resolution #}
+    {% if constructor.number_of_required_arguments and not constructor.overload_index %}
     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_minimum_arity_type_error(constructor, constructor.number_of_required_arguments) | indent(8)}}
         return;
     }
     {% endif %}
-    {% for argument in constructor.arguments %}
-    {{generate_argument(constructor, argument) | indent}}
-    {% endfor %}
-    RefPtr<{{cpp_class}}> impl = {{cpp_class}}::createForJSConstructor({{constructor.argument_list | join(', ')}});
-    v8::Handle<v8::Object> wrapper = info.Holder();
-    {% if is_constructor_raises_exception %}
-    if (exceptionState.throwIfNeeded())
-        return;
+    {% if constructor.arguments %}
+    {{generate_arguments(constructor) | indent}}
     {% endif %}
-
-    V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}Constructor::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent);
-    v8SetReturnValue(info, wrapper);
+    {{cpp_method_call(constructor, constructor.v8_set_return_value, constructor.cpp_value) | indent}}
 }
 {% endmacro %}
+
+
+{##############################################################################}
+{% macro generate_constructor_wrapper(constructor) %}
+{% if has_custom_wrap %}
+v8::Handle<v8::Object> wrapper = wrap(impl.get(), info.Holder(), info.GetIsolate());
+{% 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, info.GetIsolate(), {{wrapper_configuration}});
+{% endif %}
+v8SetReturnValue(info, wrapper);
+{% endmacro %}