diff options
author | haraken@chromium.org <haraken@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538> | 2014-06-23 13:25:04 +0000 |
---|---|---|
committer | haraken@chromium.org <haraken@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538> | 2014-06-23 13:25:04 +0000 |
commit | ccca08513db5131ce01d4c27d396e4848a30dd79 (patch) | |
tree | c87f1afde0f4eab35af2c4525da3d5c453529eac | |
parent | 14ac194d1141c3896840de5b97941f7289e5aed3 (diff) | |
download | chromium-ccca08513db5131ce01d4c27d396e4848a30dd79.tar.gz chromium-ccca08513db5131ce01d4c27d396e4848a30dd79.tar.bz2 chromium-ccca08513db5131ce01d4c27d396e4848a30dd79.zip |
Implement an infrastructure of Blink-in-JS (The IDL compiler part)
* A design doc is here: https://docs.google.com/a/google.com/document/d/13cT9Klgvt_ciAR3ONGvzKvw6fz9-f6E0FrqYFqfoc8Y/edit
* A full CL is here:
https://codereview.chromium.org/345893002/
* This CL implements the IDL compile part of the Blink-in-JS.
-- IDLExtendedAttributes.txt: Added a [PrivateScriptInterface] IDL extended attribute, which indicates that a given interface is an interface for Blink-in-JS.
-- v8_private_script_interface.py: A code generator for Blink-in-JS' IDL interface.
-- private_script_interface.{h,cpp}: Template files for Blink-in-JS' IDL interface.
-- TestPrivateScriptInterface.idl: Binding tests for a Blink-in-JS' interface.
-- DOMWrapperWorld.{h,cpp}: Added a new dedicated world for Blink-in-JS execution.
* This CL doesn't change any existing behavior, since Blink-in-JS is not yet used by any real code.
BUG=341031
Review URL: https://codereview.chromium.org/331863013
git-svn-id: svn://svn.chromium.org/blink/trunk@176753 bbb929c8-8fbe-4397-9dbb-9b2b20218538
-rw-r--r-- | Source/bindings/IDLExtendedAttributes.txt | 1 | ||||
-rw-r--r-- | Source/bindings/scripts/code_generator_v8.py | 10 | ||||
-rw-r--r-- | Source/bindings/scripts/scripts.gypi | 1 | ||||
-rw-r--r-- | Source/bindings/scripts/v8_callback_interface.py | 14 | ||||
-rw-r--r-- | Source/bindings/scripts/v8_interface.py | 2 | ||||
-rw-r--r-- | Source/bindings/scripts/v8_methods.py | 2 | ||||
-rw-r--r-- | Source/bindings/scripts/v8_private_script_interface.py | 83 | ||||
-rw-r--r-- | Source/bindings/scripts/v8_types.py | 55 | ||||
-rw-r--r-- | Source/bindings/templates/callback_interface.cpp | 1 | ||||
-rw-r--r-- | Source/bindings/templates/private_script_interface.cpp | 60 | ||||
-rw-r--r-- | Source/bindings/templates/private_script_interface.h | 28 | ||||
-rw-r--r-- | Source/bindings/templates/templates.gypi | 2 | ||||
-rw-r--r-- | Source/bindings/tests/idls/TestPrivateScriptInterface.idl | 15 | ||||
-rw-r--r-- | Source/bindings/tests/results/V8TestPrivateScriptInterface.cpp | 178 | ||||
-rw-r--r-- | Source/bindings/tests/results/V8TestPrivateScriptInterface.h | 29 | ||||
-rw-r--r-- | Source/bindings/v8/DOMWrapperWorld.cpp | 11 | ||||
-rw-r--r-- | Source/bindings/v8/DOMWrapperWorld.h | 4 |
17 files changed, 460 insertions, 36 deletions
diff --git a/Source/bindings/IDLExtendedAttributes.txt b/Source/bindings/IDLExtendedAttributes.txt index 4d6bdca28497..b576bf1056a1 100644 --- a/Source/bindings/IDLExtendedAttributes.txt +++ b/Source/bindings/IDLExtendedAttributes.txt @@ -76,6 +76,7 @@ PartialInterfaceImplementedAs=* PerContextEnabled=* PerWorldBindings PrimaryGlobal=|* +PrivateScriptInterface PutForwards=* RaisesException=|Getter|Setter|Constructor ReadOnly diff --git a/Source/bindings/scripts/code_generator_v8.py b/Source/bindings/scripts/code_generator_v8.py index f7af610ccd9a..e7233ebc4f5c 100644 --- a/Source/bindings/scripts/code_generator_v8.py +++ b/Source/bindings/scripts/code_generator_v8.py @@ -75,6 +75,7 @@ from idl_types import IdlType import v8_callback_interface from v8_globals import includes, interfaces import v8_interface +import v8_private_script_interface import v8_types from v8_utilities import capitalize, cpp_name, conditional_string, v8_class_name @@ -130,6 +131,12 @@ class CodeGeneratorV8(object): header_template_filename = 'callback_interface.h' cpp_template_filename = 'callback_interface.cpp' interface_context = v8_callback_interface.callback_interface_context + elif 'PrivateScriptInterface' in interface.extended_attributes: + # Currently private scripts don't have dependencies. Once private scripts have dependencies, + # we should add them to interface_info. + header_template_filename = 'private_script_interface.h' + cpp_template_filename = 'private_script_interface.cpp' + interface_context = v8_private_script_interface.private_script_interface_context else: header_template_filename = 'interface.h' cpp_template_filename = 'interface.cpp' @@ -143,7 +150,8 @@ class CodeGeneratorV8(object): # Add includes for interface itself and any dependencies interface_info = self.interfaces_info[interface_name] - template_context['header_includes'].add(interface_info['include_path']) + if 'PrivateScriptInterface' not in interface.extended_attributes: + template_context['header_includes'].add(interface_info['include_path']) template_context['header_includes'] = sorted(template_context['header_includes']) includes.update(interface_info.get('dependencies_include_paths', [])) template_context['cpp_includes'] = sorted(includes) diff --git a/Source/bindings/scripts/scripts.gypi b/Source/bindings/scripts/scripts.gypi index 9bf033d7eee6..26e6bfdf536b 100644 --- a/Source/bindings/scripts/scripts.gypi +++ b/Source/bindings/scripts/scripts.gypi @@ -38,6 +38,7 @@ 'v8_globals.py', 'v8_interface.py', 'v8_methods.py', + 'v8_private_script_interface.py', 'v8_types.py', 'v8_utilities.py', ], diff --git a/Source/bindings/scripts/v8_callback_interface.py b/Source/bindings/scripts/v8_callback_interface.py index a45edd84f36c..9f5dcbe7dec9 100644 --- a/Source/bindings/scripts/v8_callback_interface.py +++ b/Source/bindings/scripts/v8_callback_interface.py @@ -60,11 +60,11 @@ def cpp_type(idl_type): return 'const String&' if idl_type_name == 'void': return 'void' - # Callbacks use raw pointers, so used_as_argument=True - usual_cpp_type = idl_type.cpp_type_args(used_as_argument=True) - if usual_cpp_type.startswith(('Vector', 'HeapVector', 'WillBeHeapVector')): - return 'const %s&' % usual_cpp_type - return usual_cpp_type + # Callbacks use raw pointers, so raw_type=True + raw_cpp_type = idl_type.cpp_type_args(raw_type=True) + if raw_cpp_type.startswith(('Vector', 'HeapVector', 'WillBeHeapVector')): + return 'const %s&' % raw_cpp_type + return raw_cpp_type IdlType.callback_cpp_type = property(cpp_type) @@ -115,10 +115,6 @@ def arguments_context(arguments, call_with_this_handle): def argument_context(argument): return { 'handle': '%sHandle' % argument.name, - # FIXME: setting creation_context=v8::Handle<v8::Object>() is - # wrong, as toV8 then implicitly uses the current context, which - # causes leaks between isolated worlds if a different context is - # used. 'cpp_value_to_v8_value': argument.idl_type.cpp_value_to_v8_value( argument.name, isolate='isolate', creation_context='m_scriptState->context()->Global()'), diff --git a/Source/bindings/scripts/v8_interface.py b/Source/bindings/scripts/v8_interface.py index d9bd53866c9f..ff6a79842894 100644 --- a/Source/bindings/scripts/v8_interface.py +++ b/Source/bindings/scripts/v8_interface.py @@ -114,7 +114,7 @@ def interface_context(interface): set_wrapper_reference_to_list = [{ 'name': argument.name, # FIXME: properly should be: - # 'cpp_type': argument.idl_type.cpp_type_args(used_as_argument=True), + # 'cpp_type': argument.idl_type.cpp_type_args(raw_type=True), # (if type is non-wrapper type like NodeFilter, normally RefPtr) # Raw pointers faster though, and NodeFilter hacky anyway. 'cpp_type': argument.idl_type.implemented_as + '*', diff --git a/Source/bindings/scripts/v8_methods.py b/Source/bindings/scripts/v8_methods.py index 80fe8d9ecb80..2c6753a13573 100644 --- a/Source/bindings/scripts/v8_methods.py +++ b/Source/bindings/scripts/v8_methods.py @@ -180,7 +180,7 @@ def argument_context(interface, method, argument, index): return { 'cpp_type': idl_type.cpp_type_args(extended_attributes=extended_attributes, - used_as_argument=True, + raw_type=True, used_as_variadic_argument=argument.is_variadic), 'cpp_value': this_cpp_value, # FIXME: check that the default value's type is compatible with the argument's diff --git a/Source/bindings/scripts/v8_private_script_interface.py b/Source/bindings/scripts/v8_private_script_interface.py new file mode 100644 index 000000000000..6ded1d02436f --- /dev/null +++ b/Source/bindings/scripts/v8_private_script_interface.py @@ -0,0 +1,83 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Generate template values for V8PrivateScriptInterface. + +Blink-in-JS design doc: https://docs.google.com/a/google.com/document/d/13cT9Klgvt_ciAR3ONGvzKvw6fz9-f6E0FrqYFqfoc8Y/edit +""" + +from idl_types import IdlType +from v8_globals import includes +import v8_types +import v8_utilities + +BLINK_IN_JS_INTERFACE_H_INCLUDES = frozenset([ + 'bindings/v8/V8Binding.h', +]) + +BLINK_IN_JS_INTERFACE_CPP_INCLUDES = frozenset([ + 'bindings/core/v8/V8Window.h', + 'bindings/v8/PrivateScriptController.h', + 'core/dom/ScriptForbiddenScope.h', + 'core/frame/LocalFrame.h', +]) + + +def private_script_interface_context(private_script_interface): + includes.clear() + includes.update(BLINK_IN_JS_INTERFACE_CPP_INCLUDES) + return { + 'cpp_class': private_script_interface.name, + 'forward_declarations': forward_declarations(private_script_interface), + 'header_includes': set(BLINK_IN_JS_INTERFACE_H_INCLUDES), + 'methods': [method_context(operation) + for operation in private_script_interface.operations], + 'v8_class': v8_utilities.v8_class_name(private_script_interface), + } + + +def forward_declarations(private_script_interface): + declarations = set(['LocalFrame']) + for operation in private_script_interface.operations: + if operation.idl_type.is_wrapper_type: + declarations.add(operation.idl_type.base_type) + for argument in operation.arguments: + if argument.idl_type.is_wrapper_type: + declarations.add(argument.idl_type.base_type) + return sorted(declarations) + + +def method_context(operation): + extended_attributes = operation.extended_attributes + idl_type = operation.idl_type + idl_type_str = str(idl_type) + contents = { + 'cpp_type': idl_type.cpp_type_args(raw_type=True), + 'name': operation.name, + 'v8_value_to_cpp_value': v8_types.v8_value_to_cpp_value( + idl_type, extended_attributes, 'v8Value', 0, + isolate='scriptState->isolate()'), + } + contents.update(arguments_context(operation.arguments, idl_type)) + return contents + + +def arguments_context(arguments, idl_type): + def argument_context(argument): + return { + 'handle': '%sHandle' % argument.name, + 'cpp_value_to_v8_value': argument.idl_type.cpp_value_to_v8_value( + argument.name, isolate='scriptState->isolate()', + creation_context='scriptState->context()->Global()'), + } + + argument_declarations = ['LocalFrame* frame'] + argument_declarations.extend(['%s %s' % (argument.idl_type.cpp_type_args( + used_as_argument=True), argument.name) for argument in arguments]) + if idl_type.name != 'void': + argument_declarations.append('%s* %s' % (idl_type.cpp_type, 'output')) + return { + 'argument_declarations': argument_declarations, + 'arguments': [argument_context(argument) for argument in arguments], + } diff --git a/Source/bindings/scripts/v8_types.py b/Source/bindings/scripts/v8_types.py index 9869a50cb147..81da5487dfb8 100644 --- a/Source/bindings/scripts/v8_types.py +++ b/Source/bindings/scripts/v8_types.py @@ -119,7 +119,7 @@ CPP_SPECIAL_CONVERSION_RULES = { } -def cpp_type(idl_type, extended_attributes=None, used_as_argument=False, used_as_variadic_argument=False, used_in_cpp_sequence=False): +def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_argument=False, used_as_variadic_argument=False, used_in_cpp_sequence=False): """Returns C++ type corresponding to IDL type. |idl_type| argument is of type IdlType, while return value is a string @@ -127,8 +127,12 @@ def cpp_type(idl_type, extended_attributes=None, used_as_argument=False, used_as Args: idl_type: IdlType - used_as_argument: + raw_type: bool, True if idl_type's raw/primitive C++ type should be returned. + used_as_argument: + bool, True if the C++ type is used as an argument of a method. + used_as_variadic_argument: + bool, True if the C++ type is used as a variadic argument of a method. used_in_cpp_sequence: bool, True if the C++ type is used as an element of an array or sequence. """ @@ -166,26 +170,26 @@ def cpp_type(idl_type, extended_attributes=None, used_as_argument=False, used_as return CPP_SPECIAL_CONVERSION_RULES[base_idl_type] if base_idl_type in NON_WRAPPER_TYPES: - return 'RefPtr<%s>' % base_idl_type + return ('PassRefPtr<%s>' if used_as_argument else 'RefPtr<%s>') % base_idl_type if idl_type.is_string_type: - if not used_as_argument: + if not raw_type: return 'String' return 'V8StringResource<%s>' % string_mode() - if idl_type.is_typed_array_type and used_as_argument: + if idl_type.is_typed_array_type and raw_type: return base_idl_type + '*' if idl_type.is_interface_type: implemented_as_class = idl_type.implemented_as - if used_as_argument: + if raw_type: return implemented_as_class + '*' new_type = 'Member' if used_in_cpp_sequence else 'RawPtr' - ptr_type = cpp_ptr_type('RefPtr', new_type, idl_type.gc_type) + ptr_type = cpp_ptr_type(('PassRefPtr' if used_as_argument else 'RefPtr'), new_type, idl_type.gc_type) return cpp_template_type(ptr_type, implemented_as_class) # Default, assume native type is a pointer with same type name as idl type return base_idl_type + '*' -def cpp_type_union(idl_type, extended_attributes=None, used_as_argument=False): +def cpp_type_union(idl_type, extended_attributes=None): return (member_type.cpp_type for member_type in idl_type.member_types) @@ -392,19 +396,22 @@ V8_VALUE_TO_CPP_VALUE = { 'unsigned long long': 'toUInt64({arguments})', # Interface types 'CompareHow': 'static_cast<Range::CompareHow>({v8_value}->Int32Value())', - 'Dictionary': 'Dictionary({v8_value}, info.GetIsolate())', + 'Dictionary': 'Dictionary({v8_value}, {isolate})', 'EventTarget': 'V8DOMWrapper::isDOMWrapper({v8_value}) ? toWrapperTypeInfo(v8::Handle<v8::Object>::Cast({v8_value}))->toEventTarget(v8::Handle<v8::Object>::Cast({v8_value})) : 0', - 'MediaQueryListListener': 'MediaQueryListListener::create(ScriptState::current(info.GetIsolate()), ScriptValue(ScriptState::current(info.GetIsolate()), {v8_value}))', - 'NodeFilter': 'toNodeFilter({v8_value}, info.Holder(), ScriptState::current(info.GetIsolate()))', - 'Promise': 'ScriptPromise::cast(ScriptState::current(info.GetIsolate()), {v8_value})', - 'SerializedScriptValue': 'SerializedScriptValue::create({v8_value}, info.GetIsolate())', - 'ScriptValue': 'ScriptValue(ScriptState::current(info.GetIsolate()), {v8_value})', - 'Window': 'toDOMWindow({v8_value}, info.GetIsolate())', - 'XPathNSResolver': 'toXPathNSResolver({v8_value}, info.GetIsolate())', + 'MediaQueryListListener': 'MediaQueryListListener::create(ScriptState::current({isolate}), ScriptValue(ScriptState::current({isolate}), {v8_value}))', + 'NodeFilter': 'toNodeFilter({v8_value}, info.Holder(), ScriptState::current({isolate}))', + 'Promise': 'ScriptPromise::cast(ScriptState::current({isolate}), {v8_value})', + 'SerializedScriptValue': 'SerializedScriptValue::create({v8_value}, {isolate})', + 'ScriptValue': 'ScriptValue(ScriptState::current({isolate}), {v8_value})', + 'Window': 'toDOMWindow({v8_value}, {isolate})', + 'XPathNSResolver': 'toXPathNSResolver({v8_value}, {isolate})', } -def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index): +def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index, isolate='info.GetIsolate()'): + if idl_type.name == 'void': + return '' + # Composite types array_or_sequence_type = idl_type.array_or_sequence_type if array_or_sequence_type: @@ -430,12 +437,12 @@ def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index): 'V8{idl_type}::toNative(v8::Handle<v8::{idl_type}>::Cast({v8_value})) : 0') else: cpp_expression_format = ( - 'V8{idl_type}::toNativeWithTypeCheck(info.GetIsolate(), {v8_value})') + 'V8{idl_type}::toNativeWithTypeCheck({isolate}, {v8_value})') - return cpp_expression_format.format(arguments=arguments, idl_type=base_idl_type, v8_value=v8_value) + return cpp_expression_format.format(arguments=arguments, idl_type=base_idl_type, v8_value=v8_value, isolate=isolate) -def v8_value_to_cpp_value_array_or_sequence(array_or_sequence_type, v8_value, index): +def v8_value_to_cpp_value_array_or_sequence(array_or_sequence_type, v8_value, index, isolate='info.GetIsolate()'): # Index is None for setters, index (starting at 0) for method arguments, # and is used to provide a human-readable exception message if index is None: @@ -446,19 +453,19 @@ def v8_value_to_cpp_value_array_or_sequence(array_or_sequence_type, v8_value, in array_or_sequence_type.name != 'Dictionary'): this_cpp_type = None ref_ptr_type = cpp_ptr_type('RefPtr', 'Member', array_or_sequence_type.gc_type) - expression_format = '(to{ref_ptr_type}NativeArray<{array_or_sequence_type}, V8{array_or_sequence_type}>({v8_value}, {index}, info.GetIsolate()))' + expression_format = '(to{ref_ptr_type}NativeArray<{array_or_sequence_type}, V8{array_or_sequence_type}>({v8_value}, {index}, {isolate}))' add_includes_for_type(array_or_sequence_type) else: ref_ptr_type = None this_cpp_type = array_or_sequence_type.cpp_type - expression_format = 'toNativeArray<{cpp_type}>({v8_value}, {index}, info.GetIsolate())' - expression = expression_format.format(array_or_sequence_type=array_or_sequence_type.name, cpp_type=this_cpp_type, index=index, ref_ptr_type=ref_ptr_type, v8_value=v8_value) + expression_format = 'toNativeArray<{cpp_type}>({v8_value}, {index}, {isolate})' + expression = expression_format.format(array_or_sequence_type=array_or_sequence_type.name, cpp_type=this_cpp_type, index=index, ref_ptr_type=ref_ptr_type, v8_value=v8_value, isolate=isolate) return expression def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variable_name, index=None, declare_variable=True): """Returns an expression that converts a V8 value to a C++ value and stores it as a local value.""" - this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes, used_as_argument=True) + this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes, raw_type=True) idl_type = idl_type.preprocessed_type cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index) diff --git a/Source/bindings/templates/callback_interface.cpp b/Source/bindings/templates/callback_interface.cpp index ee0201b5007c..1c0b347f7880 100644 --- a/Source/bindings/templates/callback_interface.cpp +++ b/Source/bindings/templates/callback_interface.cpp @@ -57,6 +57,7 @@ namespace WebCore { {% if method.arguments %} v8::Handle<v8::Value> argv[] = { {{method.arguments | join(', ', 'handle')}} }; {% else %} + {# Empty array initializers are illegal, and don't compile in MSVC. #} v8::Handle<v8::Value> *argv = 0; {% endif %} diff --git a/Source/bindings/templates/private_script_interface.cpp b/Source/bindings/templates/private_script_interface.cpp new file mode 100644 index 000000000000..926eb17d3233 --- /dev/null +++ b/Source/bindings/templates/private_script_interface.cpp @@ -0,0 +1,60 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY! + +#include "config.h" +{% filter conditional(conditional_string) %} +#include "{{v8_class}}.h" + +{% for filename in cpp_includes %} +#include "{{filename}}" +{% endfor %} + +namespace WebCore { + +{% for method in methods %} +bool {{v8_class}}::{{method.name}}({{method.argument_declarations | join(', ')}}) +{ + v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld()); + if (context.IsEmpty()) + return false; + ScriptState* scriptState = ScriptState::from(context); + if (!scriptState->executionContext() || !scriptState->domWindow()) + return false; + + ScriptState::Scope scope(scriptState); + v8::Handle<v8::Value> windowWrapper = toV8(scriptState->domWindow(), scriptState->context()->Global(), scriptState->isolate()); + + {% for argument in method.arguments %} + v8::Handle<v8::Value> {{argument.handle}} = {{argument.cpp_value_to_v8_value}}; + {% endfor %} + {% if method.arguments %} + v8::Handle<v8::Value> argv[] = { {{method.arguments | join(', ', 'handle')}} }; + {% else %} + {# Empty array initializers are illegal, and don't compile in MSVC. #} + v8::Handle<v8::Value> *argv = 0; + {% endif %} + // FIXME: Support exceptions thrown from Blink-in-JS. + v8::TryCatch block; + {% if method.v8_value_to_cpp_value %} + v8::Handle<v8::Value> v8Value = PrivateScriptController::run(scriptState, "{{cpp_class}}", "{{method.name}}", windowWrapper, {{method.arguments | length}}, argv); + if (block.HasCaught()) + return false; + ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{method.name}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate()); + {{method.cpp_type}} cppValue = {{method.v8_value_to_cpp_value}}; + if (block.HasCaught()) + return false; + *output = cppValue; + {% else %}{# void return type #} + PrivateScriptController::run(scriptState, "{{cpp_class}}", "{{method.name}}", windowWrapper, {{method.arguments | length}}, argv); + if (block.HasCaught()) + return false; + {% endif %} + return true; +} + +{% endfor %} +} // namespace WebCore +{% endfilter %} diff --git a/Source/bindings/templates/private_script_interface.h b/Source/bindings/templates/private_script_interface.h new file mode 100644 index 000000000000..3842b9092836 --- /dev/null +++ b/Source/bindings/templates/private_script_interface.h @@ -0,0 +1,28 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY! + +#ifndef {{v8_class}}_h +#define {{v8_class}}_h + +{% for filename in header_includes %} +#include "{{filename}}" +{% endfor %} + +namespace WebCore { + +{% for forward_declaration in forward_declarations %} +class {{forward_declaration}}; +{% endfor %} + +class {{v8_class}} { +public: + {% for method in methods %} + static bool {{method.name}}({{method.argument_declarations | join(', ')}}); + {% endfor %} +}; + +} +#endif // {{v8_class}}_h diff --git a/Source/bindings/templates/templates.gypi b/Source/bindings/templates/templates.gypi index a019fab8d285..9e98349a53e7 100644 --- a/Source/bindings/templates/templates.gypi +++ b/Source/bindings/templates/templates.gypi @@ -12,6 +12,8 @@ 'interface.cpp', 'interface.h', 'methods.cpp', + 'private_script_interface.cpp', + 'private_script_interface.h', ], }, } diff --git a/Source/bindings/tests/idls/TestPrivateScriptInterface.idl b/Source/bindings/tests/idls/TestPrivateScriptInterface.idl new file mode 100644 index 000000000000..3de00de4da82 --- /dev/null +++ b/Source/bindings/tests/idls/TestPrivateScriptInterface.idl @@ -0,0 +1,15 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject, + PrivateScriptInterface, +] interface TestPrivateScriptInterface { + static void voidMethod(); + static short shortMethod(); + static short shortMethodWithShortArgument(short value); + static DOMString stringMethodWithStringArgument(DOMString value); + static Node nodeMethodWithNodeArgument(Node value); + static Node nodeMethodWithVariousArguments(Document document, Node node, short value1, double value2, DOMString string); +}; diff --git a/Source/bindings/tests/results/V8TestPrivateScriptInterface.cpp b/Source/bindings/tests/results/V8TestPrivateScriptInterface.cpp new file mode 100644 index 000000000000..25057f942c94 --- /dev/null +++ b/Source/bindings/tests/results/V8TestPrivateScriptInterface.cpp @@ -0,0 +1,178 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file has been auto-generated by code_generator_v8.py. DO NOT MODIFY! + +#include "config.h" +#include "V8TestPrivateScriptInterface.h" + +#include "bindings/core/v8/V8Window.h" +#include "bindings/tests/v8/V8Document.h" +#include "bindings/tests/v8/V8Node.h" +#include "bindings/v8/PrivateScriptController.h" +#include "core/dom/ScriptForbiddenScope.h" +#include "core/frame/LocalFrame.h" + +namespace WebCore { + +bool V8TestPrivateScriptInterface::voidMethod(LocalFrame* frame) +{ + v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld()); + if (context.IsEmpty()) + return false; + ScriptState* scriptState = ScriptState::from(context); + if (!scriptState->executionContext() || !scriptState->domWindow()) + return false; + + ScriptState::Scope scope(scriptState); + v8::Handle<v8::Value> windowWrapper = toV8(scriptState->domWindow(), scriptState->context()->Global(), scriptState->isolate()); + + v8::Handle<v8::Value> *argv = 0; + // FIXME: Support exceptions thrown from Blink-in-JS. + v8::TryCatch block; + PrivateScriptController::run(scriptState, "TestPrivateScriptInterface", "voidMethod", windowWrapper, 0, argv); + if (block.HasCaught()) + return false; + return true; +} + +bool V8TestPrivateScriptInterface::shortMethod(LocalFrame* frame, int* output) +{ + v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld()); + if (context.IsEmpty()) + return false; + ScriptState* scriptState = ScriptState::from(context); + if (!scriptState->executionContext() || !scriptState->domWindow()) + return false; + + ScriptState::Scope scope(scriptState); + v8::Handle<v8::Value> windowWrapper = toV8(scriptState->domWindow(), scriptState->context()->Global(), scriptState->isolate()); + + v8::Handle<v8::Value> *argv = 0; + // FIXME: Support exceptions thrown from Blink-in-JS. + v8::TryCatch block; + v8::Handle<v8::Value> v8Value = PrivateScriptController::run(scriptState, "TestPrivateScriptInterface", "shortMethod", windowWrapper, 0, argv); + if (block.HasCaught()) + return false; + ExceptionState exceptionState(ExceptionState::ExecutionContext, "shortMethod", "TestPrivateScriptInterface", scriptState->context()->Global(), scriptState->isolate()); + int cppValue = toInt16(v8Value, exceptionState); + if (block.HasCaught()) + return false; + *output = cppValue; + return true; +} + +bool V8TestPrivateScriptInterface::shortMethodWithShortArgument(LocalFrame* frame, int value, int* output) +{ + v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld()); + if (context.IsEmpty()) + return false; + ScriptState* scriptState = ScriptState::from(context); + if (!scriptState->executionContext() || !scriptState->domWindow()) + return false; + + ScriptState::Scope scope(scriptState); + v8::Handle<v8::Value> windowWrapper = toV8(scriptState->domWindow(), scriptState->context()->Global(), scriptState->isolate()); + + v8::Handle<v8::Value> valueHandle = v8::Integer::New(scriptState->isolate(), value); + v8::Handle<v8::Value> argv[] = { valueHandle }; + // FIXME: Support exceptions thrown from Blink-in-JS. + v8::TryCatch block; + v8::Handle<v8::Value> v8Value = PrivateScriptController::run(scriptState, "TestPrivateScriptInterface", "shortMethodWithShortArgument", windowWrapper, 1, argv); + if (block.HasCaught()) + return false; + ExceptionState exceptionState(ExceptionState::ExecutionContext, "shortMethodWithShortArgument", "TestPrivateScriptInterface", scriptState->context()->Global(), scriptState->isolate()); + int cppValue = toInt16(v8Value, exceptionState); + if (block.HasCaught()) + return false; + *output = cppValue; + return true; +} + +bool V8TestPrivateScriptInterface::stringMethodWithStringArgument(LocalFrame* frame, String value, String* output) +{ + v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld()); + if (context.IsEmpty()) + return false; + ScriptState* scriptState = ScriptState::from(context); + if (!scriptState->executionContext() || !scriptState->domWindow()) + return false; + + ScriptState::Scope scope(scriptState); + v8::Handle<v8::Value> windowWrapper = toV8(scriptState->domWindow(), scriptState->context()->Global(), scriptState->isolate()); + + v8::Handle<v8::Value> valueHandle = v8String(scriptState->isolate(), value); + v8::Handle<v8::Value> argv[] = { valueHandle }; + // FIXME: Support exceptions thrown from Blink-in-JS. + v8::TryCatch block; + v8::Handle<v8::Value> v8Value = PrivateScriptController::run(scriptState, "TestPrivateScriptInterface", "stringMethodWithStringArgument", windowWrapper, 1, argv); + if (block.HasCaught()) + return false; + ExceptionState exceptionState(ExceptionState::ExecutionContext, "stringMethodWithStringArgument", "TestPrivateScriptInterface", scriptState->context()->Global(), scriptState->isolate()); + V8StringResource<> cppValue = v8Value; + if (block.HasCaught()) + return false; + *output = cppValue; + return true; +} + +bool V8TestPrivateScriptInterface::nodeMethodWithNodeArgument(LocalFrame* frame, PassRefPtrWillBeRawPtr<Node> value, RefPtrWillBeRawPtr<Node>* output) +{ + v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld()); + if (context.IsEmpty()) + return false; + ScriptState* scriptState = ScriptState::from(context); + if (!scriptState->executionContext() || !scriptState->domWindow()) + return false; + + ScriptState::Scope scope(scriptState); + v8::Handle<v8::Value> windowWrapper = toV8(scriptState->domWindow(), scriptState->context()->Global(), scriptState->isolate()); + + v8::Handle<v8::Value> valueHandle = toV8(value, scriptState->context()->Global(), scriptState->isolate()); + v8::Handle<v8::Value> argv[] = { valueHandle }; + // FIXME: Support exceptions thrown from Blink-in-JS. + v8::TryCatch block; + v8::Handle<v8::Value> v8Value = PrivateScriptController::run(scriptState, "TestPrivateScriptInterface", "nodeMethodWithNodeArgument", windowWrapper, 1, argv); + if (block.HasCaught()) + return false; + ExceptionState exceptionState(ExceptionState::ExecutionContext, "nodeMethodWithNodeArgument", "TestPrivateScriptInterface", scriptState->context()->Global(), scriptState->isolate()); + Node* cppValue = V8Node::toNativeWithTypeCheck(scriptState->isolate(), v8Value); + if (block.HasCaught()) + return false; + *output = cppValue; + return true; +} + +bool V8TestPrivateScriptInterface::nodeMethodWithVariousArguments(LocalFrame* frame, PassRefPtrWillBeRawPtr<Document> document, PassRefPtrWillBeRawPtr<Node> node, int value1, double value2, String string, RefPtrWillBeRawPtr<Node>* output) +{ + v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld()); + if (context.IsEmpty()) + return false; + ScriptState* scriptState = ScriptState::from(context); + if (!scriptState->executionContext() || !scriptState->domWindow()) + return false; + + ScriptState::Scope scope(scriptState); + v8::Handle<v8::Value> windowWrapper = toV8(scriptState->domWindow(), scriptState->context()->Global(), scriptState->isolate()); + + v8::Handle<v8::Value> documentHandle = toV8(document, scriptState->context()->Global(), scriptState->isolate()); + v8::Handle<v8::Value> nodeHandle = toV8(node, scriptState->context()->Global(), scriptState->isolate()); + v8::Handle<v8::Value> value1Handle = v8::Integer::New(scriptState->isolate(), value1); + v8::Handle<v8::Value> value2Handle = v8::Number::New(scriptState->isolate(), value2); + v8::Handle<v8::Value> stringHandle = v8String(scriptState->isolate(), string); + v8::Handle<v8::Value> argv[] = { documentHandle, nodeHandle, value1Handle, value2Handle, stringHandle }; + // FIXME: Support exceptions thrown from Blink-in-JS. + v8::TryCatch block; + v8::Handle<v8::Value> v8Value = PrivateScriptController::run(scriptState, "TestPrivateScriptInterface", "nodeMethodWithVariousArguments", windowWrapper, 5, argv); + if (block.HasCaught()) + return false; + ExceptionState exceptionState(ExceptionState::ExecutionContext, "nodeMethodWithVariousArguments", "TestPrivateScriptInterface", scriptState->context()->Global(), scriptState->isolate()); + Node* cppValue = V8Node::toNativeWithTypeCheck(scriptState->isolate(), v8Value); + if (block.HasCaught()) + return false; + *output = cppValue; + return true; +} + +} // namespace WebCore diff --git a/Source/bindings/tests/results/V8TestPrivateScriptInterface.h b/Source/bindings/tests/results/V8TestPrivateScriptInterface.h new file mode 100644 index 000000000000..3371378964e9 --- /dev/null +++ b/Source/bindings/tests/results/V8TestPrivateScriptInterface.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file has been auto-generated by code_generator_v8.py. DO NOT MODIFY! + +#ifndef V8TestPrivateScriptInterface_h +#define V8TestPrivateScriptInterface_h + +#include "bindings/v8/V8Binding.h" + +namespace WebCore { + +class Document; +class LocalFrame; +class Node; + +class V8TestPrivateScriptInterface { +public: + static bool voidMethod(LocalFrame* frame); + static bool shortMethod(LocalFrame* frame, int* output); + static bool shortMethodWithShortArgument(LocalFrame* frame, int value, int* output); + static bool stringMethodWithStringArgument(LocalFrame* frame, String value, String* output); + static bool nodeMethodWithNodeArgument(LocalFrame* frame, PassRefPtrWillBeRawPtr<Node> value, RefPtrWillBeRawPtr<Node>* output); + static bool nodeMethodWithVariousArguments(LocalFrame* frame, PassRefPtrWillBeRawPtr<Document> document, PassRefPtrWillBeRawPtr<Node> node, int value1, double value2, String string, RefPtrWillBeRawPtr<Node>* output); +}; + +} +#endif // V8TestPrivateScriptInterface_h diff --git a/Source/bindings/v8/DOMWrapperWorld.cpp b/Source/bindings/v8/DOMWrapperWorld.cpp index 59cb45057160..dab909b41d80 100644 --- a/Source/bindings/v8/DOMWrapperWorld.cpp +++ b/Source/bindings/v8/DOMWrapperWorld.cpp @@ -67,6 +67,17 @@ DOMWrapperWorld& DOMWrapperWorld::mainWorld() return *cachedMainWorld; } +DOMWrapperWorld& DOMWrapperWorld::privateScriptIsolatedWorld() +{ + ASSERT(isMainThread()); + DEFINE_STATIC_LOCAL(RefPtr<DOMWrapperWorld>, cachedPrivateScriptIsolatedWorld, ()); + if (!cachedPrivateScriptIsolatedWorld) { + cachedPrivateScriptIsolatedWorld = DOMWrapperWorld::create(PrivateScriptIsolatedWorldId, privateScriptIsolatedWorldExtensionGroup); + isolatedWorldCount++; + } + return *cachedPrivateScriptIsolatedWorld; +} + typedef HashMap<int, DOMWrapperWorld*> WorldMap; static WorldMap& isolatedWorldMap() { diff --git a/Source/bindings/v8/DOMWrapperWorld.h b/Source/bindings/v8/DOMWrapperWorld.h index aa294a1fcfb3..582d51e79d2f 100644 --- a/Source/bindings/v8/DOMWrapperWorld.h +++ b/Source/bindings/v8/DOMWrapperWorld.h @@ -51,6 +51,7 @@ enum WorldIdConstants { // Embedder isolated worlds can use IDs in [1, 1<<29). EmbedderWorldIdLimit = (1 << 29), ScriptPreprocessorIsolatedWorldId, + PrivateScriptIsolatedWorldId, IsolatedWorldIdLimit, WorkerWorldId, TestingWorldId, @@ -62,6 +63,7 @@ public: static PassRefPtr<DOMWrapperWorld> create(int worldId = -1, int extensionGroup = -1); static const int mainWorldExtensionGroup = 0; + static const int privateScriptIsolatedWorldExtensionGroup = 1; static PassRefPtr<DOMWrapperWorld> ensureIsolatedWorld(int worldId, int extensionGroup); ~DOMWrapperWorld(); void dispose(); @@ -87,6 +89,7 @@ public: } static DOMWrapperWorld& mainWorld(); + static DOMWrapperWorld& privateScriptIsolatedWorld(); // Associates an isolated world (see above for description) with a security // origin. XMLHttpRequest instances used in that world will be considered @@ -106,6 +109,7 @@ public: bool isolatedWorldHasContentSecurityPolicy(); bool isMainWorld() const { return m_worldId == MainWorldId; } + bool isPrivateScriptIsolatedWorld() const { return m_worldId == PrivateScriptIsolatedWorldId; } bool isWorkerWorld() const { return m_worldId == WorkerWorldId; } bool isIsolatedWorld() const { return MainWorldId < m_worldId && m_worldId < IsolatedWorldIdLimit; } |