All hidden properties of an object are stored in a value of a regular property with empty name. This property may confuse user if returned among regular properties. It should not be exposed directly by ObjectMirror. Should we want an access to these properties from debugger we need to implement an explicit method for that.
Current patch filters the hidden_symbol from property names returned to ObjectMirror. See http://crbug.com/26491 Review URL: http://codereview.chromium.org/390001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3265 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
0b0d4efdb4
commit
cd9660f77c
@ -6002,14 +6002,33 @@ static Object* Runtime_DebugLocalPropertyNames(Arguments args) {
|
||||
|
||||
// Get the property names.
|
||||
jsproto = obj;
|
||||
int proto_with_hidden_properties = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
jsproto->GetLocalPropertyNames(*names,
|
||||
i == 0 ? 0 : local_property_count[i - 1]);
|
||||
if (!GetHiddenProperties(jsproto, false)->IsUndefined()) {
|
||||
proto_with_hidden_properties++;
|
||||
}
|
||||
if (i < length - 1) {
|
||||
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out name of hidden propeties object.
|
||||
if (proto_with_hidden_properties > 0) {
|
||||
Handle<FixedArray> old_names = names;
|
||||
names = Factory::NewFixedArray(
|
||||
names->length() - proto_with_hidden_properties);
|
||||
int dest_pos = 0;
|
||||
for (int i = 0; i < total_property_count; i++) {
|
||||
Object* name = old_names->get(i);
|
||||
if (name == Heap::hidden_symbol()) {
|
||||
continue;
|
||||
}
|
||||
names->set(dest_pos++, name);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteArray(local_property_count);
|
||||
return *Factory::NewJSArrayWithElements(names);
|
||||
}
|
||||
|
@ -3439,6 +3439,75 @@ TEST(NativeGetterThrowingErrorPropertyMirror) {
|
||||
}
|
||||
|
||||
|
||||
// Test that hidden properties object is not returned as an unnamed property
|
||||
// among regular properties.
|
||||
// See http://crbug.com/26491
|
||||
TEST(NoHiddenProperties) {
|
||||
// Create a V8 environment with debug access.
|
||||
v8::HandleScope scope;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
// Create an object in the global scope.
|
||||
const char* source = "var obj = {a: 1};";
|
||||
v8::Script::Compile(v8::String::New(source))->Run();
|
||||
v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
|
||||
env->Global()->Get(v8::String::New("obj")));
|
||||
// Set a hidden property on the object.
|
||||
obj->SetHiddenValue(v8::String::New("v8::test-debug::a"),
|
||||
v8::Int32::New(11));
|
||||
|
||||
// Get mirror for the object with property getter.
|
||||
CompileRun("var obj_mirror = debug.MakeMirror(obj);");
|
||||
CHECK(CompileRun(
|
||||
"obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
|
||||
CompileRun("var named_names = obj_mirror.propertyNames();");
|
||||
// There should be exactly one property. But there is also an unnamed
|
||||
// property whose value is hidden properties dictionary. The latter
|
||||
// property should not be in the list of reguar properties.
|
||||
CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
|
||||
CHECK(CompileRun("named_names[0] == 'a'")->BooleanValue());
|
||||
CHECK(CompileRun(
|
||||
"obj_mirror.property('a').value().value() == 1")->BooleanValue());
|
||||
|
||||
// Object created by t0 will become hidden prototype of object 'obj'.
|
||||
v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
|
||||
t0->InstanceTemplate()->Set(v8::String::New("b"), v8::Number::New(2));
|
||||
t0->SetHiddenPrototype(true);
|
||||
v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
|
||||
t1->InstanceTemplate()->Set(v8::String::New("c"), v8::Number::New(3));
|
||||
|
||||
// Create proto objects, add hidden properties to them and set them on
|
||||
// the global object.
|
||||
v8::Handle<v8::Object> protoObj = t0->GetFunction()->NewInstance();
|
||||
protoObj->SetHiddenValue(v8::String::New("v8::test-debug::b"),
|
||||
v8::Int32::New(12));
|
||||
env->Global()->Set(v8::String::New("protoObj"), protoObj);
|
||||
v8::Handle<v8::Object> grandProtoObj = t1->GetFunction()->NewInstance();
|
||||
grandProtoObj->SetHiddenValue(v8::String::New("v8::test-debug::c"),
|
||||
v8::Int32::New(13));
|
||||
env->Global()->Set(v8::String::New("grandProtoObj"), grandProtoObj);
|
||||
|
||||
// Setting prototypes: obj->protoObj->grandProtoObj
|
||||
protoObj->Set(v8::String::New("__proto__"), grandProtoObj);
|
||||
obj->Set(v8::String::New("__proto__"), protoObj);
|
||||
|
||||
// Get mirror for the object with property getter.
|
||||
CompileRun("var obj_mirror = debug.MakeMirror(obj);");
|
||||
CHECK(CompileRun(
|
||||
"obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
|
||||
CompileRun("var named_names = obj_mirror.propertyNames();");
|
||||
// There should be exactly two properties - one from the object itself and
|
||||
// another from its hidden prototype.
|
||||
CHECK_EQ(2, CompileRun("named_names.length")->Int32Value());
|
||||
CHECK(CompileRun("named_names.sort(); named_names[0] == 'a' &&"
|
||||
"named_names[1] == 'b'")->BooleanValue());
|
||||
CHECK(CompileRun(
|
||||
"obj_mirror.property('a').value().value() == 1")->BooleanValue());
|
||||
CHECK(CompileRun(
|
||||
"obj_mirror.property('b').value().value() == 2")->BooleanValue());
|
||||
}
|
||||
|
||||
|
||||
// Multithreaded tests of JSON debugger protocol
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user