Commit 12f63064 authored by antonm@chromium.org's avatar antonm@chromium.org

First phase of migration to new named property query callbacks.

Eventually named property query callbacks will return attributes
(as an integer) or an empty handle if property is not intercepted.

To gradually migrate to this new API, USE_NEW_QUERY_CALLBACK
macro would control if old or new style API is used.

So the migration plan is:

1) introduce new API which should be explictily enabled;
2) switch to new API defining USE_NEW_QUERY_CALLBACK before
  include of <v8.h> (that would require changes to client code as well)
3) remove old API from v8
4) remove #define USE_NEW_QUERY_CALLBACK from clients.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4797 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d3d295ef
......@@ -1726,13 +1726,22 @@ typedef Handle<Value> (*NamedPropertySetter)(Local<String> property,
Local<Value> value,
const AccessorInfo& info);
/**
* Returns a non-empty handle if the interceptor intercepts the request.
* The result is true if the property exists and false otherwise.
* The result is either boolean (true if property exists and false
* otherwise) or an integer encoding property attributes.
*/
#ifdef USE_NEW_QUERY_CALLBACKS
typedef Handle<Integer> (*NamedPropertyQuery)(Local<String> property,
const AccessorInfo& info);
#else
typedef Handle<Boolean> (*NamedPropertyQuery)(Local<String> property,
const AccessorInfo& info);
#endif
typedef Handle<Value> (*NamedPropertyQueryImpl)(Local<String> property,
const AccessorInfo& info);
/**
......@@ -1984,7 +1993,16 @@ class V8EXPORT FunctionTemplate : public Template {
NamedPropertyQuery query,
NamedPropertyDeleter remover,
NamedPropertyEnumerator enumerator,
Handle<Value> data);
Handle<Value> data) {
NamedPropertyQueryImpl casted =
reinterpret_cast<NamedPropertyQueryImpl>(query);
SetNamedInstancePropertyHandlerImpl(getter,
setter,
casted,
remover,
enumerator,
data);
}
void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,
IndexedPropertySetter setter,
IndexedPropertyQuery query,
......@@ -1996,6 +2014,13 @@ class V8EXPORT FunctionTemplate : public Template {
friend class Context;
friend class ObjectTemplate;
private:
void SetNamedInstancePropertyHandlerImpl(NamedPropertyGetter getter,
NamedPropertySetter setter,
NamedPropertyQueryImpl query,
NamedPropertyDeleter remover,
NamedPropertyEnumerator enumerator,
Handle<Value> data);
};
......@@ -2053,7 +2078,7 @@ class V8EXPORT ObjectTemplate : public Template {
*
* \param getter The callback to invoke when getting a property.
* \param setter The callback to invoke when setting a property.
* \param query The callback to invoke to check is an object has a property.
* \param query The callback to invoke to check if an object has a property.
* \param deleter The callback to invoke when deleting a property.
* \param enumerator The callback to invoke to enumerate all the named
* properties of an object.
......@@ -2065,7 +2090,26 @@ class V8EXPORT ObjectTemplate : public Template {
NamedPropertyQuery query = 0,
NamedPropertyDeleter deleter = 0,
NamedPropertyEnumerator enumerator = 0,
Handle<Value> data = Handle<Value>());
Handle<Value> data = Handle<Value>()) {
NamedPropertyQueryImpl casted =
reinterpret_cast<NamedPropertyQueryImpl>(query);
SetNamedPropertyHandlerImpl(getter,
setter,
casted,
deleter,
enumerator,
data);
}
private:
void SetNamedPropertyHandlerImpl(NamedPropertyGetter getter,
NamedPropertySetter setter,
NamedPropertyQueryImpl query,
NamedPropertyDeleter deleter,
NamedPropertyEnumerator enumerator,
Handle<Value> data);
public:
/**
* Sets an indexed property handler on the object template.
......
......@@ -853,10 +853,10 @@ void FunctionTemplate::SetHiddenPrototype(bool value) {
}
void FunctionTemplate::SetNamedInstancePropertyHandler(
void FunctionTemplate::SetNamedInstancePropertyHandlerImpl(
NamedPropertyGetter getter,
NamedPropertySetter setter,
NamedPropertyQuery query,
NamedPropertyQueryImpl query,
NamedPropertyDeleter remover,
NamedPropertyEnumerator enumerator,
Handle<Value> data) {
......@@ -987,12 +987,13 @@ void ObjectTemplate::SetAccessor(v8::Handle<String> name,
}
void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
NamedPropertySetter setter,
NamedPropertyQuery query,
NamedPropertyDeleter remover,
NamedPropertyEnumerator enumerator,
Handle<Value> data) {
void ObjectTemplate::SetNamedPropertyHandlerImpl(NamedPropertyGetter getter,
NamedPropertySetter setter,
NamedPropertyQueryImpl query,
NamedPropertyDeleter remover,
NamedPropertyEnumerator
enumerator,
Handle<Value> data) {
if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
ENTER_V8;
HandleScope scope;
......@@ -1000,12 +1001,12 @@ void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
i::FunctionTemplateInfo* constructor =
i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
i::Handle<i::FunctionTemplateInfo> cons(constructor);
Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
setter,
query,
remover,
enumerator,
data);
Utils::ToLocal(cons)->SetNamedInstancePropertyHandlerImpl(getter,
setter,
query,
remover,
enumerator,
data);
}
......
......@@ -2013,19 +2013,25 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
CustomArguments args(interceptor->data(), receiver, this);
v8::AccessorInfo info(args.end());
if (!interceptor->query()->IsUndefined()) {
v8::NamedPropertyQuery query =
v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
v8::NamedPropertyQueryImpl query =
v8::ToCData<v8::NamedPropertyQueryImpl>(interceptor->query());
LOG(ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
v8::Handle<v8::Boolean> result;
v8::Handle<v8::Value> result;
{
// Leaving JavaScript.
VMState state(EXTERNAL);
result = query(v8::Utils::ToLocal(name_handle), info);
}
if (!result.IsEmpty()) {
// Convert the boolean result to a property attribute
// specification.
return result->IsTrue() ? NONE : ABSENT;
// Temporary complicated logic, would be removed soon.
if (result->IsBoolean()) {
// Convert the boolean result to a property attribute
// specification.
return result->IsTrue() ? NONE : ABSENT;
} else {
ASSERT(result->IsInt32());
return static_cast<PropertyAttributes>(result->Int32Value());
}
}
} else if (!interceptor->getter()->IsUndefined()) {
v8::NamedPropertyGetter getter =
......
......@@ -27,6 +27,8 @@
#include <limits.h>
#define USE_NEW_QUERY_CALLBACKS
#include "v8.h"
#include "api.h"
......@@ -1120,11 +1122,11 @@ v8::Handle<v8::Boolean> CheckThisIndexedPropertyQuery(
}
v8::Handle<v8::Boolean> CheckThisNamedPropertyQuery(Local<String> property,
v8::Handle<v8::Integer> CheckThisNamedPropertyQuery(Local<String> property,
const AccessorInfo& info) {
ApiTestFuzzer::Fuzz();
CHECK(info.This()->Equals(bottom));
return v8::Handle<v8::Boolean>();
return v8::Handle<v8::Integer>();
}
......@@ -1221,13 +1223,13 @@ static v8::Handle<Value> PrePropertyHandlerGet(Local<String> key,
}
static v8::Handle<v8::Boolean> PrePropertyHandlerHas(Local<String> key,
const AccessorInfo&) {
static v8::Handle<v8::Integer> PrePropertyHandlerQuery(Local<String> key,
const AccessorInfo&) {
if (v8_str("pre")->Equals(key)) {
return v8::True();
return v8::Integer::New(v8::None);
}
return v8::Handle<v8::Boolean>(); // do not intercept the call
return v8::Handle<v8::Integer>(); // do not intercept the call
}
......@@ -1236,7 +1238,7 @@ THREADED_TEST(PrePropertyHandler) {
v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
0,
PrePropertyHandlerHas);
PrePropertyHandlerQuery);
LocalContext env(NULL, desc->InstanceTemplate());
Script::Compile(v8_str(
"var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
......
......@@ -27,6 +27,8 @@
#include <stdlib.h>
#define USE_NEW_QUERY_CALLBACKS
#include "v8.h"
#include "api.h"
......
......@@ -27,6 +27,8 @@
#include <stdlib.h>
#define USE_NEW_QUERY_CALLBACKS
#include "v8.h"
#include "heap.h"
......@@ -63,12 +65,12 @@ class DeclarationContext {
int get_count() const { return get_count_; }
int set_count() const { return set_count_; }
int has_count() const { return has_count_; }
int query_count() const { return query_count_; }
protected:
virtual v8::Handle<Value> Get(Local<String> key);
virtual v8::Handle<Value> Set(Local<String> key, Local<Value> value);
virtual v8::Handle<Boolean> Has(Local<String> key);
virtual v8::Handle<Integer> Query(Local<String> key);
void InitializeIfNeeded();
......@@ -85,8 +87,8 @@ class DeclarationContext {
static v8::Handle<Value> HandleSet(Local<String> key,
Local<Value> value,
const AccessorInfo& info);
static v8::Handle<Boolean> HandleHas(Local<String> key,
const AccessorInfo& info);
static v8::Handle<Integer> HandleQuery(Local<String> key,
const AccessorInfo& info);
private:
bool is_initialized_;
......@@ -95,14 +97,14 @@ class DeclarationContext {
int get_count_;
int set_count_;
int has_count_;
int query_count_;
static DeclarationContext* GetInstance(const AccessorInfo& info);
};
DeclarationContext::DeclarationContext()
: is_initialized_(false), get_count_(0), set_count_(0), has_count_(0) {
: is_initialized_(false), get_count_(0), set_count_(0), query_count_(0) {
// Do nothing.
}
......@@ -114,7 +116,7 @@ void DeclarationContext::InitializeIfNeeded() {
Local<Value> data = External::New(this);
GetHolder(function)->SetNamedPropertyHandler(&HandleGet,
&HandleSet,
&HandleHas,
&HandleQuery,
0, 0,
data);
context_ = Context::New(0, function->InstanceTemplate(), Local<Value>());
......@@ -124,7 +126,7 @@ void DeclarationContext::InitializeIfNeeded() {
void DeclarationContext::Check(const char* source,
int get, int set, int has,
int get, int set, int query,
Expectations expectations,
v8::Handle<Value> value) {
InitializeIfNeeded();
......@@ -137,7 +139,7 @@ void DeclarationContext::Check(const char* source,
Local<Value> result = Script::Compile(String::New(source))->Run();
CHECK_EQ(get, get_count());
CHECK_EQ(set, set_count());
CHECK_EQ(has, has_count());
CHECK_EQ(query, query_count());
if (expectations == EXPECT_RESULT) {
CHECK(!catcher.HasCaught());
if (!value.IsEmpty()) {
......@@ -170,11 +172,11 @@ v8::Handle<Value> DeclarationContext::HandleSet(Local<String> key,
}
v8::Handle<Boolean> DeclarationContext::HandleHas(Local<String> key,
const AccessorInfo& info) {
v8::Handle<Integer> DeclarationContext::HandleQuery(Local<String> key,
const AccessorInfo& info) {
DeclarationContext* context = GetInstance(info);
context->has_count_++;
return context->Has(key);
context->query_count_++;
return context->Query(key);
}
......@@ -194,8 +196,8 @@ v8::Handle<Value> DeclarationContext::Set(Local<String> key,
}
v8::Handle<Boolean> DeclarationContext::Has(Local<String> key) {
return v8::Handle<Boolean>();
v8::Handle<Integer> DeclarationContext::Query(Local<String> key) {
return v8::Handle<Integer>();
}
......@@ -249,8 +251,8 @@ TEST(Unknown) {
class PresentPropertyContext: public DeclarationContext {
protected:
virtual v8::Handle<Boolean> Has(Local<String> key) {
return True();
virtual v8::Handle<Integer> Query(Local<String> key) {
return Integer::New(v8::None);
}
};
......@@ -304,8 +306,8 @@ TEST(Present) {
class AbsentPropertyContext: public DeclarationContext {
protected:
virtual v8::Handle<Boolean> Has(Local<String> key) {
return False();
virtual v8::Handle<Integer> Query(Local<String> key) {
return v8::Handle<Integer>();
}
};
......@@ -316,7 +318,7 @@ TEST(Absent) {
{ AbsentPropertyContext context;
context.Check("var x; x",
1, // access
2, // declaration + initialization
1, // declaration
2, // declaration + initialization
EXPECT_RESULT, Undefined());
}
......@@ -375,24 +377,24 @@ class AppearingPropertyContext: public DeclarationContext {
AppearingPropertyContext() : state_(DECLARE) { }
protected:
virtual v8::Handle<Boolean> Has(Local<String> key) {
virtual v8::Handle<Integer> Query(Local<String> key) {
switch (state_) {
case DECLARE:
// Force declaration by returning that the
// property is absent.
state_ = INITIALIZE_IF_ASSIGN;
return False();
return Handle<Integer>();
case INITIALIZE_IF_ASSIGN:
// Return that the property is present so we only get the
// setter called when initializing with a value.
state_ = UNKNOWN;
return True();
return Integer::New(v8::None);
default:
CHECK(state_ == UNKNOWN);
break;
}
// Do the lookup in the object.
return v8::Local<Boolean>();
return v8::Handle<Integer>();
}
private:
......@@ -458,31 +460,31 @@ class ReappearingPropertyContext: public DeclarationContext {
ReappearingPropertyContext() : state_(DECLARE) { }
protected:
virtual v8::Handle<Boolean> Has(Local<String> key) {
virtual v8::Handle<Integer> Query(Local<String> key) {
switch (state_) {
case DECLARE:
// Force the first declaration by returning that
// the property is absent.
state_ = DONT_DECLARE;
return False();
return Handle<Integer>();
case DONT_DECLARE:
// Ignore the second declaration by returning
// that the property is already there.
state_ = INITIALIZE;
return True();
return Integer::New(v8::None);
case INITIALIZE:
// Force an initialization by returning that
// the property is absent. This will make sure
// that the setter is called and it will not
// lead to redeclaration conflicts (yet).
state_ = UNKNOWN;
return False();
return Handle<Integer>();
default:
CHECK(state_ == UNKNOWN);
break;
}
// Do the lookup in the object.
return v8::Local<Boolean>();
return Handle<Integer>();
}
private:
......@@ -506,9 +508,9 @@ TEST(Reappearing) {
class ExistsInPrototypeContext: public DeclarationContext {
protected:
virtual v8::Handle<Boolean> Has(Local<String> key) {
virtual v8::Handle<Integer> Query(Local<String> key) {
// Let it seem that the property exists in the prototype object.
return True();
return Integer::New(v8::None);
}
// Use the prototype as the holder for the interceptors.
......@@ -568,9 +570,9 @@ TEST(ExistsInPrototype) {
class AbsentInPrototypeContext: public DeclarationContext {
protected:
virtual v8::Handle<Boolean> Has(Local<String> key) {
virtual v8::Handle<Integer> Query(Local<String> key) {
// Let it seem that the property is absent in the prototype object.
return False();
return Handle<Integer>();
}
// Use the prototype as the holder for the interceptors.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment