30#ifndef OO_EXCLUDE_DEBUG_SUPPORT
53@interface OODebugMonitor (Private) <OOJavaScriptEngineMonitor>
56- (void) javaScriptEngineWillReset:(NSNotification *)notification;
58- (void)disconnectDebuggerWithMessage:(NSString *)message;
66- (NSMutableDictionary *)normalizeConfigDictionary:(NSDictionary *)dictionary;
67- (id)normalizeConfigValue:(
id)value forKey:(NSString *)key;
69- (NSArray *)loadSourceFile:(NSString *)filePath;
76 NSString *NSApplicationWillTerminateNotification =
@"ApplicationWillTerminate";
81 NSUserDefaults *defaults =
nil;
82 NSMutableDictionary *config =
nil;
89 andMerge:YES] mutableCopy] autorelease];
100#if OOJSENGINE_MONITOR_SUPPORT
107 selector:@selector(applicationWillTerminate:)
108 name:NSApplicationWillTerminateNotification
112 selector:@selector(javaScriptEngineWillReset:)
113 name:kOOJavaScriptEngineWillResetNotification
117 selector:@selector(setUpDebugConsoleScript)
118 name:kOOJavaScriptEngineDidResetNotification
130 [_configFromOXPs release];
131 [_configOverrides release];
135 [_sourceFiles release];
158- (BOOL)setDebugger:(
id<OODebuggerInterface>)newDebugger
160 NSString *error =
nil;
165 if (newDebugger !=
nil)
175 if (newDebugger !=
nil)
179 if ([newDebugger connectDebugMonitor:
self errorMessage:&error])
187 OOLog(
@"debugMonitor.setDebugger.failed",
@"Could not connect to debugger %@, because an error occurred: %@", newDebugger, error);
190 @catch (NSException *exception)
192 OOLog(
@"debugMonitor.setDebugger.failed",
@"Could not connect to debugger %@, because an exception occurred: %@ -- %@", newDebugger, [exception name], [exception reason]);
158- (BOOL)setDebugger:(
id<OODebuggerInterface>)newDebugger {
…}
201- (oneway void)performJSConsoleCommand:(in NSString *)command
201- (oneway void)performJSConsoleCommand:(in NSString *)command {
…}
212- (void)appendJSConsoleLine:(
id)string
213 colorKey:(NSString *)colorKey
214 emphasisRange:(NSRange)emphasisRange
216 if (
string ==
nil)
return;
220 [_debugger debugMonitor:
self
221 jsConsoleOutput:string
223 emphasisRange:emphasisRange];
225 @catch (NSException *exception)
227 OOLog(
@"debugMonitor.debuggerConnection.exception",
@"Exception while attempting to send JavaScript console text to debugger: %@ -- %@", [exception name], [exception reason]);
212- (void)appendJSConsoleLine:(
id)string {
…}
233- (void)appendJSConsoleLine:(
id)string
234 colorKey:(NSString *)colorKey
233- (void)appendJSConsoleLine:(
id)string {
…}
247 [_debugger debugMonitorClearConsole:
self];
249 @catch (NSException *exception)
251 OOLog(
@"debugMonitor.debuggerConnection.exception",
@"Exception while attempting to clear JavaScript console: %@ -- %@", [exception name], [exception reason]);
262 [_debugger debugMonitorShowConsole:
self];
264 @catch (NSException *exception)
266 OOLog(
@"debugMonitor.debuggerConnection.exception",
@"Exception while attempting to show JavaScript console: %@ -- %@", [exception name], [exception reason]);
272- (id)configurationValueForKey:(in NSString *)key
272- (id)configurationValueForKey:(in NSString *)key {
…}
278- (id)configurationValueForKey:(NSString *)key class:(Class)class defaultValue:(
id)value
282 if (
class == Nil)
class = [NSObject class];
284 result = [_configOverrides objectForKey:key];
285 if (![result isKindOfClass:
class] && result != [NSNull
null]) result = [_configFromOXPs objectForKey:key];
286 if (![result isKindOfClass:
class] && result != [NSNull
null]) result = [[
value retain] autorelease];
287 if (result == [NSNull
null]) result =
nil;
278- (id)configurationValueForKey:(NSString *)key class:(Class)class defaultValue:(
id)value {
…}
293- (
long long)configurationIntValueForKey:(NSString *)key defaultValue:(
long long)value
299 if ([
object respondsToSelector:
@selector(longLongValue)]) result = [
object longLongValue];
300 else if ([
object respondsToSelector:
@selector(intValue)]) result = [
object intValue];
293- (
long long)configurationIntValueForKey:(NSString *)key defaultValue:(
long long)value {
…}
307- (void)setConfigurationValue:(in
id)value forKey:(in NSString *)key
309 if (key ==
nil)
return;
315 [_configOverrides removeObjectForKey:key];
320 [_configOverrides setObject:value forKey:key];
331 [_debugger debugMonitor:
self
332 noteChangedConfigrationValue:value
335 @catch (NSException *exception)
337 OOLog(
@"debugMonitor.debuggerConnection.exception",
@"Exception while attempting to send configuration update to debugger: %@ -- %@", [exception name], [exception reason]);
307- (void)setConfigurationValue:(in
id)value forKey:(in NSString *)key {
…}
344 NSMutableSet *result =
nil;
346 result = [
NSMutableSet setWithCapacity:[_configFromOXPs count] + [_configOverrides count]];
347 [
result addObjectsFromArray:[_configFromOXPs allKeys]];
348 [
result addObjectsFromArray:[_configOverrides allKeys]];
350 return [[
result allObjects] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
360- (void) writeMemStat:(NSString *)format, ...
363 va_start(args, format);
364 NSString *message = [[
NSString alloc] initWithFormat:format arguments:args];
367 OOLog(
@"debug.memStats",
@"%@", message);
360- (void) writeMemStat:(NSString *)format, ... {
…}
381 unsigned magnitude = 0;
382 NSString *suffix =
@"";
384 if (
size < kThreshold << 10)
386 return [
NSString stringWithFormat:@"%zu bytes", size];
388 if (
size < kThreshold << 20)
393 else if (
size < ((
size_t)kThreshold << 30))
404 float unit = 1 << (magnitude * 10);
405 float sizef = (float)
size / unit;
406 sizef = round(sizef * 100.0f) / 100.f;
408 return [
NSString stringWithFormat:@"%.2f %@", sizef, suffix];
423- (void) dumpEntity:(
id)entity withState:(
EntityDumpState *)state parentVisible:(BOOL)parentVisible
425 if ([state->
seenEntities containsObject:entity] || entity ==
nil)
return;
426 [
state->seenEntities addObject:entity];
430 size_t entitySize = [
entity oo_objectSize];
431 size_t drawableSize = 0;
438 BOOL visible = parentVisible && [
entity isVisible];
440 NSSet *textures = [
entity allTextures];
443 [
state->entityTextures unionSet:textures];
444 if (visible) [
state->visibleEntityTextures unionSet:textures];
447 NSString *extra =
@"";
450 extra = [
extra stringByAppendingString:@", visible"];
453 if (drawableSize != 0)
455 extra = [
extra stringByAppendingFormat:@", drawable: %@", SizeString(drawableSize)];
458 [
self writeMemStat:@"%@: %@%@", [
entity shortDescription], SizeString(entitySize), extra];
466 NSEnumerator *subEnum =
nil;
468 for (subEnum = [entity subEntityEnumerator]; (subentity = [
subEnum nextObject]); )
473 if ([entity isPlayer])
476 for (i = 0; i <
count; i++)
478 subentity = [
entity missileForPylon:i];
483 if ([entity isPlanet])
489 if (atmosphere !=
nil)
495 if ([entity isWormhole])
497 NSEnumerator *shipEnum =
nil;
498 NSDictionary *shipInfo =
nil;
499 for (shipEnum = [[entity shipsInTransit] objectEnumerator]; (shipInfo = [
shipEnum nextObject]); )
423- (void) dumpEntity:(
id)entity withState:(
EntityDumpState *)state parentVisible:(BOOL)parentVisible {
…}
511 OOLog(
@"debug.memStats",
@"%@",
@"Memory statistics:");
519 NSEnumerator *texEnum =
nil;
520 for (texEnum = [allTextures objectEnumerator]; (tex = [
texEnum nextObject]); )
526 size_t totalSize = 0;
531 NSArray *entities = [UNIVERSE entityList];
540 NSEnumerator *entityEnum =
nil;
541 for (entityEnum = [entities objectEnumerator]; (entity = [
entityEnum nextObject]); )
545 for (entityEnum = [[
PLAYER scannedWormholes] objectEnumerator]; (entity = [
entityEnum nextObject]); )
551 [
self writeMemStat:@"Total entity size (excluding %u entities not accounted for): %@ (%@ entity objects, %@ drawables)",
552 gLiveEntityCount - entityDumpState.seenCount,
553 SizeString(entityDumpState.totalEntityObjSize + entityDumpState.totalDrawableSize),
554 SizeString(entityDumpState.totalEntityObjSize),
555 SizeString(entityDumpState.totalDrawableSize)];
563 for (texEnum = [allTextures objectEnumerator]; (tex = [
texEnum nextObject]); )
565 if ([textures indexOfObject:tex] == NSNotFound)
571 size_t totalTextureObjSize = 0;
572 size_t totalTextureDataSize = 0;
573 size_t visibleTextureDataSize = 0;
578 for (texEnum = [textures objectEnumerator]; (tex = [
texEnum nextObject]); )
580 size_t objSize = [
tex oo_objectSize];
583#if OOTEXTURE_RELOADABLE
584 NSString *byteCountSuffix =
@"";
586 NSString *byteCountSuffix =
@" (* 2)";
589 NSString *usage =
@"";
592 visibleTextureDataSize += dataSize;
593 usage =
@", visible";
606 SizeString(objSize + dataSize),
609 totalTextureDataSize += dataSize;
610 totalTextureObjSize += objSize;
612 totalSize += totalTextureObjSize + totalTextureDataSize;
616#if !OOTEXTURE_RELOADABLE
617 totalTextureDataSize *= 2;
619 [
self writeMemStat:@"Total texture size: %@ (%@ object overhead, %@ data, %@ visible texture data)",
620 SizeString(totalTextureObjSize + totalTextureDataSize),
621 SizeString(totalTextureObjSize),
622 SizeString(totalTextureDataSize),
623 SizeString(visibleTextureDataSize)];
627 [
self writeMemStat:@"Total: %@", SizeString(totalSize)];
637 JSRuntime *runtime = JS_GetRuntime(context);
638 size_t jsSize = JS_GetGCParameter(runtime, JSGC_BYTES);
639 size_t jsMax = JS_GetGCParameter(runtime, JSGC_MAX_BYTES);
640 uint32_t jsGCCount = JS_GetGCParameter(runtime, JSGC_NUMBER);
644 [
self writeMemStat:@"JavaScript heap: %@ (limit %@, %u collections to date)", SizeString(jsSize), SizeString(jsMax), jsGCCount];
649- (void) setTCPIgnoresDroppedPackets:(BOOL)flag
653 OOLog(
@"debugMonitor.TCPSettings",
@"The TCP console will %@ TCP packets.",
654 (flag ?
@"try to stay connected, ignoring dropped" :
@"disconnect if an error affects"));
649- (void) setTCPIgnoresDroppedPackets:(BOOL)flag {
…}
666- (void) setUsingPlugInController:(BOOL)flag
666- (void) setUsingPlugInController:(BOOL)flag {
…}
678- (NSString *)sourceCodeForFile:(in NSString *)filePath line:(in
unsigned)line
680 id linesForFile =
nil;
682 linesForFile = [_sourceFiles objectForKey:filePath];
684 if (linesForFile ==
nil)
687 if (linesForFile ==
nil) linesForFile = [
NSArray arrayWithObject:[
NSString stringWithFormat:@"<Can't load file %@>", filePath]];
690 [_sourceFiles setObject:linesForFile forKey:filePath];
693 if ([linesForFile
count] < line || line == 0)
return @"<line out of range!>";
678- (NSString *)sourceCodeForFile:(in NSString *)filePath line:(in
unsigned)line {
…}
699- (void)disconnectDebugger:(in
id<OODebuggerInterface>)debugger
700 message:(in NSString *)message
702 if (debugger ==
nil)
return;
710 OOLog(
@"debugMonitor.disconnect.ignored",
@"Attempt to disconnect debugger %@, which is not current debugger; ignoring.", debugger);
699- (void)disconnectDebugger:(in
id<OODebuggerInterface>)debugger {
…}
716- (void) applicationWillTerminate
718 [[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationWillTerminateNotification object:nil];
723- (void)applicationWillTerminate:(NSNotification *)notification
727 [[
NSUserDefaults standardUserDefaults] setObject:_configOverrides forKey:@"debug-settings-override"];
723- (void)applicationWillTerminate:(NSNotification *)notification {
…}
737@implementation OODebugMonitor (Private)
746 static NSString *path =
nil;
754 NSDictionary *jsProps = [
NSDictionary dictionaryWithObjectsAndKeys:
756 JSSpecialFunctionsObjectWrapper(context), @"special",
765 JS_DefineProperty(context, global,
"debugConsole", [
self oo_jsValueInContext:context], NULL, NULL, JSPROP_ENUMERATE);
772- (void) javaScriptEngineWillReset:(NSNotification *)notification
772- (void) javaScriptEngineWillReset:(NSNotification *)notification {
…}
781- (void)disconnectDebuggerWithMessage:(NSString *)message
785 [
_debugger disconnectDebugMonitor:
self message:message];
787 @catch (NSException *exception)
789 OOLog(
@"debugMonitor.debuggerConnection.exception",
@"Exception while attempting to disconnect debugger: %@ -- %@", [exception name], [exception reason]);
792 id debugger = _debugger;
781- (void)disconnectDebuggerWithMessage:(NSString *)message {
…}
800 NSMutableDictionary *result =
nil;
803 if (_configFromOXPs !=
nil) [
result addEntriesFromDictionary:_configFromOXPs];
804 if (_configOverrides !=
nil) [
result addEntriesFromDictionary:_configOverrides];
810- (NSArray *)loadSourceFile:(NSString *)filePath
812 NSString *contents =
nil;
813 NSArray *lines =
nil;
815 if (filePath ==
nil)
return nil;
817 contents = [
NSString stringWithContentsOfUnicodeFile:filePath];
818 if (contents ==
nil)
return nil;
823 lines = [
contents componentsSeparatedByString:@"\n"];
810- (NSArray *)loadSourceFile:(NSString *)filePath {
…}
828- (NSMutableDictionary *)normalizeConfigDictionary:(NSDictionary *)dictionary
830 NSMutableDictionary *result =
nil;
831 NSEnumerator *keyEnum =
nil;
836 for (keyEnum = [dictionary keyEnumerator]; (key = [
keyEnum nextObject]); )
841 if (key !=
nil && value !=
nil) [
result setObject:value forKey:key];
828- (NSMutableDictionary *)normalizeConfigDictionary:(NSDictionary *)dictionary {
…}
848- (id)normalizeConfigValue:(
id)value forKey:(NSString *)key
855 if ([key hasSuffix:
@"-color"] || [key hasSuffix:
@"-colour"])
860 else if ([key hasPrefix:
@"show-console"])
863 value = [
NSNumber numberWithBool:boolValue];
848- (id)normalizeConfigValue:(
id)value forKey:(NSString *)key {
…}
872 context:(in JSContext *)context
873 error:(in JSErrorReport *)errorReport
874 stackSkip:(in
unsigned)stackSkip
875 showingLocation:(in BOOL)showLocation
876 withMessage:(in NSString *)message
878 NSString *colorKey =
nil;
879 NSString *prefix =
nil;
880 NSString *filePath =
nil;
881 NSString *sourceLine =
nil;
882 NSString *scriptLine =
nil;
883 NSMutableString *formattedMessage =
nil;
884 NSRange emphasisRange;
885 NSString *showKey =
nil;
887 if (_debugger ==
nil)
return;
889 if (errorReport->flags & JSREPORT_WARNING)
891 colorKey =
@"warning";
894 else if (errorReport->flags & JSREPORT_EXCEPTION)
896 colorKey =
@"exception";
897 prefix =
@"Exception";
905 if (errorReport->flags & JSREPORT_STRICT)
907 prefix = [
prefix stringByAppendingString:@" (strict mode)"];
911 emphasisRange = NSMakeRange(0, [prefix length] + 1);
913 formattedMessage = [
NSMutableString stringWithFormat:@"%@: %@", prefix, message];
920 scriptLine = [[
thisScript weakRefUnderlyingObject] displayName];
923 if (scriptLine !=
nil)
928 if (showLocation && stackSkip == 0)
931 if (errorReport->filename != NULL) filePath = [
NSString stringWithUTF8String:errorReport->filename];
932 if ([filePath length] != 0)
938 if (sourceLine !=
nil)
949 if (errorReport->flags & JSREPORT_WARNING) showKey =
@"show-console-on-warning";
950 else showKey =
@"show-console-on-error";
959 context:(in JSContext *)context
960 logMessage:(in NSString *)message
961 ofClass:(in NSString *)messageClass
971- (jsval)oo_jsValueInContext:(JSContext *)context
985 if (_jsSelf != NULL)
return OBJECT_TO_JSVAL(_jsSelf);
986 else return JSVAL_NULL;
971- (jsval)oo_jsValueInContext:(JSContext *)context {
…}
992@implementation OODebugMonitor (Singleton)
1001+ (id)allocWithZone:(NSZone *)inZone
1001+ (id)allocWithZone:(NSZone *)inZone {
…}
1012- (id)copyWithZone:(NSZone *)inZone
1012- (id)copyWithZone:(NSZone *)inZone {
…}
static OODebugMonitor * sSingleton
JSObject * DebugMonitorToJSConsole(JSContext *context, OODebugMonitor *monitor)
void OOJSConsoleDestroy(void)
#define OOJSStopTimeLimiter()
#define kOOJSLongTimeLimit
#define OOJSStartTimeLimiterWithTimeLimit(limit)
void OOJSPauseTimeLimiter(void)
OOINLINE jsval OOJSValueFromNativeObject(JSContext *context, id object)
OOINLINE JSContext * OOJSAcquireContext(void)
#define OOJSAddGCObjectRoot(context, root, name)
OOINLINE void OOJSRelinquishContext(JSContext *context)
void OOJSResumeTimeLimiter(void)
#define OOLog(class, format,...)
void setUpDebugConsoleScript()
NSDictionary * mergedConfiguration()
OOColor * colorWithDescription:(id description)
NSArray * normalizedArray()
id configurationValueForKey:class:defaultValue:(NSString *key,[class] Class class,[defaultValue] id value)
NSArray * loadSourceFile:(NSString *filePath)
static NSString * SizeString(size_t size)
void appendJSConsoleLine:colorKey:emphasisRange:(id string,[colorKey] NSString *colorKey,[emphasisRange] NSRange emphasisRange)
void dumpMemoryStatistics()
void setUpDebugConsoleScript()
NSArray * configurationKeys()
NSMutableDictionary * normalizeConfigDictionary:(NSDictionary *dictionary)
BOOL TCPIgnoresDroppedPackets()
void writeMemStat:(NSString *format, [,] ...)
void dumpEntity:withState:parentVisible:(id entity, [withState] EntityDumpState *state, [parentVisible] BOOL parentVisible)
NSDictionary * mergedConfiguration()
NSMutableDictionary * _sourceFiles
void disconnectDebuggerWithMessage:(NSString *message)
BOOL _usingPlugInController
id normalizeConfigValue:forKey:(id value,[forKey] NSString *key)
id< OODebuggerInterface > _debugger
NSMutableDictionary * _configOverrides
void appendJSConsoleLine:colorKey:(id string,[colorKey] NSString *colorKey)
size_t dumpJSMemoryStatistics()
BOOL usingPlugInController()
BOOL _TCPIgnoresDroppedPackets
NSDictionary * _configFromOXPs
id configurationValueForKey:(in NSString *key)
struct JSObject * _jsSelf
NSString * sourceCodeForFile:line:(in NSString *filePath, [line] in unsigned line)
OODebugMonitor * sharedDebugMonitor()
id scriptWithPath:properties:(NSString *path,[properties] NSDictionary *properties)
BOOL callMethod:inContext:withArguments:count:result:(jsid methodID,[inContext] JSContext *context,[withArguments] jsval *argv,[count] intN argc,[result] jsval *outResult)
OOJSScript * currentlyRunningScript()
JSObject * globalObject()
OOJavaScriptEngine * sharedEngine()
void setMonitor:(id< OOJavaScriptEngineMonitor > inMonitor)
void removeGCObjectRoot:(JSObject **rootPtr)
NSArray * cachedTexturesByAge()
NSString * pathForFileNamed:inFolder:(NSString *fileName,[inFolder] NSString *folderName)
NSDictionary * dictionaryFromFilesNamed:inFolder:andMerge:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles)
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
NSMutableSet * visibleEntityTextures
NSMutableSet * seenEntities
size_t totalEntityObjSize
NSMutableSet * entityTextures