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:
parent
5ae761cc15
commit
d6fcda0044
@ -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
|
||||
|
16
src/api.cc
16
src/api.cc
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user