1{% extends 'interface_base.cc.tmpl' %} 2 3{% from 'methods.cc.tmpl' import runtime_timer_scope, runtime_timer_scope_disabled_by_default %} 4 5{##############################################################################} 6{% block indexed_property_getter %} 7{% if indexed_property_getter and not indexed_property_getter.is_custom %} 8{% set getter = indexed_property_getter %} 9static void IndexedPropertyGetter( 10 uint32_t index, 11 const v8::PropertyCallbackInfo<v8::Value>& info) { 12 {% if getter.is_raises_exception %} 13 ExceptionState exception_state(info.GetIsolate(), ExceptionState::kIndexedGetterContext, "{{interface_name}}"); 14 {% endif %} 15 16 {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder()); 17 18 // We assume that all the implementations support length() method, although 19 // the spec doesn't require that length() must exist. It's okay that 20 // the interface does not have length attribute as long as the 21 // implementation supports length() member function. 22 if (index >= impl->length()) 23 return; // Returns undefined due to out-of-range. 24 25 {% set getter_name = getter.name or 'AnonymousIndexedGetter' %} 26 {% set getter_arguments = ['index'] %} 27 {% if getter.is_call_with_script_state %} 28 ScriptState* script_state = ScriptState::ForRelevantRealm(info); 29 {% set getter_arguments = ['script_state'] + getter_arguments %} 30 {% endif %} 31 {% if getter.is_raises_exception %} 32 {% set getter_arguments = getter_arguments + ['exception_state'] %} 33 {% endif %} 34 {{getter.cpp_type}} result = impl->{{getter_name}}({{getter_arguments | join(', ')}}); 35 {{getter.v8_set_return_value}}; 36} 37 38{% endif %} 39{% endblock %} 40 41 42{##############################################################################} 43{% block indexed_property_getter_callback %} 44{% if indexed_property_getter or named_property_getter %} 45{% set getter = indexed_property_getter or named_property_getter %} 46void {{v8_class_or_partial}}::IndexedPropertyGetterCallback( 47 uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { 48 {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.indexed_property_getter_counter) }} 49 {% if indexed_property_getter %} 50 51 {% if getter.is_custom %} 52 {{v8_class}}::IndexedPropertyGetterCustom(index, info); 53 {% else %} 54 {{internal_namespace}}::IndexedPropertyGetter(index, info); 55 {% endif %} 56 57 {% else %}{# otherwise, named property #} 58 59 const AtomicString& property_name = AtomicString::Number(index); 60 61 {% if getter.is_custom %} 62 {{v8_class}}::NamedPropertyGetterCustom(property_name, info); 63 {% else %} 64 {{internal_namespace}}::NamedPropertyGetter(property_name, info); 65 {% endif %} 66 67 {% endif %}{# indexed_property_getter #} 68} 69 70{% endif %} 71{% endblock %} 72 73 74{##############################################################################} 75{% block indexed_property_setter %} 76{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %} 77{% if indexed_property_setter and not indexed_property_setter.is_custom %} 78{% set setter = indexed_property_setter %} 79static void IndexedPropertySetter( 80 uint32_t index, 81 v8::Local<v8::Value> v8_value, 82 const v8::PropertyCallbackInfo<v8::Value>& info) { 83 {% if setter.has_exception_state %} 84 ExceptionState exception_state( 85 info.GetIsolate(), 86 ExceptionState::kIndexedSetterContext, 87 "{{interface_name}}"); 88 {% endif %} 89 {% if setter.is_ce_reactions %} 90 CEReactionsScope ce_reactions_scope; 91 {% endif %} 92 93 {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder()); 94 {{v8_value_to_local_cpp_value(setter) | trim | indent(2)}} 95 {% if setter.has_type_checking_interface %} 96 {# Type checking for interface types (if interface not implemented, throw 97 TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} 98 if (!property_value{% if setter.is_nullable %} && !IsUndefinedOrNull(v8_value){% endif %}) { 99 exception_state.ThrowTypeError("The provided value is not of type '{{setter.idl_type}}'."); 100 return; 101 } 102 {% endif %} 103 104 {% set setter_name = setter.name or 'AnonymousIndexedSetter' %} 105 {% set setter_arguments = ['index', 'property_value'] %} 106 {% if setter.is_call_with_script_state %} 107 ScriptState* script_state = ScriptState::ForRelevantRealm(info); 108 {% set setter_arguments = ['script_state'] + setter_arguments %} 109 {% endif %} 110 {% if setter.is_raises_exception %} 111 {% set setter_arguments = setter_arguments + ['exception_state'] %} 112 {% endif %} 113 IndexedPropertySetterResult result = impl->{{setter_name}}({{setter_arguments | join(', ')}}); 114 {% if setter.is_raises_exception %} 115 if (exception_state.HadException()) 116 return; 117 {% endif %} 118 if (result == IndexedPropertySetterResult::kDidNotIntercept) 119 return; 120 V8SetReturnValue(info, v8_value); 121} 122 123{% endif %} 124{% endblock %} 125 126 127{##############################################################################} 128{% block indexed_property_setter_callback %} 129{% if indexed_property_getter or named_property_setter %} 130{% set setter = indexed_property_setter or named_property_setter %} 131void {{v8_class_or_partial}}::IndexedPropertySetterCallback( 132 uint32_t index, 133 v8::Local<v8::Value> v8_value, 134 const v8::PropertyCallbackInfo<v8::Value>& info) { 135 {% if indexed_property_setter %} 136 137 {% if setter.is_custom %} 138 {{v8_class}}::IndexedPropertySetterCustom(index, v8_value, info); 139 {% else %} 140 {{internal_namespace}}::IndexedPropertySetter(index, v8_value, info); 141 {% endif %} 142 143 {% elif not indexed_property_getter and named_property_setter %} 144 145 const AtomicString& property_name = AtomicString::Number(index); 146 147 {% if setter.is_custom %} 148 {{v8_class}}::NamedPropertySetterCustom(property_name, v8_value, info); 149 {% else %} 150 {{internal_namespace}}::NamedPropertySetter(property_name, v8_value, info); 151 {% endif %} 152 153 {% else %}{# neither of indexed_property_setter nor named_property_setter #} 154 155 // No indexed property setter defined. Do not fall back to the default 156 // setter. 157 V8SetReturnValue(info, v8::Null(info.GetIsolate())); 158 if (info.ShouldThrowOnError()) { 159 ExceptionState exception_state(info.GetIsolate(), 160 ExceptionState::kIndexedSetterContext, 161 "{{interface_name}}"); 162 {% if setter.is_ce_reactions %} 163 CEReactionsScope ce_reactions_scope; 164 {% endif %} 165 exception_state.ThrowTypeError("Index property setter is not supported."); 166 } 167 168 {% endif %}{# indexed/named_property_setter #} 169} 170 171{% endif %} 172{% endblock %} 173 174 175{##############################################################################} 176{% block indexed_property_descriptor %} 177{% if indexed_property_getter %} 178static void IndexedPropertyDescriptor( 179 uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { 180 // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty 181 // Steps 1.1 to 1.2.4 are covered here: we rely on indexedPropertyGetter() to 182 // call the getter function and check that |index| is a valid property index, 183 // in which case it will have set info.GetReturnValue() to something other 184 // than undefined. 185 {{v8_class_or_partial}}::IndexedPropertyGetterCallback(index, info); 186 v8::Local<v8::Value> getter_value = info.GetReturnValue().Get(); 187 if (!getter_value->IsUndefined()) { 188 // 1.2.5. Let |desc| be a newly created Property Descriptor with no fields. 189 // 1.2.6. Set desc.[[Value]] to the result of converting value to an 190 // ECMAScript value. 191 // 1.2.7. If O implements an interface with an indexed property setter, 192 // then set desc.[[Writable]] to true, otherwise set it to false. 193 v8::PropertyDescriptor desc(getter_value, {% if indexed_property_setter %}true{% else %}false{% endif %}); 194 // 1.2.8. Set desc.[[Enumerable]] and desc.[[Configurable]] to true. 195 desc.set_enumerable(true); 196 desc.set_configurable(true); 197 // 1.2.9. Return |desc|. 198 V8SetReturnValue(info, desc); 199 } 200} 201 202{% endif %} 203{% endblock %} 204 205 206{##############################################################################} 207{% block named_property_descriptor %} 208{% if not indexed_property_getter and named_property_getter %} 209static void NamedPropertyDescriptor( 210 uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { 211 // This function is called when an IDL interface supports named properties 212 // but not indexed properties. When a numeric property is queried, V8 calls 213 // indexedPropertyDescriptorCallback(), which calls this function. 214 215 {% if named_property_getter.is_enumerable %} 216 // Since we initialize our indexed and named property handlers differently 217 // (the former use descriptors and definers, the latter uses a query 218 // callback), we need to inefficiently call the query callback and convert 219 // the v8::PropertyAttribute integer it returns into a v8::PropertyDescriptor 220 // expected by a descriptor callback. 221 // TODO(rakuco): remove this hack once we switch named property handlers to 222 // using descriptor and definer callbacks (bug 764633). 223 const AtomicString& index_as_name = AtomicString::Number(index); 224 {% if named_property_getter.is_custom_property_query %} 225 {{v8_class}}::NamedPropertyQueryCustom(index_as_name, info); 226 {% else %} 227 {{internal_namespace}}::NamedPropertyQuery(index_as_name, info); 228 {% endif %} 229 v8::Local<v8::Value> getter_value = info.GetReturnValue().Get(); 230 if (!getter_value->IsUndefined()) { 231 DCHECK(getter_value->IsInt32()); 232 const int32_t props = 233 getter_value->ToInt32(info.GetIsolate()->GetCurrentContext()) 234 .ToLocalChecked() 235 ->Value(); 236 v8::PropertyDescriptor desc(V8String(info.GetIsolate(), index_as_name), 237 !(props & v8::ReadOnly)); 238 desc.set_enumerable(!(props & v8::DontEnum)); 239 desc.set_configurable(!(props & v8::DontDelete)); 240 V8SetReturnValue(info, desc); 241 } 242 {% else %}{# TODO(rakuco): drop this once we remove [NotEnumerable] getters #} 243 // This IDL interface defines a [NotEnumerable] getter. We need to do 244 // something similar to indexedPropertyDescriptor(): call 245 // indexedPropertyGetterCallback, let it end up calling the named property 246 // getter and, if all goes well, we create a v8::PropertyDescriptor with the 247 // right values. 248 {{v8_class_or_partial}}::IndexedPropertyGetterCallback(index, info); 249 v8::Local<v8::Value> getter_value = info.GetReturnValue().Get(); 250 if (!getter_value->IsUndefined()) { 251 v8::PropertyDescriptor desc(getter_value, {% if named_property_setter %}true{% else %}false{% endif %}); 252 desc.set_enumerable(false); 253 desc.set_configurable(true); 254 V8SetReturnValue(info, desc); 255 } 256 {% endif %} 257} 258 259{% endif %} 260{% endblock %} 261 262 263{##############################################################################} 264{% block indexed_property_descriptor_callback %} 265{% if indexed_property_getter or named_property_getter %} 266void {{v8_class_or_partial}}::IndexedPropertyDescriptorCallback( 267 uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { 268 {% if indexed_property_getter %} 269 {{internal_namespace}}::IndexedPropertyDescriptor(index, info); 270 {% else %}{# The interface only supports named properties. #} 271 {{internal_namespace}}::NamedPropertyDescriptor(index, info); 272 {% endif %}{# indexed_property_getter #} 273} 274 275{% endif %} 276{% endblock %} 277 278 279{##############################################################################} 280{% block indexed_property_deleter %} 281{% if indexed_property_deleter and not indexed_property_deleter.is_custom %} 282{% set deleter = indexed_property_deleter %} 283static void IndexedPropertyDeleter( 284 uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) { 285 {% if deleter.is_raises_exception %} 286 ExceptionState exception_state( 287 info.GetIsolate(), 288 ExceptionState::kIndexedDeletionContext, 289 "{{interface_name}}"); 290 {% endif %} 291 {% if deleter.is_ce_reactions %} 292 CEReactionsScope ce_reactions_scope; 293 {% endif %} 294 295 {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder()); 296 297 {% set deleter_name = deleter.name or 'AnonymousIndexedDeleter' %} 298 {% set deleter_arguments = ['index'] %} 299 {% if deleter.is_call_with_script_state %} 300 ScriptState* script_state = ScriptState::ForRelevantRealm(info); 301 {% set deleter_arguments = ['script_state'] + deleter_arguments %} 302 {% endif %} 303 {% if deleter.is_raises_exception %} 304 {% set deleter_arguments = deleter_arguments + ['exception_state'] %} 305 {% endif %} 306 NamedPropertyDeleterResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}}); 307 {% if deleter.is_raises_exception %} 308 if (exception_state.HadException()) 309 return; 310 {% endif %} 311 if (result == NamedPropertyDeleterResult::kDidNotIntercept) 312 return; 313 V8SetReturnValue(info, result == NamedPropertyDeleterResult::kDeleted); 314} 315 316{% endif %} 317{% endblock %} 318 319 320{##############################################################################} 321{% block indexed_property_deleter_callback %} 322{% if indexed_property_deleter or named_property_deleter %} 323{% set deleter = indexed_property_deleter or named_property_deleter %} 324void {{v8_class_or_partial}}::IndexedPropertyDeleterCallback( 325 uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) { 326 {% if indexed_property_deleter %} 327 328 {% if deleter.is_custom %} 329 {{v8_class}}::IndexedPropertyDeleterCustom(index, info); 330 {% else %} 331 {{internal_namespace}}::IndexedPropertyDeleter(index, info); 332 {% endif %} 333 334 {% else %}{# otherwise, named property #} 335 336 const AtomicString& property_name = AtomicString::Number(index); 337 338 {% if deleter.is_custom %} 339 {{v8_class}}::NamedPropertyDeleterCustom(property_name, info); 340 {% else %} 341 {{internal_namespace}}::NamedPropertyDeleter(property_name, info); 342 {% endif %} 343 344 {% endif %}{# indexed_property_deleter #} 345} 346 347{% endif %} 348{% endblock %} 349 350 351{##############################################################################} 352{% block indexed_property_definer_callback %} 353{% if indexed_property_getter %} 354void {{v8_class_or_partial}}::IndexedPropertyDefinerCallback( 355 uint32_t index, 356 const v8::PropertyDescriptor& desc, 357 const v8::PropertyCallbackInfo<v8::Value>& info) { 358{% if indexed_property_setter %} 359 // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty 360 // 3.9.3. [[DefineOwnProperty]] 361 // step 1.1. If the result of calling IsDataDescriptor(Desc) is false, then 362 // return false. 363 if (desc.has_get() || desc.has_set()) { 364 V8SetReturnValue(info, v8::Null(info.GetIsolate())); 365 if (info.ShouldThrowOnError()) { 366 ExceptionState exception_state(info.GetIsolate(), 367 ExceptionState::kIndexedSetterContext, 368 "{{interface_name}}"); 369 exception_state.ThrowTypeError("Accessor properties are not allowed."); 370 } 371 return; 372 } 373 374 // Return nothing and fall back to indexedPropertySetterCallback. 375{% else %}{# indexed_property_setter #} 376 // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty 377 // 3.9.3. [[DefineOwnProperty]] 378 // step 1.2. If O does not implement an interface with an indexed property 379 // setter, then return false. 380 // 381 // https://html.spec.whatwg.org/C/window-object.html#windowproxy-defineownproperty 382 // 7.4.6 [[DefineOwnProperty]] (P, Desc) 383 // step 2.1. If P is an array index property name, return false. 384 V8SetReturnValue(info, v8::Null(info.GetIsolate())); 385 if (info.ShouldThrowOnError()) { 386 ExceptionState exception_state(info.GetIsolate(), 387 ExceptionState::kIndexedSetterContext, 388 "{{interface_name}}"); 389 exception_state.ThrowTypeError("Index property setter is not supported."); 390 } 391{% endif %}{# indexed_property_setter #} 392} 393 394{% endif %}{# indexed_property_getter #} 395{% endblock %} 396 397 398{##############################################################################} 399{% block named_property_getter %} 400{% if named_property_getter and not named_property_getter.is_custom %} 401{% set getter = named_property_getter %} 402static void NamedPropertyGetter(const AtomicString& name, 403 const v8::PropertyCallbackInfo<v8::Value>& info) { 404 {% if getter.is_raises_exception %} 405 const std::string& name_in_utf8 = name.Utf8(); 406 ExceptionState exception_state( 407 info.GetIsolate(), 408 ExceptionState::kGetterContext, 409 "{{interface_name}}", 410 name_in_utf8.c_str()); 411 {% endif %} 412 {% if getter.is_call_with_script_state %} 413 ScriptState* script_state = ScriptState::ForRelevantRealm(info); 414 {% endif %} 415 416 {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder()); 417 {% if getter.use_output_parameter_for_result %} 418 {{getter.cpp_type}} result; 419 {{getter.cpp_value}}; 420 {% else %} 421 {{getter.cpp_type}} result = {{getter.cpp_value}}; 422 {% endif %} 423 if ({{getter.is_null_expression}}) 424 return; 425 {{getter.v8_set_return_value}}; 426} 427 428{% endif %} 429{% endblock %} 430 431 432{##############################################################################} 433{% block named_property_getter_callback %} 434{% if named_property_getter %} 435{% set getter = named_property_getter %} 436void {{v8_class_or_partial}}::NamedPropertyGetterCallback( 437 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { 438 {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.named_property_getter_counter) }} 439 if (!name->IsString()) 440 return; 441 const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>()); 442 443 {% if getter.is_custom %} 444 {{v8_class}}::NamedPropertyGetterCustom(property_name, info); 445 {% else %} 446 {{internal_namespace}}::NamedPropertyGetter(property_name, info); 447 {% endif %} 448} 449 450{% endif %} 451{% endblock %} 452 453 454{##############################################################################} 455{% block named_property_setter %} 456{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %} 457{% if named_property_setter and not named_property_setter.is_custom %} 458{% set setter = named_property_setter %} 459static void NamedPropertySetter( 460 const AtomicString& name, 461 v8::Local<v8::Value> v8_value, 462 const v8::PropertyCallbackInfo<v8::Value>& info) { 463 {% if setter.has_exception_state %} 464 const std::string& name_in_utf8 = name.Utf8(); 465 ExceptionState exception_state( 466 info.GetIsolate(), 467 ExceptionState::kSetterContext, 468 "{{interface_name}}", 469 name_in_utf8.c_str()); 470 {% endif %} 471 {% if setter.is_ce_reactions %} 472 CEReactionsScope ce_reactions_scope; 473 {% endif %} 474 {% if setter.is_call_with_script_state %} 475 ScriptState* script_state = ScriptState::ForRelevantRealm(info); 476 {% endif %} 477 478 {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder()); 479 {{v8_value_to_local_cpp_value(setter) | trim | indent(2)}} 480 {% if setter.has_type_checking_interface %} 481 {# Type checking for interface types (if interface not implemented, throw 482 TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} 483 if (!property_value{% if setter.is_nullable %} && !IsUndefinedOrNull(v8_value){% endif %}) { 484 exception_state.ThrowTypeError("The provided value is not of type '{{setter.idl_type}}'."); 485 return; 486 } 487 {% endif %} 488 489 {% set setter_name = setter.name or 'AnonymousNamedSetter' %} 490 {% set setter_arguments = ['name', 'property_value'] %} 491 {% if setter.is_call_with_script_state %} 492 {% set setter_arguments = ['script_state'] + setter_arguments %} 493 {% endif %} 494 {% if setter.is_raises_exception %} 495 {% set setter_arguments = setter_arguments + ['exception_state'] %} 496 {% endif %} 497 NamedPropertySetterResult result = impl->{{setter_name}}({{setter_arguments | join(', ')}}); 498 {% if setter.is_raises_exception %} 499 if (exception_state.HadException()) 500 return; 501 {% endif %} 502 if (result == NamedPropertySetterResult::kDidNotIntercept) 503 return; 504 V8SetReturnValue(info, v8_value); 505} 506 507{% endif %} 508{% endblock %} 509 510 511{##############################################################################} 512{% block named_property_setter_callback %} 513{% if named_property_setter %} 514{% set setter = named_property_setter %} 515void {{v8_class_or_partial}}::NamedPropertySetterCallback( 516 v8::Local<v8::Name> name, 517 v8::Local<v8::Value> v8_value, 518 const v8::PropertyCallbackInfo<v8::Value>& info) { 519 {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.named_property_setter_counter) }} 520 if (!name->IsString()) 521 return; 522 const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>()); 523 524 {% if setter.is_custom %} 525 {{v8_class}}::NamedPropertySetterCustom(property_name, v8_value, info); 526 {% else %} 527 {{internal_namespace}}::NamedPropertySetter(property_name, v8_value, info); 528 {% endif %} 529} 530 531{% endif %} 532{% endblock %} 533 534 535{##############################################################################} 536{% block named_property_deleter %} 537{% if named_property_deleter and not named_property_deleter.is_custom %} 538{% set deleter = named_property_deleter %} 539static void NamedPropertyDeleter( 540 const AtomicString& name, const v8::PropertyCallbackInfo<v8::Boolean>& info) { 541 {% if deleter.is_raises_exception %} 542 const std::string& name_in_utf8 = name.Utf8(); 543 ExceptionState exception_state( 544 info.GetIsolate(), 545 ExceptionState::kDeletionContext, 546 "{{interface_name}}", 547 name_in_utf8.c_str()); 548 {% endif %} 549 {% if deleter.is_ce_reactions %} 550 CEReactionsScope ce_reactions_scope; 551 {% endif %} 552 {% if deleter.is_call_with_script_state %} 553 ScriptState* script_state = ScriptState::ForRelevantRealm(info); 554 {% endif %} 555 556 {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder()); 557 558 {% set deleter_name = deleter.name or 'AnonymousNamedDeleter' %} 559 {% set deleter_arguments = ['name'] %} 560 {% if deleter.is_call_with_script_state %} 561 {% set deleter_arguments = ['script_state'] + deleter_arguments %} 562 {% endif %} 563 {% if deleter.is_raises_exception %} 564 {% set deleter_arguments = deleter_arguments + ['exception_state'] %} 565 {% endif %} 566 NamedPropertyDeleterResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}}); 567 {% if deleter.is_raises_exception %} 568 if (exception_state.HadException()) 569 return; 570 {% endif %} 571 if (result == NamedPropertyDeleterResult::kDidNotIntercept) 572 return; 573 V8SetReturnValue(info, result == NamedPropertyDeleterResult::kDeleted); 574} 575 576{% endif %} 577{% endblock %} 578 579 580{##############################################################################} 581{% block named_property_deleter_callback %} 582{% if named_property_deleter %} 583{% set deleter = named_property_deleter %} 584void {{v8_class_or_partial}}::NamedPropertyDeleterCallback( 585 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) { 586 if (!name->IsString()) 587 return; 588 const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>()); 589 590 {% if deleter.is_custom %} 591 {{v8_class}}::NamedPropertyDeleterCustom(property_name, info); 592 {% else %} 593 {{internal_namespace}}::NamedPropertyDeleter(property_name, info); 594 {% endif %} 595} 596 597{% endif %} 598{% endblock %} 599 600 601{##############################################################################} 602{% block named_property_query %} 603{% if named_property_getter and named_property_getter.is_enumerable and 604 not named_property_getter.is_custom_property_query %} 605{% set getter = named_property_getter %} 606{# If there is an enumerator, there MUST be a query method to properly 607 communicate property attributes. #} 608{% if indexed_property_getter %} 609static void NamedPropertyQuery( 610 const AtomicString& name, const v8::PropertyCallbackInfo<v8::Integer>& info) { 611{% else %} 612{# If we do not have an indexed property getter, this function is called #} 613{# from namedPropertyDescriptor(), whose v8::PropertyCallbackInfo has a #} 614{# v8::Value instead of a v8::Integer. We use this template trick to make #} 615{# the compiler accept the call. #} 616{# TODO(rakuco): remove this hack once we switch named property handlers to #} 617{# using descriptor and definer callbacks (bug 764633). #} 618template <typename T> 619static void NamedPropertyQuery( 620 const AtomicString& name, const v8::PropertyCallbackInfo<T>& info) { 621{% endif %} 622 const std::string& name_in_utf8 = name.Utf8(); 623 ExceptionState exception_state( 624 info.GetIsolate(), 625 ExceptionState::kGetterContext, 626 "{{interface_name}}", 627 name_in_utf8.c_str()); 628 {% if getter.is_call_with_script_state %} 629 ScriptState* script_state = ScriptState::ForRelevantRealm(info); 630 {% endif %} 631 632 {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder()); 633 634 {% set getter_arguments = ['name', 'exception_state'] %} 635 {% if getter.is_call_with_script_state %} 636 {% set getter_arguments = ['script_state'] + getter_arguments %} 637 {% endif %} 638 bool result = impl->NamedPropertyQuery({{getter_arguments | join(', ')}}); 639 if (!result) 640 return; 641 // https://heycam.github.io/webidl/#LegacyPlatformObjectGetOwnProperty 642 // 2.7. If |O| implements an interface with a named property setter, then set 643 // desc.[[Writable]] to true, otherwise set it to false. 644 // 2.8. If |O| implements an interface with the 645 // [LegacyUnenumerableNamedProperties] extended attribute, then set 646 // desc.[[Enumerable]] to false, otherwise set it to true. 647 {% if named_property_setter %} 648 {% set desc_properties = ['v8::None'] %} 649 {% else %} 650 {% set desc_properties = ['v8::ReadOnly'] %} 651 {% endif %} 652 {% if has_legacy_unenumerable_named_properties %} 653 {% set desc_properties = ['v8::DontEnum'] + desc_properties %} 654 {% endif %} 655 V8SetReturnValueInt(info, {{desc_properties | join(' | ')}}); 656} 657 658{% endif %} 659{% endblock %} 660 661 662{##############################################################################} 663{% block named_property_query_callback %} 664{% if named_property_getter and named_property_getter.is_enumerable %} 665{% set getter = named_property_getter %} 666void {{v8_class_or_partial}}::NamedPropertyQueryCallback( 667 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) { 668 {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.named_property_query_counter) }} 669 if (!name->IsString()) 670 return; 671 const AtomicString& property_name = ToCoreAtomicString(name.As<v8::String>()); 672 673 {% if getter.is_custom_property_query %} 674 {{v8_class}}::NamedPropertyQueryCustom(property_name, info); 675 {% else %} 676 {{internal_namespace}}::NamedPropertyQuery(property_name, info); 677 {% endif %} 678} 679 680{% endif %} 681{% endblock %} 682 683 684{##############################################################################} 685{% block named_property_enumerator %} 686{% if named_property_getter and named_property_getter.is_enumerable and 687 not named_property_getter.is_custom_property_enumerator %} 688static void NamedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) { 689 ExceptionState exception_state( 690 info.GetIsolate(), 691 ExceptionState::kEnumerationContext, 692 "{{interface_name}}"); 693 694 {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder()); 695 696 Vector<String> names; 697 impl->NamedPropertyEnumerator(names, exception_state); 698 if (exception_state.HadException()) 699 return; 700 V8SetReturnValue(info, ToV8(names, info.Holder(), info.GetIsolate()).As<v8::Array>()); 701} 702 703{% endif %} 704{% endblock %} 705 706 707{##############################################################################} 708{% block named_property_enumerator_callback %} 709{% if named_property_getter and named_property_getter.is_enumerable %} 710{% set getter = named_property_getter %} 711void {{v8_class_or_partial}}::NamedPropertyEnumeratorCallback( 712 const v8::PropertyCallbackInfo<v8::Array>& info) { 713 {% if getter.is_custom_property_enumerator %} 714 {{v8_class}}::NamedPropertyEnumeratorCustom(info); 715 {% else %} 716 {{internal_namespace}}::NamedPropertyEnumerator(info); 717 {% endif %} 718} 719 720{% endif %} 721{% endblock %} 722 723 724{##############################################################################} 725{% block named_constructor %} 726{% from 'methods.cc.tmpl' import generate_constructor with context %} 727{% if named_constructor %} 728{% set active_scriptwrappable_inheritance = 729 'kInheritFromActiveScriptWrappable' 730 if active_scriptwrappable else 731 'kNotInheritFromActiveScriptWrappable' %} 732// Suppress warning: global constructors, because struct WrapperTypeInfo is trivial 733// and does not depend on another global objects. 734#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__) 735#pragma clang diagnostic push 736#pragma clang diagnostic ignored "-Wglobal-constructors" 737#endif 738const WrapperTypeInfo {{snake_case_v8_class}}_constructor_wrapper_type_info = { 739 gin::kEmbedderBlink, 740 {{v8_class}}Constructor::DomTemplate, 741 {{install_conditional_features_func or 'nullptr'}}, 742 "{{interface_name}}", 743 nullptr, 744 WrapperTypeInfo::kWrapperTypeObjectPrototype, 745 WrapperTypeInfo::{{wrapper_class_id}}, 746 WrapperTypeInfo::{{active_scriptwrappable_inheritance}}, 747}; 748#if defined(COMPONENT_BUILD) && defined(WIN32) && defined(__clang__) 749#pragma clang diagnostic pop 750#endif 751 752{{generate_constructor(named_constructor)}} 753v8::Local<v8::FunctionTemplate> {{v8_class}}Constructor::DomTemplate( 754 v8::Isolate* isolate, const DOMWrapperWorld& world) { 755 static int dom_template_key; // This address is used for a key to look up the dom template. 756 V8PerIsolateData* data = V8PerIsolateData::From(isolate); 757 v8::Local<v8::FunctionTemplate> result = 758 data->FindInterfaceTemplate(world, &dom_template_key); 759 if (!result.IsEmpty()) 760 return result; 761 762 result = v8::FunctionTemplate::New(isolate, {{v8_class}}ConstructorCallback); 763 v8::Local<v8::ObjectTemplate> instance_template = result->InstanceTemplate(); 764 instance_template->SetInternalFieldCount({{v8_class}}::kInternalFieldCount); 765 result->SetClassName(V8AtomicString(isolate, "{{named_constructor.name}}")); 766 result->Inherit({{v8_class}}::DomTemplate(isolate, world)); 767 data->SetInterfaceTemplate(world, &dom_template_key, result); 768 return result; 769} 770 771void {{v8_class}}Constructor::NamedConstructorAttributeGetter( 772 v8::Local<v8::Name> property_name, 773 const v8::PropertyCallbackInfo<v8::Value>& info) { 774 v8::Local<v8::Context> creationContext = info.Holder()->CreationContext(); 775 V8PerContextData* per_context_data = V8PerContextData::From(creationContext); 776 if (!per_context_data) { 777 // TODO(yukishiino): Return a valid named constructor even after the context is detached 778 return; 779 } 780 781 v8::Local<v8::Function> named_constructor = 782 per_context_data->ConstructorForType({{v8_class}}Constructor::GetWrapperTypeInfo()); 783 784 // Set the prototype of named constructors to the regular constructor. 785 static const V8PrivateProperty::SymbolKey kPrivatePropertyInitialized; 786 auto private_property = 787 V8PrivateProperty::GetSymbol( 788 info.GetIsolate(), kPrivatePropertyInitialized); 789 v8::Local<v8::Context> current_context = info.GetIsolate()->GetCurrentContext(); 790 v8::Local<v8::Value> private_value; 791 792 if (!private_property.GetOrUndefined(named_constructor).ToLocal(&private_value) || 793 private_value->IsUndefined()) { 794 v8::Local<v8::Function> interface = 795 per_context_data->ConstructorForType({{v8_class}}::GetWrapperTypeInfo()); 796 v8::Local<v8::Value> interface_prototype = 797 interface->Get(current_context, V8AtomicString(info.GetIsolate(), "prototype")) 798 .ToLocalChecked(); 799 // https://heycam.github.io/webidl/#named-constructors 800 // 8. Perform ! DefinePropertyOrThrow(F, "prototype", 801 // PropertyDescriptor{[[Value]]: proto, [[Writable]]: false, 802 // [[Enumerable]]: false, 803 // [Configurable]]: false}). 804 const v8::PropertyAttribute prototype_attributes = 805 static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum | v8::DontDelete); 806 bool result = named_constructor->DefineOwnProperty( 807 current_context, V8AtomicString(info.GetIsolate(), "prototype"), 808 interface_prototype, prototype_attributes).ToChecked(); 809 CHECK(result); 810 private_property.Set(named_constructor, v8::True(info.GetIsolate())); 811 } 812 813 V8SetReturnValue(info, named_constructor); 814} 815 816{% endif %} 817{% endblock %} 818 819{##############################################################################} 820{% block overloaded_constructor %} 821{% if constructor_overloads %} 822static void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) { 823 ExceptionState exception_state(info.GetIsolate(), ExceptionState::kConstructionContext, "{{interface_name}}"); 824 {# This follows the overload resolution algorithm. #} 825 {# https://heycam.github.io/webidl/#dfn-overload-resolution-algorithm #} 826 {# 3. Initialize argcount to be min(maxarg, n). #} 827 switch (std::min({{constructor_overloads.maxarg}}, info.Length())) { 828 {# 4. Remove from S all entries whose type list is not of length argcount. #} 829 {% for length, tests_constructors in constructor_overloads.length_tests_methods %} 830 {# 12. If i = d, then: #} 831 case {{length}}: 832 {# Then resolve by testing argument #} 833 {% for test, constructor in tests_constructors %} 834 if ({{test}}) { 835 {{internal_namespace}}::Constructor{{constructor.overload_index}}(info); 836 return; 837 } 838 {% if "exception_state" in test %} 839 if (exception_state.HadException()) { 840 exception_state.RethrowV8Exception(exception_state.GetException()); 841 return; 842 } 843 {% endif %} 844 {% endfor %} 845 break; 846 {% endfor %} 847 default: 848 {# Invalid arity, throw error #} 849 {# Report full list of valid arities if gaps and above minimum #} 850 {% if constructor_overloads.valid_arities %} 851 if (info.Length() >= {{constructor_overloads.length}}) { 852 exception_state.ThrowTypeError(ExceptionMessages::InvalidArity("{{constructor_overloads.valid_arities}}", info.Length())); 853 return; 854 } 855 {% endif %} 856 {# Otherwise just report "not enough arguments" #} 857 exception_state.ThrowTypeError(ExceptionMessages::NotEnoughArguments({{constructor_overloads.length}}, info.Length())); 858 return; 859 } 860 {# No match, throw error #} 861 exception_state.ThrowTypeError("No matching constructor signature."); 862} 863 864{% endif %} 865{% endblock %} 866 867 868{##############################################################################} 869{% block constructor_callback %} 870{% if constructors or has_custom_constructor or has_html_constructor %} 871{{exported}}void ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { 872 {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.constructor_counter) }} 873 {% if measure_as %} 874 ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); 875 UseCounter::Count(execution_context_for_measurement, WebFeature::k{{measure_as('Constructor')}}); 876 {% if high_entropy %} 877 Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{measure_as('Constructor')}}); 878 {% endif %} 879 {% endif %} 880 if (!info.IsConstructCall()) { 881 V8ThrowException::ThrowTypeError( 882 info.GetIsolate(), 883 ExceptionMessages::ConstructorNotCallableAsFunction("{{interface_name}}")); 884 return; 885 } 886 887 if (ConstructorMode::Current(info.GetIsolate()) == ConstructorMode::kWrapExistingObject) { 888 V8SetReturnValue(info, info.Holder()); 889 return; 890 } 891 892 {% if has_custom_constructor %} 893 {{v8_class}}::ConstructorCustom(info); 894 {% elif has_html_constructor %} 895 V8HTMLConstructor::HtmlConstructor( 896 info, *{{v8_class}}::GetWrapperTypeInfo(), HTMLElementType::k{{interface_name}}); 897 {% else %} 898 {{internal_namespace}}::Constructor(info); 899 {% endif %} 900} 901 902{% endif %} 903{% endblock %} 904 905 906{##############################################################################} 907{% macro install_origin_safe_method(method, instance_template, prototype_template, interface_template, signature) %} 908{% from 'utilities.cc.tmpl' import property_location %} 909{# TODO(dcheng): Currently, bindings must create a function object for each 910 realm as a hack to support the incumbent realm. Clean this up when Blink 911 properly supports the incumbent realm. #} 912{% set function_callback = 913 '%s::%sMethodCallback' % (v8_class_or_partial, method.camel_case_name) %} 914{% set property_attribute = 915 'static_cast<v8::PropertyAttribute>(%s)' % 916 ' | '.join(method.property_attributes or ['v8::None']) %} 917{% set holder_check = 'V8DOMConfiguration::kCheckHolder' %} 918static const V8DOMConfiguration::MethodConfiguration k{{method.camel_case_name}}OriginSafeMethodConfiguration[] = { 919{% if method.is_per_world_bindings %} 920{% set function_callback_for_main_world = '%sForMainWorld' % function_callback %} 921 { 922 "{{method.name}}", 923 {{function_callback_for_main_world}}, 924 {{method.length}}, 925 {{property_attribute}}, 926 {{property_location(method)}}, 927 {{holder_check}}, 928 V8DOMConfiguration::kCheckAccess, 929 V8DOMConfiguration::kHasSideEffect, 930 V8DOMConfiguration::MainWorld, 931 }, 932 { 933 "{{method.name}}", 934 {{function_callback}}, 935 {{method.length}}, 936 {{property_attribute}}, 937 {{property_location(method)}}, 938 {{holder_check}}, 939 V8DOMConfiguration::kCheckAccess, 940 V8DOMConfiguration::kHasSideEffect, 941 V8DOMConfiguration::NonMainWorlds, 942 } 943{% else %} 944 { 945 "{{method.name}}", 946 {{function_callback}}, 947 {{method.length}}, 948 {{property_attribute}}, 949 {{property_location(method)}}, 950 {{holder_check}}, 951 V8DOMConfiguration::kCheckAccess, 952 V8DOMConfiguration::kHasSideEffect, 953 V8DOMConfiguration::kAllWorlds, 954 } 955{% endif %} 956}; 957for (const auto& method_config : k{{method.camel_case_name}}OriginSafeMethodConfiguration) 958 V8DOMConfiguration::InstallMethod(isolate, world, {{instance_template}}, {{prototype_template}}, {{interface_template}}, {{signature}}, method_config); 959{%- endmacro %} 960 961 962{##############################################################################} 963{% macro install_indexed_property_handler(target) %} 964{% set indexed_property_getter_callback = 965 '%s::IndexedPropertyGetterCallback' % v8_class_or_partial %} 966{% set indexed_property_setter_callback = 967 '%s::IndexedPropertySetterCallback' % v8_class_or_partial 968 if indexed_property_getter or named_property_setter else 'nullptr' %} 969{% set indexed_property_descriptor_callback = 970 '%s::IndexedPropertyDescriptorCallback' % v8_class_or_partial 971 if indexed_property_getter or named_property_getter else 'nullptr' %} 972{% set indexed_property_deleter_callback = 973 '%s::IndexedPropertyDeleterCallback' % v8_class_or_partial 974 if indexed_property_deleter or named_property_deleter else 'nullptr' %} 975{% set indexed_property_enumerator_callback = 976 'IndexedPropertyEnumerator<%s>' % cpp_class 977 if indexed_property_getter.is_enumerable else 'nullptr' %} 978{% set indexed_property_definer_callback = 979 '%s::IndexedPropertyDefinerCallback' % v8_class_or_partial 980 if indexed_property_getter else 'nullptr' %} 981{% set property_handler_flags = 982 'v8::PropertyHandlerFlags::kHasNoSideEffect' 983 if indexed_property_getter.has_no_side_effect else 'v8::PropertyHandlerFlags::kNone' %} 984v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig( 985 {{indexed_property_getter_callback}}, 986 {{indexed_property_setter_callback}}, 987 {{indexed_property_descriptor_callback}}, 988 {{indexed_property_deleter_callback}}, 989 {{indexed_property_enumerator_callback}}, 990 {{indexed_property_definer_callback}}, 991 v8::Local<v8::Value>(), 992 {{property_handler_flags}}); 993{{target}}->SetHandler(indexedPropertyHandlerConfig); 994{%- endmacro %} 995 996 997{##############################################################################} 998{% macro install_named_property_handler(target) %} 999{% set named_property_getter_callback = 1000 '%s::NamedPropertyGetterCallback' % v8_class_or_partial %} 1001{% set named_property_setter_callback = 1002 '%s::NamedPropertySetterCallback' % v8_class_or_partial 1003 if named_property_setter else 'nullptr' %} 1004{% set named_property_query_callback = 1005 '%s::NamedPropertyQueryCallback' % v8_class_or_partial 1006 if named_property_getter.is_enumerable else 'nullptr' %} 1007{% set named_property_deleter_callback = 1008 '%s::NamedPropertyDeleterCallback' % v8_class_or_partial 1009 if named_property_deleter else 'nullptr' %} 1010{% set named_property_enumerator_callback = 1011 '%s::NamedPropertyEnumeratorCallback' % v8_class_or_partial 1012 if named_property_getter.is_enumerable else 'nullptr' %} 1013{% set property_handler_flags_list = 1014 ['int(v8::PropertyHandlerFlags::kOnlyInterceptStrings)'] %} 1015{% if not is_override_builtins %} 1016{% set property_handler_flags_list = 1017 property_handler_flags_list + ['int(v8::PropertyHandlerFlags::kNonMasking)'] %} 1018{% endif %} 1019{% if named_property_getter.has_no_side_effect %} 1020{% set property_handler_flags_list = 1021 property_handler_flags_list + ['int(v8::PropertyHandlerFlags::kHasNoSideEffect)'] %} 1022{% endif %} 1023{% set property_handler_flags = 1024 'static_cast<v8::PropertyHandlerFlags>(%s)' % 1025 ' | '.join(property_handler_flags_list) %} 1026v8::NamedPropertyHandlerConfiguration namedPropertyHandlerConfig({{named_property_getter_callback}}, {{named_property_setter_callback}}, {{named_property_query_callback}}, {{named_property_deleter_callback}}, {{named_property_enumerator_callback}}, v8::Local<v8::Value>(), {{property_handler_flags}}); 1027{{target}}->SetHandler(namedPropertyHandlerConfig); 1028{%- endmacro %} 1029 1030 1031{##############################################################################} 1032{% block get_dom_template %} 1033{% if not is_array_buffer_or_view %} 1034v8::Local<v8::FunctionTemplate> {{v8_class}}::DomTemplate( 1035 v8::Isolate* isolate, const DOMWrapperWorld& world) { 1036 {% set install_template_function = '%s::install_%s_template_function_' % (v8_class, snake_case_v8_class) if has_partial_interface else 'Install%sTemplate' % v8_class %} 1037 return V8DOMConfiguration::DomClassTemplate( 1038 isolate, world, const_cast<WrapperTypeInfo*>({{v8_class}}::GetWrapperTypeInfo()), 1039 {{install_template_function}}); 1040} 1041 1042{% endif %} 1043{% endblock %} 1044 1045 1046{##############################################################################} 1047{% block get_dom_template_for_named_properties_object %} 1048{% if has_named_properties_object %} 1049v8::Local<v8::FunctionTemplate> 1050{{v8_class}}::DomTemplateForNamedPropertiesObject( 1051 v8::Isolate* isolate, const DOMWrapperWorld& world) { 1052 v8::Local<v8::FunctionTemplate> parentTemplate = 1053 V8{{parent_interface}}::DomTemplate(isolate, world); 1054 1055 v8::Local<v8::FunctionTemplate> named_properties_function_template = 1056 v8::FunctionTemplate::New(isolate, 1057 V8ObjectConstructor::IsValidConstructorMode); 1058 named_properties_function_template->SetClassName( 1059 V8AtomicString(isolate, "{{interface_name}}Properties")); 1060 named_properties_function_template->Inherit(parentTemplate); 1061 1062 v8::Local<v8::ObjectTemplate> named_properties_object_template = 1063 named_properties_function_template->PrototypeTemplate(); 1064 named_properties_object_template->SetInternalFieldCount( 1065 {{v8_class}}::kInternalFieldCount); 1066 // Named Properties object has SetPrototype method of Immutable Prototype Exotic Objects 1067 named_properties_object_template->SetImmutableProto(); 1068 V8DOMConfiguration::SetClassString( 1069 isolate, named_properties_object_template, "{{interface_name}}Properties"); 1070 {{install_named_property_handler('named_properties_object_template') | trim | indent(2)}} 1071 1072 return named_properties_function_template; 1073} 1074 1075{% endif %} 1076{% endblock %} 1077 1078 1079{##############################################################################} 1080{% block has_instance %} 1081{% if not is_array_buffer_or_view %} 1082 1083bool {{v8_class}}::HasInstance(v8::Local<v8::Value> v8_value, v8::Isolate* isolate) { 1084 return V8PerIsolateData::From(isolate)->HasInstance({{v8_class}}::GetWrapperTypeInfo(), v8_value); 1085} 1086 1087v8::Local<v8::Object> {{v8_class}}::FindInstanceInPrototypeChain( 1088 v8::Local<v8::Value> v8_value, v8::Isolate* isolate) { 1089 return V8PerIsolateData::From(isolate)->FindInstanceInPrototypeChain( 1090 {{v8_class}}::GetWrapperTypeInfo(), v8_value); 1091} 1092 1093{% endif %} 1094{% endblock %} 1095 1096 1097{##############################################################################} 1098{% block to_impl %} 1099{% if interface_name == 'ArrayBuffer' or interface_name == 'SharedArrayBuffer' %} 1100{{cpp_class}}* V8{{interface_name}}::ToImpl(v8::Local<v8::Object> object) { 1101 DCHECK(object->Is{{interface_name}}()); 1102 v8::Local<v8::{{interface_name}}> v8buffer = object.As<v8::{{interface_name}}>(); 1103 // TODO(ahaas): The use of IsExternal is wrong here. Instead we should call 1104 // ToScriptWrappable(object)->ToImpl<ArrayBuffer>() and check for nullptr. 1105 // We can then also avoid the call to Externalize below. 1106 if (v8buffer->IsExternal()) { 1107 const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(object); 1108 CHECK(wrapper_type); 1109 CHECK_EQ(wrapper_type->gin_embedder, gin::kEmbedderBlink); 1110 return ToScriptWrappable(object)->ToImpl<{{cpp_class}}>(); 1111 } 1112 1113 // Transfer the ownership of the allocated memory to an {{interface_name}} without 1114 // copying. 1115 auto backing_store = v8buffer->GetBackingStore(); 1116 v8buffer->Externalize(backing_store); 1117 ArrayBufferContents contents(std::move(backing_store)); 1118 {{cpp_class}}* buffer = {{cpp_class}}::Create(contents); 1119 v8::Local<v8::Object> associatedWrapper = buffer->AssociateWithWrapper(v8::Isolate::GetCurrent(), buffer->GetWrapperTypeInfo(), object); 1120 DCHECK(associatedWrapper == object); 1121 1122 return buffer; 1123} 1124 1125{% elif interface_name == 'ArrayBufferView' %} 1126{{cpp_class}}* V8ArrayBufferView::ToImpl(v8::Local<v8::Object> object) { 1127 DCHECK(object->IsArrayBufferView()); 1128 ScriptWrappable* script_wrappable = ToScriptWrappable(object); 1129 if (script_wrappable) 1130 return script_wrappable->ToImpl<{{cpp_class}}>(); 1131 1132 if (object->IsInt8Array()) 1133 return V8Int8Array::ToImpl(object); 1134 if (object->IsInt16Array()) 1135 return V8Int16Array::ToImpl(object); 1136 if (object->IsInt32Array()) 1137 return V8Int32Array::ToImpl(object); 1138 if (object->IsUint8Array()) 1139 return V8Uint8Array::ToImpl(object); 1140 if (object->IsUint8ClampedArray()) 1141 return V8Uint8ClampedArray::ToImpl(object); 1142 if (object->IsUint16Array()) 1143 return V8Uint16Array::ToImpl(object); 1144 if (object->IsUint32Array()) 1145 return V8Uint32Array::ToImpl(object); 1146 if (object->IsBigInt64Array()) 1147 return V8BigInt64Array::ToImpl(object); 1148 if (object->IsBigUint64Array()) 1149 return V8BigUint64Array::ToImpl(object); 1150 if (object->IsFloat32Array()) 1151 return V8Float32Array::ToImpl(object); 1152 if (object->IsFloat64Array()) 1153 return V8Float64Array::ToImpl(object); 1154 if (object->IsDataView()) 1155 return V8DataView::ToImpl(object); 1156 1157 NOTREACHED(); 1158 return nullptr; 1159} 1160 1161{% elif is_array_buffer_or_view %} 1162{{cpp_class}}* {{v8_class}}::ToImpl(v8::Local<v8::Object> object) { 1163 DCHECK(object->Is{{interface_name}}()); 1164 ScriptWrappable* script_wrappable = ToScriptWrappable(object); 1165 if (script_wrappable) 1166 return script_wrappable->ToImpl<{{cpp_class}}>(); 1167 1168 v8::Local<v8::{{interface_name}}> v8_view = object.As<v8::{{interface_name}}>(); 1169 v8::Local<v8::Object> array_buffer = v8_view->Buffer(); 1170 {{cpp_class}}* typed_array = nullptr; 1171 if (array_buffer->IsArrayBuffer()) { 1172 typed_array = {{cpp_class}}::Create( 1173 V8ArrayBuffer::ToImpl(array_buffer), 1174 v8_view->ByteOffset(), 1175 v8_view->{% if interface_name == 'DataView' %}Byte{% endif %}Length()); 1176 } else if (array_buffer->IsSharedArrayBuffer()) { 1177 typed_array = {{cpp_class}}::Create( 1178 V8SharedArrayBuffer::ToImpl(array_buffer), 1179 v8_view->ByteOffset(), 1180 v8_view->{% if interface_name == 'DataView' %}Byte{% endif %}Length()); 1181 } else { 1182 NOTREACHED(); 1183 } 1184 v8::Local<v8::Object> associated_wrapper = 1185 typed_array->AssociateWithWrapper( 1186 v8::Isolate::GetCurrent(), typed_array->GetWrapperTypeInfo(), object); 1187 DCHECK(associated_wrapper == object); 1188 1189 return typed_array->ToImpl<{{cpp_class}}>(); 1190} 1191 1192{% endif %} 1193{% endblock %} 1194 1195 1196{##############################################################################} 1197{% block to_impl_with_type_check %} 1198{{cpp_class}}* {{v8_class}}::ToImplWithTypeCheck( 1199 v8::Isolate* isolate, v8::Local<v8::Value> value) { 1200{% if is_array_buffer_or_view %} 1201 return value->Is{{interface_name}}() ? ToImpl(v8::Local<v8::Object>::Cast(value)) : nullptr; 1202{% else %} 1203 return HasInstance(value, isolate) ? ToImpl(v8::Local<v8::Object>::Cast(value)) : nullptr; 1204{% endif %} 1205} 1206 1207{% endblock %} 1208 1209 1210{##############################################################################} 1211{% block partial_interface %} 1212{% if has_partial_interface %} 1213{% if needs_runtime_enabled_installer %} 1214InstallRuntimeEnabledFeaturesFunction 1215{{v8_class}}::install_runtime_enabled_features_function_ = 1216 &{{v8_class}}::InstallRuntimeEnabledFeaturesImpl; 1217{% endif %} 1218{% if not is_array_buffer_or_view %} 1219InstallRuntimeEnabledFeaturesOnTemplateFunction 1220{{v8_class}}::install_runtime_enabled_features_on_template_function_ = 1221 &{{v8_class}}::InstallRuntimeEnabledFeaturesOnTemplate; 1222{% endif %} 1223 1224InstallTemplateFunction 1225{{v8_class}}::install_{{snake_case_v8_class}}_template_function_ = 1226 &{{v8_class}}::Install{{v8_class}}Template; 1227 1228void {{v8_class}}::UpdateWrapperTypeInfo( 1229 InstallTemplateFunction install_template_function, 1230 InstallRuntimeEnabledFeaturesFunction install_runtime_enabled_features_function, 1231 InstallRuntimeEnabledFeaturesOnTemplateFunction install_runtime_enabled_features_on_template_function, 1232 InstallConditionalFeaturesFunction install_conditional_features_function) { 1233 {{v8_class}}::install_{{snake_case_v8_class}}_template_function_ = 1234 install_template_function; 1235 1236 {% if needs_runtime_enabled_installer %} 1237 CHECK(install_runtime_enabled_features_function); 1238 {{v8_class}}::install_runtime_enabled_features_function_ = 1239 install_runtime_enabled_features_function; 1240 1241 {% endif %} 1242 {% if not is_array_buffer_or_view %} 1243 CHECK(install_runtime_enabled_features_on_template_function); 1244 {{v8_class}}::install_runtime_enabled_features_on_template_function_ = 1245 install_runtime_enabled_features_on_template_function; 1246 {% endif %} 1247 1248 if (install_conditional_features_function) { 1249 {{v8_class}}::GetWrapperTypeInfo()->install_conditional_features_function = 1250 install_conditional_features_function; 1251 } 1252} 1253 1254{% for method in methods if method.overloads and method.overloads.has_partial_overloads %} 1255void {{v8_class}}::Register{{method.camel_case_name}}MethodForPartialInterface(void (*method)(const v8::FunctionCallbackInfo<v8::Value>&)) { 1256 {{internal_namespace}}::{{method.name}}MethodForPartialInterface = method; 1257} 1258 1259{% endfor %} 1260{% endif %}{# has_partial_interface #} 1261{% endblock %} 1262