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