Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(486)

Unified Diff: webkit/port/bindings/v8/v8_proxy.cpp

Issue 42634: Revert change 12507 and 12532 because it breaks the ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/port/bindings/v8/v8_proxy.h ('k') | webkit/webkit.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/port/bindings/v8/v8_proxy.cpp
===================================================================
--- webkit/port/bindings/v8/v8_proxy.cpp (revision 12533)
+++ webkit/port/bindings/v8/v8_proxy.cpp (working copy)
@@ -36,6 +36,7 @@
#include <v8-debug.h>
#include "v8_proxy.h"
+#include "dom_wrapper_map.h"
#include "v8_index.h"
#include "v8_binding.h"
#include "v8_custom.h"
@@ -44,12 +45,206 @@
#include "V8DOMWindow.h"
#include "ChromiumBridge.h"
-#include "DOMObjectsInclude.h"
+#include "BarInfo.h"
+#include "CanvasGradient.h"
+#include "CanvasPattern.h"
+#include "CanvasPixelArray.h"
+#include "CanvasRenderingContext2D.h"
+#include "CanvasStyle.h"
+#include "CharacterData.h"
+#include "ClientRect.h"
+#include "ClientRectList.h"
+#include "Clipboard.h"
+#include "Console.h"
+#include "Counter.h"
+#include "CSSCharsetRule.h"
+#include "CSSFontFaceRule.h"
+#include "CSSImportRule.h"
+#include "CSSMediaRule.h"
+#include "CSSPageRule.h"
+#include "CSSRule.h"
+#include "CSSRuleList.h"
+#include "CSSValueList.h"
+#include "CSSStyleRule.h"
+#include "CSSStyleSheet.h"
+#include "CSSVariablesDeclaration.h"
+#include "CSSVariablesRule.h"
+#include "Database.h"
+#include "DocumentType.h"
+#include "DocumentFragment.h"
+#include "DOMCoreException.h"
+#include "DOMImplementation.h"
+#include "DOMParser.h"
+#include "DOMSelection.h"
+#include "DOMStringList.h"
+#include "DOMWindow.h"
+#include "Entity.h"
+#include "EventListener.h"
+#include "EventTarget.h"
+#include "Event.h"
+#include "EventException.h"
+#include "ExceptionCode.h"
+#include "File.h"
+#include "FileList.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameTree.h"
+#include "History.h"
+#include "HTMLNames.h"
+#include "HTMLDocument.h"
+#include "HTMLElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLSelectElement.h"
+#include "HTMLOptionsCollection.h"
+#include "ImageData.h"
+#include "InspectorController.h"
+#include "KeyboardEvent.h"
+#include "Location.h"
+#include "MediaError.h"
+#include "MediaList.h"
+#include "MediaPlayer.h"
+#include "MessageChannel.h"
+#include "MessageEvent.h"
+#include "MessagePort.h"
+#include "MimeTypeArray.h"
+#include "MouseEvent.h"
+#include "MutationEvent.h"
+#include "Navigator.h" // for MimeTypeArray
+#include "NodeFilter.h"
+#include "Notation.h"
+#include "NodeList.h"
+#include "NodeIterator.h"
+#include "OverflowEvent.h"
+#include "Page.h"
+#include "Plugin.h"
+#include "PluginArray.h"
+#include "ProcessingInstruction.h"
+#include "ProgressEvent.h"
+#include "Range.h"
+#include "RangeException.h"
+#include "Rect.h"
+#include "RGBColor.h"
+#include "Screen.h"
+#include "ScriptExecutionContext.h"
+#include "SecurityOrigin.h"
+#include "Settings.h"
+#include "SQLTransaction.h"
+#include "SQLResultSet.h"
+#include "SQLResultSetRowList.h"
+#include "StyleSheet.h"
+#include "StyleSheetList.h"
+#include "SVGColor.h"
+#include "SVGPaint.h"
+#include "TextEvent.h"
+#include "TextMetrics.h"
+#include "TimeRanges.h"
+#include "TreeWalker.h"
+#include "XSLTProcessor.h"
+#include "V8AbstractEventListener.h"
+#include "V8CustomEventListener.h"
+#include "V8DOMWindow.h"
+#include "V8HTMLElement.h"
+#include "V8LazyEventListener.h"
+#include "V8ObjectEventListener.h"
+#include "WebKitAnimationEvent.h"
+#include "WebKitCSSKeyframeRule.h"
+#include "WebKitCSSKeyframesRule.h"
+#include "WebKitCSSMatrix.h"
+#include "WebKitCSSTransformValue.h"
+#include "WebKitPoint.h"
+#include "WebKitTransitionEvent.h"
+#include "WheelEvent.h"
+#include "XMLHttpRequest.h"
+#include "XMLHttpRequestException.h"
+#include "XMLHttpRequestProgressEvent.h"
+#include "XMLHttpRequestUpload.h"
+#include "XMLSerializer.h"
+#include "XPathException.h"
+#include "XPathExpression.h"
+#include "XPathNSResolver.h"
+#include "XPathResult.h"
+
+
#include "ScriptController.h"
+#if ENABLE(SVG)
+#include "SVGAngle.h"
+#include "SVGAnimatedPoints.h"
+#include "SVGElement.h"
+#include "SVGElementInstance.h"
+#include "SVGElementInstanceList.h"
+#include "SVGException.h"
+#include "SVGLength.h"
+#include "SVGLengthList.h"
+#include "SVGNumberList.h"
+#include "SVGPathSeg.h"
+#include "SVGPathSegArc.h"
+#include "SVGPathSegClosePath.h"
+#include "SVGPathSegCurvetoCubic.h"
+#include "SVGPathSegCurvetoCubicSmooth.h"
+#include "SVGPathSegCurvetoQuadratic.h"
+#include "SVGPathSegCurvetoQuadraticSmooth.h"
+#include "SVGPathSegLineto.h"
+#include "SVGPathSegLinetoHorizontal.h"
+#include "SVGPathSegLinetoVertical.h"
+#include "SVGPathSegList.h"
+#include "SVGPathSegMoveto.h"
+#include "SVGPointList.h"
+#include "SVGPreserveAspectRatio.h"
+#include "SVGRenderingIntent.h"
+#include "SVGStringList.h"
+#include "SVGTransform.h"
+#include "SVGTransformList.h"
+#include "SVGUnitTypes.h"
+#include "SVGURIReference.h"
+#include "SVGZoomEvent.h"
+#include "V8SVGPODTypeWrapper.h"
+#endif // SVG
+
+#if ENABLE(WORKERS)
+#include "Worker.h"
+#include "WorkerContext.h"
+#include "WorkerLocation.h"
+#include "WorkerNavigator.h"
+#endif // WORKERS
+
+#if ENABLE(XPATH)
+#include "XPathEvaluator.h"
+#endif
+
+
namespace WebCore {
+
+// DOM binding algorithm:
+//
+// There are two kinds of DOM objects:
+// 1. DOM tree nodes, such as Document, HTMLElement, ...
+// there classes implements TreeShared<T> interface;
+// 2. Non-node DOM objects, such as CSSRule, Location, etc.
+// these classes implement a ref-counted scheme.
+//
+// A DOM object may have a JS wrapper object. If a tree node
+// is alive, its JS wrapper must be kept alive even it is not
+// reachable from JS roots.
+// However, JS wrappers of non-node objects can go away if
+// not reachable from other JS objects. It works like a cache.
+//
+// DOM objects are ref-counted, and JS objects are traced from
+// a set of root objects. They can create a cycle. To break
+// cycles, we do following:
+// Handles from DOM objects to JS wrappers are always weak,
+// so JS wrappers of non-node object cannot create a cycle.
+// Before starting a global GC, we create a virtual connection
+// between nodes in the same tree in the JS heap. If the wrapper
+// of one node in a tree is alive, wrappers of all nodes in
+// the same tree are considered alive. This is done by creating
+// object groups in GC prologue callbacks. The mark-compact
+// collector will remove these groups after each GC.
+
+
// Static utility context.
v8::Persistent<v8::Context> V8Proxy::m_utilityContext;
@@ -57,6 +252,10 @@
V8ExtensionList V8Proxy::m_extensions;
+// A helper class for undetectable document.all
+class UndetectableHTMLCollection : public HTMLCollection {
+};
+
#ifndef NDEBUG
// Keeps track of global handles created (not JS wrappers
// of DOM objects). Often these global handles are source
@@ -186,14 +385,66 @@
}
#endif // NDEBUG
+static void WeakDOMObjectCallback(v8::Persistent<v8::Value> obj, void* para);
+static void WeakActiveDOMObjectCallback(v8::Persistent<v8::Value> obj,
+ void* para);
+static void WeakNodeCallback(v8::Persistent<v8::Value> obj, void* para);
+// A map from DOM node to its JS wrapper.
+static DOMWrapperMap<Node>& GetDOMNodeMap()
+{
+ static DOMWrapperMap<Node> static_dom_node_map(&WeakNodeCallback);
+ return static_dom_node_map;
+}
+
+
+// A map from a DOM object (non-node) to its JS wrapper. This map does not
+// contain the DOM objects which can have pending activity (active dom objects).
+DOMWrapperMap<void>& GetDOMObjectMap()
+{
+ static DOMWrapperMap<void>
+ static_dom_object_map(&WeakDOMObjectCallback);
+ return static_dom_object_map;
+}
+
+
+// A map from a DOM object to its JS wrapper for DOM objects which
+// can have pending activity.
+static DOMWrapperMap<void>& GetActiveDOMObjectMap()
+{
+ static DOMWrapperMap<void>
+ static_active_dom_object_map(&WeakActiveDOMObjectCallback);
+ return static_active_dom_object_map;
+}
+
#if ENABLE(SVG)
+static void WeakSVGElementInstanceCallback(v8::Persistent<v8::Value> obj,
+ void* param);
+
+// A map for SVGElementInstances.
+static DOMWrapperMap<SVGElementInstance>& dom_svg_element_instance_map()
+{
+ static DOMWrapperMap<SVGElementInstance>
+ static_dom_svg_element_instance_map(&WeakSVGElementInstanceCallback);
+ return static_dom_svg_element_instance_map;
+}
+
+static void WeakSVGElementInstanceCallback(v8::Persistent<v8::Value> obj,
+ void* param)
+{
+ SVGElementInstance* instance = static_cast<SVGElementInstance*>(param);
+ ASSERT(dom_svg_element_instance_map().contains(instance));
+
+ instance->deref();
+ dom_svg_element_instance_map().forget(instance);
+}
+
v8::Handle<v8::Value> V8Proxy::SVGElementInstanceToV8Object(
SVGElementInstance* instance)
{
if (!instance)
return v8::Null();
- v8::Handle<v8::Object> existing_instance = getDOMSVGElementInstanceMap().get(instance);
+ v8::Handle<v8::Object> existing_instance = dom_svg_element_instance_map().get(instance);
if (!existing_instance.IsEmpty())
return existing_instance;
@@ -206,12 +457,32 @@
instance);
if (!result.IsEmpty()) {
// Only update the DOM SVG element map if the result is non-empty.
- getDOMSVGElementInstanceMap().set(instance,
+ dom_svg_element_instance_map().set(instance,
v8::Persistent<v8::Object>::New(result));
}
return result;
}
+
+// SVG non-node elements may have a reference to a context node which
+// should be notified when the element is change
+static void WeakSVGObjectWithContext(v8::Persistent<v8::Value> obj,
+ void* dom_obj);
+
+// Map of SVG objects with contexts to V8 objects
+static DOMWrapperMap<void>& dom_svg_object_with_context_map() {
+ static DOMWrapperMap<void>
+ static_dom_svg_object_with_context_map(&WeakSVGObjectWithContext);
+ return static_dom_svg_object_with_context_map;
+}
+
+// Map of SVG objects with contexts to their contexts
+static HashMap<void*, SVGElement*>& svg_object_to_context_map()
+{
+ static HashMap<void*, SVGElement*> static_svg_object_to_context_map;
+ return static_svg_object_to_context_map;
+}
+
v8::Handle<v8::Value> V8Proxy::SVGObjectWithContextToV8Object(
V8ClassIndex::V8WrapperType type, void* object)
{
@@ -219,7 +490,7 @@
return v8::Null();
v8::Persistent<v8::Object> result =
- getDOMSVGObjectWithContextMap().get(object);
+ dom_svg_object_with_context_map().get(object);
if (!result.IsEmpty()) return result;
// Special case: SVGPathSegs need to be downcast to their real type
@@ -242,16 +513,38 @@
default:
ASSERT(false);
}
- getDOMSVGObjectWithContextMap().set(object, result);
+ dom_svg_object_with_context_map().set(object, result);
}
return result;
}
-// Map of SVG objects with contexts to their contexts
-static HashMap<void*, SVGElement*>& svg_object_to_context_map() {
- static HashMap<void*, SVGElement*> static_svg_object_to_context_map;
- return static_svg_object_to_context_map;
+static void WeakSVGObjectWithContext(v8::Persistent<v8::Value> obj,
+ void* dom_obj)
+{
+ v8::HandleScope handle_scope;
+ ASSERT(dom_svg_object_with_context_map().contains(dom_obj));
+ ASSERT(obj->IsObject());
+
+ // Forget function removes object from the map and dispose the wrapper.
+ dom_svg_object_with_context_map().forget(dom_obj);
+
+ V8ClassIndex::V8WrapperType type =
+ V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
+
+ switch (type) {
+#define MAKE_CASE(TYPE, NAME) \
+ case V8ClassIndex::TYPE: static_cast<NAME*>(dom_obj)->deref(); break;
+SVG_OBJECT_TYPES(MAKE_CASE)
+#undef MAKE_CASE
+#define MAKE_CASE(TYPE, NAME) \
+ case V8ClassIndex::TYPE: \
+ static_cast<V8SVGPODTypeWrapper<NAME>*>(dom_obj)->deref(); break;
+SVG_POD_NATIVE_TYPES(MAKE_CASE)
+#undef MAKE_CASE
+ default:
+ ASSERT(false);
+ }
}
void V8Proxy::SetSVGContext(void* obj, SVGElement* context)
@@ -274,8 +567,66 @@
{
return svg_object_to_context_map().get(obj);
}
+
#endif
+// Called when obj is near death (not reachable from JS roots)
+// It is time to remove the entry from the table and dispose
+// the handle.
+static void WeakDOMObjectCallback(v8::Persistent<v8::Value> obj,
+ void* dom_obj) {
+ v8::HandleScope scope;
+ ASSERT(GetDOMObjectMap().contains(dom_obj));
+ ASSERT(obj->IsObject());
+
+ // Forget function removes object from the map and dispose the wrapper.
+ GetDOMObjectMap().forget(dom_obj);
+
+ V8ClassIndex::V8WrapperType type =
+ V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
+ switch (type) {
+#define MAKE_CASE(TYPE, NAME) \
+ case V8ClassIndex::TYPE: static_cast<NAME*>(dom_obj)->deref(); break;
+ DOM_OBJECT_TYPES(MAKE_CASE)
+#undef MAKE_CASE
+ default:
+ ASSERT(false);
+ }
+}
+
+
+static void WeakActiveDOMObjectCallback(v8::Persistent<v8::Value> obj,
+ void* dom_obj)
+{
+ v8::HandleScope scope;
+ ASSERT(GetActiveDOMObjectMap().contains(dom_obj));
+ ASSERT(obj->IsObject());
+
+ // Forget function removes object from the map and dispose the wrapper.
+ GetActiveDOMObjectMap().forget(dom_obj);
+
+ V8ClassIndex::V8WrapperType type =
+ V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj));
+ switch (type) {
+#define MAKE_CASE(TYPE, NAME) \
+ case V8ClassIndex::TYPE: static_cast<NAME*>(dom_obj)->deref(); break;
+ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
+#undef MAKE_CASE
+ default:
+ ASSERT(false);
+ }
+}
+
+static void WeakNodeCallback(v8::Persistent<v8::Value> obj, void* param)
+{
+ Node* node = static_cast<Node*>(param);
+ ASSERT(GetDOMNodeMap().contains(node));
+
+ GetDOMNodeMap().forget(node);
+ node->deref();
+}
+
+
// A map from a DOM node to its JS wrapper, the wrapper
// is kept as a strong reference to survive GCs.
static DOMObjectMap& gc_protected_map() {
@@ -290,11 +641,11 @@
return;
if (gc_protected_map().contains(dom_object))
return;
- if (!getDOMObjectMap().contains(dom_object))
+ if (!GetDOMObjectMap().contains(dom_object))
return;
// Create a new (strong) persistent handle for the object.
- v8::Persistent<v8::Object> wrapper = getDOMObjectMap().get(dom_object);
+ v8::Persistent<v8::Object> wrapper = GetDOMObjectMap().get(dom_object);
if (wrapper.IsEmpty()) return;
gc_protected_map().set(dom_object, *v8::Persistent<v8::Object>::New(wrapper));
@@ -321,12 +672,12 @@
v8::HandleScope scope;
#ifndef NDEBUG
- EnumerateDOMObjectMap(getDOMObjectMap().impl());
+ EnumerateDOMObjectMap(GetDOMObjectMap().impl());
#endif
// Run through all objects with possible pending activity making their
// wrappers non weak if there is pending activity.
- DOMObjectMap active_map = getActiveDOMObjectMap().impl();
+ DOMObjectMap active_map = GetActiveDOMObjectMap().impl();
for (DOMObjectMap::iterator it = active_map.begin(), end = active_map.end();
it != end; ++it) {
void* obj = it->first;
@@ -389,7 +740,7 @@
typedef std::pair<uintptr_t, Node*> GrouperPair;
typedef Vector<GrouperPair> GrouperList;
- DOMNodeMap node_map = getDOMNodeMap().impl();
+ DOMNodeMap node_map = GetDOMNodeMap().impl();
GrouperList grouper;
grouper.reserveCapacity(node_map.size());
@@ -455,7 +806,7 @@
group.reserveCapacity(next_key_index - i);
for (; i < next_key_index; ++i) {
v8::Persistent<v8::Value> wrapper =
- getDOMNodeMap().get(grouper[i].second);
+ GetDOMNodeMap().get(grouper[i].second);
if (!wrapper.IsEmpty())
group.append(wrapper);
}
@@ -474,7 +825,7 @@
// Run through all objects with pending activity making their wrappers weak
// again.
- DOMObjectMap active_map = getActiveDOMObjectMap().impl();
+ DOMObjectMap active_map = GetActiveDOMObjectMap().impl();
for (DOMObjectMap::iterator it = active_map.begin(), end = active_map.end();
it != end; ++it) {
void* obj = it->first;
@@ -486,7 +837,7 @@
NAME* impl = static_cast<NAME*>(obj); \
if (impl->hasPendingActivity()) { \
ASSERT(!wrapper.IsWeak()); \
- wrapper.MakeWeak(impl, &weakActiveDOMObjectCallback); \
+ wrapper.MakeWeak(impl, &WeakActiveDOMObjectCallback); \
} \
break; \
}
@@ -499,8 +850,8 @@
#ifndef NDEBUG
// Check all survivals are weak.
- EnumerateDOMObjectMap(getDOMObjectMap().impl());
- EnumerateDOMNodeMap(getDOMNodeMap().impl());
+ EnumerateDOMObjectMap(GetDOMObjectMap().impl());
+ EnumerateDOMNodeMap(GetDOMNodeMap().impl());
EnumerateDOMObjectMap(gc_protected_map());
EnumerateGlobalHandles();
#undef USE_VAR
@@ -762,8 +1113,8 @@
bool V8Proxy::DOMObjectHasJSWrapper(void* obj) {
- return getDOMObjectMap().contains(obj) ||
- getActiveDOMObjectMap().contains(obj);
+ return GetDOMObjectMap().contains(obj) ||
+ GetActiveDOMObjectMap().contains(obj);
}
@@ -781,7 +1132,7 @@
default: break;
}
#endif
- getDOMObjectMap().set(obj, wrapper);
+ GetDOMObjectMap().set(obj, wrapper);
}
// The caller must have increased obj's ref count.
@@ -797,14 +1148,14 @@
#undef MAKE_CASE
}
#endif
- getActiveDOMObjectMap().set(obj, wrapper);
+ GetActiveDOMObjectMap().set(obj, wrapper);
}
// The caller must have increased node's ref count.
void V8Proxy::SetJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper)
{
ASSERT(MaybeDOMWrapper(wrapper));
- getDOMNodeMap().set(node, wrapper);
+ GetDOMNodeMap().set(node, wrapper);
}
PassRefPtr<EventListener> V8Proxy::createInlineEventListener(
@@ -2281,8 +2632,8 @@
// Non DOM node
v8::Persistent<v8::Object> result = is_active_dom_object ?
- getActiveDOMObjectMap().get(imp) :
- getDOMObjectMap().get(imp);
+ GetActiveDOMObjectMap().get(imp) :
+ GetDOMObjectMap().get(imp);
if (result.IsEmpty()) {
v8::Local<v8::Object> v8obj = InstantiateV8Object(type, type, imp);
if (!v8obj.IsEmpty()) {
@@ -2752,7 +3103,7 @@
if (!event)
return v8::Null();
- v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event);
+ v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(event);
if (!wrapper.IsEmpty())
return wrapper;
@@ -2811,7 +3162,7 @@
{
if (!node) return v8::Null();
- v8::Handle<v8::Object> wrapper = getDOMNodeMap().get(node);
+ v8::Handle<v8::Object> wrapper = GetDOMNodeMap().get(node);
if (!wrapper.IsEmpty())
return wrapper;
@@ -2957,7 +3308,7 @@
// XMLHttpRequest is created within its JS counterpart.
XMLHttpRequest* xhr = target->toXMLHttpRequest();
if (xhr) {
- v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xhr);
+ v8::Handle<v8::Object> wrapper = GetActiveDOMObjectMap().get(xhr);
ASSERT(!wrapper.IsEmpty());
return wrapper;
}
@@ -2965,14 +3316,14 @@
// MessagePort is created within its JS counterpart
MessagePort* port = target->toMessagePort();
if (port) {
- v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port);
+ v8::Handle<v8::Object> wrapper = GetActiveDOMObjectMap().get(port);
ASSERT(!wrapper.IsEmpty());
return wrapper;
}
XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload();
if (upload) {
- v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload);
+ v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(upload);
ASSERT(!wrapper.IsEmpty());
return wrapper;
}
@@ -3014,7 +3365,7 @@
{
if (!sheet) return v8::Null();
- v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(sheet);
+ v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(sheet);
if (!wrapper.IsEmpty())
return wrapper;
@@ -3046,7 +3397,7 @@
{
if (!value) return v8::Null();
- v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(value);
+ v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(value);
if (!wrapper.IsEmpty())
return wrapper;
@@ -3083,7 +3434,7 @@
{
if (!rule) return v8::Null();
- v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(rule);
+ v8::Handle<v8::Object> wrapper = GetDOMObjectMap().get(rule);
if (!wrapper.IsEmpty())
return wrapper;
« no previous file with comments | « webkit/port/bindings/v8/v8_proxy.h ('k') | webkit/webkit.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698