API: added function to find instance of template in prototype chain.

Also inlined Object::IsInstanceOf.

This new function is intended to be used to speed up DOM bindings.

Review URL: http://codereview.chromium.org/165044

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2636 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vitalyr@chromium.org 2009-08-06 13:35:21 +00:00
parent 5ae761cc15
commit d6fcda0044
6 changed files with 89 additions and 19 deletions

View File

@ -1098,6 +1098,12 @@ class V8EXPORT Object : public Value {
*/
Local<Value> GetPrototype();
/**
* Finds an instance of the given function template in the prototype
* chain.
*/
Local<Object> FindInstanceInPrototypeChain(Handle<FunctionTemplate> tmpl);
/**
* Call builtin Object.prototype.toString on this object.
* This is different from Value::ToString() that may call

View File

@ -1928,6 +1928,22 @@ Local<Value> v8::Object::GetPrototype() {
}
Local<Object> v8::Object::FindInstanceInPrototypeChain(
v8::Handle<FunctionTemplate> tmpl) {
ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
return Local<v8::Object>());
ENTER_V8;
i::JSObject* object = *Utils::OpenHandle(this);
i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
while (!object->IsInstanceOf(tmpl_info)) {
i::Object* prototype = object->GetPrototype();
if (!prototype->IsJSObject()) return Local<Object>();
object = i::JSObject::cast(prototype);
}
return Utils::ToLocal(i::Handle<i::JSObject>(object));
}
Local<Array> v8::Object::GetPropertyNames() {
ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
ENTER_V8;

View File

@ -100,6 +100,25 @@ PropertyDetails PropertyDetails::AsDeleted() {
}
bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
// There is a constraint on the object; check.
if (!this->IsJSObject()) return false;
// Fetch the constructor function of the object.
Object* cons_obj = JSObject::cast(this)->map()->constructor();
if (!cons_obj->IsJSFunction()) return false;
JSFunction* fun = JSFunction::cast(cons_obj);
// Iterate through the chain of inheriting function templates to
// see if the required one occurs.
for (Object* type = fun->shared()->function_data();
type->IsFunctionTemplateInfo();
type = FunctionTemplateInfo::cast(type)->parent_template()) {
if (type == expected) return true;
}
// Didn't find the required type in the inheritance chain.
return false;
}
bool Object::IsSmi() {
return HAS_SMI_TAG(this);
}

View File

@ -50,24 +50,6 @@ namespace internal {
const int kGetterIndex = 0;
const int kSetterIndex = 1;
bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
// There is a constraint on the object; check
if (!this->IsJSObject()) return false;
// Fetch the constructor function of the object
Object* cons_obj = JSObject::cast(this)->map()->constructor();
if (!cons_obj->IsJSFunction()) return false;
JSFunction* fun = JSFunction::cast(cons_obj);
// Iterate through the chain of inheriting function templates to
// see if the required one occurs.
for (Object* type = fun->shared()->function_data();
type->IsFunctionTemplateInfo();
type = FunctionTemplateInfo::cast(type)->parent_template()) {
if (type == expected) return true;
}
// Didn't find the required type in the inheritance chain.
return false;
}
static Object* CreateJSValue(JSFunction* constructor, Object* value) {
Object* result = Heap::AllocateJSObject(constructor);

View File

@ -801,7 +801,7 @@ class Object BASE_EMBEDDED {
// Returns true if this object is an instance of the specified
// function template.
bool IsInstanceOf(FunctionTemplateInfo* type);
inline bool IsInstanceOf(FunctionTemplateInfo* type);
inline bool IsStruct();
#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();

View File

@ -633,6 +633,53 @@ THREADED_TEST(FunctionTemplate) {
}
THREADED_TEST(FindInstanceInPrototypeChain) {
v8::HandleScope scope;
LocalContext env;
Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
derived->Inherit(base);
Local<v8::Function> base_function = base->GetFunction();
Local<v8::Function> derived_function = derived->GetFunction();
Local<v8::Function> other_function = other->GetFunction();
Local<v8::Object> base_instance = base_function->NewInstance();
Local<v8::Object> derived_instance = derived_function->NewInstance();
Local<v8::Object> derived_instance2 = derived_function->NewInstance();
Local<v8::Object> other_instance = other_function->NewInstance();
derived_instance2->Set(v8_str("__proto__"), derived_instance);
other_instance->Set(v8_str("__proto__"), derived_instance2);
// base_instance is only an instance of base.
CHECK_EQ(base_instance,
base_instance->FindInstanceInPrototypeChain(base));
CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
// derived_instance is an instance of base and derived.
CHECK_EQ(derived_instance,
derived_instance->FindInstanceInPrototypeChain(base));
CHECK_EQ(derived_instance,
derived_instance->FindInstanceInPrototypeChain(derived));
CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
// other_instance is an instance of other and its immediate
// prototype derived_instance2 is an instance of base and derived.
// Note, derived_instance is an instance of base and derived too,
// but it comes after derived_instance2 in the prototype chain of
// other_instance.
CHECK_EQ(derived_instance2,
other_instance->FindInstanceInPrototypeChain(base));
CHECK_EQ(derived_instance2,
other_instance->FindInstanceInPrototypeChain(derived));
CHECK_EQ(other_instance,
other_instance->FindInstanceInPrototypeChain(other));
}
static v8::Handle<Value> handle_property(Local<String> name,
const AccessorInfo&) {
ApiTestFuzzer::Fuzz();