Index: Source/bindings/templates/interface.cpp |
diff --git a/Source/bindings/templates/interface.cpp b/Source/bindings/templates/interface.cpp |
index da1bde7c00ad299236e677fce5c95d309024a149..84fbc2fd68ef51ee1e4e4dc71cd7ce57e585ba84 100644 |
--- a/Source/bindings/templates/interface.cpp |
+++ b/Source/bindings/templates/interface.cpp |
@@ -7,7 +7,7 @@ |
'%sV8Internal::%sAttributeGetterCallback' % |
(cpp_class, attribute.name) |
if not attribute.constructor_type else |
- '{0}V8Internal::{0}ConstructorGetter'.format(interface_name) %} |
+ '{0}V8Internal::{0}ConstructorGetter'.format(cpp_class) %} |
{% set getter_callback_for_main_world = |
'%sV8Internal::%sAttributeGetterCallbackForMainWorld' % |
(cpp_class, attribute.name) |
@@ -26,9 +26,24 @@ |
' | '.join(attribute.access_control_list) %} |
{% set property_attribute = 'static_cast<v8::PropertyAttribute>(%s)' % |
' | '.join(attribute.property_attributes) %} |
-{% set on_prototype = ', 0 /* on instance */' |
- if not attribute.is_expose_js_accessors else '' %} |
-{"{{attribute.name}}", {{getter_callback}}, {{setter_callback}}, {{getter_callback_for_main_world}}, {{setter_callback_for_main_world}}, {{wrapper_type_info}}, {{access_control}}, {{property_attribute}}{{on_prototype}}} |
+{% set on_prototype = '1 /* on prototype */' |
+ if interface_name == 'Window' and attribute.idl_type == 'EventHandler' |
+ else '0 /* on instance */' %} |
haraken
2014/02/06 07:57:44
I don't fully understand why we need to treat Even
Nils Barth (inactive)
2014/02/06 08:40:14
Got it; agreed it would be simpler to eliminate th
|
+{% set attribute_configuration_list = [ |
+ '"%s"' % attribute.name, |
+ getter_callback, |
+ setter_callback, |
+ getter_callback_for_main_world, |
+ setter_callback_for_main_world, |
+ wrapper_type_info, |
+ access_control, |
+ property_attribute, |
+ ] %} |
+{% if not attribute.is_expose_js_accessors %} |
+{% set attribute_configuration_list = attribute_configuration_list |
+ + [on_prototype] %} |
+{% endif %} |
+{{'{'}}{{attribute_configuration_list|join(', ')}}{{'}'}} |
{%- endmacro %} |
@@ -46,7 +61,7 @@ |
{##############################################################################} |
{% block constructor_getter %} |
{% if has_constructor_attributes %} |
-static void {{interface_name}}ConstructorGetter(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info) |
+static void {{cpp_class}}ConstructorGetter(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info) |
{ |
v8::Handle<v8::Value> data = info.Data(); |
ASSERT(data->IsExternal()); |
@@ -64,15 +79,24 @@ static void {{interface_name}}ConstructorGetter(v8::Local<v8::String>, const v8: |
{% block replaceable_attribute_setter_and_callback %} |
{% if has_replaceable_attributes or has_constructor_attributes %} |
{# FIXME: rename to ForceSetAttributeOnThis, since also used for Constructors #} |
-static void {{interface_name}}ReplaceableAttributeSetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) |
+static void {{cpp_class}}ReplaceableAttributeSetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) |
{ |
+ {% if is_check_security %} |
+ {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder()); |
+ v8::String::Utf8Value attributeName(name); |
+ ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "{{interface_name}}", info.Holder(), info.GetIsolate()); |
+ if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), exceptionState)) { |
+ exceptionState.throwIfNeeded(); |
+ return; |
+ } |
+ {% endif %} |
info.This()->ForceSet(name, jsValue); |
} |
{# FIXME: rename to ForceSetAttributeOnThisCallback, since also used for Constructors #} |
-static void {{interface_name}}ReplaceableAttributeSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) |
+static void {{cpp_class}}ReplaceableAttributeSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) |
{ |
- {{interface_name}}V8Internal::{{interface_name}}ReplaceableAttributeSetter(name, jsValue, info); |
+ {{cpp_class}}V8Internal::{{cpp_class}}ReplaceableAttributeSetter(name, jsValue, info); |
} |
{% endif %} |
@@ -382,6 +406,8 @@ static void namedPropertySetterCallback(v8::Local<v8::String> name, v8::Local<v8 |
{% block named_property_query %} |
{% if named_property_getter and named_property_getter.is_enumerable and |
not named_property_getter.is_custom_property_query %} |
+{# If there is an enumerator, there MUST be a query method to properly |
+ communicate property attributes. #} |
static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info) |
{ |
{{cpp_class}}* collection = {{v8_class}}::toNative(info.Holder()); |
@@ -699,6 +725,19 @@ void {{v8_class}}::visitDOMWrapper(void* object, const v8::Persistent<v8::Object |
{##############################################################################} |
+{% block shadow_attributes %} |
+{% if interface_name == 'Window' %} |
+static const V8DOMConfiguration::AttributeConfiguration shadowAttributes[] = { |
+ {% for attribute in attributes if attribute.is_unforgeable %} |
+ {{attribute_configuration(attribute)}}, |
+ {% endfor %} |
+}; |
+ |
+{% endif %} |
+{% endblock %} |
+ |
+ |
+{##############################################################################} |
{% block class_attributes %} |
{# FIXME: rename to install_attributes and put into configure_class_template #} |
{% if has_attribute_configuration %} |
@@ -707,7 +746,8 @@ static const V8DOMConfiguration::AttributeConfiguration {{v8_class}}Attributes[] |
if not (attribute.is_expose_js_accessors or |
attribute.is_static or |
attribute.runtime_enabled_function or |
- attribute.per_context_enabled_function) %} |
+ attribute.per_context_enabled_function or |
+ (interface_name == 'Window' and attribute.is_unforgeable)) %} |
haraken
2014/02/06 07:57:44
Do we need interface_name=='Window'?
Nils Barth (inactive)
2014/02/06 08:40:14
Yes - this is exactly the shadowAttributes, direct
|
{% filter conditional(attribute.conditional_string) %} |
{{attribute_configuration(attribute)}}, |
{% endfilter %} |
@@ -813,6 +853,22 @@ void {{v8_class}}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value> |
{##############################################################################} |
+{% block configure_shadow_object_template %} |
+{% if interface_name == 'Window' %} |
+static void configureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ, v8::Isolate* isolate, WrapperWorldType currentWorldType) |
+{ |
+ V8DOMConfiguration::installAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttributes, WTF_ARRAY_LENGTH(shadowAttributes), isolate, currentWorldType); |
+ |
+ // Install a security handler with V8. |
+ templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&V8Window::wrapperTypeInfo))); |
+ templ->SetInternalFieldCount(V8Window::internalFieldCount); |
+} |
+ |
+{% endif %} |
+{% endblock %} |
+ |
+ |
+{##############################################################################} |
{% block configure_class_template %} |
{# FIXME: rename to install_dom_template and Install{{v8_class}}DOMTemplate #} |
static void configure{{v8_class}}Template(v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Isolate* isolate, WrapperWorldType currentWorldType) |
@@ -860,7 +916,9 @@ static void configure{{v8_class}}Template(v8::Handle<v8::FunctionTemplate> funct |
instanceTemplate->SetAccessCheckCallbacks({{cpp_class}}V8Internal::namedSecurityCheck, {{cpp_class}}V8Internal::indexedSecurityCheck, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&{{v8_class}}::wrapperTypeInfo))); |
{% endif %} |
{% for attribute in attributes |
- if attribute.runtime_enabled_function and not attribute.is_static %} |
+ if attribute.runtime_enabled_function and |
+ not attribute.per_context_enabled_function and |
+ not attribute.is_static %} |
{% filter conditional(attribute.conditional_string) %} |
if ({{attribute.runtime_enabled_function}}()) { |
static const V8DOMConfiguration::AttributeConfiguration attributeConfiguration =\ |
@@ -872,6 +930,14 @@ static void configure{{v8_class}}Template(v8::Handle<v8::FunctionTemplate> funct |
{% if constants %} |
{{install_constants() | indent}} |
{% endif %} |
+ {# Special operations #} |
+ {# V8 has access-check callback API and it's used on Window instead of |
+ deleters or enumerators; see ObjectTemplate::SetAccessCheckCallbacks. |
+ In addition, the getter should be set on the prototype template, to get |
+ the implementation straight out of the Window prototype, regardless of |
+ what prototype is actually set on the object. #} |
+ {% set set_on_template = 'PrototypeTemplate' if interface_name == 'Window' |
+ else 'InstanceTemplate' %} |
{% if indexed_property_getter %} |
{# if have indexed properties, MUST have an indexed property getter #} |
{% set indexed_property_getter_callback = |
@@ -886,7 +952,7 @@ static void configure{{v8_class}}Template(v8::Handle<v8::FunctionTemplate> funct |
{% set indexed_property_enumerator_callback = |
'indexedPropertyEnumerator<%s>' % cpp_class |
if indexed_property_getter.is_enumerable else '0' %} |
- functionTemplate->InstanceTemplate()->SetIndexedPropertyHandler({{indexed_property_getter_callback}}, {{indexed_property_setter_callback}}, {{indexed_property_query_callback}}, {{indexed_property_deleter_callback}}, {{indexed_property_enumerator_callback}}); |
+ functionTemplate->{{set_on_template}}()->SetIndexedPropertyHandler({{indexed_property_getter_callback}}, {{indexed_property_setter_callback}}, {{indexed_property_query_callback}}, {{indexed_property_deleter_callback}}, {{indexed_property_enumerator_callback}}); |
{% endif %} |
{% if named_property_getter %} |
{# if have named properties, MUST have a named property getter #} |
@@ -904,8 +970,9 @@ static void configure{{v8_class}}Template(v8::Handle<v8::FunctionTemplate> funct |
{% set named_property_enumerator_callback = |
'%sV8Internal::namedPropertyEnumeratorCallback' % cpp_class |
if named_property_getter.is_enumerable else '0' %} |
- functionTemplate->InstanceTemplate()->SetNamedPropertyHandler({{named_property_getter_callback}}, {{named_property_setter_callback}}, {{named_property_query_callback}}, {{named_property_deleter_callback}}, {{named_property_enumerator_callback}}); |
+ functionTemplate->{{set_on_template}}()->SetNamedPropertyHandler({{named_property_getter_callback}}, {{named_property_setter_callback}}, {{named_property_query_callback}}, {{named_property_deleter_callback}}, {{named_property_enumerator_callback}}); |
{% endif %} |
+ {# End special operations #} |
{% if has_custom_legacy_call_as_function %} |
functionTemplate->InstanceTemplate()->SetCallAsFunctionHandler({{v8_class}}::legacyCallCustom); |
{% endif %} |
@@ -1131,6 +1198,38 @@ EventTarget* {{v8_class}}::toEventTarget(v8::Handle<v8::Object> object) |
{##############################################################################} |
+{% block get_shadow_object_template %} |
+{% if interface_name == 'Window' %} |
+v8::Handle<v8::ObjectTemplate> V8Window::getShadowObjectTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType) |
+{ |
+ if (currentWorldType == MainWorld) { |
+ DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForMainWorld, ()); |
+ if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) { |
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); |
+ v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); |
+ configureShadowObjectTemplate(templ, isolate, currentWorldType); |
+ V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ); |
+ return templ; |
+ } |
+ return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForMainWorld); |
+ } else { |
+ DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForNonMainWorld, ()); |
+ if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) { |
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); |
+ v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); |
+ configureShadowObjectTemplate(templ, isolate, currentWorldType); |
+ V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ); |
+ return templ; |
+ } |
+ return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForNonMainWorld); |
+ } |
+} |
+ |
+{% endif %} |
+{% endblock %} |
+ |
+ |
+{##############################################################################} |
{% block wrap %} |
{% if special_wrap_for or is_document %} |
v8::Handle<v8::Object> wrap({{cpp_class}}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |