Commit bda5ce9c authored by peter.rybin@gmail.com's avatar peter.rybin@gmail.com

Introduce InternalProperty type and expose internal properties for bound functions

Committed: https://code.google.com/p/v8/source/detail?r=12346

Review URL: https://chromiumcodereview.appspot.com/10834376

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12477 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 266cca47
...@@ -154,6 +154,7 @@ var FUNCTION_TYPE = 'function'; ...@@ -154,6 +154,7 @@ var FUNCTION_TYPE = 'function';
var REGEXP_TYPE = 'regexp'; var REGEXP_TYPE = 'regexp';
var ERROR_TYPE = 'error'; var ERROR_TYPE = 'error';
var PROPERTY_TYPE = 'property'; var PROPERTY_TYPE = 'property';
var INTERNAL_PROPERTY_TYPE = 'internalProperty';
var FRAME_TYPE = 'frame'; var FRAME_TYPE = 'frame';
var SCRIPT_TYPE = 'script'; var SCRIPT_TYPE = 'script';
var CONTEXT_TYPE = 'context'; var CONTEXT_TYPE = 'context';
...@@ -212,6 +213,7 @@ var ScopeType = { Global: 0, ...@@ -212,6 +213,7 @@ var ScopeType = { Global: 0,
// - RegExpMirror // - RegExpMirror
// - ErrorMirror // - ErrorMirror
// - PropertyMirror // - PropertyMirror
// - InternalPropertyMirror
// - FrameMirror // - FrameMirror
// - ScriptMirror // - ScriptMirror
...@@ -357,6 +359,15 @@ Mirror.prototype.isProperty = function() { ...@@ -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. * Check whether the mirror reflects a stack frame.
* @returns {boolean} True if the mirror reflects a stack frame * @returns {boolean} True if the mirror reflects a stack frame
...@@ -594,23 +605,6 @@ ObjectMirror.prototype.protoObject = function() { ...@@ -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() { ObjectMirror.prototype.hasNamedInterceptor = function() {
// Get information on interceptors for this object. // Get information on interceptors for this object.
var x = %GetInterceptorInfo(this.value_); var x = %GetInterceptorInfo(this.value_);
...@@ -701,7 +695,7 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) { ...@@ -701,7 +695,7 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
* Return the properties for this object as an array of PropertyMirror objects. * Return the properties for this object as an array of PropertyMirror objects.
* @param {number} kind Indicate whether named, indexed or both kinds of * @param {number} kind Indicate whether named, indexed or both kinds of
* properties are requested * 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 specified value
* @return {Array} Property mirrors for this object * @return {Array} Property mirrors for this object
*/ */
...@@ -716,6 +710,16 @@ ObjectMirror.prototype.properties = function(kind, limit) { ...@@ -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) { ObjectMirror.prototype.property = function(name) {
var details = %DebugGetPropertyDetails(this.value_, %ToString(name)); var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
if (details) { if (details) {
...@@ -789,6 +793,37 @@ ObjectMirror.prototype.toText = function() { ...@@ -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. * Mirror object for functions.
* @param {function} value The function object reflected by this mirror. * @param {function} value The function object reflected by this mirror.
...@@ -1268,6 +1303,33 @@ PropertyMirror.prototype.isNative = function() { ...@@ -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 kFrameDetailsFrameIdIndex = 0;
var kFrameDetailsReceiverIndex = 1; var kFrameDetailsReceiverIndex = 1;
var kFrameDetailsFunctionIndex = 2; var kFrameDetailsFunctionIndex = 2;
...@@ -2202,7 +2264,8 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference, ...@@ -2202,7 +2264,8 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
break; break;
case PROPERTY_TYPE: case PROPERTY_TYPE:
throw new Error('PropertyMirror cannot be serialized independeltly'); case INTERNAL_PROPERTY_TYPE:
throw new Error('PropertyMirror cannot be serialized independently');
break; break;
case FRAME_TYPE: case FRAME_TYPE:
...@@ -2278,7 +2341,8 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference, ...@@ -2278,7 +2341,8 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
* "prototypeObject":{"ref":<number>}, * "prototypeObject":{"ref":<number>},
* "namedInterceptor":<boolean>, * "namedInterceptor":<boolean>,
* "indexedInterceptor":<boolean>, * "indexedInterceptor":<boolean>,
* "properties":[<properties>]} * "properties":[<properties>],
* "internalProperties":[<internal properties>]}
*/ */
JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content, JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
details) { details) {
...@@ -2289,11 +2353,6 @@ JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content, ...@@ -2289,11 +2353,6 @@ JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
content.protoObject = this.serializeReference(mirror.protoObject()); content.protoObject = this.serializeReference(mirror.protoObject());
content.prototypeObject = this.serializeReference(mirror.prototypeObject()); 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. // Add flags to indicate whether there are interceptors.
if (mirror.hasNamedInterceptor()) { if (mirror.hasNamedInterceptor()) {
content.namedInterceptor = true; content.namedInterceptor = true;
...@@ -2355,6 +2414,15 @@ JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content, ...@@ -2355,6 +2414,15 @@ JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
} }
} }
content.properties = p; 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) { ...@@ -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) { JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
content.index = mirror.index(); content.index = mirror.index();
content.receiver = this.serializeReference(mirror.receiver()); content.receiver = this.serializeReference(mirror.receiver());
......
// 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -49,19 +49,19 @@ function testObjectMirror(obj, cls_name, ctor_name, hasSpecialProperties) { ...@@ -49,19 +49,19 @@ function testObjectMirror(obj, cls_name, ctor_name, hasSpecialProperties) {
JSON.stringify(serializer.serializeReferencedObjects())); JSON.stringify(serializer.serializeReferencedObjects()));
// Check the mirror hierachy. // Check the mirror hierachy.
assertTrue(mirror instanceof debug.Mirror, 'Unexpected mirror hierachy'); assertTrue(mirror instanceof debug.Mirror, 'Unexpected mirror hierarchy');
assertTrue(mirror instanceof debug.ValueMirror, 'Unexpected mirror hierachy'); assertTrue(mirror instanceof debug.ValueMirror, 'Unexpected mirror hierarchy');
assertTrue(mirror instanceof debug.ObjectMirror, 'Unexpected mirror hierachy'); assertTrue(mirror instanceof debug.ObjectMirror, 'Unexpected mirror hierarchy');
// Check the mirror properties. // Check the mirror properties.
assertTrue(mirror.isObject(), 'Unexpected mirror'); assertTrue(mirror.isObject(), 'Unexpected mirror');
assertEquals('object', mirror.type(), 'Unexpected mirror type'); assertEquals('object', mirror.type(), 'Unexpected mirror type');
assertFalse(mirror.isPrimitive(), 'Unexpected primitive mirror'); assertFalse(mirror.isPrimitive(), 'Unexpected primitive mirror');
assertEquals(cls_name, mirror.className(), 'Unexpected mirror class name'); 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'); assertEquals(ctor_name, mirror.constructorFunction().name(), 'Unexpected constructor function name');
assertTrue(mirror.protoObject() instanceof debug.Mirror, 'Unexpected mirror hierachy'); assertTrue(mirror.protoObject() instanceof debug.Mirror, 'Unexpected mirror hierarchy');
assertTrue(mirror.prototypeObject() instanceof debug.Mirror, 'Unexpected mirror hierachy'); assertTrue(mirror.prototypeObject() instanceof debug.Mirror, 'Unexpected mirror hierarchy');
assertFalse(mirror.hasNamedInterceptor(), 'No named interceptor expected'); assertFalse(mirror.hasNamedInterceptor(), 'No named interceptor expected');
assertFalse(mirror.hasIndexedInterceptor(), 'No indexed interceptor expected'); assertFalse(mirror.hasIndexedInterceptor(), 'No indexed interceptor expected');
...@@ -69,12 +69,19 @@ function testObjectMirror(obj, cls_name, ctor_name, hasSpecialProperties) { ...@@ -69,12 +69,19 @@ function testObjectMirror(obj, cls_name, ctor_name, hasSpecialProperties) {
var properties = mirror.properties(); var properties = mirror.properties();
assertEquals(names.length, properties.length); assertEquals(names.length, properties.length);
for (var i = 0; i < properties.length; i++) { for (var i = 0; i < properties.length; i++) {
assertTrue(properties[i] instanceof debug.Mirror, 'Unexpected mirror hierachy'); assertTrue(properties[i] instanceof debug.Mirror, 'Unexpected mirror hierarchy');
assertTrue(properties[i] instanceof debug.PropertyMirror, 'Unexpected mirror hierachy'); assertTrue(properties[i] instanceof debug.PropertyMirror, 'Unexpected mirror hierarchy');
assertEquals('property', properties[i].type(), 'Unexpected mirror type'); assertEquals('property', properties[i].type(), 'Unexpected mirror type');
assertEquals(names[i], properties[i].name(), 'Unexpected property name'); 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) { for (var p in obj) {
var property_mirror = mirror.property(p); var property_mirror = mirror.property(p);
assertTrue(property_mirror instanceof debug.PropertyMirror); assertTrue(property_mirror instanceof debug.PropertyMirror);
...@@ -172,6 +179,7 @@ testObjectMirror(this, 'global', '', true); // Global object has special proper ...@@ -172,6 +179,7 @@ testObjectMirror(this, 'global', '', true); // Global object has special proper
testObjectMirror(this.__proto__, 'Object', ''); testObjectMirror(this.__proto__, 'Object', '');
testObjectMirror([], 'Array', 'Array'); testObjectMirror([], 'Array', 'Array');
testObjectMirror([1,2], 'Array', 'Array'); testObjectMirror([1,2], 'Array', 'Array');
testObjectMirror(Object(17), 'Number', 'Number');
// Test circular references. // Test circular references.
o = {}; o = {};
...@@ -230,3 +238,29 @@ assertTrue(mirror.property('length').isNative()); ...@@ -230,3 +238,29 @@ assertTrue(mirror.property('length').isNative());
assertEquals('a', mirror.property(0).value().value()); assertEquals('a', mirror.property(0).value().value());
assertEquals('b', mirror.property(1).value().value()); assertEquals('b', mirror.property(1).value().value());
assertEquals('c', mirror.property(2).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);
...@@ -85,8 +85,10 @@ compiler/regress-stacktrace-methods: PASS, PASS || TIMEOUT if $mode == release ...@@ -85,8 +85,10 @@ compiler/regress-stacktrace-methods: PASS, PASS || TIMEOUT if $mode == release
array-splice: PASS || TIMEOUT array-splice: PASS || TIMEOUT
# Long running test. # Long running test.
mirror-object: PASS || TIMEOUT
string-indexof-2: PASS || TIMEOUT string-indexof-2: PASS || TIMEOUT
# BUG(2314): Crankshaft generates incorrect (crashing) code on ARM
# mirror-object: PASS || TIMEOUT
mirror-object: SKIP
# BUG(3251035): Timeouts in long looping crankshaft optimization # BUG(3251035): Timeouts in long looping crankshaft optimization
# tests. Skipping because having them timeout takes too long on the # tests. Skipping because having them timeout takes too long on the
......
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