git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@5265 127b21dd-08f5-0310-b4b7-95ae10353056
1136 lines
32 KiB
Objective-C
1136 lines
32 KiB
Objective-C
/*
|
|
|
|
OOJSConsole.m
|
|
|
|
|
|
Oolite
|
|
Copyright (C) 2004-2012 Giles C Williams and contributors
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
|
|
*/
|
|
|
|
#ifndef OO_EXCLUDE_DEBUG_SUPPORT
|
|
|
|
#import "OOJSConsole.h"
|
|
#import "OODebugMonitor.h"
|
|
#include <stdint.h>
|
|
|
|
#import "OOJSEngineTimeManagement.h"
|
|
#import "OOJSScript.h"
|
|
#import "OOJSVector.h"
|
|
#import "OOJSEntity.h"
|
|
#import "OOJSCall.h"
|
|
#import "OOLoggingExtended.h"
|
|
#import "OOConstToString.h"
|
|
#import "OOOpenGLExtensionManager.h"
|
|
#import "OODebugFlags.h"
|
|
#import "OODebugMonitor.h"
|
|
#import "OOProfilingStopwatch.h"
|
|
#import "ResourceManager.h"
|
|
|
|
|
|
@interface Entity (OODebugInspector)
|
|
|
|
// Method added by inspector in Debug OXP under OS X only.
|
|
- (void) inspect;
|
|
|
|
@end
|
|
|
|
|
|
NSString *OOPlatformDescription(void);
|
|
|
|
|
|
static JSObject *sConsolePrototype = NULL;
|
|
static JSObject *sConsoleSettingsPrototype = NULL;
|
|
|
|
|
|
static JSBool ConsoleGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
|
|
static JSBool ConsoleSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
|
|
static void ConsoleFinalize(JSContext *context, JSObject *this);
|
|
|
|
// Methods
|
|
static JSBool ConsoleConsoleMessage(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleClearConsole(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleScriptStack(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleInspectEntity(JSContext *context, uintN argc, jsval *vp);
|
|
#if OO_DEBUG
|
|
static JSBool ConsoleCallObjCMethod(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleSetUpCallObjC(JSContext *context, uintN argc, jsval *vp);
|
|
#endif
|
|
static JSBool ConsoleIsExecutableJavaScript(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleDisplayMessagesInClass(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleSetDisplayMessagesInClass(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleWriteLogMarker(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleWriteMemoryStats(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleGarbageCollect(JSContext *context, uintN argc, jsval *vp);
|
|
#if DEBUG
|
|
static JSBool ConsoleDumpNamedRoots(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleDumpHeap(JSContext *context, uintN argc, jsval *vp);
|
|
#endif
|
|
#if OOJS_PROFILE
|
|
static JSBool ConsoleProfile(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleGetProfile(JSContext *context, uintN argc, jsval *vp);
|
|
static JSBool ConsoleTrace(JSContext *context, uintN argc, jsval *vp);
|
|
#endif
|
|
|
|
static JSBool ConsoleSettingsDeleteProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
|
|
static JSBool ConsoleSettingsGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
|
|
static JSBool ConsoleSettingsSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
|
|
|
|
#if OOJS_PROFILE
|
|
static JSBool PerformProfiling(JSContext *context, NSString *nominalFunction, uintN argc, jsval *argv, jsval *rval, BOOL trace, OOTimeProfile **profile);
|
|
#endif
|
|
|
|
|
|
static JSClass sConsoleClass =
|
|
{
|
|
"Console",
|
|
JSCLASS_HAS_PRIVATE,
|
|
|
|
JS_PropertyStub, // addProperty
|
|
JS_PropertyStub, // delProperty
|
|
ConsoleGetProperty, // getProperty
|
|
ConsoleSetProperty, // setProperty
|
|
JS_EnumerateStub, // enumerate
|
|
JS_ResolveStub, // resolve
|
|
JS_ConvertStub, // convert
|
|
ConsoleFinalize, // finalize
|
|
JSCLASS_NO_OPTIONAL_MEMBERS
|
|
};
|
|
|
|
|
|
enum
|
|
{
|
|
// Property IDs
|
|
kConsole_debugFlags, // debug flags, integer, read/write
|
|
kConsole_shaderMode, // shader mode, symbolic string, read/write
|
|
kConsole_maximumShaderMode, // highest supported shader mode, symbolic string, read-only
|
|
kConsole_reducedDetailMode, // reduced detail mode, boolean, read/write
|
|
kConsole_displayFPS, // display FPS (and related info), boolean, read/write
|
|
kConsole_platformDescription, // Information about system we're running on in unspecified format, string, read-only
|
|
kConsole_ignoreDroppedPackets, // boolean (default false), read/write
|
|
kConsole_pedanticMode, // JS pedantic mode (JS_STRICT flag, not the same as "use strict"), boolean (default true), read/write
|
|
kConsole_showErrorLocations, // Show error/warning source locations, boolean (default true), read/write
|
|
kConsole_dumpStackForErrors, // Write stack dump when reporting error/exception, boolean (default false), read/write
|
|
kConsole_dumpStackForWarnings, // Write stack dump when reporting warning, boolean (default false), read/write
|
|
|
|
kConsole_glVendorString, // OpenGL GL_VENDOR string, string, read-only
|
|
kConsole_glRendererString, // OpenGL GL_RENDERER string, string, read-only
|
|
kConsole_glFixedFunctionTextureUnitCount, // GL_MAX_TEXTURE_UNITS_ARB, integer, read-only
|
|
kConsole_glFragmentShaderTextureUnitCount, // GL_MAX_TEXTURE_IMAGE_UNITS_ARB, integer, read-only
|
|
|
|
// Symbolic constants for debug flags:
|
|
kConsole_DEBUG_LINKED_LISTS,
|
|
kConsole_DEBUG_COLLISIONS,
|
|
kConsole_DEBUG_DOCKING,
|
|
kConsole_DEBUG_OCTREE_LOGGING,
|
|
kConsole_DEBUG_BOUNDING_BOXES,
|
|
kConsole_DEBUG_OCTREE_DRAW,
|
|
kConsole_DEBUG_DRAW_NORMALS,
|
|
kConsole_DEBUG_NO_DUST,
|
|
kConsole_DEBUG_NO_SHADER_FALLBACK,
|
|
kConsole_DEBUG_SHADER_VALIDATION,
|
|
|
|
kConsole_DEBUG_MISC
|
|
};
|
|
|
|
|
|
static JSPropertySpec sConsoleProperties[] =
|
|
{
|
|
// JS name ID flags
|
|
{ "debugFlags", kConsole_debugFlags, OOJS_PROP_READWRITE_CB },
|
|
{ "shaderMode", kConsole_shaderMode, OOJS_PROP_READWRITE_CB },
|
|
{ "maximumShaderMode", kConsole_maximumShaderMode, OOJS_PROP_READONLY_CB },
|
|
{ "reducedDetailMode", kConsole_reducedDetailMode, OOJS_PROP_READWRITE_CB },
|
|
{ "displayFPS", kConsole_displayFPS, OOJS_PROP_READWRITE_CB },
|
|
{ "platformDescription", kConsole_platformDescription, OOJS_PROP_READONLY_CB },
|
|
{ "pedanticMode", kConsole_pedanticMode, OOJS_PROP_READWRITE_CB },
|
|
{ "ignoreDroppedPackets", kConsole_ignoreDroppedPackets, OOJS_PROP_READWRITE_CB },
|
|
{ "__showErrorLocations", kConsole_showErrorLocations, OOJS_PROP_HIDDEN_READWRITE_CB },
|
|
{ "__dumpStackForErrors", kConsole_dumpStackForErrors, OOJS_PROP_HIDDEN_READWRITE_CB },
|
|
{ "__dumpStackForWarnings", kConsole_dumpStackForWarnings, OOJS_PROP_HIDDEN_READWRITE_CB },
|
|
{ "glVendorString", kConsole_glVendorString, OOJS_PROP_READONLY_CB },
|
|
{ "glRendererString", kConsole_glRendererString, OOJS_PROP_READONLY_CB },
|
|
{ "glFixedFunctionTextureUnitCount", kConsole_glFixedFunctionTextureUnitCount, OOJS_PROP_READONLY_CB },
|
|
{ "glFragmentShaderTextureUnitCount", kConsole_glFragmentShaderTextureUnitCount, OOJS_PROP_READONLY_CB },
|
|
|
|
#define DEBUG_FLAG_DECL(x) { #x, kConsole_##x, OOJS_PROP_READONLY_CB }
|
|
DEBUG_FLAG_DECL(DEBUG_LINKED_LISTS),
|
|
DEBUG_FLAG_DECL(DEBUG_COLLISIONS),
|
|
DEBUG_FLAG_DECL(DEBUG_DOCKING),
|
|
DEBUG_FLAG_DECL(DEBUG_OCTREE_LOGGING),
|
|
DEBUG_FLAG_DECL(DEBUG_BOUNDING_BOXES),
|
|
DEBUG_FLAG_DECL(DEBUG_OCTREE_DRAW),
|
|
DEBUG_FLAG_DECL(DEBUG_DRAW_NORMALS),
|
|
DEBUG_FLAG_DECL(DEBUG_NO_DUST),
|
|
DEBUG_FLAG_DECL(DEBUG_NO_SHADER_FALLBACK),
|
|
DEBUG_FLAG_DECL(DEBUG_SHADER_VALIDATION),
|
|
|
|
DEBUG_FLAG_DECL(DEBUG_MISC),
|
|
#undef DEBUG_FLAG_DECL
|
|
|
|
{ 0 }
|
|
};
|
|
|
|
|
|
static JSFunctionSpec sConsoleMethods[] =
|
|
{
|
|
// JS name Function min args
|
|
{ "consoleMessage", ConsoleConsoleMessage, 2 },
|
|
{ "clearConsole", ConsoleClearConsole, 0 },
|
|
{ "scriptStack", ConsoleScriptStack, 0 },
|
|
{ "inspectEntity", ConsoleInspectEntity, 1 },
|
|
#if OO_DEBUG
|
|
{ "__setUpCallObjC", ConsoleSetUpCallObjC, 1 },
|
|
#endif
|
|
{ "isExecutableJavaScript", ConsoleIsExecutableJavaScript, 2 },
|
|
{ "displayMessagesInClass", ConsoleDisplayMessagesInClass, 1 },
|
|
{ "setDisplayMessagesInClass", ConsoleSetDisplayMessagesInClass, 2 },
|
|
{ "writeLogMarker", ConsoleWriteLogMarker, 0 },
|
|
{ "writeMemoryStats", ConsoleWriteMemoryStats, 0 },
|
|
{ "garbageCollect", ConsoleGarbageCollect, 0 },
|
|
#if DEBUG
|
|
{ "dumpNamedRoots", ConsoleDumpNamedRoots, 0 },
|
|
{ "dumpHeap", ConsoleDumpHeap, 0 },
|
|
#endif
|
|
#if OOJS_PROFILE
|
|
{ "profile", ConsoleProfile, 1 },
|
|
{ "getProfile", ConsoleGetProfile, 1 },
|
|
{ "trace", ConsoleTrace, 1 },
|
|
#endif
|
|
{ 0 }
|
|
};
|
|
|
|
|
|
static JSClass sConsoleSettingsClass =
|
|
{
|
|
"ConsoleSettings",
|
|
JSCLASS_HAS_PRIVATE,
|
|
|
|
JS_PropertyStub, // addProperty
|
|
ConsoleSettingsDeleteProperty, // delProperty
|
|
ConsoleSettingsGetProperty, // getProperty
|
|
ConsoleSettingsSetProperty, // setProperty
|
|
JS_EnumerateStub, // enumerate. FIXME: this should work.
|
|
JS_ResolveStub, // resolve
|
|
JS_ConvertStub, // convert
|
|
ConsoleFinalize, // finalize (same as Console)
|
|
JSCLASS_NO_OPTIONAL_MEMBERS
|
|
};
|
|
|
|
|
|
static void InitOOJSConsole(JSContext *context, JSObject *global)
|
|
{
|
|
sConsolePrototype = JS_InitClass(context, global, NULL, &sConsoleClass, OOJSUnconstructableConstruct, 0, sConsoleProperties, sConsoleMethods, NULL, NULL);
|
|
OOJSRegisterObjectConverter(&sConsoleClass, OOJSBasicPrivateObjectConverter);
|
|
|
|
sConsoleSettingsPrototype = JS_InitClass(context, global, NULL, &sConsoleSettingsClass, OOJSUnconstructableConstruct, 0, NULL, NULL, NULL, NULL);
|
|
OOJSRegisterObjectConverter(&sConsoleSettingsClass, OOJSBasicPrivateObjectConverter);
|
|
}
|
|
|
|
|
|
void OOJSConsoleDestroy(void)
|
|
{
|
|
sConsolePrototype = NULL;
|
|
}
|
|
|
|
|
|
JSObject *DebugMonitorToJSConsole(JSContext *context, OODebugMonitor *monitor)
|
|
{
|
|
OOJS_PROFILE_ENTER
|
|
|
|
OOJavaScriptEngine *engine = nil;
|
|
JSObject *object = NULL;
|
|
JSObject *settingsObject = NULL;
|
|
jsval value;
|
|
|
|
NSCAssert(JS_EnterLocalRootScope(context), @"Failed to create JS GC root scope");
|
|
engine = [OOJavaScriptEngine sharedEngine];
|
|
|
|
if (sConsolePrototype == NULL)
|
|
{
|
|
InitOOJSConsole(context, [engine globalObject]);
|
|
}
|
|
|
|
// Create Console object
|
|
object = JS_NewObject(context, &sConsoleClass, sConsolePrototype, NULL);
|
|
if (object != NULL)
|
|
{
|
|
if (!JS_SetPrivate(context, object, [monitor weakRetain])) object = NULL;
|
|
}
|
|
|
|
if (object != NULL)
|
|
{
|
|
// Create ConsoleSettings object
|
|
settingsObject = JS_NewObject(context, &sConsoleSettingsClass, sConsoleSettingsPrototype, NULL);
|
|
if (settingsObject != NULL)
|
|
{
|
|
if (!JS_SetPrivate(context, settingsObject, [monitor weakRetain])) settingsObject = NULL;
|
|
}
|
|
if (settingsObject != NULL)
|
|
{
|
|
value = OBJECT_TO_JSVAL(settingsObject);
|
|
if (!JS_SetProperty(context, object, "settings", &value))
|
|
{
|
|
settingsObject = NULL;
|
|
}
|
|
}
|
|
|
|
if (settingsObject == NULL) object = NULL;
|
|
}
|
|
|
|
JS_LeaveLocalRootScope(context);
|
|
|
|
return object;
|
|
// Analyzer: object leaked. (x2) [Expected, objects are retained by JS object.]
|
|
|
|
OOJS_PROFILE_EXIT
|
|
}
|
|
|
|
|
|
static JSBool ConsoleGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
|
|
{
|
|
if (!JSID_IS_INT(propID)) return YES;
|
|
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
switch (JSID_TO_INT(propID))
|
|
{
|
|
#ifndef NDEBUG
|
|
case kConsole_debugFlags:
|
|
*value = INT_TO_JSVAL((uint32_t)gDebugFlags);
|
|
break;
|
|
#endif
|
|
|
|
case kConsole_shaderMode:
|
|
// EMMSTRAN: if still relevant, OOConstToJSString-ify.
|
|
*value = OOJSValueFromNativeObject(context, OOStringFromShaderSetting([UNIVERSE shaderEffectsLevel]));
|
|
break;
|
|
|
|
case kConsole_maximumShaderMode:
|
|
*value = OOJSValueFromNativeObject(context, OOStringFromShaderSetting([[OOOpenGLExtensionManager sharedManager] maximumShaderSetting]));
|
|
break;
|
|
|
|
case kConsole_reducedDetailMode:
|
|
*value = OOJSValueFromBOOL([UNIVERSE reducedDetail]);
|
|
break;
|
|
|
|
case kConsole_displayFPS:
|
|
*value = OOJSValueFromBOOL([UNIVERSE displayFPS]);
|
|
break;
|
|
|
|
case kConsole_platformDescription:
|
|
*value = OOJSValueFromNativeObject(context, OOPlatformDescription());
|
|
break;
|
|
|
|
case kConsole_pedanticMode:
|
|
{
|
|
uint32_t options = JS_GetOptions(context);
|
|
*value = OOJSValueFromBOOL(options & JSOPTION_STRICT);
|
|
}
|
|
break;
|
|
|
|
case kConsole_ignoreDroppedPackets:
|
|
*value = OOJSValueFromBOOL([[OODebugMonitor sharedDebugMonitor] TCPIgnoresDroppedPackets]);
|
|
break;
|
|
|
|
case kConsole_showErrorLocations:
|
|
*value = OOJSValueFromBOOL([[OOJavaScriptEngine sharedEngine] showErrorLocations]);
|
|
break;
|
|
|
|
case kConsole_dumpStackForErrors:
|
|
*value = OOJSValueFromBOOL([[OOJavaScriptEngine sharedEngine] dumpStackForErrors]);
|
|
break;
|
|
|
|
case kConsole_dumpStackForWarnings:
|
|
*value = OOJSValueFromBOOL([[OOJavaScriptEngine sharedEngine] dumpStackForWarnings]);
|
|
break;
|
|
|
|
case kConsole_glVendorString:
|
|
*value = OOJSValueFromNativeObject(context, [[OOOpenGLExtensionManager sharedManager] vendorString]);
|
|
break;
|
|
|
|
case kConsole_glRendererString:
|
|
*value = OOJSValueFromNativeObject(context, [[OOOpenGLExtensionManager sharedManager] rendererString]);
|
|
break;
|
|
|
|
case kConsole_glFixedFunctionTextureUnitCount:
|
|
*value = INT_TO_JSVAL((uint32_t)[[OOOpenGLExtensionManager sharedManager] textureUnitCount]);
|
|
break;
|
|
|
|
case kConsole_glFragmentShaderTextureUnitCount:
|
|
*value = INT_TO_JSVAL((uint32_t)[[OOOpenGLExtensionManager sharedManager] textureImageUnitCount]);
|
|
break;
|
|
|
|
#define DEBUG_FLAG_CASE(x) case kConsole_##x: *value = INT_TO_JSVAL(x); break;
|
|
DEBUG_FLAG_CASE(DEBUG_LINKED_LISTS);
|
|
DEBUG_FLAG_CASE(DEBUG_COLLISIONS);
|
|
DEBUG_FLAG_CASE(DEBUG_DOCKING);
|
|
DEBUG_FLAG_CASE(DEBUG_OCTREE_LOGGING);
|
|
DEBUG_FLAG_CASE(DEBUG_BOUNDING_BOXES);
|
|
DEBUG_FLAG_CASE(DEBUG_OCTREE_DRAW);
|
|
DEBUG_FLAG_CASE(DEBUG_DRAW_NORMALS);
|
|
DEBUG_FLAG_CASE(DEBUG_NO_DUST);
|
|
DEBUG_FLAG_CASE(DEBUG_NO_SHADER_FALLBACK);
|
|
DEBUG_FLAG_CASE(DEBUG_SHADER_VALIDATION);
|
|
|
|
DEBUG_FLAG_CASE(DEBUG_MISC);
|
|
#undef DEBUG_FLAG_CASE
|
|
|
|
default:
|
|
OOJSReportBadPropertySelector(context, this, propID, sConsoleProperties);
|
|
return NO;
|
|
}
|
|
|
|
return YES;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
static JSBool ConsoleSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
|
|
{
|
|
if (!JSID_IS_INT(propID)) return YES;
|
|
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
int32 iValue;
|
|
NSString *sValue = nil;
|
|
JSBool bValue = NO;
|
|
|
|
switch (JSID_TO_INT(propID))
|
|
{
|
|
#ifndef NDEBUG
|
|
case kConsole_debugFlags:
|
|
if (JS_ValueToInt32(context, *value, &iValue))
|
|
{
|
|
gDebugFlags = iValue;
|
|
}
|
|
break;
|
|
#endif
|
|
case kConsole_shaderMode:
|
|
sValue = OOStringFromJSValue(context, *value);
|
|
if (sValue != nil)
|
|
{
|
|
OOJS_BEGIN_FULL_NATIVE(context)
|
|
OOShaderSetting setting = OOShaderSettingFromString(sValue);
|
|
[UNIVERSE setShaderEffectsLevel:setting transiently:YES];
|
|
OOJS_END_FULL_NATIVE
|
|
}
|
|
break;
|
|
|
|
case kConsole_reducedDetailMode:
|
|
if (JS_ValueToBoolean(context, *value, &bValue))
|
|
{
|
|
OOJS_BEGIN_FULL_NATIVE(context)
|
|
[UNIVERSE setReducedDetail:bValue transiently:YES];
|
|
OOJS_END_FULL_NATIVE
|
|
}
|
|
break;
|
|
|
|
case kConsole_displayFPS:
|
|
if (JS_ValueToBoolean(context, *value, &bValue))
|
|
{
|
|
[UNIVERSE setDisplayFPS:bValue];
|
|
}
|
|
break;
|
|
|
|
case kConsole_pedanticMode:
|
|
if (JS_ValueToBoolean(context, *value, &bValue))
|
|
{
|
|
uint32_t options = JS_GetOptions(context);
|
|
if (bValue) options |= JSOPTION_STRICT;
|
|
else options &= ~JSOPTION_STRICT;
|
|
|
|
JS_SetOptions(context, options);
|
|
}
|
|
break;
|
|
|
|
case kConsole_ignoreDroppedPackets:
|
|
if (JS_ValueToBoolean(context, *value, &bValue))
|
|
{
|
|
[[OODebugMonitor sharedDebugMonitor] setTCPIgnoresDroppedPackets:bValue];
|
|
}
|
|
break;
|
|
|
|
case kConsole_showErrorLocations:
|
|
if (JS_ValueToBoolean(context, *value, &bValue))
|
|
{
|
|
[[OOJavaScriptEngine sharedEngine] setShowErrorLocations:bValue];
|
|
}
|
|
break;
|
|
|
|
case kConsole_dumpStackForErrors:
|
|
if (JS_ValueToBoolean(context, *value, &bValue))
|
|
{
|
|
[[OOJavaScriptEngine sharedEngine] setDumpStackForErrors:bValue];
|
|
}
|
|
break;
|
|
|
|
case kConsole_dumpStackForWarnings:
|
|
if (JS_ValueToBoolean(context, *value, &bValue))
|
|
{
|
|
[[OOJavaScriptEngine sharedEngine] setDumpStackForWarnings:bValue];
|
|
}
|
|
break;
|
|
|
|
default:
|
|
OOJSReportBadPropertySelector(context, this, propID, sConsoleProperties);
|
|
return NO;
|
|
}
|
|
|
|
return YES;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
static BOOL DoWeDefineAllDebugFlags(enum OODebugFlags flags) GCC_ATTR((unused));
|
|
static BOOL DoWeDefineAllDebugFlags(enum OODebugFlags flags)
|
|
{
|
|
/* This function doesn't do anything, but will generate a warning
|
|
(Enumeration value 'DEBUG_FOO' not handled in switch) if a debug flag
|
|
is added without updating it. The point is that if you get such a
|
|
warning, you should first add a JS symbolic constant for the flag,
|
|
then add it to the switch to supress the warning.
|
|
NOTE: don't add a default: to this switch, or I will have to hurt you.
|
|
-- Ahruman 2010-04-11
|
|
*/
|
|
switch (flags)
|
|
{
|
|
case DEBUG_LINKED_LISTS:
|
|
case DEBUG_COLLISIONS:
|
|
case DEBUG_DOCKING:
|
|
case DEBUG_OCTREE_LOGGING:
|
|
case DEBUG_BOUNDING_BOXES:
|
|
case DEBUG_OCTREE_DRAW:
|
|
case DEBUG_DRAW_NORMALS:
|
|
case DEBUG_NO_DUST:
|
|
case DEBUG_NO_SHADER_FALLBACK:
|
|
case DEBUG_SHADER_VALIDATION:
|
|
case DEBUG_MISC:
|
|
return YES;
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
|
|
static void ConsoleFinalize(JSContext *context, JSObject *this)
|
|
{
|
|
OOJS_PROFILE_ENTER
|
|
|
|
[(id)JS_GetPrivate(context, this) release];
|
|
JS_SetPrivate(context, this, nil);
|
|
|
|
OOJS_PROFILE_EXIT_VOID
|
|
}
|
|
|
|
|
|
static JSBool ConsoleSettingsDeleteProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
NSString *key = nil;
|
|
id monitor = nil;
|
|
|
|
if (!JSID_IS_STRING(propID)) return NO;
|
|
key = OOStringFromJSString(context, JSID_TO_STRING(propID));
|
|
|
|
monitor = OOJSNativeObjectFromJSObject(context, this);
|
|
if (![monitor isKindOfClass:[OODebugMonitor class]])
|
|
{
|
|
OOJSReportError(context, @"Expected OODebugMonitor, got %@ in %s. %@", [monitor class], __PRETTY_FUNCTION__, @"This is an internal error, please report it.");
|
|
return NO;
|
|
}
|
|
|
|
[monitor setConfigurationValue:nil forKey:key];
|
|
*value = JSVAL_TRUE;
|
|
return YES;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
static JSBool ConsoleSettingsGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
|
|
{
|
|
if (!JSID_IS_STRING(propID)) return YES;
|
|
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
NSString *key = nil;
|
|
id settingValue = nil;
|
|
id monitor = nil;
|
|
|
|
key = OOStringFromJSString(context, JSID_TO_STRING(propID));
|
|
|
|
monitor = OOJSNativeObjectFromJSObject(context, this);
|
|
if (![monitor isKindOfClass:[OODebugMonitor class]])
|
|
{
|
|
OOJSReportError(context, @"Expected OODebugMonitor, got %@ in %s. %@", [monitor class], __PRETTY_FUNCTION__, @"This is an internal error, please report it.");
|
|
return NO;
|
|
}
|
|
|
|
settingValue = [monitor configurationValueForKey:key];
|
|
if (settingValue != NULL) *value = [settingValue oo_jsValueInContext:context];
|
|
else *value = JSVAL_VOID;
|
|
|
|
return YES;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
static JSBool ConsoleSettingsSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
|
|
{
|
|
if (!JSID_IS_STRING(propID)) return YES;
|
|
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
NSString *key = nil;
|
|
id settingValue = nil;
|
|
id monitor = nil;
|
|
|
|
key = OOStringFromJSString(context, JSID_TO_STRING(propID));
|
|
|
|
monitor = OOJSNativeObjectFromJSObject(context, this);
|
|
if (![monitor isKindOfClass:[OODebugMonitor class]])
|
|
{
|
|
OOJSReportError(context, @"Expected OODebugMonitor, got %@ in %s. %@", [monitor class], __PRETTY_FUNCTION__, @"This is an internal error, please report it.");
|
|
return NO;
|
|
}
|
|
|
|
// Not OOJS_BEGIN_FULL_NATIVE() - we use JSAPI while paused.
|
|
OOJSPauseTimeLimiter();
|
|
if (JSVAL_IS_NULL(*value) || JSVAL_IS_VOID(*value))
|
|
{
|
|
[monitor setConfigurationValue:nil forKey:key];
|
|
}
|
|
else
|
|
{
|
|
settingValue = OOJSNativeObjectFromJSValue(context, *value);
|
|
if (settingValue != nil)
|
|
{
|
|
[monitor setConfigurationValue:settingValue forKey:key];
|
|
}
|
|
else
|
|
{
|
|
OOJSReportWarning(context, @"debugConsole.settings: could not convert %@ to native object.", OOStringFromJSValue(context, *value));
|
|
}
|
|
}
|
|
OOJSResumeTimeLimiter();
|
|
|
|
return YES;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// *** Methods ***
|
|
|
|
// function consoleMessage(colorCode : String, message : String [, emphasisStart : Number, emphasisLength : Number]) : void
|
|
static JSBool ConsoleConsoleMessage(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
NSRange emphasisRange = {0, 0};
|
|
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
id monitor = nil;
|
|
NSString *colorKey = nil,
|
|
*message = nil;
|
|
jsdouble location, length;
|
|
|
|
// Not OOJS_BEGIN_FULL_NATIVE() - we use JSAPI while paused.
|
|
OOJSPauseTimeLimiter();
|
|
monitor = OOJSNativeObjectOfClassFromJSObject(context, OOJS_THIS, [OODebugMonitor class]);
|
|
if (monitor == nil)
|
|
{
|
|
OOJSReportError(context, @"Expected OODebugMonitor, got %@ in %s. %@", [monitor class], __PRETTY_FUNCTION__, @"This is an internal error, please report it.");
|
|
OOJSResumeTimeLimiter();
|
|
return NO;
|
|
}
|
|
|
|
if (argc > 0) colorKey = OOStringFromJSValue(context,OOJS_ARGV[0]);
|
|
if (argc > 1) message = OOStringFromJSValue(context,OOJS_ARGV[1]);
|
|
|
|
if (argc > 3)
|
|
{
|
|
// Attempt to get two numbers, specifying an emphasis range.
|
|
if (JS_ValueToNumber(context, OOJS_ARGV[2], &location) &&
|
|
JS_ValueToNumber(context, OOJS_ARGV[3], &length))
|
|
{
|
|
emphasisRange = (NSRange){location, length};
|
|
}
|
|
}
|
|
|
|
if (message == nil)
|
|
{
|
|
if (colorKey == nil)
|
|
{
|
|
OOJSReportWarning(context, @"Console.consoleMessage() called with no parameters.");
|
|
}
|
|
else
|
|
{
|
|
message = colorKey;
|
|
colorKey = @"command-result";
|
|
}
|
|
}
|
|
|
|
if (message != nil)
|
|
{
|
|
[monitor appendJSConsoleLine:message
|
|
colorKey:colorKey
|
|
emphasisRange:emphasisRange];
|
|
}
|
|
OOJSResumeTimeLimiter();
|
|
|
|
OOJS_RETURN_VOID;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function clearConsole() : void
|
|
static JSBool ConsoleClearConsole(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
id monitor = nil;
|
|
|
|
monitor = OOJSNativeObjectFromJSObject(context, OOJS_THIS);
|
|
if (![monitor isKindOfClass:[OODebugMonitor class]])
|
|
{
|
|
OOJSReportError(context, @"Expected OODebugMonitor, got %@ in %s. %@", [monitor class], __PRETTY_FUNCTION__, @"This is an internal error, please report it.");
|
|
return NO;
|
|
}
|
|
|
|
[monitor clearJSConsole];
|
|
OOJS_RETURN_VOID;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function scriptStack() : Array
|
|
static JSBool ConsoleScriptStack(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
OOJS_RETURN_OBJECT([OOJSScript scriptStack]);
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function inspectEntity(entity : Entity) : void
|
|
static JSBool ConsoleInspectEntity(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
Entity *entity = nil;
|
|
|
|
if (JSValueToEntity(context, OOJS_ARGV[0], &entity))
|
|
{
|
|
OOJS_BEGIN_FULL_NATIVE(context)
|
|
if ([entity respondsToSelector:@selector(inspect)])
|
|
{
|
|
[entity inspect];
|
|
}
|
|
OOJS_END_FULL_NATIVE
|
|
}
|
|
|
|
OOJS_RETURN_VOID;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
#if OO_DEBUG
|
|
// function callObjC(selector : String [, ...]) : Object
|
|
static JSBool ConsoleCallObjCMethod(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
id object = nil;
|
|
jsval result;
|
|
BOOL OK;
|
|
|
|
object = OOJSNativeObjectFromJSObject(context, OOJS_THIS);
|
|
if (object == nil)
|
|
{
|
|
OOJSReportError(context, @"Attempt to call __callObjCMethod() for non-Objective-C object %@.", OOStringFromJSValueEvenIfNull(context, JS_THIS(context, vp)));
|
|
return NO;
|
|
}
|
|
|
|
OOJSPauseTimeLimiter();
|
|
result = JSVAL_VOID;
|
|
OK = OOJSCallObjCObjectMethod(context, object, [object oo_jsClassName], argc, OOJS_ARGV, &result);
|
|
OOJSResumeTimeLimiter();
|
|
|
|
OOJS_SET_RVAL(result);
|
|
return OK;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function __setUpCallObjC(object) -- object is expected to be Object.prototye.
|
|
static JSBool ConsoleSetUpCallObjC(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
if (EXPECT_NOT(!JSVAL_IS_OBJECT(OOJS_ARGV[0])))
|
|
{
|
|
OOJSReportBadArguments(context, @"Console", @"__setUpCallObjC", argc, OOJS_ARGV, nil, @"Object.prototype");
|
|
return NO;
|
|
}
|
|
|
|
JSObject *obj = JSVAL_TO_OBJECT(OOJS_ARGV[0]);
|
|
JS_DefineFunction(context, obj, "callObjC", ConsoleCallObjCMethod, 1, OOJS_METHOD_READONLY);
|
|
OOJS_RETURN_VOID;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
#endif
|
|
|
|
|
|
// function isExecutableJavaScript(this : Object, string : String) : Boolean
|
|
static JSBool ConsoleIsExecutableJavaScript(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
BOOL result = NO;
|
|
JSObject *target = NULL;
|
|
|
|
if (argc < 2 || !JS_ValueToObject(context, OOJS_ARGV[0], &target) || !JSVAL_IS_STRING(OOJS_ARGV[1]))
|
|
{
|
|
OOJS_RETURN_BOOL(NO); // Fail silently
|
|
}
|
|
|
|
// Not OOJS_BEGIN_FULL_NATIVE() - we use JSAPI while paused.
|
|
OOJSPauseTimeLimiter();
|
|
|
|
// FIXME: this must be possible using just JSAPI functions.
|
|
NSString *string = OOStringFromJSValue(context, OOJS_ARGV[1]);
|
|
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
|
|
result = JS_BufferIsCompilableUnit(context, target, [stringData bytes], [stringData length]);
|
|
|
|
OOJSResumeTimeLimiter();
|
|
|
|
OOJS_RETURN_BOOL(YES);
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function displayMessagesInClass(class : String) : Boolean
|
|
static JSBool ConsoleDisplayMessagesInClass(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
NSString *messageClass = nil;
|
|
|
|
messageClass = OOStringFromJSValue(context, OOJS_ARGV[0]);
|
|
OOJS_RETURN_BOOL(messageClass != nil && OOLogWillDisplayMessagesInClass(messageClass));
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function setDisplayMessagesInClass(class : String, flag : Boolean) : void
|
|
static JSBool ConsoleSetDisplayMessagesInClass(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
NSString *messageClass = nil;
|
|
JSBool flag;
|
|
|
|
messageClass = OOStringFromJSValue(context, OOJS_ARGV[0]);
|
|
if (messageClass != nil && JS_ValueToBoolean(context, OOJS_ARGV[1], &flag))
|
|
{
|
|
OOLogSetDisplayMessagesInClass(messageClass, flag);
|
|
}
|
|
OOJS_RETURN_VOID;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function writeLogMarker() : void
|
|
static JSBool ConsoleWriteLogMarker(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
OOLogInsertMarker();
|
|
OOJS_RETURN_VOID;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function writeMemoryStats() : void
|
|
static JSBool ConsoleWriteMemoryStats(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
OOJS_BEGIN_FULL_NATIVE(context)
|
|
[[OODebugMonitor sharedDebugMonitor] dumpMemoryStatistics];
|
|
OOJS_END_FULL_NATIVE
|
|
|
|
OOJS_RETURN_VOID;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function garbageCollect() : string
|
|
static JSBool ConsoleGarbageCollect(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
uint32_t bytesBefore = JS_GetGCParameter(JS_GetRuntime(context), JSGC_BYTES);
|
|
JS_GC(context);
|
|
uint32_t bytesAfter = JS_GetGCParameter(JS_GetRuntime(context), JSGC_BYTES);
|
|
|
|
OOJS_RETURN_OBJECT(([NSString stringWithFormat:@"Bytes before: %u Bytes after: %u", bytesBefore, bytesAfter]));
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
#if DEBUG
|
|
typedef struct
|
|
{
|
|
JSContext *context;
|
|
FILE *file;
|
|
} DumpCallbackData;
|
|
|
|
static void DumpCallback(const char *name, void *rp, JSGCRootType type, void *datap)
|
|
{
|
|
assert(type == JS_GC_ROOT_VALUE_PTR || type == JS_GC_ROOT_GCTHING_PTR);
|
|
|
|
DumpCallbackData *data = datap;
|
|
|
|
const char *typeString = "unknown type";
|
|
jsval value;
|
|
switch (type)
|
|
{
|
|
case JS_GC_ROOT_VALUE_PTR:
|
|
typeString = "value";
|
|
value = *(jsval *)rp;
|
|
break;
|
|
|
|
case JS_GC_ROOT_GCTHING_PTR:
|
|
typeString = "gc-thing";
|
|
value = OBJECT_TO_JSVAL(*(JSObject **)rp);
|
|
}
|
|
|
|
fprintf(data->file, "%s @ %p (%s): %s\n", name, rp, typeString, [OOJSDescribeValue(data->context, value, NO) UTF8String]);
|
|
}
|
|
|
|
|
|
static JSBool ConsoleDumpNamedRoots(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
|
|
BOOL OK = NO;
|
|
NSString *path = [[ResourceManager diagnosticFileLocation] stringByAppendingPathComponent:@"js-roots.txt"];
|
|
FILE *file = fopen([path UTF8String], "w");
|
|
if (file != NULL)
|
|
{
|
|
DumpCallbackData data =
|
|
{
|
|
.context = context,
|
|
.file = file
|
|
};
|
|
JS_DumpNamedRoots(JS_GetRuntime(context), DumpCallback, &data);
|
|
fclose(file);
|
|
OK = YES;
|
|
}
|
|
|
|
[pool release];
|
|
OOJS_RETURN_BOOL(OK);
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
static JSBool ConsoleDumpHeap(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
BOOL OK = NO;
|
|
NSString *path = [[ResourceManager diagnosticFileLocation] stringByAppendingPathComponent:@"js-heaps.txt"];
|
|
FILE *file = fopen([path UTF8String], "w");
|
|
if (file != NULL)
|
|
{
|
|
OK = JS_DumpHeap(context, file, NULL, 0, NULL, SIZE_MAX, NULL);
|
|
fclose(file);
|
|
}
|
|
|
|
OOJS_RETURN_BOOL(OK);
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
#endif
|
|
|
|
|
|
#if OOJS_PROFILE
|
|
|
|
// function profile(func : function [, Object this = debugConsole.script]) : String
|
|
static JSBool ConsoleProfile(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
if (EXPECT_NOT(OOJSIsProfiling()))
|
|
{
|
|
OOJSReportError(context, @"Profiling functions may not be called while already profiling.");
|
|
return NO;
|
|
}
|
|
|
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
OOTimeProfile *profile = nil;
|
|
|
|
JSBool result = PerformProfiling(context, @"profile", argc, OOJS_ARGV, NULL, NO, &profile);
|
|
if (result)
|
|
{
|
|
OOJS_SET_RVAL(OOJSValueFromNativeObject(context, [profile description]));
|
|
}
|
|
|
|
[pool release];
|
|
return result;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function getProfile(func : function [, Object this = debugConsole.script]) : Object { totalTime : Number, jsTime : Number, extensionTime : Number }
|
|
static JSBool ConsoleGetProfile(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
|
|
if (EXPECT_NOT(OOJSIsProfiling()))
|
|
{
|
|
OOJSReportError(context, @"Profiling functions may not be called while already profiling.");
|
|
return NO;
|
|
}
|
|
|
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
OOTimeProfile *profile = nil;
|
|
|
|
JSBool result = PerformProfiling(context, @"getProfile", argc, OOJS_ARGV, NULL, NO, &profile);
|
|
if (result)
|
|
{
|
|
OOJS_SET_RVAL(OOJSValueFromNativeObject(context, profile));
|
|
}
|
|
|
|
[pool release];
|
|
return result;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
// function trace(func : function [, Object this = debugConsole.script]) : [return type of func]
|
|
static JSBool ConsoleTrace(JSContext *context, uintN argc, jsval *vp)
|
|
{
|
|
OOJS_NATIVE_ENTER(context)
|
|
|
|
if (EXPECT_NOT(OOJSIsProfiling()))
|
|
{
|
|
OOJSReportError(context, @"Profiling functions may not be called while already profiling.");
|
|
return NO;
|
|
}
|
|
|
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
jsval rval;
|
|
|
|
JSBool result = PerformProfiling(context, @"trace", argc, OOJS_ARGV, &rval, YES, NULL);
|
|
if (result)
|
|
{
|
|
OOJS_SET_RVAL(rval);
|
|
}
|
|
|
|
[pool release];
|
|
return result;
|
|
|
|
OOJS_NATIVE_EXIT
|
|
}
|
|
|
|
|
|
static JSBool PerformProfiling(JSContext *context, NSString *nominalFunction, uintN argc, jsval *argv, jsval *outRval, BOOL trace, OOTimeProfile **outProfile)
|
|
{
|
|
// Get function.
|
|
jsval function = argv[0];
|
|
if (!OOJSValueIsFunction(context, function))
|
|
{
|
|
OOJSReportBadArguments(context, @"Console", nominalFunction, 1, argv, nil, @"function");
|
|
return NO;
|
|
}
|
|
|
|
// Get "this" object.
|
|
jsval this;
|
|
if (argc > 1) this = argv[1];
|
|
else
|
|
{
|
|
jsval debugConsole = OOJSValueFromNativeObject(context, [OODebugMonitor sharedDebugMonitor]);
|
|
assert(JSVAL_IS_OBJECT(debugConsole) && !JSVAL_IS_NULL(debugConsole));
|
|
JS_GetProperty(context, JSVAL_TO_OBJECT(debugConsole), "script", &this);
|
|
}
|
|
|
|
JSObject *thisObj;
|
|
if (!JS_ValueToObject(context, this, &thisObj)) thisObj = NULL;
|
|
|
|
jsval ignored;
|
|
if (outRval == NULL) outRval = &ignored;
|
|
|
|
// Fiddle with time limiter.
|
|
// We want to save the current limit, reset the limiter, and set the time limit to a long time.
|
|
#define LONG_TIME (1e7) // A long time - 115.7 days - but, crucially, finite.
|
|
|
|
OOTimeDelta originalLimit = OOJSGetTimeLimiterLimit();
|
|
OOJSSetTimeLimiterLimit(LONG_TIME);
|
|
OOJSResetTimeLimiter();
|
|
|
|
OOJSBeginProfiling(trace);
|
|
|
|
// Call the function.
|
|
BOOL result = JS_CallFunctionValue(context, thisObj, function, 0, NULL, outRval);
|
|
|
|
// Get results.
|
|
OOTimeProfile *profile = OOJSEndProfiling();
|
|
if (outProfile != NULL) *outProfile = profile;
|
|
|
|
// Restore original timer state.
|
|
OOJSSetTimeLimiterLimit(originalLimit);
|
|
OOJSResetTimeLimiter();
|
|
|
|
JS_ReportPendingException(context);
|
|
|
|
return result;
|
|
}
|
|
|
|
#endif // OOJS_PROFILE
|
|
|
|
#endif /* OO_EXCLUDE_DEBUG_SUPPORT */
|