diff --git a/src/debug-delay.js b/src/debug-delay.js index 24b83a53cc..d38894652c 100644 --- a/src/debug-delay.js +++ b/src/debug-delay.js @@ -994,22 +994,25 @@ ResponsePacket.prototype.toJSONProtocol = function() { if (this.body) { json += ',"body":'; // Encode the body part. - if (this.body.toJSONProtocol) { - json += this.body.toJSONProtocol(true); + var serializer = MakeMirrorSerializer(true); + if (this.body instanceof Mirror) { + json += serializer.serializeValue(this.body); } else if (this.body instanceof Array) { json += '['; for (var i = 0; i < this.body.length; i++) { if (i != 0) json += ','; - if (this.body[i].toJSONProtocol) { - json += this.body[i].toJSONProtocol(true) + if (this.body[i] instanceof Mirror) { + json += serializer.serializeValue(this.body[i]); } else { - json += SimpleObjectToJSON_(this.body[i]); + json += SimpleObjectToJSON_(this.body[i], serializer); } } json += ']'; } else { - json += SimpleObjectToJSON_(this.body); + json += SimpleObjectToJSON_(this.body, serializer); } + json += ',"refs":'; + json += serializer.serializeReferencedObjects(); } if (this.message) { json += ',"message":' + StringToJSON_(this.message) ; @@ -1568,9 +1571,11 @@ DebugCommandProcessor.prototype.formatCFrame = function(cframe_value) { * a general implementation but sufficient for the debugger. Note that circular * structures will cause infinite recursion. * @param {Object} object The object to format as JSON + * @param {MirrorSerializer} mirror_serializer The serializer to use if any + * mirror objects are encountered. * @return {string} JSON formatted object value */ -function SimpleObjectToJSON_(object) { +function SimpleObjectToJSON_(object, mirror_serializer) { var content = []; for (var key in object) { // Only consider string keys. @@ -1584,9 +1589,9 @@ function SimpleObjectToJSON_(object) { if (typeof property_value.toJSONProtocol == 'function') { property_value_json = property_value.toJSONProtocol(true) } else if (IS_ARRAY(property_value)){ - property_value_json = SimpleArrayToJSON_(property_value); + property_value_json = SimpleArrayToJSON_(property_value, mirror_serializer); } else { - property_value_json = SimpleObjectToJSON_(property_value); + property_value_json = SimpleObjectToJSON_(property_value, mirror_serializer); } break; @@ -1620,10 +1625,12 @@ function SimpleObjectToJSON_(object) { /** * Convert an array to its JSON representation. This is a VERY simple * implementation just to support what is needed for the debugger. - * @param {Array} arrya The array to format as JSON + * @param {Array} array The array to format as JSON + * @param {MirrorSerializer} mirror_serializer The serializer to use if any + * mirror objects are encountered. * @return {string} JSON formatted array value */ -function SimpleArrayToJSON_(array) { +function SimpleArrayToJSON_(array, mirror_serializer) { // Make JSON array representation. var json = '['; for (var i = 0; i < array.length; i++) { @@ -1631,8 +1638,8 @@ function SimpleArrayToJSON_(array) { json += ','; } var elem = array[i]; - if (elem.toJSONProtocol) { - json += elem.toJSONProtocol(true) + if (elem instanceof Mirror) { + json += mirror_serializer.serializeValue(elem); } else if (IS_OBJECT(elem)) { json += SimpleObjectToJSON_(elem); } else if (IS_BOOLEAN(elem)) { diff --git a/src/debug.cc b/src/debug.cc index 368a9755d0..ef059addc8 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -1303,6 +1303,22 @@ bool Debug::IsDebugGlobal(GlobalObject* global) { } +void Debug::ClearMirrorCache() { + ASSERT(Top::context() == *Debug::debug_context()); + + // Clear the mirror cache. + Handle function_name = + Factory::LookupSymbol(CStrVector("ClearMirrorCache")); + Handle fun(Top::global()->GetProperty(*function_name)); + ASSERT(fun->IsJSFunction()); + bool caught_exception; + Handle js_object = Execution::TryCall( + Handle::cast(fun), + Handle(Debug::debug_context()->global()), + 0, NULL, &caught_exception); +} + + bool Debugger::debugger_active_ = false; bool Debugger::compiling_natives_ = false; bool Debugger::is_loading_debugger_ = false; @@ -1628,6 +1644,9 @@ void Debugger::ProcessDebugEvent(v8::DebugEvent event, } } } + + // Clear the mirror cache. + Debug::ClearMirrorCache(); } diff --git a/src/debug.h b/src/debug.h index 56b8026226..66f54bb0c9 100644 --- a/src/debug.h +++ b/src/debug.h @@ -260,6 +260,9 @@ class Debug { static char* RestoreDebug(char* from); static int ArchiveSpacePerThread(); + // Mirror cache handling. + static void ClearMirrorCache(); + // Code generation assumptions. static const int kIa32CallInstructionLength = 5; static const int kIa32JSReturnSequenceLength = 6; diff --git a/src/mirror-delay.js b/src/mirror-delay.js index 7e25501e0d..538d004b1a 100644 --- a/src/mirror-delay.js +++ b/src/mirror-delay.js @@ -33,6 +33,18 @@ RegExp; Date; +var next_handle_ = 0; +var mirror_cache_ = []; + +/** + * Clear the mirror handle cache. + */ +function ClearMirrorCache() { + next_handle_ = 0; + mirror_cache_ = []; +} + + /** * Returns the mirror for a specified value or object. * @@ -40,17 +52,50 @@ Date; * @returns {Mirror} the mirror reflects the passed value or object */ function MakeMirror(value) { - if (IS_UNDEFINED(value)) return new UndefinedMirror(); - if (IS_NULL(value)) return new NullMirror(); - if (IS_BOOLEAN(value)) return new BooleanMirror(value); - if (IS_NUMBER(value)) return new NumberMirror(value); - if (IS_STRING(value)) return new StringMirror(value); - if (IS_ARRAY(value)) return new ArrayMirror(value); - if (IS_DATE(value)) return new DateMirror(value); - if (IS_FUNCTION(value)) return new FunctionMirror(value); - if (IS_REGEXP(value)) return new RegExpMirror(value); - if (IS_ERROR(value)) return new ErrorMirror(value); - return new ObjectMirror(value); + var mirror; + for (id in mirror_cache_) { + mirror = mirror_cache_[id]; + if (mirror.value() === value) { + return mirror; + } + } + + if (IS_UNDEFINED(value)) { + mirror = new UndefinedMirror(); + } else if (IS_NULL(value)) { + mirror = new NullMirror(); + } else if (IS_BOOLEAN(value)) { + mirror = new BooleanMirror(value); + } else if (IS_NUMBER(value)) { + mirror = new NumberMirror(value); + } else if (IS_STRING(value)) { + mirror = new StringMirror(value); + } else if (IS_ARRAY(value)) { + mirror = new ArrayMirror(value); + } else if (IS_DATE(value)) { + mirror = new DateMirror(value); + } else if (IS_FUNCTION(value)) { + mirror = new FunctionMirror(value); + } else if (IS_REGEXP(value)) { + mirror = new RegExpMirror(value); + } else if (IS_ERROR(value)) { + mirror = new ErrorMirror(value); + } else { + mirror = new ObjectMirror(value); + } + + mirror_cache_[mirror.handle()] = mirror; + return mirror; +} + + +/** + * Returns the mirror for the undifined value. + * + * @returns {Mirror} the mirror reflects the undifined value + */ +function GetUndefinedMirror() { + return MakeMirror(void 0); } @@ -87,7 +132,6 @@ const FUNCTION_TYPE = 'function'; const REGEXP_TYPE = 'regexp'; const ERROR_TYPE = 'error'; const PROPERTY_TYPE = 'property'; -const ACCESSOR_TYPE = 'accessor'; const FRAME_TYPE = 'frame'; const SCRIPT_TYPE = 'script'; @@ -154,6 +198,15 @@ Mirror.prototype.type = function() { }; +/** + * Check whether the mirror reflects a value. + * @returns {boolean} True if the mirror reflects a value. + */ +Mirror.prototype.isValue = function() { + return this instanceof ValueMirror; +} + + /** * Check whether the mirror reflects the undefined value. * @returns {boolean} True if the mirror reflects the undefined value. @@ -289,18 +342,6 @@ Mirror.prototype.isScript = function() { } -/** - * Serialize object in JSON format. The actual serialization is handled by the - * JSONProtocolSerializer. - * @param {boolean} details Indicate level of details to include - * @return {string} JSON serialization - */ -Mirror.prototype.toJSONProtocol = function(details) { - var serializer = new JSONProtocolSerializer(details) - return serializer.serialize(this) -} - - Mirror.prototype.toText = function() { // Simpel to text which is used when on specialization in subclass. return "#<" + builtins.GetInstanceName(this.constructor.name) + ">"; @@ -316,11 +357,17 @@ Mirror.prototype.toText = function() { */ function ValueMirror(type, value) { Mirror.call(this, type); + this.handle_ = next_handle_++; this.value_ = value; } inherits(ValueMirror, Mirror); +Mirror.prototype.handle = function() { + return this.handle_; +}; + + /** * Check whether this is a primitive value. * @return {boolean} True if the mirror reflects a primitive value @@ -335,7 +382,7 @@ ValueMirror.prototype.isPrimitive = function() { }; - /** +/** * Get the actual value reflected by this mirror. * @return {value} The value reflected by this mirror */ @@ -581,7 +628,7 @@ ObjectMirror.prototype.property = function(name) { } // Nothing found. - return new UndefinedMirror(); + return GetUndefinedMirror(); }; @@ -608,7 +655,7 @@ ObjectMirror.prototype.lookupProperty = function(value) { } // Nothing found. - return new UndefinedMirror(); + return GetUndefinedMirror(); }; @@ -687,8 +734,6 @@ FunctionMirror.prototype.source = function() { // Return source if function is resolved. Otherwise just fall through to // return undefined. if (this.resolved()) { - // This builtins function is context independant (only uses runtime - // calls and typeof. return builtins.FunctionSourceString(this.value_); } }; @@ -763,17 +808,17 @@ UnresolvedFunctionMirror.prototype.className = function() { UnresolvedFunctionMirror.prototype.constructorFunction = function() { - return new UndefinedMirror(); + return GetUndefinedMirror(); }; UnresolvedFunctionMirror.prototype.prototypeObject = function() { - return new UndefinedMirror(); + return GetUndefinedMirror(); }; UnresolvedFunctionMirror.prototype.protoObject = function() { - return new UndefinedMirror(); + return GetUndefinedMirror(); }; @@ -815,7 +860,7 @@ ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, opt_ if (details) { value = new PropertyMirror(this, i, details); } else { - value = new UndefinedMirror(); + value = GetUndefinedMirror(); } values[i - from_index] = value; } @@ -1225,7 +1270,7 @@ FrameMirror.prototype.func = function() { // value returned from the VM might be a string if the function for the // frame is unresolved. if (IS_FUNCTION(f)) { - return new FunctionMirror(f); + return MakeMirror(f); } else { return new UnresolvedFunctionMirror(f); } @@ -1345,7 +1390,7 @@ FrameMirror.prototype.invocationText = function() { } // Try to find the function as a property in the receiver. Include the // prototype chain in the lookup. - var property = new UndefinedMirror(); + var property = GetUndefinedMirror(); if (!receiver.isUndefined()) { for (var r = receiver; !r.isNull() && property.isUndefined(); r = r.protoObject()) { property = r.lookupProperty(func); @@ -1526,16 +1571,106 @@ ScriptMirror.prototype.toText = function() { } -function JSONProtocolSerializer(details) { - this.details_ = details; +/** + * Returns a mirror serializer + * + * @param {boolean} details Set to true to include details + * @returns {MirrorSerializer} mirror serializer + */ +function MakeMirrorSerializer(details) { + return new JSONProtocolSerializer(details); } -JSONProtocolSerializer.prototype.serialize = function(mirror) { - // Collect the JSON property/value pairs in a array. +/** + * Object for serializing a mirror objects and its direct references. + * @param {boolean} details Indicates whether to include details for the mirror + * serialized + * @constructor + */ +function JSONProtocolSerializer(details) { + this.details_ = details; + this.mirrors_ = [ ]; +} + + +/** + * Returns a serialization of an object reference. The referenced object are + * added to the serialization state. + * + * @param {Mirror} mirror The mirror to serialize + * @returns {String} JSON serialization + */ +JSONProtocolSerializer.prototype.serializeReference = function(mirror) { + return this.serialize_(mirror, true, true); +} + + +/** + * Returns a serialization of an object value. The referenced objects are + * added to the serialization state. + * + * @param {Mirror} mirror The mirror to serialize + * @returns {String} JSON serialization + */ +JSONProtocolSerializer.prototype.serializeValue = function(mirror) { + var json = this.serialize_(mirror, false, true); + return json; +} + + +/** + * Returns a serialization of all the objects referenced. + * + * @param {Mirror} mirror The mirror to serialize + * @returns {String} JSON serialization + */ +JSONProtocolSerializer.prototype.serializeReferencedObjects = function() { + // Collect the JSON serialization of the referenced objects in an array. + var content = new Array(); + + // Get the number of referenced objects. + var count = this.mirrors_.length; + + for (var i = 0; i < count; i++) { + content.push(this.serialize_(this.mirrors_[i], false, false)); + } + + var json = ArrayToJSONArray_(content); + return json; +} + + +JSONProtocolSerializer.prototype.add_ = function(mirror) { + // If this mirror is already in the list just return. + for (var i = 0; i < this.mirrors_.length; i++) { + if (this.mirrors_[i] === mirror) { + return; + } + } + + // Add the mirror to the list of mirrors to be serialized. + this.mirrors_.push(mirror); +} + + +JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference, details) { + // If serializing a reference to a value just return the reference and add the + // mirror to the referenced mirrors. + if (reference && mirror.isValue()) { + this.add_(mirror); + return '{ref:' + mirror.handle() + '}'; + } + + // Collect the JSON property/value pairs in an array. var content = new Array(); - // Always add the type + // Add the handle for value mirrors. + if (mirror.isValue()) { + content.push(MakeJSONPair_('handle', NumberToJSON_(mirror.handle()))); + } + + // Always add the type. content.push(MakeJSONPair_('type', StringToJSON_(mirror.type()))); switch (mirror.type()) { @@ -1573,35 +1708,11 @@ JSONProtocolSerializer.prototype.serialize = function(mirror) { case ERROR_TYPE: case REGEXP_TYPE: // Add object representation. - this.serializeObject_(mirror, content); + this.serializeObject_(mirror, content, details); break; case PROPERTY_TYPE: - // Properties are represented by name, value, attributes and type. - content.push(MakeJSONPair_('name', - StringToJSON_(mirror.name()))); - content.push(MakeJSONPair_('value', - mirror.value().toJSONProtocol(this.details_))); - if (mirror.attributes() != PropertyAttribute.None) { - content.push(MakeJSONPair_('attributes', - NumberToJSON_(mirror.attributes()))); - } - if (mirror.propertyType() != PropertyType.Normal) { - content.push(MakeJSONPair_('propertyType', - NumberToJSON_(mirror.propertyType()))); - } - break; - - case ACCESSOR_TYPE: - // An accessor can either be native or defined through JavaScript. - if (mirror.isNative()) { - content.push(MakeJSONPair_('native', BooleanToJSON_(true))); - } else { - content.push(MakeJSONPair_('getter', - mirror.getter().toJSONProtocol(false))); - content.push(MakeJSONPair_('setter', - mirror.setter().toJSONProtocol(false))); - } + throw new Error('PropertyMirror cannot be serialized independeltly') break; case FRAME_TYPE: @@ -1623,7 +1734,6 @@ JSONProtocolSerializer.prototype.serialize = function(mirror) { content.push(MakeJSONPair_('scriptType', NumberToJSON_(mirror.scriptType()))); break; - } // Always add the text representation. @@ -1634,86 +1744,120 @@ JSONProtocolSerializer.prototype.serialize = function(mirror) { } -JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content) { +/** + * Serialize object information to the following JSON format. + * + * {"className":"", + * "constructorFunction":{"ref":}, + * "protoObject":{"ref":}, + * "prototypeObject":{"ref":}, + * "namedInterceptor":, + * "indexedInterceptor":, + * "properties":[]} + */ +JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content, details) { + // Add general object properties. content.push(MakeJSONPair_('className', StringToJSON_(mirror.className()))); + content.push(MakeJSONPair_('constructorFunction', + this.serializeReference(mirror.constructorFunction()))); + content.push(MakeJSONPair_('protoObject', + this.serializeReference(mirror.protoObject()))); + content.push(MakeJSONPair_('prototypeObject', + this.serializeReference(mirror.prototypeObject()))); - if (this.details_) { - content.push(MakeJSONPair_('constructorFunction', - mirror.constructorFunction().toJSONProtocol(false))); - content.push(MakeJSONPair_('protoObject', - mirror.protoObject().toJSONProtocol(false))); - content.push(MakeJSONPair_('prototypeObject', - mirror.prototypeObject().toJSONProtocol(false))); - - // Add properties. For arrays don't include indexed proeprties. - var kind = PropertyKind.Named; - if (!mirror.isArray()) { - kind |= PropertyKind.Indexed - } - var propertyNames = mirror.propertyNames(kind); - var x = new Array(propertyNames.length); - for (var i = 0; i < propertyNames.length; i++) { - x[i] = mirror.property(propertyNames[i]).toJSONProtocol(false); - } - content.push(MakeJSONPair_('properties', ArrayToJSONArray_(x))); - - // For arrays the indexed properties are added separately and the length is - // added as well. - if (mirror.isArray()) { - var propertyNames = mirror.propertyNames(PropertyKind.Indexed); - var x = new Array(propertyNames.length); - for (var i = 0; i < propertyNames.length; i++) { - x[i] = mirror.property(propertyNames[i]).toJSONProtocol(false); - } - content.push(MakeJSONPair_('indexedProperties', ArrayToJSONArray_(x))); - - // Add the array length. - content.push(MakeJSONPair_('length', NumberToJSON_(mirror.length()))); - } - } - + // Add flags to indicate whether there are interceptors. if (mirror.hasNamedInterceptor()) { content.push(MakeJSONPair_('namedInterceptor', BooleanToJSON_(true))); } - if (mirror.hasIndexedInterceptor()) { content.push(MakeJSONPair_('indexedInterceptor', BooleanToJSON_(true))); } + // Add function specific properties. if (mirror.isFunction()) { // Add function specific properties. content.push(MakeJSONPair_('name', StringToJSON_(mirror.name()))); content.push(MakeJSONPair_('resolved', BooleanToJSON_(mirror.resolved()))); - if (this.details_ && mirror.resolved()) { + if (mirror.resolved()) { content.push(MakeJSONPair_('source', StringToJSON_(mirror.source()))); } if (mirror.script()) { - content.push(MakeJSONPair_('script', mirror.script().toJSONProtocol())); + content.push(MakeJSONPair_('script', this.serializeValue(mirror.script()))); } - } else if (mirror.isDate()) { + } + + // Add date specific properties. + if (mirror.isDate()) { // Add date specific properties. content.push(MakeJSONPair_('value', DateToJSON_(mirror.value()))); - } else if (mirror.isRegExp()) { - // Add regexp specific properties. - content.push(MakeJSONPair_('source', StringToJSON_(mirror.source()))); - content.push(MakeJSONPair_('global', BooleanToJSON_(mirror.global()))); - content.push(MakeJSONPair_('ignoreCase', - BooleanToJSON_(mirror.ignoreCase()))); - content.push(MakeJSONPair_('multiline', - BooleanToJSON_(mirror.multiline()))); - } else if (mirror.isError()) { - // Add error specific properties. - content.push(MakeJSONPair_('message', StringToJSON_(mirror.message()))); } + + // Add actual properties - named properties followed by indexed properties. + var propertyNames = mirror.propertyNames(PropertyKind.Named); + var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed); + var p = new Array(propertyNames.length + propertyIndexes.length); + for (var i = 0; i < propertyNames.length; i++) { + var property_mirror = mirror.property(propertyNames[i]); + p[i] = this.serializeProperty_(property_mirror); + if (details) { + this.add_(property_mirror.value()); + } + } + for (var i = 0; i < propertyIndexes.length; i++) { + var property_mirror = mirror.property(propertyIndexes[i]); + p[propertyNames.length + i] = this.serializeProperty_(property_mirror); + if (details) { + this.add_(property_mirror.value()); + } + } + content.push(MakeJSONPair_('properties', ArrayToJSONArray_(p))); +} + + +/** + * Serialize property information to the following JSON format for building the + * array of properties. + * + * {"name":"", + * "attributes":, + * "propertyType":, + * "ref":} + * + * If the attribute for the property is PropertyAttribute.None it is not added. + * If the propertyType for the property is PropertyType.Normal it is not added. + * Here are a couple of examples. + * + * {"name":"hello","ref":1} + * {"name":"length","attributes":7,"propertyType":3,"ref":2} + * + * @param {PropertyMirror} property_mirror The property to serialize + * @returns {String} JSON serialization + */ +JSONProtocolSerializer.prototype.serializeProperty_ = function(property_mirror) { + var builder = new builtins.StringBuilder(); + builder.add('{"name":'); + builder.add(StringToJSON_(property_mirror.name())); + if (property_mirror.attributes() != PropertyAttribute.None) { + builder.add(',"attributes":'); + builder.add(NumberToJSON_(property_mirror.attributes())); + } + if (property_mirror.propertyType() != PropertyType.Normal) { + builder.add(',"propertyType":'); + builder.add(NumberToJSON_(property_mirror.propertyType())); + } + builder.add(',"ref":'); + builder.add(NumberToJSON_(property_mirror.value().handle())); + builder.add('}'); + return builder.generate(); } JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) { content.push(MakeJSONPair_('index', NumberToJSON_(mirror.index()))); content.push(MakeJSONPair_('receiver', - mirror.receiver().toJSONProtocol(false))); - content.push(MakeJSONPair_('func', mirror.func().toJSONProtocol(false))); + this.serializeReference(mirror.receiver()))); + content.push(MakeJSONPair_('func', this.serializeReference(mirror.func()))); content.push(MakeJSONPair_('constructCall', BooleanToJSON_(mirror.isConstructCall()))); content.push(MakeJSONPair_('debuggerFrame', @@ -1726,7 +1870,7 @@ JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) { arg.push(MakeJSONPair_('name', StringToJSON_(argument_name))); } arg.push(MakeJSONPair_('value', - mirror.argumentValue(i).toJSONProtocol(false))); + this.serializeReference(mirror.argumentValue(i)))); x[i] = ArrayToJSONObject_(arg); } content.push(MakeJSONPair_('arguments', ArrayToJSONArray_(x))); @@ -1734,7 +1878,7 @@ JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) { for (var i = 0; i < mirror.localCount(); i++) { var name = MakeJSONPair_('name', StringToJSON_(mirror.localName(i))); var value = MakeJSONPair_('value', - mirror.localValue(i).toJSONProtocol(false)); + this.serializeReference(mirror.localValue(i))); x[i] = '{' + name + ',' + value + '}'; } content.push(MakeJSONPair_('locals', ArrayToJSONArray_(x))); diff --git a/test/mjsunit/debug-backtrace.js b/test/mjsunit/debug-backtrace.js index 91e1476209..db7a70a42a 100644 --- a/test/mjsunit/debug-backtrace.js +++ b/test/mjsunit/debug-backtrace.js @@ -43,14 +43,33 @@ Debug = debug.Debug listenerCalled = false; exception = false; -function safeEval(code) { - try { - return eval('(' + code + ')'); - } catch (e) { - return undefined; + +function ParsedResponse(json) { + this.response_ = eval('(' + json + ')'); + this.refs_ = []; + if (this.response_.refs) { + for (var i = 0; i < this.response_.refs.length; i++) { + this.refs_[this.response_.refs[i].handle] = this.response_.refs[i]; + } } } + +ParsedResponse.prototype.response = function() { + return this.response_; +} + + +ParsedResponse.prototype.body = function() { + return this.response_.body; +} + + +ParsedResponse.prototype.lookup = function(handle) { + return this.refs_[handle]; +} + + function listener(event, exec_state, event_data, data) { try { if (event == Debug.DebugEvent.Break) @@ -60,13 +79,19 @@ function listener(event, exec_state, event_data, data) { // 1: g // 2: [anonymous] + var response; + var backtrace; + var frame; + var source; + // Get the debug command processor. var dcp = exec_state.debugCommandProcessor(); // Get the backtrace. var json; json = '{"seq":0,"type":"request","command":"backtrace"}' - var backtrace = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + backtrace = response.body(); assertEquals(0, backtrace.fromFrame); assertEquals(3, backtrace.toFrame); assertEquals(3, backtrace.totalFrames); @@ -76,15 +101,16 @@ function listener(event, exec_state, event_data, data) { assertEquals('frame', frames[i].type); } assertEquals(0, frames[0].index); - assertEquals("f", frames[0].func.name); + assertEquals("f", response.lookup(frames[0].func.ref).name); assertEquals(1, frames[1].index); - assertEquals("g", frames[1].func.name); + assertEquals("g", response.lookup(frames[1].func.ref).name); assertEquals(2, frames[2].index); - assertEquals("", frames[2].func.name); + assertEquals("", response.lookup(frames[2].func.ref).name); // Get backtrace with two frames. json = '{"seq":0,"type":"request","command":"backtrace","arguments":{"fromFrame":1,"toFrame":3}}' - var backtrace = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + backtrace = response.body(); assertEquals(1, backtrace.fromFrame); assertEquals(3, backtrace.toFrame); assertEquals(3, backtrace.totalFrames); @@ -94,71 +120,77 @@ function listener(event, exec_state, event_data, data) { assertEquals('frame', frames[i].type); } assertEquals(1, frames[0].index); - assertEquals("g", frames[0].func.name); + assertEquals("g", response.lookup(frames[0].func.ref).name); assertEquals(2, frames[1].index); - assertEquals("", frames[1].func.name); + assertEquals("", response.lookup(frames[1].func.ref).name); // Get the individual frames. - var frame; json = '{"seq":0,"type":"request","command":"frame"}' - frame = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + frame = response.body(); assertEquals(0, frame.index); - assertEquals("f", frame.func.name); + assertEquals("f", response.lookup(frame.func.ref).name); assertTrue(frame.constructCall); assertEquals(31, frame.line); assertEquals(3, frame.column); assertEquals(2, frame.arguments.length); assertEquals('x', frame.arguments[0].name); - assertEquals('number', frame.arguments[0].value.type); - assertEquals(1, frame.arguments[0].value.value); + assertEquals('number', response.lookup(frame.arguments[0].value.ref).type); + assertEquals(1, response.lookup(frame.arguments[0].value.ref).value); assertEquals('y', frame.arguments[1].name); - assertEquals('undefined', frame.arguments[1].value.type); + assertEquals('undefined', response.lookup(frame.arguments[1].value.ref).type); json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":0}}' - frame = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + frame = response.body(); assertEquals(0, frame.index); - assertEquals("f", frame.func.name); + assertEquals("f", response.lookup(frame.func.ref).name); assertEquals(31, frame.line); assertEquals(3, frame.column); assertEquals(2, frame.arguments.length); assertEquals('x', frame.arguments[0].name); - assertEquals('number', frame.arguments[0].value.type); - assertEquals(1, frame.arguments[0].value.value); + assertEquals('number', response.lookup(frame.arguments[0].value.ref).type); + assertEquals(1, response.lookup(frame.arguments[0].value.ref).value); assertEquals('y', frame.arguments[1].name); - assertEquals('undefined', frame.arguments[1].value.type); + assertEquals('undefined', response.lookup(frame.arguments[1].value.ref).type); json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":1}}' - frame = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + frame = response.body(); assertEquals(1, frame.index); - assertEquals("g", frame.func.name); + assertEquals("g", response.lookup(frame.func.ref).name); assertFalse(frame.constructCall); assertEquals(35, frame.line); assertEquals(2, frame.column); assertEquals(0, frame.arguments.length); json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":2}}' - frame = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + frame = response.body(); assertEquals(2, frame.index); - assertEquals("", frame.func.name); + assertEquals("", response.lookup(frame.func.ref).name); // Source slices for the individual frames (they all refer to this script). json = '{"seq":0,"type":"request","command":"source",' + '"arguments":{"frame":0,"fromLine":30,"toLine":32}}' - source = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + source = response.body(); assertEquals("function f(x, y) {", source.source.substring(0, 18)); assertEquals(30, source.fromLine); assertEquals(32, source.toLine); json = '{"seq":0,"type":"request","command":"source",' + '"arguments":{"frame":1,"fromLine":31,"toLine":32}}' - source = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + source = response.body(); assertEquals(" a=1;", source.source.substring(0, 6)); assertEquals(31, source.fromLine); assertEquals(32, source.toLine); json = '{"seq":0,"type":"request","command":"source",' + '"arguments":{"frame":2,"fromLine":35,"toLine":36}}' - source = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + source = response.body(); assertEquals(" new f(1);", source.source.substring(0, 11)); assertEquals(35, source.fromLine); assertEquals(36, source.toLine); @@ -166,12 +198,13 @@ function listener(event, exec_state, event_data, data) { // Test line interval way beyond this script will result in an error. json = '{"seq":0,"type":"request","command":"source",' + '"arguments":{"frame":0,"fromLine":10000,"toLine":20000}}' - response = safeEval(dcp.processDebugJSONRequest(json)); - assertFalse(response.success); + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + assertFalse(response.response().success); // Test without arguments. json = '{"seq":0,"type":"request","command":"source"}' - source = safeEval(dcp.processDebugJSONRequest(json)).body; + response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + source = response.body(); assertEquals(Debug.findScript(f).source, source.source); listenerCalled = true; diff --git a/test/mjsunit/debug-mirror-cache.js b/test/mjsunit/debug-mirror-cache.js new file mode 100644 index 0000000000..0dc040517c --- /dev/null +++ b/test/mjsunit/debug-mirror-cache.js @@ -0,0 +1,85 @@ +// Copyright 2008 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --expose-debug-as debug +// The functions used for testing backtraces. They are at the top to make the +// testing of source line/column easier. +function f(x, y) { + a=1; +}; + +function g() { + new f(1); +}; + + +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug + +listenerCallCount = 0; +listenerExceptionCount = 0; + + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) + { + listenerCallCount++; + + // Check that mirror cache is cleared when entering debugger. + assertEquals(0, debug.next_handle_, "Mirror cache not cleared"); + assertEquals(0, debug.mirror_cache_.length, "Mirror cache not cleared"); + + // Get the debug command processor. + var dcp = exec_state.debugCommandProcessor(); + + // Make a backtrace request to create some mirrors. + var json; + json = '{"seq":0,"type":"request","command":"backtrace"}' + dcp.processDebugJSONRequest(json); + + // Some mirrors where cached. + assertFalse(debug.next_handle_ == 0, "Mirror cache not used"); + assertFalse(debug.mirror_cache_.length == 0, "Mirror cache not used"); + } + } catch (e) { + print(e); + listenerExceptionCount++; + }; +}; + +// Add the debug event listener. +Debug.addListener(listener); + +// Enter the debugger twice. +debugger; +debugger; + +// Make sure that the debug event listener vas invoked. +assertEquals(2, listenerCallCount, "Listener not called"); +assertEquals(0, listenerExceptionCount, "Exception in listener"); + diff --git a/test/mjsunit/mirror-array.js b/test/mjsunit/mirror-array.js index 93c87bdfc7..1873d1eb6e 100644 --- a/test/mjsunit/mirror-array.js +++ b/test/mjsunit/mirror-array.js @@ -28,50 +28,80 @@ // Flags: --expose-debug-as debug // Test the mirror object for objects +function MirrorRefCache(json_refs) { + var tmp = eval('(' + json_refs + ')'); + this.refs_ = []; + for (var i = 0; i < tmp.length; i++) { + this.refs_[tmp[i].handle] = tmp[i]; + } +} + +MirrorRefCache.prototype.lookup = function(handle) { + return this.refs_[handle]; +} + function testArrayMirror(a, names) { // Create mirror and JSON representation. var mirror = debug.MakeMirror(a); - var json = mirror.toJSONProtocol(true); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); + var refs = new MirrorRefCache(serializer.serializeReferencedObjects()); // Check the mirror hierachy. - assertTrue(mirror instanceof debug.Mirror); - assertTrue(mirror instanceof debug.ValueMirror); - assertTrue(mirror instanceof debug.ObjectMirror); - assertTrue(mirror instanceof debug.ArrayMirror); + 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.ArrayMirror, 'Unexpected mirror hierachy'); // Check the mirror properties. - assertTrue(mirror.isArray()); - assertEquals('object', mirror.type()); - assertFalse(mirror.isPrimitive()); - assertEquals('Array', mirror.className()); - assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror); - assertTrue(mirror.protoObject() instanceof debug.Mirror); - assertTrue(mirror.prototypeObject() instanceof debug.Mirror); + assertTrue(mirror.isArray(), 'Unexpected mirror'); + assertEquals('object', mirror.type(), 'Unexpected mirror type'); + assertFalse(mirror.isPrimitive(), 'Unexpected primitive mirror'); + assertEquals('Array', mirror.className(), 'Unexpected mirror class name'); + assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror, 'Unexpected mirror hierachy'); + assertEquals('Array', 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'); assertEquals(mirror.length(), a.length, "Length mismatch"); - var indexedValueMirrors = mirror.indexedPropertiesFromRange(); - assertEquals(indexedValueMirrors.length, a.length); - for (var i = 0; i < indexedValueMirrors.length; i++) { - assertTrue(indexedValueMirrors[i] instanceof debug.Mirror); - if (a[i]) { - assertTrue(indexedValueMirrors[i] instanceof debug.PropertyMirror); - } + var indexedProperties = mirror.indexedPropertiesFromRange(); + assertEquals(indexedProperties.length, a.length); + for (var i = 0; i < indexedProperties.length; i++) { + assertTrue(indexedProperties[i] instanceof debug.Mirror, 'Unexpected mirror hierachy'); + assertTrue(indexedProperties[i] instanceof debug.PropertyMirror, 'Unexpected mirror hierachy'); } // Parse JSON representation and check. var fromJSON = eval('(' + json + ')'); - assertEquals('object', fromJSON.type); - assertEquals('Array', fromJSON.className); - assertEquals('function', fromJSON.constructorFunction.type); - assertEquals('Array', fromJSON.constructorFunction.name); - assertEquals(a.length, fromJSON.length, "Length mismatch in parsed JSON"); + assertEquals('object', fromJSON.type, 'Unexpected mirror type in JSON'); + assertEquals('Array', fromJSON.className, 'Unexpected mirror class name in JSON'); + assertEquals(mirror.constructorFunction().handle(), fromJSON.constructorFunction.ref, 'Unexpected constructor function handle in JSON'); + assertEquals('function', refs.lookup(fromJSON.constructorFunction.ref).type, 'Unexpected constructor function type in JSON'); + assertEquals('Array', refs.lookup(fromJSON.constructorFunction.ref).name, 'Unexpected constructor function name in JSON'); + assertEquals(void 0, fromJSON.namedInterceptor, 'No named interceptor expected in JSON'); + assertEquals(void 0, fromJSON.indexedInterceptor, 'No indexed interceptor expected in JSON'); - // Check that the serialization contains all indexed properties. - for (var i = 0; i < fromJSON.indexedProperties.length; i++) { - var index = fromJSON.indexedProperties[i].name; - assertEquals(indexedValueMirrors[index].name(), index); - assertEquals(indexedValueMirrors[index].value().type(), fromJSON.indexedProperties[i].value.type, index); + // Check that the serialization contains all indexed properties and the length property. + var length_found = false; + for (var i = 0; i < fromJSON.properties.length; i++) { + if (fromJSON.properties[i].name == 'length') { + length_found = true; + assertEquals('number', refs.lookup(fromJSON.properties[i].ref).type, "Unexpected type of the length property"); + assertEquals(a.length, refs.lookup(fromJSON.properties[i].ref).value, "Length mismatch in parsed JSON"); + } else { + var index = parseInt(fromJSON.properties[i].name); + print(index); + if (!isNaN(index)) { + print(index); + // This test assumes that the order of the indexeed properties is in the + // same order in the serialization as returned from + // indexedPropertiesFromRange() + assertEquals(indexedProperties[index].name(), index); + assertEquals(indexedProperties[index].value().type(), refs.lookup(fromJSON.properties[i].ref).type, 'Unexpected serialized type'); + } + } } + assertTrue(length_found, 'Property length not found'); // Check that the serialization contains all names properties. if (names) { @@ -84,8 +114,6 @@ function testArrayMirror(a, names) { } assertTrue(found, names[i]) } - } else { - assertEquals(1, fromJSON.properties.length) } } diff --git a/test/mjsunit/mirror-boolean.js b/test/mjsunit/mirror-boolean.js index 214704812b..4f93089241 100644 --- a/test/mjsunit/mirror-boolean.js +++ b/test/mjsunit/mirror-boolean.js @@ -31,7 +31,8 @@ function testBooleanMirror(b) { // Create mirror and JSON representation. var mirror = debug.MakeMirror(b); - var json = mirror.toJSONProtocol(true); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); diff --git a/test/mjsunit/mirror-date.js b/test/mjsunit/mirror-date.js index e96badcfc3..a6334d0f12 100644 --- a/test/mjsunit/mirror-date.js +++ b/test/mjsunit/mirror-date.js @@ -31,7 +31,8 @@ function testDateMirror(d, iso8601) { // Create mirror and JSON representation. var mirror = debug.MakeMirror(d); - var json = mirror.toJSONProtocol(true); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); diff --git a/test/mjsunit/mirror-error.js b/test/mjsunit/mirror-error.js index 49eaaff7f6..37ec46c863 100644 --- a/test/mjsunit/mirror-error.js +++ b/test/mjsunit/mirror-error.js @@ -28,10 +28,24 @@ // Flags: --expose-debug-as debug // Test the mirror object for regular error objects +function MirrorRefCache(json_refs) { + var tmp = eval('(' + json_refs + ')'); + this.refs_ = []; + for (var i = 0; i < tmp.length; i++) { + this.refs_[tmp[i].handle] = tmp[i]; + } +} + +MirrorRefCache.prototype.lookup = function(handle) { + return this.refs_[handle]; +} + function testErrorMirror(e) { // Create mirror and JSON representation. var mirror = debug.MakeMirror(e); - var json = mirror.toJSONProtocol(true); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); + var refs = new MirrorRefCache(serializer.serializeReferencedObjects()); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); @@ -49,7 +63,18 @@ function testErrorMirror(e) { var fromJSON = eval('(' + json + ')'); assertEquals('error', fromJSON.type); assertEquals('Error', fromJSON.className); - assertEquals(fromJSON.message, e.message, 'message'); + if (e.message) { + var found_message = false; + for (var i in fromJSON.properties) { + var p = fromJSON.properties[i]; + print(p.name); + if (p.name == 'message') { + assertEquals(e.message, refs.lookup(p.ref).value); + found_message = true; + } + } + assertTrue(found_message, 'Property message not found'); + } // Check the formatted text (regress 1231579). assertEquals(fromJSON.text, e.toString(), 'toString'); diff --git a/test/mjsunit/mirror-function.js b/test/mjsunit/mirror-function.js index 43ff50f068..59d9e7862a 100644 --- a/test/mjsunit/mirror-function.js +++ b/test/mjsunit/mirror-function.js @@ -28,10 +28,24 @@ // Flags: --expose-debug-as debug // Test the mirror object for functions. +function MirrorRefCache(json_refs) { + var tmp = eval('(' + json_refs + ')'); + this.refs_ = []; + for (var i = 0; i < tmp.length; i++) { + this.refs_[tmp[i].handle] = tmp[i]; + } +} + +MirrorRefCache.prototype.lookup = function(handle) { + return this.refs_[handle]; +} + function testFunctionMirror(f) { // Create mirror and JSON representation. var mirror = debug.MakeMirror(f); - var json = mirror.toJSONProtocol(true); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); + var refs = new MirrorRefCache(serializer.serializeReferencedObjects()); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); @@ -58,8 +72,8 @@ function testFunctionMirror(f) { var fromJSON = eval('(' + json + ')'); assertEquals('function', fromJSON.type); assertEquals('Function', fromJSON.className); - assertEquals('function', fromJSON.constructorFunction.type); - assertEquals('Function', fromJSON.constructorFunction.name); + assertEquals('function', refs.lookup(fromJSON.constructorFunction.ref).type); + assertEquals('Function', refs.lookup(fromJSON.constructorFunction.ref).name); assertTrue(fromJSON.resolved); assertEquals(f.name, fromJSON.name); assertEquals(f.toString(), fromJSON.source); diff --git a/test/mjsunit/mirror-null.js b/test/mjsunit/mirror-null.js index 4233efae2c..db68966a47 100644 --- a/test/mjsunit/mirror-null.js +++ b/test/mjsunit/mirror-null.js @@ -30,7 +30,8 @@ // Create mirror and JSON representation. var mirror = debug.MakeMirror(null); -var json = mirror.toJSONProtocol(true); +var serializer = debug.MakeMirrorSerializer(); +var json = serializer.serializeValue(mirror); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); diff --git a/test/mjsunit/mirror-number.js b/test/mjsunit/mirror-number.js index 20280c3b36..33488efcb8 100644 --- a/test/mjsunit/mirror-number.js +++ b/test/mjsunit/mirror-number.js @@ -31,7 +31,8 @@ function testNumberMirror(n) { // Create mirror and JSON representation. var mirror = debug.MakeMirror(n); - var json = mirror.toJSONProtocol(true); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); diff --git a/test/mjsunit/mirror-object.js b/test/mjsunit/mirror-object.js index 5f86acdfde..b9b0e1a9e8 100644 --- a/test/mjsunit/mirror-object.js +++ b/test/mjsunit/mirror-object.js @@ -28,38 +28,53 @@ // Flags: --expose-debug-as debug // Test the mirror object for objects -function testObjectMirror(o, cls_name, ctor_name, hasSpecialProperties) { +function MirrorRefCache(json_refs) { + var tmp = eval('(' + json_refs + ')'); + this.refs_ = []; + for (var i = 0; i < tmp.length; i++) { + this.refs_[tmp[i].handle] = tmp[i]; + } +} + +MirrorRefCache.prototype.lookup = function(handle) { + return this.refs_[handle]; +} + +function testObjectMirror(obj, cls_name, ctor_name, hasSpecialProperties) { // Create mirror and JSON representation. - var mirror = debug.MakeMirror(o); - var json = mirror.toJSONProtocol(true); + var mirror = debug.MakeMirror(obj); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); + var refs = new MirrorRefCache(serializer.serializeReferencedObjects()); // Check the mirror hierachy. - assertTrue(mirror instanceof debug.Mirror); - assertTrue(mirror instanceof debug.ValueMirror); - assertTrue(mirror instanceof debug.ObjectMirror); + assertTrue(mirror instanceof debug.Mirror, 'Unexpected mirror hierachy'); + assertTrue(mirror instanceof debug.ValueMirror, 'Unexpected mirror hierachy'); + assertTrue(mirror instanceof debug.ObjectMirror, 'Unexpected mirror hierachy'); // Check the mirror properties. - assertTrue(mirror.isObject()); - assertEquals('object', mirror.type()); - assertFalse(mirror.isPrimitive()); - assertEquals(cls_name, mirror.className()); - assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror); - assertTrue(mirror.protoObject() instanceof debug.Mirror); - assertTrue(mirror.prototypeObject() instanceof debug.Mirror); - assertFalse(mirror.hasNamedInterceptor(), "hasNamedInterceptor()"); - assertFalse(mirror.hasIndexedInterceptor(), "hasIndexedInterceptor()"); + 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'); + 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'); + assertFalse(mirror.hasNamedInterceptor(), 'No named interceptor expected'); + assertFalse(mirror.hasIndexedInterceptor(), 'No indexed interceptor expected'); var names = mirror.propertyNames(); var properties = mirror.properties() assertEquals(names.length, properties.length); for (var i = 0; i < properties.length; i++) { - assertTrue(properties[i] instanceof debug.Mirror); - assertTrue(properties[i] instanceof debug.PropertyMirror); - assertEquals('property', properties[i].type()); - assertEquals(names[i], properties[i].name()); + assertTrue(properties[i] instanceof debug.Mirror, 'Unexpected mirror hierachy'); + assertTrue(properties[i] instanceof debug.PropertyMirror, 'Unexpected mirror hierachy'); + assertEquals('property', properties[i].type(), 'Unexpected mirror type'); + assertEquals(names[i], properties[i].name(), 'Unexpected property name'); } - for (var p in o) { + for (var p in obj) { var property_mirror = mirror.property(p); assertTrue(property_mirror instanceof debug.PropertyMirror); assertEquals(p, property_mirror.name()); @@ -74,46 +89,55 @@ function testObjectMirror(o, cls_name, ctor_name, hasSpecialProperties) { // Parse JSON representation and check. var fromJSON = eval('(' + json + ')'); - assertEquals('object', fromJSON.type); - assertEquals(cls_name, fromJSON.className); - assertEquals('function', fromJSON.constructorFunction.type); - if (ctor_name !== undefined) - assertEquals(ctor_name, fromJSON.constructorFunction.name); - assertEquals(void 0, fromJSON.namedInterceptor); - assertEquals(void 0, fromJSON.indexedInterceptor); - - // For array the index properties are seperate from named properties. - if (!cls_name == 'Array') { - assertEquals(names.length, fromJSON.properties.length, 'Some properties missing in JSON'); - } + assertEquals('object', fromJSON.type, 'Unexpected mirror type in JSON'); + assertEquals(cls_name, fromJSON.className, 'Unexpected mirror class name in JSON'); + assertEquals(mirror.constructorFunction().handle(), fromJSON.constructorFunction.ref, 'Unexpected constructor function handle in JSON'); + assertEquals('function', refs.lookup(fromJSON.constructorFunction.ref).type, 'Unexpected constructor function type in JSON'); + assertEquals(ctor_name, refs.lookup(fromJSON.constructorFunction.ref).name, 'Unexpected constructor function name in JSON'); + assertEquals(mirror.protoObject().handle(), fromJSON.protoObject.ref, 'Unexpected proto object handle in JSON'); + assertEquals(mirror.protoObject().type(), refs.lookup(fromJSON.protoObject.ref).type, 'Unexpected proto object type in JSON'); + assertEquals(mirror.prototypeObject().handle(), fromJSON.prototypeObject.ref, 'Unexpected prototype object handle in JSON'); + assertEquals(mirror.prototypeObject().type(), refs.lookup(fromJSON.prototypeObject.ref).type, 'Unexpected prototype object type in JSON'); + assertEquals(void 0, fromJSON.namedInterceptor, 'No named interceptor expected in JSON'); + assertEquals(void 0, fromJSON.indexedInterceptor, 'No indexed interceptor expected in JSON'); // Check that the serialization contains all properties. + assertEquals(names.length, fromJSON.properties.length, 'Some properties missing in JSON'); for (var i = 0; i < fromJSON.properties.length; i++) { var name = fromJSON.properties[i].name; if (!name) name = fromJSON.properties[i].index; var found = false; for (var j = 0; j < names.length; j++) { if (names[j] == name) { - assertEquals(properties[i].value().type(), fromJSON.properties[i].value.type); - // If property type is normal nothing is serialized. + // Check that serialized handle is correct. + assertEquals(properties[i].value().handle(), fromJSON.properties[i].ref, 'Unexpected serialized handle'); + + // Check that serialized name is correct. + assertEquals(properties[i].name(), fromJSON.properties[i].name, 'Unexpected serialized name'); + + // If property type is normal property type is not serialized. if (properties[i].propertyType() != debug.PropertyType.Normal) { - assertEquals(properties[i].propertyType(), fromJSON.properties[i].propertyType); + assertEquals(properties[i].propertyType(), fromJSON.properties[i].propertyType, 'Unexpected serialized property type'); } else { - assertTrue(typeof(fromJSON.properties[i].propertyType) === 'undefined'); + assertTrue(typeof(fromJSON.properties[i].propertyType) === 'undefined', 'Unexpected serialized property type'); } - // If there are no attributes nothing is serialized. + + // If there are no attributes attributes are not serialized. if (properties[i].attributes() != debug.PropertyAttribute.None) { - assertEquals(properties[i].attributes(), fromJSON.properties[i].attributes); + assertEquals(properties[i].attributes(), fromJSON.properties[i].attributes, 'Unexpected serialized attributes'); } else { - assertTrue(typeof(fromJSON.properties[i].attributes) === 'undefined'); + assertTrue(typeof(fromJSON.properties[i].attributes) === 'undefined', 'Unexpected serialized attributes'); } - if (!properties[i].value().isPrimitive()) { - // NaN is not equal to NaN. - if (isNaN(properties[i].value().value())) { - assertTrue(isNaN(fromJSON.properties[i].value.value)); - } else { - assertEquals(properties[i].value().value(), fromJSON.properties[i].value.value); - } + + // Lookup the serialized object from the handle reference. + var o = refs.lookup(fromJSON.properties[i].ref); + assertTrue(o != void 0, 'Referenced object is not serialized'); + + assertEquals(properties[i].value().type(), o.type, 'Unexpected serialized property type for ' + name); + if (properties[i].value().isPrimitive()) { + assertEquals(properties[i].value().value(), o.value, 'Unexpected serialized property value for ' + name); + } else if (properties[i].value().isFunction()) { + assertEquals(properties[i].value().source(), o.source, 'Unexpected serialized property value for ' + name); } found = true; } @@ -134,7 +158,7 @@ testObjectMirror({}, 'Object', 'Object'); testObjectMirror({'a':1,'b':2}, 'Object', 'Object'); testObjectMirror({'1':void 0,'2':null,'f':function pow(x,y){return Math.pow(x,y);}}, 'Object', 'Object'); testObjectMirror(new Point(-1.2,2.003), 'Object', 'Point'); -testObjectMirror(this, 'global', undefined, true); // Global object has special properties +testObjectMirror(this, 'global', '', true); // Global object has special properties testObjectMirror([], 'Array', 'Array'); testObjectMirror([1,2], 'Array', 'Array'); diff --git a/test/mjsunit/mirror-regexp.js b/test/mjsunit/mirror-regexp.js index 443caeb60f..0490b17f02 100644 --- a/test/mjsunit/mirror-regexp.js +++ b/test/mjsunit/mirror-regexp.js @@ -39,10 +39,24 @@ var expected_attributes = { 'lastIndex': debug.PropertyAttribute.DontEnum | debug.PropertyAttribute.DontDelete }; +function MirrorRefCache(json_refs) { + var tmp = eval('(' + json_refs + ')'); + this.refs_ = []; + for (var i = 0; i < tmp.length; i++) { + this.refs_[tmp[i].handle] = tmp[i]; + } +} + +MirrorRefCache.prototype.lookup = function(handle) { + return this.refs_[handle]; +} + function testRegExpMirror(r) { // Create mirror and JSON representation. var mirror = debug.MakeMirror(r); - var json = mirror.toJSONProtocol(true); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); + var refs = new MirrorRefCache(serializer.serializeReferencedObjects()); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); @@ -54,10 +68,6 @@ function testRegExpMirror(r) { assertTrue(mirror.isRegExp()); assertEquals('regexp', mirror.type()); assertFalse(mirror.isPrimitive()); - assertEquals(mirror.source(), r.source, 'source'); - assertEquals(mirror.global(), r.global, 'global'); - assertEquals(mirror.ignoreCase(), r.ignoreCase, 'ignoreCase'); - assertEquals(mirror.multiline(), r.multiline, 'multiline'); for (var p in expected_attributes) { assertEquals(mirror.property(p).attributes(), expected_attributes[p], @@ -71,16 +81,21 @@ function testRegExpMirror(r) { var fromJSON = eval('(' + json + ')'); assertEquals('regexp', fromJSON.type); assertEquals('RegExp', fromJSON.className); - assertEquals(fromJSON.source, r.source, 'source'); - assertEquals(fromJSON.global, r.global, 'global'); - assertEquals(fromJSON.ignoreCase, r.ignoreCase, 'ignoreCase'); - assertEquals(fromJSON.multiline, r.multiline, 'multiline'); for (var p in expected_attributes) { for (var i = 0; i < fromJSON.properties.length; i++) { if (fromJSON.properties[i].name == p) { - assertEquals(fromJSON.properties[i].attributes, - expected_attributes[p], - p + ' attributes'); + assertEquals(expected_attributes[p], + fromJSON.properties[i].attributes, + 'Unexpected value for ' + p + ' attributes'); + assertEquals(mirror.property(p).propertyType(), + fromJSON.properties[i].propertyType, + 'Unexpected value for ' + p + ' propertyType'); + assertEquals(mirror.property(p).value().handle(), + fromJSON.properties[i].ref, + 'Unexpected handle for ' + p); + assertEquals(mirror.property(p).value().value(), + refs.lookup(fromJSON.properties[i].ref).value, + 'Unexpected value for ' + p); } } } diff --git a/test/mjsunit/mirror-script.js b/test/mjsunit/mirror-script.js index 0034829a8e..c02964550f 100644 --- a/test/mjsunit/mirror-script.js +++ b/test/mjsunit/mirror-script.js @@ -31,8 +31,8 @@ function testScriptMirror(f, file_name, file_lines, script_type) { // Create mirror and JSON representation. var mirror = debug.MakeMirror(f).script(); - var json = mirror.toJSONProtocol(true); - print(json); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); diff --git a/test/mjsunit/mirror-string.js b/test/mjsunit/mirror-string.js index 0a382d3cfc..eeabc5fe2a 100644 --- a/test/mjsunit/mirror-string.js +++ b/test/mjsunit/mirror-string.js @@ -33,7 +33,8 @@ const kMaxProtocolStringLength = 80; // Constant from mirror-delay.js function testStringMirror(s) { // Create mirror and JSON representation. var mirror = debug.MakeMirror(s); - var json = mirror.toJSONProtocol(true); + var serializer = debug.MakeMirrorSerializer(); + var json = serializer.serializeValue(mirror); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); diff --git a/test/mjsunit/mirror-undefined.js b/test/mjsunit/mirror-undefined.js index fc35c8d030..2b5b84c6ad 100644 --- a/test/mjsunit/mirror-undefined.js +++ b/test/mjsunit/mirror-undefined.js @@ -30,7 +30,8 @@ // Create mirror and JSON representation. var mirror = debug.MakeMirror(void 0); -var json = mirror.toJSONProtocol(true); +var serializer = debug.MakeMirrorSerializer(); +var json = serializer.serializeValue(mirror); // Check the mirror hierachy. assertTrue(mirror instanceof debug.Mirror); diff --git a/test/mjsunit/mirror-unresolved-function.js b/test/mjsunit/mirror-unresolved-function.js index ab49508947..21d0e561b0 100644 --- a/test/mjsunit/mirror-unresolved-function.js +++ b/test/mjsunit/mirror-unresolved-function.js @@ -28,8 +28,22 @@ // Flags: --expose-debug-as debug // Test the mirror object for unresolved functions. +function MirrorRefCache(json_refs) { + var tmp = eval('(' + json_refs + ')'); + this.refs_ = []; + for (var i = 0; i < tmp.length; i++) { + this.refs_[tmp[i].handle] = tmp[i]; + } +} + +MirrorRefCache.prototype.lookup = function(handle) { + return this.refs_[handle]; +} + var mirror = new debug.UnresolvedFunctionMirror("f"); -var json = mirror.toJSONProtocol(true); +var serializer = debug.MakeMirrorSerializer(); +var json = serializer.serializeValue(mirror); +var refs = new MirrorRefCache(serializer.serializeReferencedObjects()); // Check the mirror hierachy for unresolved functions. assertTrue(mirror instanceof debug.Mirror); @@ -50,12 +64,15 @@ assertEquals('undefined', mirror.protoObject().type()); assertEquals('undefined', mirror.prototypeObject().type()); // Parse JSON representation of unresolved functions and check. -/*var fromJSON = eval('(' + json + ')'); -assertEquals('function', fromJSON.type); -assertEquals('Function', fromJSON.className); -assertEquals('undefined', fromJSON.constructorFunction.type); -assertEquals('undefined', fromJSON.protoObject.type); -assertEquals('undefined', fromJSON.prototypeObject.type); +var fromJSON = eval('(' + json + ')'); +assertEquals('function', fromJSON.type, 'Unexpected mirror type in JSON'); +assertEquals('Function', fromJSON.className, 'Unexpected mirror class name in JSON'); +assertEquals(mirror.constructorFunction().handle(), fromJSON.constructorFunction.ref, 'Unexpected constructor function handle in JSON'); +assertEquals('undefined', refs.lookup(fromJSON.constructorFunction.ref).type, 'Unexpected constructor function type in JSON'); +assertEquals(mirror.protoObject().handle(), fromJSON.protoObject.ref, 'Unexpected proto object handle in JSON'); +assertEquals('undefined', refs.lookup(fromJSON.protoObject.ref).type, 'Unexpected proto object type in JSON'); +assertEquals(mirror.prototypeObject().handle(), fromJSON.prototypeObject.ref, 'Unexpected prototype object handle in JSON'); +assertEquals('undefined', refs.lookup(fromJSON.prototypeObject.ref).type, 'Unexpected prototype object type in JSON'); assertFalse(fromJSON.resolved); assertEquals("f", fromJSON.name); -assertEquals(void 0, fromJSON.source);*/ +assertEquals(void 0, fromJSON.source); diff --git a/test/mjsunit/regress/regress-1081309.js b/test/mjsunit/regress/regress-1081309.js index 68710391fe..3da338609e 100644 --- a/test/mjsunit/regress/regress-1081309.js +++ b/test/mjsunit/regress/regress-1081309.js @@ -34,14 +34,32 @@ Debug = debug.Debug listenerCalled = false; exception = false; -function safeEval(code) { - try { - return eval('(' + code + ')'); - } catch (e) { - return undefined; +function ParsedResponse(json) { + this.response_ = eval('(' + json + ')'); + this.refs_ = []; + if (this.response_.refs) { + for (var i = 0; i < this.response_.refs.length; i++) { + this.refs_[this.response_.refs[i].handle] = this.response_.refs[i]; + } } } + +ParsedResponse.prototype.response = function() { + return this.response_; +} + + +ParsedResponse.prototype.body = function() { + return this.response_.body; +} + + +ParsedResponse.prototype.lookup = function(handle) { + return this.refs_[handle]; +} + + function listener(event, exec_state, event_data, data) { try { if (event == Debug.DebugEvent.Exception) @@ -56,12 +74,13 @@ function listener(event, exec_state, event_data, data) { // Get the backtrace. var json; json = '{"seq":0,"type":"request","command":"backtrace"}' - var backtrace = safeEval(dcp.processDebugJSONRequest(json)).body; + var response = new ParsedResponse(dcp.processDebugJSONRequest(json)); + var backtrace = response.body(); assertEquals(2, backtrace.totalFrames); assertEquals(2, backtrace.frames.length); - assertEquals("g", backtrace.frames[0].func.name); - assertEquals("", backtrace.frames[1].func.name); + assertEquals("g", response.lookup(backtrace.frames[0].func.ref).name); + assertEquals("", response.lookup(backtrace.frames[1].func.ref).name); listenerCalled = true; }