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

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

Issue 3195: Use static type information from IDL to streamline the wrapping and unwrappin... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 3 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
« webkit/port/bindings/v8/v8_proxy.h ('K') | « webkit/port/bindings/v8/v8_proxy.h ('k') | no next file » | 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 2436)
+++ webkit/port/bindings/v8/v8_proxy.cpp (working copy)
@@ -291,9 +291,9 @@
dom_svg_element_instance_map().forget(instance);
}
-v8::Handle<v8::Object> V8Proxy::SVGElementInstanceToV8Object(
+v8::Handle<v8::Value> V8Proxy::SVGElementInstanceToV8Object(
SVGElementInstance* instance) {
- if (!instance) return v8::Handle<v8::Object>();
+ if (!instance) return v8::Null();
v8::Handle<v8::Object> existing_instance =
dom_svg_element_instance_map().get(instance);
@@ -305,7 +305,9 @@
// Instantiate the V8 object and remember it
v8::Handle<v8::Object> result =
- InstantiateV8Object(V8ClassIndex::SVGELEMENTINSTANCE, instance);
+ InstantiateV8Object(V8ClassIndex::SVGELEMENTINSTANCE,
+ V8ClassIndex::SVGELEMENTINSTANCE,
+ instance);
if (!result.IsEmpty()) {
// Only update the DOM SVG element map if the result is non-empty.
dom_svg_element_instance_map().set(instance,
@@ -332,9 +334,9 @@
return static_svg_object_to_context_map;
}
-v8::Handle<v8::Object> V8Proxy::SVGObjectWithContextToV8Object(
+v8::Handle<v8::Value> V8Proxy::SVGObjectWithContextToV8Object(
Peerable* object, V8ClassIndex::V8WrapperType type) {
- if (!object) return v8::Handle<v8::Object>();
+ if (!object) return v8::Null();
// Special case: SVGPathSegs need to be downcast to their real type
if (type == V8ClassIndex::SVGPATHSEG) {
@@ -344,7 +346,7 @@
v8::Persistent<v8::Object> result =
dom_svg_object_with_context_map().get(object);
if (result.IsEmpty()) {
- v8::Local<v8::Object> v8obj = InstantiateV8Object(type, object);
+ v8::Local<v8::Object> v8obj = InstantiateV8Object(type, type, object);
if (!v8obj.IsEmpty()) {
result = v8::Persistent<v8::Object>::New(v8obj);
dom_svg_object_with_context_map().set(object, result);
@@ -1108,18 +1110,18 @@
break;
case V8ClassIndex::HTMLSELECTELEMENT:
desc->InstanceTemplate()->SetNamedPropertyHandler(
- CollectionNamedPropertyGetter<HTMLSelectElement>,
+ NodeCollectionNamedPropertyGetter<HTMLSelectElement>,
0,
0,
0,
0,
v8::External::New(reinterpret_cast<void*>(V8ClassIndex::NODE)));
desc->InstanceTemplate()->SetIndexedPropertyHandler(
- CollectionIndexedPropertyGetter<HTMLSelectElement>,
+ NodeCollectionIndexedPropertyGetter<HTMLSelectElement>,
USE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection),
0,
0,
- CollectionIndexedPropertyEnumerator<HTMLSelectElement>,
+ NodeCollectionIndexedPropertyEnumerator<HTMLSelectElement>,
v8::External::New(reinterpret_cast<void*>(V8ClassIndex::NODE)));
break;
case V8ClassIndex::HTMLDOCUMENT: {
@@ -1185,7 +1187,7 @@
0,
0,
0,
- CollectionIndexedPropertyEnumerator<HTMLFormElement>,
+ NodeCollectionIndexedPropertyEnumerator<HTMLFormElement>,
v8::External::New(reinterpret_cast<void*>(V8ClassIndex::NODE)));
break;
case V8ClassIndex::STYLESHEET: // fall through
@@ -1808,8 +1810,6 @@
ASSERT(type != V8ClassIndex::EVENTTARGET);
ASSERT(type != V8ClassIndex::EVENT);
- if (!imp) return v8::Null();
-
#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
switch (type) {
@@ -1844,11 +1844,13 @@
#undef MAKE_CASE
+ if (!imp) return v8::Null();
+
// Non DOM node
Peerable* obj = static_cast<Peerable*>(imp);
v8::Persistent<v8::Object> result = dom_object_map().get(obj);
if (result.IsEmpty()) {
- v8::Local<v8::Object> v8obj = InstantiateV8Object(type, imp);
+ v8::Local<v8::Object> v8obj = InstantiateV8Object(type, type, imp);
if (!v8obj.IsEmpty()) {
result = v8::Persistent<v8::Object>::New(v8obj);
dom_object_map().set(obj, result);
@@ -1892,17 +1894,16 @@
V8ClassIndex::V8WrapperType V8Proxy::GetDOMWrapperType(
v8::Handle<v8::Object> object) {
- if (!MaybeDOMWrapper(object)) {
- return V8ClassIndex::INVALID_CLASS_INDEX;
- }
+ ASSERT(MaybeDOMWrapper(object));
- v8::Handle<v8::Value> type = object->GetInternalField(1);
+ v8::Handle<v8::Value> type =
+ object->GetInternalField(V8Custom::kDOMWrapperTypeIndex);
return V8ClassIndex::FromInt(type->Int32Value());
}
-void* V8Proxy::FastToNativeObjectImpl(V8ClassIndex::V8WrapperType type,
- v8::Handle<v8::Value> object) {
+void* V8Proxy::ToNativeObjectImpl(V8ClassIndex::V8WrapperType type,
+ v8::Handle<v8::Value> object) {
// Native event listener is per frame, it cannot be handled
// by this generic function.
ASSERT(type != V8ClassIndex::EVENTLISTENER);
@@ -1910,27 +1911,28 @@
ASSERT(MaybeDOMWrapper(object));
+ switch (type) {
#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
- switch (type) {
NODE_WRAPPER_TYPES(MAKE_CASE)
Mike Belshe 2008/09/23 00:36:13 I wonder if we shouldn't #ifndef NDEBUG these to a
Feng Qian 2008/09/23 21:46:04 Here I'd like to let it return NULL so the render
HTMLELEMENT_TYPES(MAKE_CASE)
#if ENABLE(SVG)
SVGNODE_WRAPPER_TYPES(MAKE_CASE)
SVGELEMENT_TYPES(MAKE_CASE)
#endif
- return FastDOMWrapperToNative<Node>(object);
+ ASSERT(false);
+ return NULL;
case V8ClassIndex::XMLHTTPREQUEST:
- return FastDOMWrapperToNative<XMLHttpRequest>(object);
+ return DOMWrapperToNative<XMLHttpRequest>(object);
case V8ClassIndex::EVENT:
- return FastDOMWrapperToNative<Event>(object);
+ return DOMWrapperToNative<Event>(object);
case V8ClassIndex::CSSRULE:
- return FastDOMWrapperToNative<CSSRule>(object);
+ return DOMWrapperToNative<CSSRule>(object);
default:
break;
}
#undef MAKE_CASE
- return FastDOMWrapperToNative<Peerable>(object);
+ return DOMWrapperToNative<Peerable>(object);
}
@@ -1950,41 +1952,6 @@
}
-void* V8Proxy::ToNativeObjectImpl(V8ClassIndex::V8WrapperType type,
- v8::Handle<v8::Value> object) {
- // Native event listener is per frame, it cannot be handled
- // by this generic function.
- ASSERT(type != V8ClassIndex::EVENTLISTENER);
- ASSERT(type != V8ClassIndex::EVENTTARGET);
-
- // It could be null, undefined, etc.
- if (!MaybeDOMWrapper(object))
- return 0;
-
-#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
- switch (type) {
- NODE_WRAPPER_TYPES(MAKE_CASE)
- HTMLELEMENT_TYPES(MAKE_CASE)
-#if ENABLE(SVG)
- SVGNODE_WRAPPER_TYPES(MAKE_CASE)
- SVGELEMENT_TYPES(MAKE_CASE)
-#endif
- return DOMWrapperToNative<Node>(object);
- case V8ClassIndex::XMLHTTPREQUEST:
- return DOMWrapperToNative<XMLHttpRequest>(object);
- case V8ClassIndex::EVENT:
- return DOMWrapperToNative<Event>(object);
- case V8ClassIndex::CSSRULE:
- return DOMWrapperToNative<CSSRule>(object);
- default:
- break;
- }
-#undef MAKE_CASE
-
- return DOMWrapperToNative<Peerable>(object);
-}
-
-
NodeFilter* V8Proxy::ToNativeNodeFilter(v8::Handle<v8::Value> filter) {
// A NodeFilter is used when walking through a DOM tree or iterating tree
// nodes.
@@ -2002,28 +1969,29 @@
v8::Local<v8::Object> V8Proxy::InstantiateV8Object(
- V8ClassIndex::V8WrapperType type, void* imp) {
- V8ClassIndex::V8WrapperType wrapper_type = type;
+ V8ClassIndex::V8WrapperType desc_type,
+ V8ClassIndex::V8WrapperType cptr_type,
+ void* imp) {
// Make a special case for document.all
- if (type == V8ClassIndex::HTMLCOLLECTION &&
+ if (desc_type == V8ClassIndex::HTMLCOLLECTION &&
static_cast<HTMLCollection*>(imp)->type() == HTMLCollection::DocAll) {
- wrapper_type = V8ClassIndex::UNDETECTABLEHTMLCOLLECTION;
+ desc_type = V8ClassIndex::UNDETECTABLEHTMLCOLLECTION;
}
// Special case for HTMLInputElements that support selection.
- if (type == V8ClassIndex::HTMLINPUTELEMENT) {
+ if (desc_type == V8ClassIndex::HTMLINPUTELEMENT) {
HTMLInputElement* element = static_cast<HTMLInputElement*>(imp);
if (element->canHaveSelection()) {
- wrapper_type = V8ClassIndex::HTMLSELECTIONINPUTELEMENT;
+ desc_type = V8ClassIndex::HTMLSELECTIONINPUTELEMENT;
}
}
- v8::Persistent<v8::FunctionTemplate> desc = GetTemplate(wrapper_type);
+ v8::Persistent<v8::FunctionTemplate> desc = GetTemplate(desc_type);
v8::Local<v8::Function> function = desc->GetFunction();
v8::Local<v8::Object> instance = SafeAllocation::NewInstance(function);
if (!instance.IsEmpty()) {
// Avoid setting the DOM wrapper for failed allocations.
- SetDOMWrapper(instance, V8ClassIndex::ToInt(type), imp);
+ SetDOMWrapper(instance, V8ClassIndex::ToInt(cptr_type), imp);
}
return instance;
}
@@ -2040,50 +2008,72 @@
v8::Handle<v8::Value> V8Proxy::WrapCPointer(void* cptr) {
// Represent void* as int
int addr = reinterpret_cast<int>(cptr);
- if ((addr & 0x01) == 0) {
- return v8::Number::New(addr >> 1);
- } else {
- return v8::External::New(cptr);
- }
+ ASSERT((addr & 0x01) == 0); // the address must be aligned.
+ return v8::Integer::New(addr >> 1);
}
void* V8Proxy::ExtractCPointerImpl(v8::Handle<v8::Value> obj) {
- if (obj->IsNumber()) {
- int addr = obj->Int32Value();
- return reinterpret_cast<void*>(addr << 1);
- } else if (obj->IsExternal()) {
- return v8::Handle<v8::External>::Cast(obj)->Value();
- }
- ASSERT(false);
- return 0;
+ ASSERT(obj->IsNumber());
+ int addr = obj->Int32Value();
+ return reinterpret_cast<void*>(addr << 1);
}
-bool V8Proxy::SetDOMWrapper(v8::Handle<v8::Object> obj, int type, void* cptr) {
+void V8Proxy::SetDOMWrapper(v8::Handle<v8::Object> obj, int type, void* cptr) {
ASSERT(obj->InternalFieldCount() >= 2);
obj->SetInternalField(V8Custom::kDOMWrapperObjectIndex, WrapCPointer(cptr));
obj->SetInternalField(V8Custom::kDOMWrapperTypeIndex, v8::Integer::New(type));
- return true;
}
+#ifndef NDEBUG
bool V8Proxy::MaybeDOMWrapper(v8::Handle<v8::Value> value) {
if (value.IsEmpty() || !value->IsObject()) return false;
v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(value);
- if (obj->InternalFieldCount() < V8Custom::kDefaultWrapperInternalFieldCount)
- return false;
+ if (obj->InternalFieldCount() == 0) return false;
+ ASSERT(obj->InternalFieldCount() >=
+ V8Custom::kDefaultWrapperInternalFieldCount);
+
+ v8::Handle<v8::Value> type =
+ obj->GetInternalField(V8Custom::kDOMWrapperTypeIndex);
+ ASSERT(type->IsInt32());
+ ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() &&
+ type->Int32Value() < V8ClassIndex::CLASSINDEX_END);
+
v8::Handle<v8::Value> wrapper =
obj->GetInternalField(V8Custom::kDOMWrapperObjectIndex);
- if (!wrapper->IsNumber() && !wrapper->IsExternal()) return false;
+ ASSERT(wrapper->IsNumber() || wrapper->IsExternal());
+ return true;
+}
+#endif
+
+
+bool V8Proxy::IsDOMEventWrapper(v8::Handle<v8::Value> value) {
+ if (value.IsEmpty() || !value->IsObject()) return false;
+
+ v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(value);
+ if (obj->InternalFieldCount() == 0) return false;
+
+ ASSERT(obj->InternalFieldCount() >=
+ V8Custom::kDefaultWrapperInternalFieldCount);
+
+ v8::Handle<v8::Value> wrapper =
+ obj->GetInternalField(V8Custom::kDOMWrapperObjectIndex);
+ ASSERT(wrapper->IsNumber() || wrapper->IsExternal());
+
v8::Handle<v8::Value> type =
obj->GetInternalField(V8Custom::kDOMWrapperTypeIndex);
- if (!type->IsNumber()) return false;
+ ASSERT(type->IsInt32());
+ ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() &&
+ type->Int32Value() < V8ClassIndex::CLASSINDEX_END);
- return true;
+ // All kinds of events use EVENT as dom type in JS wrappers.
+ // See EventToV8Object
+ return V8ClassIndex::FromInt(type->Int32Value()) == V8ClassIndex::EVENT;
}
@@ -2329,7 +2319,8 @@
type = V8ClassIndex::PROGRESSEVENT;
// Set the peer object for future access.
- v8::Handle<v8::Object> result = InstantiateV8Object(type, event);
+ v8::Handle<v8::Object> result =
+ InstantiateV8Object(type, V8ClassIndex::EVENT, event);
if (result.IsEmpty()) {
// Instantiation failed. Avoid updating the DOM object map and
// return null which is already handled by callers of this function
@@ -2343,8 +2334,9 @@
}
-v8::Handle<v8::Object> V8Proxy::NodeToV8Object(Node* node) {
- if (!node) return v8::Handle<v8::Object>();
+// Caller checks node is not null.
+v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) {
+ if (!node) return v8::Null();
v8::Handle<v8::Object> peer = dom_node_map().get(node);
if (!peer.IsEmpty()) {
@@ -2416,7 +2408,8 @@
// Set the peer object for future access.
// InstantiateV8Object automatically casts node to Peerable*.
- v8::Local<v8::Object> result = InstantiateV8Object(type, node);
+ v8::Local<v8::Object> result =
+ InstantiateV8Object(type, V8ClassIndex::NODE, node);
if (result.IsEmpty()) {
// If instantiation failed it's important not to add the result
// to the DOM node map. Instead we return an empty handle, which
@@ -2507,7 +2500,9 @@
v8::Handle<v8::Value> V8Proxy::DOMImplementationToV8Object(
DOMImplementation* impl) {
v8::Handle<v8::Object> result =
- InstantiateV8Object(V8ClassIndex::DOMIMPLEMENTATION, impl);
+ InstantiateV8Object(V8ClassIndex::DOMIMPLEMENTATION,
+ V8ClassIndex::DOMIMPLEMENTATION,
+ impl);
if (result.IsEmpty()) {
// If the instantiation failed, we ignore it and return null instead
// of returning an empty handle.
@@ -2517,8 +2512,8 @@
}
-v8::Handle<v8::Object> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet) {
- if (!sheet) return v8::Handle<v8::Object>();
+v8::Handle<v8::Value> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet) {
+ if (!sheet) return v8::Null();
v8::Handle<v8::Object> peer = dom_object_map().get(sheet);
if (!peer.IsEmpty()) {
@@ -2528,7 +2523,8 @@
V8ClassIndex::V8WrapperType type = V8ClassIndex::STYLESHEET;
if (sheet->isCSSStyleSheet()) type = V8ClassIndex::CSSSTYLESHEET;
- v8::Handle<v8::Object> result = InstantiateV8Object(type, sheet);
+ v8::Handle<v8::Object> result =
+ InstantiateV8Object(type, V8ClassIndex::STYLESHEET, sheet);
if (!result.IsEmpty()) {
// Only update the DOM object map if the result is non-empty.
dom_object_map().set(sheet, v8::Persistent<v8::Object>::New(result));
@@ -2537,7 +2533,8 @@
// Add a hidden reference from stylesheet object to its owner node.
Node* owner_node = sheet->ownerNode();
if (owner_node) {
- v8::Handle<v8::Object> owner = NodeToV8Object(owner_node);
+ v8::Handle<v8::Object> owner =
+ v8::Handle<v8::Object>::Cast(NodeToV8Object(owner_node));
result->SetInternalField(V8Custom::kStyleSheetOwnerNodeIndex, owner);
}
@@ -2545,8 +2542,8 @@
}
-v8::Handle<v8::Object> V8Proxy::CSSValueToV8Object(CSSValue* value) {
- if (!value) return v8::Handle<v8::Object>();
+v8::Handle<v8::Value> V8Proxy::CSSValueToV8Object(CSSValue* value) {
+ if (!value) return v8::Null();
v8::Handle<v8::Object> peer = dom_object_map().get(value);
if (!peer.IsEmpty()) {
@@ -2568,7 +2565,8 @@
else
type = V8ClassIndex::CSSVALUE;
- v8::Handle<v8::Object> result = InstantiateV8Object(type, value);
+ v8::Handle<v8::Object> result =
+ InstantiateV8Object(type, V8ClassIndex::CSSVALUE, value);
if (!result.IsEmpty()) {
// Only update the DOM object map if the result is non-empty.
dom_object_map().set(value, v8::Persistent<v8::Object>::New(result));
@@ -2577,8 +2575,8 @@
}
-v8::Handle<v8::Object> V8Proxy::CSSRuleToV8Object(CSSRule* rule) {
- if (!rule) return v8::Handle<v8::Object>();
+v8::Handle<v8::Value> V8Proxy::CSSRuleToV8Object(CSSRule* rule) {
+ if (!rule) return v8::Null();
v8::Handle<v8::Object> peer = dom_object_map().get(rule);
if (!peer.IsEmpty()) {
@@ -2611,7 +2609,8 @@
}
// Set the peer object for future access.
- v8::Handle<v8::Object> result = InstantiateV8Object(type, rule);
+ v8::Handle<v8::Object> result =
+ InstantiateV8Object(type, V8ClassIndex::CSSRULE, rule);
if (!result.IsEmpty()) {
// Only update the DOM object map if the result is non-empty.
dom_object_map().set(rule, v8::Persistent<v8::Object>::New(result));
@@ -2619,7 +2618,9 @@
return result;
}
-v8::Handle<v8::Object> V8Proxy::WindowToV8Object(DOMWindow* window) {
+v8::Handle<v8::Value> V8Proxy::WindowToV8Object(DOMWindow* window) {
+ if (!window) return v8::Null();
+
// Initializes environment of a frame, and return the global object
// of the frame.
Frame* frame = window->frame();
« webkit/port/bindings/v8/v8_proxy.h ('K') | « webkit/port/bindings/v8/v8_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698