LCOV - code coverage report
Current view: top level - Core/Scripting - OOJSEngineDebuggerHelpers.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 9 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOJSEngineDebuggerHelpers.m
       4             : 
       5             : JavaScript support for Oolite
       6             : Copyright (C) 2007-2013 David Taylor and Jens Ayton.
       7             : 
       8             : This program is free software; you can redistribute it and/or
       9             : modify it under the terms of the GNU General Public License
      10             : as published by the Free Software Foundation; either version 2
      11             : of the License, or (at your option) any later version.
      12             : 
      13             : This program is distributed in the hope that it will be useful,
      14             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             : GNU General Public License for more details.
      17             : 
      18             : You should have received a copy of the GNU General Public License
      19             : along with this program; if not, write to the Free Software
      20             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      21             : MA 02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : 
      26             : /*
      27             :         These functions exist to help debugging JavaScript code. They can be called
      28             :         directly from gdb, for example:
      29             :         
      30             :                 call (char *)JSValueToStrDbg(someValue)
      31             :         
      32             :         The functions are:
      33             :         
      34             :                 const char *JSValueToStrDbg(jsval)
      35             :                 const char *JSObjectToStrDbg(JSObject *)
      36             :                 const char *JSStringToStrDbg(JSString *)
      37             :                 Converts any JS value/object/JSString to a string, using the complete
      38             :                 process and potentially calling into SpiderMonkey with a secondory
      39             :                 context and invoking JS toString() methods. This might mess up
      40             :                 SpiderMonkey internal state in some cases.
      41             :                 
      42             :                 const char *JSValueToStrSafeDbg(jsval)
      43             :                 const char *JSObjectToStrSafeDbg(JSObject *)
      44             :                 const char *JSStringToStrSafeDbg(JSString *)
      45             :                 As above, but without calling into SpiderMonkey functions that require
      46             :                 a context. In particular, as of the FF4b9 version of SpiderMonkey only
      47             :                 interned strings can be converted, and for objects only the class name
      48             :                 is provided.
      49             :                 
      50             :                 const char *JSIDToStrSafeDbg(jsid)
      51             :                 Like JSValueToStrSafeDbg() for jsids. (String jsids must always be
      52             :                 interned, so this is generally sufficient.)
      53             :                 
      54             :                 const char *JSValueTypeDbg(jsval)
      55             :                 Returns the type of the jsval, or the class name if it's an object.
      56             :         
      57             :         All dynamic strings are autoreleased.
      58             :  
      59             :          Another useful function is OOJSDumpStack (results are found in the log):
      60             :                 
      61             :                 call OOJSDumpStack(context)
      62             :         
      63             :         A set of macros can be found in tools/gdb-macros.txt.
      64             :         In almost all Oolite functions that deal with JavaScript, there is a single
      65             :         JSContext called "context". In SpiderMonkey functions, it's called "cx".
      66             :         
      67             :         
      68             :         In addition to calling them from the debug console, Xcode users might want
      69             :         to use them in data formatters (by double-clicking the "Summary" field for
      70             :         a variable of the appropriate type). I recommend the following:
      71             :         
      72             :                 jsval:          {JSValueToStrSafeDbg($VAR)}:s
      73             :                 jsval*:         {JSValueToStrSafeDbg(*$VAR)}:s
      74             :                 jsid:           {JSIDToStrSafeDbg($VAR)}:s
      75             :                 JSObject*:      {JSObjectToStrSafeDbg($VAR)}:s
      76             :                 JSString*:      {JSStringToStrSafeDbg($VAR)}:s
      77             :         
      78             :         These, and a variety of Oolite type formatters, can be set up using
      79             :         Mac-specific/DataFormatters.
      80             : */
      81             : 
      82             : 
      83             : #ifndef NDEBUG
      84             : 
      85             : #import "OOJavaScriptEngine.h"
      86             : 
      87             : 
      88           0 : const char *JSValueToStrDbg(jsval val)
      89             : {
      90             :         JSContext *context = OOJSAcquireContext();
      91             :         const char *result = [OOStringFromJSValueEvenIfNull(context, val) UTF8String];
      92             :         OOJSRelinquishContext(context);
      93             :         
      94             :         return result;
      95             : }
      96             : 
      97             : 
      98           0 : const char *JSObjectToStrDbg(JSObject *obj)
      99             : {
     100             :         if (obj == NULL)  return "null";
     101             :         return JSValueToStrDbg(OBJECT_TO_JSVAL(obj));
     102             : }
     103             : 
     104             : 
     105           0 : const char *JSStringToStrDbg(JSString *str)
     106             : {
     107             :         if (str == NULL)  return "null";
     108             :         return JSValueToStrDbg(STRING_TO_JSVAL(str));
     109             : }
     110             : 
     111             : 
     112           0 : const char *JSValueTypeDbg(jsval val)
     113             : {
     114             :         if (JSVAL_IS_INT(val))          return "integer";
     115             :         if (JSVAL_IS_DOUBLE(val))       return "double";
     116             :         if (JSVAL_IS_STRING(val))       return "string";
     117             :         if (JSVAL_IS_BOOLEAN(val))      return "boolean";
     118             :         if (JSVAL_IS_NULL(val))         return "null";
     119             :         if (JSVAL_IS_VOID(val))         return "void";
     120             : #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
     121             :         if (JSVAL_IS_MAGIC_IMPL(val))
     122             :         {
     123             :                 switch(val.s.payload.why)
     124             :                 {
     125             :                         case JS_ARRAY_HOLE:                     return "magic (array hole)";
     126             :                         case JS_ARGS_HOLE:                      return "magic (args hole)";
     127             :                         case JS_NATIVE_ENUMERATE:       return "magic (native enumerate)";
     128             :                         case JS_NO_ITER_VALUE:          return "magic (no iter value)";
     129             :                         case JS_GENERATOR_CLOSING:      return "magic (generator closing)";
     130             :                         case JS_NO_CONSTANT:            return "magic (no constant)";
     131             :                         case JS_THIS_POISON:            return "magic (this poison)";
     132             :                         case JS_ARG_POISON:                     return "magic (arg poison)";
     133             :                         case JS_SERIALIZE_NO_NODE:      return "magic (serialize no node)";
     134             :                         case JS_GENERIC_MAGIC:          return "magic (generic)";
     135             :                 };
     136             :                 return "magic";
     137             :         }
     138             : #endif
     139             :         if (JSVAL_IS_OBJECT(val))  return OOJSGetClass(NULL, JSVAL_TO_OBJECT(val))->name;    // Fun fact: although a context is required if JS_THREADSAFE is defined, it isn't actually used.
     140             :         return "unknown";
     141             : }
     142             : 
     143             : 
     144             : // Doesn't follow pointers, mess with requests or otherwise poke the SpiderMonkey.
     145           0 : const char *JSValueToStrSafeDbg(jsval val)
     146             : {
     147             :         NSString *formatted = nil;
     148             :         
     149             :         if (JSVAL_IS_INT(val))                  formatted = [NSString stringWithFormat:@"%i", JSVAL_TO_INT(val)];
     150             :         else if (JSVAL_IS_DOUBLE(val))  formatted = [NSString stringWithFormat:@"%g", JSVAL_TO_DOUBLE(val)];
     151             :         else if (JSVAL_IS_BOOLEAN(val)) formatted = (JSVAL_TO_BOOLEAN(val)) ? @"true" : @"false";
     152             :         else if (JSVAL_IS_STRING(val))
     153             :         {
     154             :                 JSString                *string = JSVAL_TO_STRING(val);
     155             :                 const jschar    *chars = NULL;
     156             :                 size_t                  length = JS_GetStringLength(string);
     157             :                 
     158             :                 if (JS_StringHasBeenInterned(string))
     159             :                 {
     160             :                         chars = JS_GetInternedStringChars(string);
     161             :                 }
     162             :                 // Flat strings can be extracted without a context, but cannot be detected.
     163             :                 
     164             :                 if (chars == NULL)  formatted = [NSString stringWithFormat:@"string [%zu chars]", length];
     165             :                 else  formatted = [NSString stringWithCharacters:chars length:length];
     166             :         }
     167             :         else if (JSVAL_IS_VOID(val))    return "undefined";
     168             :         else                                                    return JSValueTypeDbg(val);
     169             :         
     170             :         return [formatted UTF8String];
     171             : }
     172             : 
     173             : 
     174           0 : const char *JSObjectToStrSafeDbg(JSObject *obj)
     175             : {
     176             :         if (obj == NULL)  return "null";
     177             :         return JSValueToStrSafeDbg(OBJECT_TO_JSVAL(obj));
     178             : }
     179             : 
     180             : 
     181           0 : const char *JSStringToStrSafeDbg(JSString *str)
     182             : {
     183             :         if (str == NULL)  return "null";
     184             :         return JSValueToStrSafeDbg(STRING_TO_JSVAL(str));
     185             : }
     186             : 
     187             : 
     188           0 : const char *JSIDToStrSafeDbg(jsid anID)
     189             : {
     190             :         NSString *formatted = nil;
     191             :         
     192             :         if (JSID_IS_INT(anID))                  formatted = [NSString stringWithFormat:@"%i", JSID_TO_INT(anID)];
     193             :         else if (JSID_IS_VOID(anID))    return "void";
     194             :         else if (JSID_IS_EMPTY(anID))   return "empty";
     195             :         else if (JSID_IS_ZERO(anID))    return "0";
     196             :         else if (JSID_IS_OBJECT(anID))  return OOJSGetClass(NULL, JSID_TO_OBJECT(anID))->name;
     197             :         else if (JSID_IS_DEFAULT_XML_NAMESPACE(anID))  return "default XML namespace";
     198             :         else if (JSID_IS_STRING(anID))
     199             :         {
     200             :                 JSString                *string = JSID_TO_STRING(anID);
     201             :                 const jschar    *chars = NULL;
     202             :                 size_t                  length = JS_GetStringLength(string);
     203             :                 
     204             :                 if (JS_StringHasBeenInterned(string))
     205             :                 {
     206             :                         chars = JS_GetInternedStringChars(string);
     207             :                 }
     208             :                 else
     209             :                 {
     210             :                         // Bug; jsid strings must be interned.
     211             :                         return "*** uninterned string in jsid! ***";
     212             :                 }
     213             :                 formatted = [NSString stringWithCharacters:chars length:length];
     214             :         }
     215             :         else
     216             :         {
     217             :                 formatted = [NSString stringWithFormat:@"unknown <0x%llX>", (long long)JSID_BITS(anID)];
     218             :         }
     219             :         
     220             :         return [formatted UTF8String];
     221             : }
     222             : #endif

Generated by: LCOV version 1.14