Introduce InternalProperty type and expose internal properties for bound functions
Review URL: https://chromiumcodereview.appspot.com/10834376 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12346 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1fcddc4456
commit
cfc4c37768
@ -154,6 +154,7 @@ var FUNCTION_TYPE = 'function';
|
||||
var REGEXP_TYPE = 'regexp';
|
||||
var ERROR_TYPE = 'error';
|
||||
var PROPERTY_TYPE = 'property';
|
||||
var INTERNAL_PROPERTY_TYPE = 'internalProperty';
|
||||
var FRAME_TYPE = 'frame';
|
||||
var SCRIPT_TYPE = 'script';
|
||||
var CONTEXT_TYPE = 'context';
|
||||
@ -212,6 +213,7 @@ var ScopeType = { Global: 0,
|
||||
// - RegExpMirror
|
||||
// - ErrorMirror
|
||||
// - PropertyMirror
|
||||
// - InternalPropertyMirror
|
||||
// - FrameMirror
|
||||
// - ScriptMirror
|
||||
|
||||
@ -357,6 +359,15 @@ Mirror.prototype.isProperty = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the mirror reflects an internal property.
|
||||
* @returns {boolean} True if the mirror reflects an internal property
|
||||
*/
|
||||
Mirror.prototype.isInternalProperty = function() {
|
||||
return this instanceof InternalPropertyMirror;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the mirror reflects a stack frame.
|
||||
* @returns {boolean} True if the mirror reflects a stack frame
|
||||
@ -594,23 +605,6 @@ ObjectMirror.prototype.protoObject = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the primitive value if this is object of Boolean, Number or String
|
||||
* type (but not Date). Otherwise return undefined.
|
||||
*/
|
||||
ObjectMirror.prototype.primitiveValue = function() {
|
||||
if (!IS_STRING_WRAPPER(this.value_) && !IS_NUMBER_WRAPPER(this.value_) &&
|
||||
!IS_BOOLEAN_WRAPPER(this.value_)) {
|
||||
return void 0;
|
||||
}
|
||||
var primitiveValue = %_ValueOf(this.value_);
|
||||
if (IS_UNDEFINED(primitiveValue)) {
|
||||
return void 0;
|
||||
}
|
||||
return MakeMirror(primitiveValue);
|
||||
};
|
||||
|
||||
|
||||
ObjectMirror.prototype.hasNamedInterceptor = function() {
|
||||
// Get information on interceptors for this object.
|
||||
var x = %GetInterceptorInfo(this.value_);
|
||||
@ -701,7 +695,7 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
|
||||
* Return the properties for this object as an array of PropertyMirror objects.
|
||||
* @param {number} kind Indicate whether named, indexed or both kinds of
|
||||
* properties are requested
|
||||
* @param {number} limit Limit the number of properties returend to the
|
||||
* @param {number} limit Limit the number of properties returned to the
|
||||
specified value
|
||||
* @return {Array} Property mirrors for this object
|
||||
*/
|
||||
@ -716,6 +710,16 @@ ObjectMirror.prototype.properties = function(kind, limit) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the internal properties for this object as an array of
|
||||
* InternalPropertyMirror objects.
|
||||
* @return {Array} Property mirrors for this object
|
||||
*/
|
||||
ObjectMirror.prototype.internalProperties = function() {
|
||||
return ObjectMirror.GetInternalProperties(this.value_);
|
||||
}
|
||||
|
||||
|
||||
ObjectMirror.prototype.property = function(name) {
|
||||
var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
|
||||
if (details) {
|
||||
@ -789,6 +793,37 @@ ObjectMirror.prototype.toText = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the internal properties of the value, such as [[PrimitiveValue]] of
|
||||
* scalar wrapper objects and properties of the bound function.
|
||||
* This method is done static to be accessible from Debug API with the bare
|
||||
* values without mirrors.
|
||||
* @return {Array} array (possibly empty) of InternalProperty instances
|
||||
*/
|
||||
ObjectMirror.GetInternalProperties = function(value) {
|
||||
if (IS_STRING_WRAPPER(value) || IS_NUMBER_WRAPPER(value) ||
|
||||
IS_BOOLEAN_WRAPPER(value)) {
|
||||
var primitiveValue = %_ValueOf(value);
|
||||
return [new InternalPropertyMirror("[[PrimitiveValue]]", primitiveValue)];
|
||||
} else if (IS_FUNCTION(value)) {
|
||||
var bindings = %BoundFunctionGetBindings(value);
|
||||
var result = [];
|
||||
if (bindings && IS_ARRAY(bindings)) {
|
||||
result.push(new InternalPropertyMirror("[[TargetFunction]]",
|
||||
bindings[0]));
|
||||
result.push(new InternalPropertyMirror("[[BoundThis]]", bindings[1]));
|
||||
var boundArgs = [];
|
||||
for (var i = 2; i < bindings.length; i++) {
|
||||
boundArgs.push(bindings[i]);
|
||||
}
|
||||
result.push(new InternalPropertyMirror("[[BoundArgs]]", boundArgs));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mirror object for functions.
|
||||
* @param {function} value The function object reflected by this mirror.
|
||||
@ -1268,6 +1303,33 @@ PropertyMirror.prototype.isNative = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Mirror object for internal properties. Internal property reflects properties
|
||||
* not accessible from user code such as [[BoundThis]] in bound function.
|
||||
* Their names are merely symbolic.
|
||||
* @param {string} name The name of the property
|
||||
* @param {value} property value
|
||||
* @constructor
|
||||
* @extends Mirror
|
||||
*/
|
||||
function InternalPropertyMirror(name, value) {
|
||||
%_CallFunction(this, INTERNAL_PROPERTY_TYPE, Mirror);
|
||||
this.name_ = name;
|
||||
this.value_ = value;
|
||||
}
|
||||
inherits(InternalPropertyMirror, Mirror);
|
||||
|
||||
|
||||
InternalPropertyMirror.prototype.name = function() {
|
||||
return this.name_;
|
||||
};
|
||||
|
||||
|
||||
InternalPropertyMirror.prototype.value = function() {
|
||||
return MakeMirror(this.value_, false);
|
||||
};
|
||||
|
||||
|
||||
var kFrameDetailsFrameIdIndex = 0;
|
||||
var kFrameDetailsReceiverIndex = 1;
|
||||
var kFrameDetailsFunctionIndex = 2;
|
||||
@ -2202,7 +2264,8 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
|
||||
break;
|
||||
|
||||
case PROPERTY_TYPE:
|
||||
throw new Error('PropertyMirror cannot be serialized independeltly');
|
||||
case INTERNAL_PROPERTY_TYPE:
|
||||
throw new Error('PropertyMirror cannot be serialized independently');
|
||||
break;
|
||||
|
||||
case FRAME_TYPE:
|
||||
@ -2278,7 +2341,8 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
|
||||
* "prototypeObject":{"ref":<number>},
|
||||
* "namedInterceptor":<boolean>,
|
||||
* "indexedInterceptor":<boolean>,
|
||||
* "properties":[<properties>]}
|
||||
* "properties":[<properties>],
|
||||
* "internalProperties":[<internal properties>]}
|
||||
*/
|
||||
JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
|
||||
details) {
|
||||
@ -2289,11 +2353,6 @@ JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
|
||||
content.protoObject = this.serializeReference(mirror.protoObject());
|
||||
content.prototypeObject = this.serializeReference(mirror.prototypeObject());
|
||||
|
||||
var primitiveValue = mirror.primitiveValue();
|
||||
if (!IS_UNDEFINED(primitiveValue)) {
|
||||
content.primitiveValue = this.serializeReference(primitiveValue);
|
||||
}
|
||||
|
||||
// Add flags to indicate whether there are interceptors.
|
||||
if (mirror.hasNamedInterceptor()) {
|
||||
content.namedInterceptor = true;
|
||||
@ -2355,6 +2414,15 @@ JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
|
||||
}
|
||||
}
|
||||
content.properties = p;
|
||||
|
||||
var internalProperties = mirror.internalProperties();
|
||||
if (internalProperties.length > 0) {
|
||||
var ip = [];
|
||||
for (var i = 0; i < internalProperties.length; i++) {
|
||||
ip.push(this.serializeInternalProperty_(internalProperties[i]));
|
||||
}
|
||||
content.internalProperties = ip;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -2422,6 +2490,33 @@ JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Serialize internal property information to the following JSON format for
|
||||
* building the array of properties.
|
||||
*
|
||||
* {"name":"<property name>",
|
||||
* "ref":<number>}
|
||||
*
|
||||
* {"name":"[[BoundThis]]","ref":117}
|
||||
*
|
||||
* @param {InternalPropertyMirror} propertyMirror The property to serialize.
|
||||
* @returns {Object} Protocol object representing the property.
|
||||
*/
|
||||
JSONProtocolSerializer.prototype.serializeInternalProperty_ =
|
||||
function(propertyMirror) {
|
||||
var result = {};
|
||||
|
||||
result.name = propertyMirror.name();
|
||||
var propertyValue = propertyMirror.value();
|
||||
if (this.inlineRefs_() && propertyValue.isValue()) {
|
||||
result.value = this.serializeReferenceWithDisplayData_(propertyValue);
|
||||
} else {
|
||||
result.ref = propertyValue.handle();
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
|
||||
content.index = mirror.index();
|
||||
content.receiver = this.serializeReference(mirror.receiver());
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -49,19 +49,19 @@ function testObjectMirror(obj, cls_name, ctor_name, hasSpecialProperties) {
|
||||
JSON.stringify(serializer.serializeReferencedObjects()));
|
||||
|
||||
// Check the mirror hierachy.
|
||||
assertTrue(mirror instanceof debug.Mirror, 'Unexpected mirror hierachy');
|
||||
assertTrue(mirror instanceof debug.ValueMirror, 'Unexpected mirror hierachy');
|
||||
assertTrue(mirror instanceof debug.ObjectMirror, 'Unexpected mirror hierachy');
|
||||
assertTrue(mirror instanceof debug.Mirror, 'Unexpected mirror hierarchy');
|
||||
assertTrue(mirror instanceof debug.ValueMirror, 'Unexpected mirror hierarchy');
|
||||
assertTrue(mirror instanceof debug.ObjectMirror, 'Unexpected mirror hierarchy');
|
||||
|
||||
// Check the mirror properties.
|
||||
assertTrue(mirror.isObject(), 'Unexpected mirror');
|
||||
assertEquals('object', mirror.type(), 'Unexpected mirror type');
|
||||
assertFalse(mirror.isPrimitive(), 'Unexpected primitive mirror');
|
||||
assertEquals(cls_name, mirror.className(), 'Unexpected mirror class name');
|
||||
assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror, 'Unexpected mirror hierachy');
|
||||
assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror, 'Unexpected mirror hierarchy');
|
||||
assertEquals(ctor_name, mirror.constructorFunction().name(), 'Unexpected constructor function name');
|
||||
assertTrue(mirror.protoObject() instanceof debug.Mirror, 'Unexpected mirror hierachy');
|
||||
assertTrue(mirror.prototypeObject() instanceof debug.Mirror, 'Unexpected mirror hierachy');
|
||||
assertTrue(mirror.protoObject() instanceof debug.Mirror, 'Unexpected mirror hierarchy');
|
||||
assertTrue(mirror.prototypeObject() instanceof debug.Mirror, 'Unexpected mirror hierarchy');
|
||||
assertFalse(mirror.hasNamedInterceptor(), 'No named interceptor expected');
|
||||
assertFalse(mirror.hasIndexedInterceptor(), 'No indexed interceptor expected');
|
||||
|
||||
@ -69,12 +69,19 @@ function testObjectMirror(obj, cls_name, ctor_name, hasSpecialProperties) {
|
||||
var properties = mirror.properties();
|
||||
assertEquals(names.length, properties.length);
|
||||
for (var i = 0; i < properties.length; i++) {
|
||||
assertTrue(properties[i] instanceof debug.Mirror, 'Unexpected mirror hierachy');
|
||||
assertTrue(properties[i] instanceof debug.PropertyMirror, 'Unexpected mirror hierachy');
|
||||
assertTrue(properties[i] instanceof debug.Mirror, 'Unexpected mirror hierarchy');
|
||||
assertTrue(properties[i] instanceof debug.PropertyMirror, 'Unexpected mirror hierarchy');
|
||||
assertEquals('property', properties[i].type(), 'Unexpected mirror type');
|
||||
assertEquals(names[i], properties[i].name(), 'Unexpected property name');
|
||||
}
|
||||
|
||||
var internalProperties = mirror.internalProperties();
|
||||
for (var i = 0; i < internalProperties.length; i++) {
|
||||
assertTrue(internalProperties[i] instanceof debug.Mirror, 'Unexpected mirror hierarchy');
|
||||
assertTrue(internalProperties[i] instanceof debug.InternalPropertyMirror, 'Unexpected mirror hierarchy');
|
||||
assertEquals('internalProperty', internalProperties[i].type(), 'Unexpected mirror type');
|
||||
}
|
||||
|
||||
for (var p in obj) {
|
||||
var property_mirror = mirror.property(p);
|
||||
assertTrue(property_mirror instanceof debug.PropertyMirror);
|
||||
@ -172,6 +179,7 @@ testObjectMirror(this, 'global', '', true); // Global object has special proper
|
||||
testObjectMirror(this.__proto__, 'Object', '');
|
||||
testObjectMirror([], 'Array', 'Array');
|
||||
testObjectMirror([1,2], 'Array', 'Array');
|
||||
testObjectMirror(Object(17), 'Number', 'Number');
|
||||
|
||||
// Test circular references.
|
||||
o = {};
|
||||
@ -230,3 +238,29 @@ assertTrue(mirror.property('length').isNative());
|
||||
assertEquals('a', mirror.property(0).value().value());
|
||||
assertEquals('b', mirror.property(1).value().value());
|
||||
assertEquals('c', mirror.property(2).value().value());
|
||||
|
||||
// Test value wrapper internal properties.
|
||||
mirror = debug.MakeMirror(Object("Capybara"));
|
||||
var ip = mirror.internalProperties();
|
||||
assertEquals(1, ip.length);
|
||||
assertEquals("[[PrimitiveValue]]", ip[0].name());
|
||||
assertEquals("string", ip[0].value().type());
|
||||
assertEquals("Capybara", ip[0].value().value());
|
||||
|
||||
// Test bound function internal properties.
|
||||
mirror = debug.MakeMirror(Number.bind(Array, 2));
|
||||
ip = mirror.internalProperties();
|
||||
assertEquals(3, ip.length);
|
||||
var property_map = {};
|
||||
for (var i = 0; i < ip.length; i++) {
|
||||
property_map[ip[i].name()] = ip[i];
|
||||
}
|
||||
assertTrue("[[BoundThis]]" in property_map);
|
||||
assertEquals("function", property_map["[[BoundThis]]"].value().type());
|
||||
assertEquals(Array, property_map["[[BoundThis]]"].value().value());
|
||||
assertTrue("[[TargetFunction]]" in property_map);
|
||||
assertEquals("function", property_map["[[TargetFunction]]"].value().type());
|
||||
assertEquals(Number, property_map["[[TargetFunction]]"].value().value());
|
||||
assertTrue("[[BoundArgs]]" in property_map);
|
||||
assertEquals("object", property_map["[[BoundArgs]]"].value().type());
|
||||
assertEquals(1, property_map["[[BoundArgs]]"].value().value().length);
|
||||
|
Loading…
Reference in New Issue
Block a user