| OLD | NEW |
| (Empty) |
| 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) | |
| 5 { | |
| 6 {# Local variables #} | |
| 7 {% if method.has_exception_state %} | |
| 8 ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{method.na
me}}", "{{interface_name}}", info.Holder(), info.GetIsolate()); | |
| 9 {% endif %} | |
| 10 {# Overloaded methods have length checked during overload resolution #} | |
| 11 {% if method.number_of_required_arguments and not method.overload_index %} | |
| 12 if (UNLIKELY(info.Length() < {{method.number_of_required_arguments}})) { | |
| 13 {{throw_minimum_arity_type_error(method, method.number_of_required_argum
ents) | indent(8)}} | |
| 14 return; | |
| 15 } | |
| 16 {% endif %} | |
| 17 {% if not method.is_static %} | |
| 18 {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); | |
| 19 {% endif %} | |
| 20 {% if method.is_custom_element_callbacks %} | |
| 21 CustomElementProcessingStack::CallbackDeliveryScope deliveryScope; | |
| 22 {% endif %} | |
| 23 {# Security checks #} | |
| 24 {% if method.is_check_security_for_window %} | |
| 25 if (LocalDOMWindow* window = impl->toDOMWindow()) { | |
| 26 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), window
->frame(), exceptionState)) { | |
| 27 {{throw_from_exception_state(method)}}; | |
| 28 return; | |
| 29 } | |
| 30 if (!window->document()) | |
| 31 return; | |
| 32 } | |
| 33 {% elif method.is_check_security_for_frame %} | |
| 34 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->fram
e(), exceptionState)) { | |
| 35 {{throw_from_exception_state(method)}}; | |
| 36 return; | |
| 37 } | |
| 38 {% endif %} | |
| 39 {% if method.is_check_security_for_node %} | |
| 40 if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), impl->{{met
hod.name}}(exceptionState), exceptionState)) { | |
| 41 v8SetReturnValueNull(info); | |
| 42 {{throw_from_exception_state(method)}}; | |
| 43 return; | |
| 44 } | |
| 45 {% endif %} | |
| 46 {# Call method #} | |
| 47 {% if method.arguments %} | |
| 48 {{generate_arguments(method, world_suffix) | indent}} | |
| 49 {% endif %} | |
| 50 {% if world_suffix %} | |
| 51 {{cpp_method_call(method, method.v8_set_return_value_for_main_world, method.
cpp_value) | indent}} | |
| 52 {% else %} | |
| 53 {{cpp_method_call(method, method.v8_set_return_value, method.cpp_value) | in
dent}} | |
| 54 {% endif %} | |
| 55 } | |
| 56 {% endfilter %} | |
| 57 {% endmacro %} | |
| 58 | |
| 59 | |
| 60 {######################################} | |
| 61 {% macro generate_arguments(method, world_suffix) %} | |
| 62 {% for argument in method.arguments %} | |
| 63 {{generate_argument_var_declaration(argument)}}; | |
| 64 {% endfor %} | |
| 65 { | |
| 66 {% if method.arguments_need_try_catch %} | |
| 67 v8::TryCatch block; | |
| 68 V8RethrowTryCatchScope rethrow(block); | |
| 69 {% endif %} | |
| 70 {% for argument in method.arguments %} | |
| 71 {% if argument.default_value %} | |
| 72 if (!info[{{argument.index}}]->IsUndefined()) { | |
| 73 {{generate_argument(method, argument, world_suffix) | indent(8)}} | |
| 74 } else { | |
| 75 {{argument.name}} = {{argument.default_value}}; | |
| 76 } | |
| 77 {% else %} | |
| 78 {{generate_argument(method, argument, world_suffix) | indent}} | |
| 79 {% endif %} | |
| 80 {% endfor %} | |
| 81 } | |
| 82 {% endmacro %} | |
| 83 | |
| 84 | |
| 85 {######################################} | |
| 86 {% macro generate_argument_var_declaration(argument) %} | |
| 87 {% if argument.is_callback_interface %} | |
| 88 {# FIXME: remove EventListener special case #} | |
| 89 {% if argument.idl_type == 'EventListener' %} | |
| 90 RefPtr<{{argument.idl_type}}> {{argument.name}} | |
| 91 {%- else %} | |
| 92 OwnPtr<{{argument.idl_type}}> {{argument.name}} = nullptr; | |
| 93 {%- endif %}{# argument.idl_type == 'EventListener' #} | |
| 94 {%- elif argument.is_clamp %}{# argument.is_callback_interface #} | |
| 95 {# NaN is treated as 0: http://www.w3.org/TR/WebIDL/#es-type-mapping #} | |
| 96 {{argument.cpp_type}} {{argument.name}} = 0 | |
| 97 {%- else %} | |
| 98 {{argument.cpp_type}} {{argument.name}} | |
| 99 {%- endif %} | |
| 100 {% endmacro %} | |
| 101 | |
| 102 | |
| 103 {######################################} | |
| 104 {% macro generate_argument(method, argument, world_suffix) %} | |
| 105 {% if argument.is_optional and not argument.has_default and | |
| 106 argument.idl_type != 'Dictionary' and | |
| 107 not argument.is_callback_interface %} | |
| 108 {# Optional arguments without a default value generate an early call with | |
| 109 fewer arguments if they are omitted. | |
| 110 Optional Dictionary arguments default to empty dictionary. #} | |
| 111 if (UNLIKELY(info.Length() <= {{argument.index}})) { | |
| 112 {% if world_suffix %} | |
| 113 {{cpp_method_call(method, argument.v8_set_return_value_for_main_world, argum
ent.cpp_value) | indent}} | |
| 114 {% else %} | |
| 115 {{cpp_method_call(method, argument.v8_set_return_value, argument.cpp_value)
| indent}} | |
| 116 {% endif %} | |
| 117 {% if argument.has_event_listener_argument %} | |
| 118 {{hidden_dependency_action(method.name) | indent}} | |
| 119 {% endif %} | |
| 120 return; | |
| 121 } | |
| 122 {% endif %} | |
| 123 {% if argument.has_type_checking_interface and not argument.is_variadic_wrapper_
type %} | |
| 124 {# Type checking for wrapper interface types (if interface not implemented, | |
| 125 throw a TypeError), per http://www.w3.org/TR/WebIDL/#es-interface | |
| 126 Note: for variadic arguments, the type checking is done for each matched | |
| 127 argument instead; see argument.is_variadic_wrapper_type code-path below. #} | |
| 128 if (info.Length() > {{argument.index}} && {% if argument.is_nullable %}!isUndefi
nedOrNull(info[{{argument.index}}]) && {% endif %}!V8{{argument.idl_type}}::hasI
nstance(info[{{argument.index}}], info.GetIsolate())) { | |
| 129 {{throw_type_error(method, '"parameter %s is not of type \'%s\'."' % | |
| 130 (argument.index + 1, argument.idl_type)) | indent
}} | |
| 131 return; | |
| 132 } | |
| 133 {% endif %}{# argument.has_type_checking_interface #} | |
| 134 {% if argument.is_callback_interface %} | |
| 135 {# FIXME: remove EventListener special case #} | |
| 136 {% if argument.idl_type == 'EventListener' %} | |
| 137 {% if method.name == 'removeEventListener' or method.name == 'removeListener' %} | |
| 138 {{argument.name}} = V8EventListenerList::getEventListener(ScriptState::current(i
nfo.GetIsolate()), info[{{argument.index}}], ListenerFindOnly); | |
| 139 {% else %}{# method.name == 'addEventListener' #} | |
| 140 {{argument.name}} = V8EventListenerList::getEventListener(ScriptState::current(i
nfo.GetIsolate()), info[{{argument.index}}], ListenerFindOrCreate); | |
| 141 {% endif %}{# method.name #} | |
| 142 {% else %}{# argument.idl_type == 'EventListener' #} | |
| 143 {# Callback functions must be functions: | |
| 144 http://www.w3.org/TR/WebIDL/#es-callback-function #} | |
| 145 {% if argument.is_optional %} | |
| 146 if (info.Length() > {{argument.index}} && !isUndefinedOrNull(info[{{argument.ind
ex}}])) { | |
| 147 if (!info[{{argument.index}}]->IsFunction()) { | |
| 148 {{throw_type_error(method, | |
| 149 '"The callback provided as parameter %s is not a function."' % | |
| 150 (argument.index + 1)) | indent(8)}} | |
| 151 return; | |
| 152 } | |
| 153 {{argument.name}} = V8{{argument.idl_type}}::create(v8::Handle<v8::Function>
::Cast(info[{{argument.index}}]), ScriptState::current(info.GetIsolate())); | |
| 154 } | |
| 155 {% else %}{# argument.is_optional #} | |
| 156 if (info.Length() <= {{argument.index}} || !{% if argument.is_nullable %}(info[{
{argument.index}}]->IsFunction() || info[{{argument.index}}]->IsNull()){% else %
}info[{{argument.index}}]->IsFunction(){% endif %}) { | |
| 157 {{throw_type_error(method, | |
| 158 '"The callback provided as parameter %s is not a function."' % | |
| 159 (argument.index + 1)) | indent }} | |
| 160 return; | |
| 161 } | |
| 162 {{argument.name}} = {% if argument.is_nullable %}info[{{argument.index}}]->IsNul
l() ? nullptr : {% endif %}V8{{argument.idl_type}}::create(v8::Handle<v8::Functi
on>::Cast(info[{{argument.index}}]), ScriptState::current(info.GetIsolate())); | |
| 163 {% endif %}{# argument.is_optional #} | |
| 164 {% endif %}{# argument.idl_type == 'EventListener' #} | |
| 165 {% elif argument.is_clamp %}{# argument.is_callback_interface #} | |
| 166 {# NaN is treated as 0: http://www.w3.org/TR/WebIDL/#es-type-mapping #} | |
| 167 double {{argument.name}}NativeValue; | |
| 168 {% if method.idl_type == 'Promise' %} | |
| 169 TONATIVE_VOID_PROMISE_INTERNAL({{argument.name}}NativeValue, info[{{argument.ind
ex}}]->NumberValue(), info); | |
| 170 {% else %} | |
| 171 TONATIVE_VOID_INTERNAL({{argument.name}}NativeValue, info[{{argument.index}}]->N
umberValue()); | |
| 172 {% endif %} | |
| 173 if (!std::isnan({{argument.name}}NativeValue)) | |
| 174 {# IDL type is used for clamping, for the right bounds, since different | |
| 175 IDL integer types have same internal C++ type (int or unsigned) #} | |
| 176 {{argument.name}} = clampTo<{{argument.idl_type}}>({{argument.name}}NativeVa
lue); | |
| 177 {% elif argument.idl_type == 'SerializedScriptValue' %} | |
| 178 {{argument.name}} = SerializedScriptValue::create(info[{{argument.index}}], 0, e
xceptionState, info.GetIsolate()); | |
| 179 if (exceptionState.hadException()) { | |
| 180 {{throw_from_exception_state(method)}}; | |
| 181 return; | |
| 182 } | |
| 183 {% elif argument.is_variadic_wrapper_type %} | |
| 184 for (int i = {{argument.index}}; i < info.Length(); ++i) { | |
| 185 if (!V8{{argument.idl_type}}::hasInstance(info[i], info.GetIsolate())) { | |
| 186 {{throw_type_error(method, '"parameter %s is not of type \'%s\'."' % | |
| 187 (argument.index + 1, argument.idl_type)) | in
dent(8)}} | |
| 188 return; | |
| 189 } | |
| 190 {{argument.name}}.append(V8{{argument.idl_type}}::toNative(v8::Handle<v8::Ob
ject>::Cast(info[i]))); | |
| 191 } | |
| 192 {% else %}{# argument.is_nullable #} | |
| 193 {{argument.v8_value_to_local_cpp_value}}; | |
| 194 {% endif %}{# argument.is_nullable #} | |
| 195 {# Type checking, possibly throw a TypeError, per: | |
| 196 http://www.w3.org/TR/WebIDL/#es-type-mapping #} | |
| 197 {% if argument.has_type_checking_unrestricted %} | |
| 198 {# Non-finite floating point values (NaN, +Infinity or −Infinity), per: | |
| 199 http://heycam.github.io/webidl/#es-float | |
| 200 http://heycam.github.io/webidl/#es-double #} | |
| 201 if (!std::isfinite({{argument.name}})) { | |
| 202 {{throw_type_error(method, '"%s parameter %s is non-finite."' % | |
| 203 (argument.idl_type, argument.index + 1)) | indent
}} | |
| 204 return; | |
| 205 } | |
| 206 {% elif argument.enum_validation_expression %} | |
| 207 {# Invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #} | |
| 208 String string = {{argument.name}}; | |
| 209 if (!({{argument.enum_validation_expression}})) { | |
| 210 {{throw_type_error(method, | |
| 211 '"parameter %s (\'" + string + "\') is not a valid enum value."' % | |
| 212 (argument.index + 1)) | indent}} | |
| 213 return; | |
| 214 } | |
| 215 {% elif argument.idl_type in ['Dictionary', 'Promise'] %} | |
| 216 {# Dictionaries must have type Undefined, Null or Object: | |
| 217 http://heycam.github.io/webidl/#es-dictionary | |
| 218 We also require this for our implementation of promises, though not in spec: | |
| 219 http://heycam.github.io/webidl/#es-promise #} | |
| 220 if (!{{argument.name}}.isUndefinedOrNull() && !{{argument.name}}.isObject()) { | |
| 221 {{throw_type_error(method, '"parameter %s (\'%s\') is not an object."' % | |
| 222 (argument.index + 1, argument.name)) | indent}} | |
| 223 return; | |
| 224 } | |
| 225 {% endif %} | |
| 226 {% endmacro %} | |
| 227 | |
| 228 | |
| 229 {######################################} | |
| 230 {% macro cpp_method_call(method, v8_set_return_value, cpp_value) %} | |
| 231 {# Local variables #} | |
| 232 {% if method.is_call_with_script_state %} | |
| 233 {# [CallWith=ScriptState] #} | |
| 234 ScriptState* scriptState = ScriptState::current(info.GetIsolate()); | |
| 235 {% endif %} | |
| 236 {% if method.is_call_with_execution_context %} | |
| 237 {# [ConstructorCallWith=ExecutionContext] #} | |
| 238 {# [CallWith=ExecutionContext] #} | |
| 239 ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate()); | |
| 240 {% endif %} | |
| 241 {% if method.is_call_with_script_arguments %} | |
| 242 {# [CallWith=ScriptArguments] #} | |
| 243 RefPtr<ScriptArguments> scriptArguments(createScriptArguments(scriptState, info,
{{method.number_of_arguments}})); | |
| 244 {% endif %} | |
| 245 {% if method.is_call_with_document %} | |
| 246 {# [ConstructorCallWith=Document] #} | |
| 247 Document& document = *toDocument(currentExecutionContext(info.GetIsolate())); | |
| 248 {% endif %} | |
| 249 {# Call #} | |
| 250 {% if method.idl_type == 'void' %} | |
| 251 {{cpp_value}}; | |
| 252 {% elif method.is_implemented_in_private_script %} | |
| 253 {{method.cpp_type}} result{{method.cpp_type_initializer}}; | |
| 254 if (!{{method.cpp_value}}) | |
| 255 return; | |
| 256 {% elif method.is_constructor %} | |
| 257 {{method.cpp_type}} impl = {{cpp_value}}; | |
| 258 {% elif method.use_local_result and not method.union_arguments %} | |
| 259 {{method.cpp_type}} result = {{cpp_value}}; | |
| 260 {% endif %} | |
| 261 {# Post-call #} | |
| 262 {% if method.is_raises_exception %} | |
| 263 if (exceptionState.hadException()) { | |
| 264 {{throw_from_exception_state(method)}}; | |
| 265 return; | |
| 266 } | |
| 267 {% endif %} | |
| 268 {# Set return value #} | |
| 269 {% if method.is_constructor %} | |
| 270 {{generate_constructor_wrapper(method)}} | |
| 271 {%- elif method.union_arguments %} | |
| 272 {{union_type_method_call_and_set_return_value(method)}} | |
| 273 {%- elif v8_set_return_value %} | |
| 274 {% if method.is_explicit_nullable %} | |
| 275 if (result.isNull()) | |
| 276 v8SetReturnValueNull(info); | |
| 277 else | |
| 278 {{v8_set_return_value}}; | |
| 279 {% else %} | |
| 280 {{v8_set_return_value}}; | |
| 281 {% endif %} | |
| 282 {%- endif %}{# None for void #} | |
| 283 {# Post-set #} | |
| 284 {% if interface_name in ('EventTarget', 'MediaQueryList') | |
| 285 and method.name in ('addEventListener', 'removeEventListener', 'addListener'
, 'removeListener') %} | |
| 286 {% set hidden_dependency_action = 'addHiddenValueToArray' | |
| 287 if method.name in ('addEventListener', 'addListener') else 'removeHiddenV
alueFromArray' %} | |
| 288 {% set argument_index = '1' if interface_name == 'EventTarget' else '0' %} | |
| 289 {# Length check needed to skip action on legacy calls without enough arguments. | |
| 290 http://crbug.com/353484 #} | |
| 291 if (info.Length() >= {{argument_index}} + 1 && listener && !impl->toNode()) | |
| 292 {{hidden_dependency_action}}(info.Holder(), info[{{argument_index}}], {{v8_c
lass}}::eventListenerCacheIndex, info.GetIsolate()); | |
| 293 {% endif %} | |
| 294 {% endmacro %} | |
| 295 | |
| 296 | |
| 297 {######################################} | |
| 298 {% macro union_type_method_call_and_set_return_value(method) %} | |
| 299 {% for argument in method.union_arguments %} | |
| 300 {{argument.cpp_type}} {{argument.cpp_value}}{{argument.cpp_type_initializer}}; | |
| 301 {% endfor %} | |
| 302 {{method.cpp_value}}; | |
| 303 {% if method.is_null_expression %}{# used by getters #} | |
| 304 if ({{method.is_null_expression}}) | |
| 305 return; | |
| 306 {% endif %} | |
| 307 {% for argument in method.union_arguments %} | |
| 308 if ({{argument.null_check_value}}) { | |
| 309 {{argument.v8_set_return_value}}; | |
| 310 return; | |
| 311 } | |
| 312 {% endfor %} | |
| 313 {# Fall back to null if none of the union members results are returned #} | |
| 314 {% if method.is_null_expression %} | |
| 315 ASSERT_NOT_REACHED(); | |
| 316 {% else %} | |
| 317 v8SetReturnValueNull(info); | |
| 318 {% endif %} | |
| 319 {% endmacro %} | |
| 320 | |
| 321 | |
| 322 {######################################} | |
| 323 {% macro throw_type_error(method, error_message) %} | |
| 324 {% if method.has_exception_state %} | |
| 325 exceptionState.throwTypeError({{error_message}}); | |
| 326 {{throw_from_exception_state(method)}}; | |
| 327 {% elif method.idl_type == 'Promise' %} | |
| 328 v8SetReturnValue(info, ScriptPromise::rejectRaw(info.GetIsolate(), V8ThrowExcept
ion::createTypeError({{type_error_message(method, error_message)}}, info.GetIsol
ate()))); | |
| 329 {% else %} | |
| 330 V8ThrowException::throwTypeError({{type_error_message(method, error_message)}},
info.GetIsolate()); | |
| 331 {% endif %}{# method.has_exception_state #} | |
| 332 {% endmacro %} | |
| 333 | |
| 334 | |
| 335 {######################################} | |
| 336 {% macro type_error_message(method, error_message) %} | |
| 337 {% if method.is_constructor %} | |
| 338 ExceptionMessages::failedToConstruct("{{interface_name}}", {{error_message}}) | |
| 339 {%- else %} | |
| 340 ExceptionMessages::failedToExecute("{{method.name}}", "{{interface_name}}", {{er
ror_message}}) | |
| 341 {%- endif %} | |
| 342 {%- endmacro %} | |
| 343 | |
| 344 | |
| 345 {######################################} | |
| 346 {% macro throw_from_exception_state(method) %} | |
| 347 {% if method.idl_type == 'Promise' %} | |
| 348 v8SetReturnValue(info, exceptionState.reject(ScriptState::current(info.GetIsolat
e())).v8Value()) | |
| 349 {%- else %} | |
| 350 exceptionState.throwIfNeeded() | |
| 351 {%- endif %} | |
| 352 {%- endmacro %} | |
| 353 | |
| 354 | |
| 355 {######################################} | |
| 356 {% macro throw_minimum_arity_type_error(method, number_of_required_arguments) %} | |
| 357 {% if method.has_exception_state %} | |
| 358 setMinimumArityTypeError(exceptionState, {{number_of_required_arguments}}, info.
Length()); | |
| 359 {{throw_from_exception_state(method)}}; | |
| 360 {%- elif method.idl_type == 'Promise' %} | |
| 361 v8SetReturnValue(info, ScriptPromise::rejectRaw(info.GetIsolate(), {{create_mini
mum_arity_type_error_without_exception_state(method, number_of_required_argument
s)}})); | |
| 362 {%- else %} | |
| 363 V8ThrowException::throwException({{create_minimum_arity_type_error_without_excep
tion_state(method, number_of_required_arguments)}}, info.GetIsolate()); | |
| 364 {%- endif %} | |
| 365 {%- endmacro %} | |
| 366 | |
| 367 | |
| 368 {######################################} | |
| 369 {% macro create_minimum_arity_type_error_without_exception_state(method, number_
of_required_arguments) %} | |
| 370 {% if method.is_constructor %} | |
| 371 createMinimumArityTypeErrorForConstructor("{{interface_name}}", {{number_of_requ
ired_arguments}}, info.Length(), info.GetIsolate()) | |
| 372 {%- else %} | |
| 373 createMinimumArityTypeErrorForMethod("{{method.name}}", "{{interface_name}}", {{
number_of_required_arguments}}, info.Length(), info.GetIsolate()) | |
| 374 {%- endif %} | |
| 375 {%- endmacro %} | |
| 376 | |
| 377 | |
| 378 {##############################################################################} | |
| 379 {# FIXME: We should return a rejected Promise if an error occurs in this | |
| 380 function when ALL methods in this overload return Promise. In order to do so, | |
| 381 we must ensure either ALL or NO methods in this overload return Promise #} | |
| 382 {% macro overload_resolution_method(overloads, world_suffix) %} | |
| 383 static void {{overloads.name}}Method{{world_suffix}}(const v8::FunctionCallbackI
nfo<v8::Value>& info) | |
| 384 { | |
| 385 ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{overloads
.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate()); | |
| 386 {# First resolve by length #} | |
| 387 {# 2. Initialize argcount to be min(maxarg, n). #} | |
| 388 switch (std::min({{overloads.maxarg}}, info.Length())) { | |
| 389 {# 3. Remove from S all entries whose type list is not of length argcount. #
} | |
| 390 {% for length, tests_methods in overloads.length_tests_methods %} | |
| 391 {# 10. If i = d, then: #} | |
| 392 case {{length}}: | |
| 393 {# Then resolve by testing argument #} | |
| 394 {% for test, method in tests_methods %} | |
| 395 {% filter runtime_enabled(not overloads.runtime_enabled_function_all and | |
| 396 method.runtime_enabled_function) %} | |
| 397 if ({{test}}) { | |
| 398 {{method.name}}{{method.overload_index}}Method{{world_suffix}}(info)
; | |
| 399 return; | |
| 400 } | |
| 401 {% endfilter %} | |
| 402 {% endfor %} | |
| 403 break; | |
| 404 {% endfor %} | |
| 405 default: | |
| 406 {# Invalid arity, throw error #} | |
| 407 {# Report full list of valid arities if gaps and above minimum #} | |
| 408 {% if overloads.valid_arities %} | |
| 409 if (info.Length() >= {{overloads.minarg}}) { | |
| 410 setArityTypeError(exceptionState, "{{overloads.valid_arities}}", inf
o.Length()); | |
| 411 exceptionState.throwIfNeeded(); | |
| 412 return; | |
| 413 } | |
| 414 {% endif %} | |
| 415 {# Otherwise just report "not enough arguments" #} | |
| 416 exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments({{ov
erloads.minarg}}, info.Length())); | |
| 417 exceptionState.throwIfNeeded(); | |
| 418 return; | |
| 419 } | |
| 420 {# No match, throw error #} | |
| 421 exceptionState.throwTypeError("No function was found that matched the signat
ure provided."); | |
| 422 exceptionState.throwIfNeeded(); | |
| 423 } | |
| 424 {% endmacro %} | |
| 425 | |
| 426 | |
| 427 {##############################################################################} | |
| 428 {% macro method_callback(method, world_suffix) %} | |
| 429 {% filter conditional(method.conditional_string) %} | |
| 430 static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCall
backInfo<v8::Value>& info) | |
| 431 { | |
| 432 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMMethod"); | |
| 433 {% if not method.overloads %}{# Overloaded methods are measured in overload_
resolution_method() #} | |
| 434 {% endif %}{# not method.overloads #} | |
| 435 {% if method.is_custom %} | |
| 436 {{v8_class}}::{{method.name}}MethodCustom(info); | |
| 437 {% else %} | |
| 438 {{cpp_class}}V8Internal::{{method.name}}Method{{world_suffix}}(info); | |
| 439 {% endif %} | |
| 440 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution"); | |
| 441 } | |
| 442 {% endfilter %} | |
| 443 {% endmacro %} | |
| 444 | |
| 445 | |
| 446 {##############################################################################} | |
| 447 {% macro origin_safe_method_getter(method, world_suffix) %} | |
| 448 static void {{method.name}}OriginSafeMethodGetter{{world_suffix}}(const v8::Prop
ertyCallbackInfo<v8::Value>& info) | |
| 449 { | |
| 450 {% set signature = 'v8::Local<v8::Signature>()' | |
| 451 if method.is_do_not_check_signature else | |
| 452 'v8::Signature::New(info.GetIsolate(), %s::domTemplate(in
fo.GetIsolate()))' % v8_class %} | |
| 453 static int domTemplateKey; // This address is used for a key to look up the
dom template. | |
| 454 V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate()); | |
| 455 {# FIXME: 1 case of [DoNotCheckSignature] in Window.idl may differ #} | |
| 456 v8::Handle<v8::FunctionTemplate> privateTemplate = data->domTemplate(&domTem
plateKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}
, v8Undefined(), {{signature}}, {{method.length}}); | |
| 457 | |
| 458 v8::Handle<v8::Object> holder = {{v8_class}}::findInstanceInPrototypeChain(i
nfo.This(), info.GetIsolate()); | |
| 459 if (holder.IsEmpty()) { | |
| 460 // This is only reachable via |object.__proto__.func|, in which case it | |
| 461 // has already passed the same origin security check | |
| 462 v8SetReturnValue(info, privateTemplate->GetFunction()); | |
| 463 return; | |
| 464 } | |
| 465 {{cpp_class}}* impl = {{v8_class}}::toNative(holder); | |
| 466 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->fram
e(), DoNotReportSecurityError)) { | |
| 467 static int sharedTemplateKey; // This address is used for a key to look
up the dom template. | |
| 468 v8::Handle<v8::FunctionTemplate> sharedTemplate = data->domTemplate(&sha
redTemplateKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_su
ffix}}, v8Undefined(), {{signature}}, {{method.length}}); | |
| 469 v8SetReturnValue(info, sharedTemplate->GetFunction()); | |
| 470 return; | |
| 471 } | |
| 472 | |
| 473 {# The findInstanceInPrototypeChain() call above only returns a non-empty ha
ndle if info.This() is an Object. #} | |
| 474 v8::Local<v8::Value> hiddenValue = v8::Handle<v8::Object>::Cast(info.This())
->GetHiddenValue(v8AtomicString(info.GetIsolate(), "{{method.name}}")); | |
| 475 if (!hiddenValue.IsEmpty()) { | |
| 476 v8SetReturnValue(info, hiddenValue); | |
| 477 return; | |
| 478 } | |
| 479 | |
| 480 v8SetReturnValue(info, privateTemplate->GetFunction()); | |
| 481 } | |
| 482 | |
| 483 static void {{method.name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Lo
cal<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info) | |
| 484 { | |
| 485 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter"); | |
| 486 {{cpp_class}}V8Internal::{{method.name}}OriginSafeMethodGetter{{world_suffix
}}(info); | |
| 487 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution"); | |
| 488 } | |
| 489 {% endmacro %} | |
| 490 | |
| 491 | |
| 492 {##############################################################################} | |
| 493 {% macro method_implemented_in_private_script(method) %} | |
| 494 bool {{v8_class}}::PrivateScript::{{method.name}}Method({{method.argument_declar
ations_for_private_script | join(', ')}}) | |
| 495 { | |
| 496 if (!frame) | |
| 497 return false; | |
| 498 v8::HandleScope handleScope(toIsolate(frame)); | |
| 499 ScriptForbiddenScope::AllowUserAgentScript script; | |
| 500 v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privat
eScriptIsolatedWorld()); | |
| 501 if (context.IsEmpty()) | |
| 502 return false; | |
| 503 ScriptState* scriptState = ScriptState::from(context); | |
| 504 if (!scriptState->executionContext()) | |
| 505 return false; | |
| 506 | |
| 507 ScriptState::Scope scope(scriptState); | |
| 508 v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Glob
al(), scriptState->isolate()); | |
| 509 | |
| 510 {% for argument in method.arguments %} | |
| 511 v8::Handle<v8::Value> {{argument.handle}} = {{argument.private_script_cpp_va
lue_to_v8_value}}; | |
| 512 {% endfor %} | |
| 513 {% if method.arguments %} | |
| 514 v8::Handle<v8::Value> argv[] = { {{method.arguments | join(', ', 'handle')}}
}; | |
| 515 {% else %} | |
| 516 {# Empty array initializers are illegal, and don\'t compile in MSVC. #} | |
| 517 v8::Handle<v8::Value> *argv = 0; | |
| 518 {% endif %} | |
| 519 ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{method.na
me}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate()
); | |
| 520 v8::TryCatch block; | |
| 521 {% if method.idl_type == 'void' %} | |
| 522 PrivateScriptRunner::runDOMMethod(scriptState, "{{cpp_class}}", "{{method.na
me}}", holder, {{method.arguments | length}}, argv); | |
| 523 if (block.HasCaught()) { | |
| 524 PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolat
e(), exceptionState, block); | |
| 525 block.ReThrow(); | |
| 526 return false; | |
| 527 } | |
| 528 {% else %} | |
| 529 v8::Handle<v8::Value> v8Value = PrivateScriptRunner::runDOMMethod(scriptStat
e, "{{cpp_class}}", "{{method.name}}", holder, {{method.arguments | length}}, ar
gv); | |
| 530 if (block.HasCaught()) { | |
| 531 PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolat
e(), exceptionState, block); | |
| 532 block.ReThrow(); | |
| 533 return false; | |
| 534 } | |
| 535 {{method.private_script_v8_value_to_local_cpp_value}}; | |
| 536 RELEASE_ASSERT(!exceptionState.hadException()); | |
| 537 *result = cppValue; | |
| 538 {% endif %} | |
| 539 return true; | |
| 540 } | |
| 541 {% endmacro %} | |
| 542 | |
| 543 | |
| 544 {##############################################################################} | |
| 545 {% macro generate_constructor(constructor) %} | |
| 546 {% set name = '%sConstructorCallback' % v8_class | |
| 547 if constructor.is_named_constructor else | |
| 548 'constructor%s' % (constructor.overload_index or '') %} | |
| 549 static void {{name}}(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 550 { | |
| 551 {% if constructor.is_named_constructor %} | |
| 552 if (!info.IsConstructCall()) { | |
| 553 V8ThrowException::throwTypeError(ExceptionMessages::constructorNotCallab
leAsFunction("{{constructor.name}}"), info.GetIsolate()); | |
| 554 return; | |
| 555 } | |
| 556 | |
| 557 if (ConstructorMode::current(info.GetIsolate()) == ConstructorMode::WrapExis
tingObject) { | |
| 558 v8SetReturnValue(info, info.Holder()); | |
| 559 return; | |
| 560 } | |
| 561 {% endif %} | |
| 562 {% if constructor.has_exception_state %} | |
| 563 ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interf
ace_name}}", info.Holder(), info.GetIsolate()); | |
| 564 {% endif %} | |
| 565 {# Overloaded constructors have length checked during overload resolution #} | |
| 566 {% if constructor.number_of_required_arguments and not constructor.overload_
index %} | |
| 567 if (UNLIKELY(info.Length() < {{constructor.number_of_required_arguments}}))
{ | |
| 568 {{throw_minimum_arity_type_error(constructor, constructor.number_of_requ
ired_arguments) | indent(8)}} | |
| 569 return; | |
| 570 } | |
| 571 {% endif %} | |
| 572 {% if constructor.arguments %} | |
| 573 {{generate_arguments(constructor) | indent}} | |
| 574 {% endif %} | |
| 575 {{cpp_method_call(constructor, constructor.v8_set_return_value, constructor.
cpp_value) | indent}} | |
| 576 } | |
| 577 {% endmacro %} | |
| 578 | |
| 579 | |
| 580 {##############################################################################} | |
| 581 {% macro generate_constructor_wrapper(constructor) %} | |
| 582 {% if has_custom_wrap %} | |
| 583 v8::Handle<v8::Object> wrapper = wrap(impl.get(), info.Holder(), info.GetIsolate
()); | |
| 584 {% else %} | |
| 585 {% set constructor_class = v8_class + ('Constructor' | |
| 586 if constructor.is_named_constructor else | |
| 587 '') %} | |
| 588 v8::Handle<v8::Object> wrapper = info.Holder(); | |
| 589 V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{constr
uctor_class}}::wrapperTypeInfo, wrapper, info.GetIsolate()); | |
| 590 {% endif %} | |
| 591 v8SetReturnValue(info, wrapper); | |
| 592 {% endmacro %} | |
| 593 | |
| 594 | |
| 595 {##############################################################################} | |
| 596 {% macro method_configuration(method) %} | |
| 597 {% set method_callback = | |
| 598 '%sV8Internal::%sMethodCallback' % (cpp_class, method.name) %} | |
| 599 {% set method_callback_for_main_world = | |
| 600 '%sV8Internal::%sMethodCallbackForMainWorld' % (cpp_class, method.name) | |
| 601 if method.is_per_world_bindings else '0' %} | |
| 602 {% set only_exposed_to_private_script = 'V8DOMConfiguration::OnlyExposedToPrivat
eScript' if method.only_exposed_to_private_script else 'V8DOMConfiguration::Expo
sedToAllScripts' %} | |
| 603 {"{{method.name}}", {{method_callback}}, {{method_callback_for_main_world}}, {{m
ethod.length}}, {{only_exposed_to_private_script}}} | |
| 604 {%- endmacro %} | |
| 605 | |
| 606 | |
| 607 {######################################} | |
| 608 {% macro install_custom_signature(method) %} | |
| 609 {% set method_callback = '%sV8Internal::%sMethodCallback' % (cpp_class, method.n
ame) %} | |
| 610 {% set method_callback_for_main_world = '%sForMainWorld' % method_callback | |
| 611 if method.is_per_world_bindings else '0' %} | |
| 612 {% set property_attribute = | |
| 613 'static_cast<v8::PropertyAttribute>(%s)' % ' | '.join(method.property_attribut
es) | |
| 614 if method.property_attributes else 'v8::None' %} | |
| 615 {% set only_exposed_to_private_script = 'V8DOMConfiguration::OnlyExposedToPrivat
eScript' if method.only_exposed_to_private_script else 'V8DOMConfiguration::Expo
sedToAllScripts' %} | |
| 616 static const V8DOMConfiguration::MethodConfiguration {{method.name}}MethodConfig
uration = { | |
| 617 "{{method.name}}", {{method_callback}}, {{method_callback_for_main_world}},
{{method.length}}, {{only_exposed_to_private_script}}, | |
| 618 }; | |
| 619 V8DOMConfiguration::installMethod({{method.function_template}}, {{method.signatu
re}}, {{property_attribute}}, {{method.name}}MethodConfiguration, isolate); | |
| 620 {%- endmacro %} | |
| OLD | NEW |