/* OOJavaScriptEngine.h JavaScript support for Oolite Copyright (C) 2007 David Taylor and Jens Ayton. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #import #import "Universe.h" #import "PlayerEntity.h" #import "PlayerEntityLegacyScriptEngine.h" #import #define OOJSENGINE_MONITOR_SUPPORT (!defined(NDEBUG)) @protocol OOJavaScriptEngineMonitor; enum { kOOJavaScriptEngineContextPoolCount = 3 }; @interface OOJavaScriptEngine : NSObject { JSRuntime *runtime; JSContext *mainContext; JSContext *contextPool[kOOJavaScriptEngineContextPoolCount]; uint8_t contextPoolCount; uint8_t mainContextInUse; JSObject *globalObject; #if OOJSENGINE_MONITOR_SUPPORT id monitor; #endif } + (OOJavaScriptEngine *)sharedEngine; - (JSObject *)globalObject; // The current context. NULL if nothing executing. // - (JSContext *)context; // Call a JS function, setting up new contexts as necessary. - (BOOL) callJSFunction:(JSFunction *)function forObject:(JSObject *)jsThis argc:(uintN)argc argv:(jsval *)argv result:(jsval *)outResult; // Get a context for doing something other than calling a function. - (JSContext *)acquireContext; - (void)releaseContext:(JSContext *)context; - (BOOL) addGCRoot:(void *)rootPtr named:(const char *)name; - (void) removeGCRoot:(void *)rootPtr; @end void OOReportJavaScriptError(JSContext *context, NSString *format, ...); void OOReportJavaScriptErrorWithArguments(JSContext *context, NSString *format, va_list args); void OOReportJavaScriptWarning(JSContext *context, NSString *format, ...); void OOReportJavaScriptWarningWithArguments(JSContext *context, NSString *format, va_list args); void OOReportJavaScriptBadPropertySelector(JSContext *context, NSString *className, jsint selector); /* NumberFromArgumentList() Get a single number from an argument list. The optional outConsumed argument can be used to find out how many parameters were used (currently, this will be 0 on failure, otherwise 1). On failure, it will return NO, annd the number will be unaltered. If scriptClass and function are non-nil, a warning will be reported to the log. */ BOOL NumberFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed); OOINLINE jsval BOOLToJSVal(BOOL b) INLINE_CONST_FUNC; OOINLINE jsval BOOLToJSVal(BOOL b) { return BOOLEAN_TO_JSVAL(b != NO); } /* JSFooNSBar() Wrappers to corresponding JS_FooBar()/JS_FooUCBar() functions, but taking an NSString. Additionally, a NULL context parameter may be used. */ BOOL JSGetNSProperty(JSContext *context, JSObject *object, NSString *name, jsval *value); BOOL JSSetNSProperty(JSContext *context, JSObject *object, NSString *name, jsval *value); BOOL JSDefineNSProperty(JSContext *context, JSObject *object, NSString *name, jsval value, JSPropertyOp getter, JSPropertyOp setter, uintN attrs); @interface NSObject (OOJavaScriptConversion) /* -javaScriptValueInContext: Return the JavaScript object representation of an object. The default implementation returns JSVAL_VOID. At this time, NSString, NSNumber, NSArray, NSDictionary, NSNull, Entity, OOScript and OOJSTimer override this. */ - (jsval)javaScriptValueInContext:(JSContext *)context; /* -javaScriptDescription -javaScriptDescriptionWithClassName: -jsClassName See comments for -descriptionComponents in OOCocoa.h. */ - (NSString *)javaScriptDescription; - (NSString *)javaScriptDescriptionWithClassName:(NSString *)className; - (NSString *)jsClassName; @end /* JSObjectWrapperToString Implementation of toString() for JS classes whose private storage is an Objective-C object reference (generally an OOWeakReference). Calls -javaScriptDescription and, if that fails, -description. */ JSBool JSObjectWrapperToString(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult); /* JSObjectWrapperFinalize Finalizer for JS classes whose private storage is a retained object reference (generally an OOWeakReference). */ void JSObjectWrapperFinalize(JSContext *context, JSObject *this); @interface NSString (OOJavaScriptExtensions) // Convert a JSString to an NSString. + (id)stringWithJavaScriptString:(JSString *)string; // Convert an arbitrary JS object to an NSString, using JS_ValueToString. + (id)stringWithJavaScriptValue:(jsval)value inContext:(JSContext *)context; // For diagnostic messages; produces things like @"(42, true, "a string", an object description)". + (id)stringWithJavaScriptParameters:(jsval *)params count:(uintN)count inContext:(JSContext *)context; // Concatenate sequence of arbitrary JS objects into string. + (id)concatenationOfStringsFromJavaScriptValues:(jsval *)values count:(size_t)count separator:(NSString *)separator inContext:(JSContext *)context; // Add escape codes for string so that it's a valid JavaScript literal (if you put "" or '' around it). - (NSString *)escapedForJavaScriptLiteral; @end OOINLINE NSString *JSValToNSString(JSContext *context, jsval value) { return [NSString stringWithJavaScriptValue:value inContext:context]; } // OOEntityFilterPredicate wrapping a JavaScript function. typedef struct { JSContext *context; JSFunction *function; JSObject *jsThis; } JSFunctionPredicateParameter; BOOL JSFunctionPredicate(Entity *entity, void *parameter); // YES for ships and planets. Parameter: ignored. BOOL JSEntityIsJavaScriptVisiblePredicate(Entity *entity, void *parameter); // YES for ships other than sub-entities and menu-display ships, and planets other than atmospheres and menu miniatures. Parameter: ignored. BOOL JSEntityIsJavaScriptSearchablePredicate(Entity *entity, void *parameter); id JSValueToObject(JSContext *context, jsval value); id JSObjectToObject(JSContext *context, JSObject *object); /* Support for JSValueToObject() JSClassConverterCallback specifies the prototype for a callback function which converts a JavaScript object to an Objective-C object. JSBasicPrivateObjectConverter() is a JSClassConverterCallback which returns the JS object's private storage value. It automatically unpacks OOWeakReferences if relevant. JSRegisterObjectConverter() registers a callback for a specific JS class. It is not automatically propagated to subclasses. */ typedef id (*JSClassConverterCallback)(JSContext *context, JSObject *object); id JSBasicPrivateObjectConverter(JSContext *context, JSObject *object); void JSRegisterObjectConverter(JSClass *theClass, JSClassConverterCallback converter); #if OOJSENGINE_MONITOR_SUPPORT /* Protocol for debugging "monitor" object. The monitor is an object -- in Oolite, or via Distributed Objects -- which is provided with debugging information by the OOJavaScriptEngine. Currently, this is implemented in the Debug OXP for Mac OS X only. */ @protocol OOJavaScriptEngineMonitor // Sent for JS errors or warnings. - (oneway void)jsEngine:(in byref OOJavaScriptEngine *)engine context:(in JSContext *)context error:(in JSErrorReport *)errorReport withMessage:(in NSString *)message; // Sent for JS log messages. Note: messageClass will be nil of Log() is used rather than LogWithClass(). - (oneway void)jsEngine:(in byref OOJavaScriptEngine *)engine context:(in JSContext *)context logMessage:(in NSString *)message ofClass:(in NSString *)messageClass; @end @interface OOJavaScriptEngine (OOMonitorSupport) - (void)setMonitor:(id)monitor; @end #endif