Oolite 1.91.0.7646-241128-10e222e
Loading...
Searching...
No Matches
OOJavaScriptEngine.h
Go to the documentation of this file.
1/*
2
3OOJavaScriptEngine.h
4
5JavaScript support for Oolite
6Copyright (C) 2007-2013 David Taylor and Jens Ayton.
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21MA 02110-1301, USA.
22
23*/
24
25
26#import "OOCocoa.h"
27#import "Universe.h"
28#import "PlayerEntity.h"
30#include <jsapi.h>
31
32
33#define OOJSENGINE_MONITOR_SUPPORT OOLITE_DEBUG
34
35
36#import "OOJSPropID.h"
37
38
39@protocol OOJavaScriptEngineMonitor;
40
41
42@interface OOJavaScriptEngine: NSObject
43{
44@private
45 JSRuntime *_runtime;
46 JSObject *_globalObject;
48
49 JSClass *_objectClass;
50 JSClass *_stringClass;
51 JSClass *_arrayClass;
52 JSClass *_numberClass;
53 JSClass *_booleanClass;
54
55#ifndef NDEBUG
58#endif
59#if OOJSENGINE_MONITOR_SUPPORT
60 id<OOJavaScriptEngineMonitor> _monitor;
61#endif
62}
63
64+ (OOJavaScriptEngine *) sharedEngine;
65
66- (JSObject *) globalObject;
67
68- (void) runMissionCallback;
69
70/* Tear down context and global object and rebuild them from scratch. This
71 invalidates -globalObject and the main thread context.
72*/
73- (BOOL) reset;
74
75// Call a JS function, setting up new contexts as necessary. Caller is responsible for ensuring the jsval passed really is a function.
76- (BOOL) callJSFunction:(jsval)function
77 forObject:(JSObject *)jsThis
78 argc:(uintN)argc
79 argv:(jsval *)argv
80 result:(jsval *)outResult;
81
82- (void) removeGCObjectRoot:(JSObject **)rootPtr;
83- (void) removeGCValueRoot:(jsval *)rootPtr;
84
85- (void) garbageCollectionOpportunity:(BOOL)force;
86
87- (BOOL) showErrorLocations;
88- (void) setShowErrorLocations:(BOOL)value;
89
90- (JSClass *) objectClass;
91- (JSClass *) stringClass;
92- (JSClass *) arrayClass;
93- (JSClass *) numberClass;
94- (JSClass *) booleanClass;
95
96#ifndef NDEBUG
97- (BOOL) dumpStackForErrors;
98- (void) setDumpStackForErrors:(BOOL)value;
99
100- (BOOL) dumpStackForWarnings;
101- (void) setDumpStackForWarnings:(BOOL)value;
102
103// Install handler for JS "debugger" statment.
104- (void) enableDebuggerStatement;
105#endif
106
107@end
108
109
110#if !JS_THREADSAFE
111#define JS_IsInRequest(context) (((void)(context)), YES)
112#define JS_BeginRequest(context) do {} while (0)
113#define JS_EndRequest(context) do {} while (0)
114#endif
115
116
117// Get the main thread's JS context, and begin a request on it.
119{
120 extern JSContext *gOOJSMainThreadContext;
121 NSCAssert(gOOJSMainThreadContext != NULL, @"Attempt to use JavaScript context before JavaScript engine is initialized.");
124}
125
126
127// End a request on the main thread's context.
128OOINLINE void OOJSRelinquishContext(JSContext *context)
129{
130#ifndef NDEBUG
131 extern JSContext *gOOJSMainThreadContext;
132 NSCParameterAssert(context == gOOJSMainThreadContext && JS_IsInRequest(context));
133#endif
134 JS_EndRequest(context);
135}
136
137
138// Notifications sent when JavaScript engine is reset.
139extern NSString * const kOOJavaScriptEngineWillResetNotification;
140extern NSString * const kOOJavaScriptEngineDidResetNotification;
141
142
143/* Error and warning reporters.
144
145 Note that after reporting an error in a JavaScript callback, the caller
146 must return NO to signal an error.
147*/
148void OOJSReportError(JSContext *context, NSString *format, ...);
149void OOJSReportErrorWithArguments(JSContext *context, NSString *format, va_list args);
150void OOJSReportErrorForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format, ...);
151
152void OOJSReportWarning(JSContext *context, NSString *format, ...);
153void OOJSReportWarningWithArguments(JSContext *context, NSString *format, va_list args);
154void OOJSReportWarningForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format, ...);
155
156void OOJSReportBadPropertySelector(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec);
157void OOJSReportBadPropertyValue(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec, jsval value);
158void OOJSReportBadArguments(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, NSString *message, NSString *expectedArgsDescription);
159
160/* OOJSSetWarningOrErrorStackSkip()
161
162 Indicate that the direct call site is not relevant for error handler.
163 Currently, if non-zero, no call site information is provided.
164 Ideally, we'd stack crawl instead.
165*/
166void OOJSSetWarningOrErrorStackSkip(unsigned skip);
167
168
169/* OOJSArgumentListGetNumber()
170
171 Get a single number from an argument list. The optional outConsumed
172 argument can be used to find out how many parameters were used (currently,
173 this will be 0 on failure, otherwise 1).
174
175 On failure, it will return NO and raise an error. If the caller is a JS
176 callback, it must return NO to signal an error.
177*/
178BOOL OOJSArgumentListGetNumber(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed);
179
180/* OOJSArgumentListGetNumberNoError()
181
182 Like OOJSArgumentListGetNumber(), but does not report an error on failure.
183*/
184BOOL OOJSArgumentListGetNumberNoError(JSContext *context, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed);
185
186
187// Typed as int rather than BOOL to work with more general expressions such as bitfield tests.
190{
191 return BOOLEAN_TO_JSVAL(b != NO);
192}
193
194
195@interface NSObject (OOJavaScript)
196
197/* -oo_jsValueInContext:
198
199 Return the JavaScript value representation of an object. The default
200 implementation returns JSVAL_VOID.
201
202 SAFETY NOTE: if this message is sent to nil, the return value depends on
203 the platform and whether JS_USE_JSVAL_JSID_STRUCT_TYPES is set. If the
204 receiver may be nil, use OOJSValueFromNativeObject() instead.
205
206 One case where it is safe to use oo_jsValueInContext: is with objects
207 retrieved from Foundation collections, as they can never be nil.
208
209 Requires a request on context.
210*/
211- (jsval) oo_jsValueInContext:(JSContext *)context;
212
213/* -oo_jsDescription
214 -oo_jsDescriptionWithClassName:
215 -oo_jsClassName
216
217 See comments for -descriptionComponents in OOCocoa.h.
218*/
219- (NSString *) oo_jsDescription;
220- (NSString *) oo_jsDescriptionWithClassName:(NSString *)className;
221- (NSString *) oo_jsClassName;
222
223/* oo_clearJSSelf:
224 This is called by OOJSObjectWrapperFinalize() when a JS object wrapper is
225 collected. The default implementation does nothing.
226*/
227- (void) oo_clearJSSelf:(JSObject *)selfVal;
228
229@end
230
231
232/* OOJSValueFromNativeObject()
233 Return a JavaScript value representation of an object, or null if passed
234 nil.
235
236 Requires a request on context.
237*/
238OOINLINE jsval OOJSValueFromNativeObject(JSContext *context, id object)
239{
240 if (object != nil) return [object oo_jsValueInContext:context];
241 return JSVAL_NULL;
242}
243
244
245/* OOJSObjectFromNativeObject()
246 Return a JavaScript object representation of an object, or null if passed
247 nil. The value is boxed if necessary.
248
249 Requires a request on context.
250*/
251JSObject *OOJSObjectFromNativeObject(JSContext *context, id object);
252
253
254/* OOJSValue: an object whose purpose in life is to hold a JavaScript value.
255 This is somewhat useful for putting JavaScript objects in ObjC collections,
256 for instance to pass as properties to script loaders. The value is
257 GC rooted for the lifetime of the OOJSValue.
258
259 All methods take a context parameter, which must either be nil or a context
260 in a request.
261*/
262@interface OOJSValue: NSObject
263{
264 jsval _val;
265}
266
267+ (id) valueWithJSValue:(jsval)value inContext:(JSContext *)context;
268+ (id) valueWithJSObject:(JSObject *)object inContext:(JSContext *)context;
269
270- (id) initWithJSValue:(jsval)value inContext:(JSContext *)context;
271- (id) initWithJSObject:(JSObject *)object inContext:(JSContext *)context;
272
273@end
274
275
276
277/**** String utilities ****/
278
279/* OOJSSTR(const char * [literal])
280
281 Create and cache a jsval referring to an interned string literal.
282*/
283#define OOJSSTR(str) ({ static jsval strCache; static BOOL inited; if (EXPECT_NOT(!inited)) OOJSStrLiteralCachePRIVATE(""str, &strCache, &inited); strCache; })
284void OOJSStrLiteralCachePRIVATE(const char *string, jsval *strCache, BOOL *inited);
285
286
287// Convert a JSString to an NSString.
288NSString *OOStringFromJSString(JSContext *context, JSString *string);
289
290/* Convert an arbitrary JS object to an NSString, calling JS_ValueToString.
291 OOStringFromJSValue() returns nil if value is null or undefined,
292 OOStringFromJSValueEvenIfNull() returns "null" or "undefined".
293*/
294NSString *OOStringFromJSValue(JSContext *context, jsval value);
295NSString *OOStringFromJSValueEvenIfNull(JSContext *context, jsval value);
296
297
298/* OOStringFromJSPropertyIDAndSpec(context, propID, propertySpec)
299
300 Returns the name of a property given either a name or a tinyid. (Intended
301 for error reporting inside JSPropertyOps.)
302*/
303NSString *OOStringFromJSPropertyIDAndSpec(JSContext *context, jsid propID, JSPropertySpec *propertySpec);
304
305
306/* Describe a value for debugging or error reporting. Strings are quoted,
307 escaped and limited in length. Functions are described as "function foo"
308 (or just "function" if they're anonymous). Up to four elements of arrays
309 are included, followed by total count of there are more than four.
310 If abbreviateObjects, the description "[object Object]" is replaced with
311 "{...}", which may or may not be clearer depending on context.
312*/
313NSString *OOJSDescribeValue(JSContext *context, jsval value, BOOL abbreviateObjects);
314
315
316// Convert a jsid to an NSString.
317NSString *OOStringFromJSID(jsid propID);
318
319// Convert an NSString to a jsid.
320jsid OOJSIDFromString(NSString *string);
321
322
323@interface NSString (OOJavaScriptExtensions)
324
325// For diagnostic messages; produces things like @"(42, true, "a string", an object description)".
326+ (NSString *) stringWithJavaScriptParameters:(jsval *)params count:(uintN)count inContext:(JSContext *)context;
327
328// Concatenate sequence of arbitrary JS objects into string.
329+ (NSString *) concatenationOfStringsFromJavaScriptValues:(jsval *)values count:(size_t)count separator:(NSString *)separator inContext:(JSContext *)context;
330
331// Add escape codes for string so that it's a valid JavaScript literal (if you put "" or '' around it).
332- (NSString *) escapedForJavaScriptLiteral;
333
334@end
335
336
337// OOEntityFilterPredicate wrapping a JavaScript function.
338typedef struct
339{
340 JSContext *context;
341 jsval function; // Caller is responsible for ensuring this is a function object (using OOJSValueIsFunction()).
342 JSObject *jsThis;
343 BOOL errorFlag; // Set if a JS exception occurs. The
344 // exception will have been reported.
345 // This also supresses further filtering.
347BOOL JSFunctionPredicate(Entity *entity, void *parameter);
348
349// YES for ships and (normal) planets. Parameter: ignored.
350BOOL JSEntityIsJavaScriptVisiblePredicate(Entity *entity, void *parameter);
351
352// YES for ships other than sub-entities and menu-display ships, and planets other than atmospheres and menu miniatures. Parameter: ignored.
353BOOL JSEntityIsJavaScriptSearchablePredicate(Entity *entity, void *parameter);
354
355// YES for menu-display ships. Parameter: ignored
356BOOL JSEntityIsDemoShipPredicate(Entity *entity, void *parameter);
357
358
359// These require a request on context.
360id OOJSNativeObjectFromJSValue(JSContext *context, jsval value);
361id OOJSNativeObjectFromJSObject(JSContext *context, JSObject *object);
362id OOJSNativeObjectOfClassFromJSValue(JSContext *context, jsval value, Class requiredClass);
363id OOJSNativeObjectOfClassFromJSObject(JSContext *context, JSObject *object, Class requiredClass);
364
365
366OOINLINE JSClass *OOJSGetClass(JSContext *cx, JSObject *obj) ALWAYS_INLINE_FUNC;
367OOINLINE JSClass *OOJSGetClass(JSContext *cx, JSObject *obj)
368{
369#if JS_THREADSAFE
370 return JS_GetClass(cx, obj);
371#else
372 return JS_GetClass(obj);
373#endif
374}
375
376
377/* OOJSValueIsFunction(context, value)
378
379 Test whether a jsval is a function object. The main tripping point here
380 is that JSVAL_IS_OBJECT() is true for JSVAL_NULL, but JS_ObjectIsFunction()
381 crashes if passed null.
382*/
383OOINLINE BOOL OOJSValueIsFunction(JSContext *context, jsval value)
384{
385 return JSVAL_IS_OBJECT(value) && !JSVAL_IS_NULL(value) && JS_ObjectIsFunction(context, JSVAL_TO_OBJECT(value));
386}
387
388
389/* OOJSValueIsArray(context, value)
390
391 Test whether a jsval is an array object. The main tripping point here
392 is that JSVAL_IS_OBJECT() is true for JSVAL_NULL, but JS_IsArrayObject()
393 crashes if passed null.
394
395 Also, it should be called JS_ObjectIsArray() for consistency.
396*/
397OOINLINE BOOL OOJSValueIsArray(JSContext *context, jsval value)
398{
399 return JSVAL_IS_OBJECT(value) && !JSVAL_IS_NULL(value) && JS_IsArrayObject(context, JSVAL_TO_OBJECT(value));
400}
401
402
403/* OOJSDictionaryFromJSValue(context, value)
404 OOJSDictionaryFromJSObject(context, object)
405
406 Converts a JavaScript value to a dictionary by calling
407 OOJSNativeObjectFromJSValue() on each of its values.
408
409 Only enumerable own (i.e., not inherited) properties with string keys are
410 included.
411
412 Requires a request on context.
413*/
414NSDictionary *OOJSDictionaryFromJSValue(JSContext *context, jsval value);
415NSDictionary *OOJSDictionaryFromJSObject(JSContext *context, JSObject *object);
416
417
418/* OOJSDictionaryFromStringTable(context, value)
419
420 Treat an arbitrary JavaScript object as a dictionary mapping strings to
421 strings, and convert to a corresponding NSDictionary. The values are
422 converted to strings using JS_ValueToString().
423
424 Only enumerable own (i.e., not inherited) properties with string keys are
425 included.
426
427 Requires a request on context.
428*/
429NSDictionary *OOJSDictionaryFromStringTable(JSContext *context, jsval value);
430
431
432/*
433 DEFINE_JS_OBJECT_GETTER()
434 Defines a helper to extract Objective-C objects from the private field of
435 JS objects, with runtime type checking. The generated accessor requires
436 a request on context. Weakrefs are automatically unpacked.
437
438 Types which extend other types, such as entity subtypes, must register
439 their relationships with OOJSRegisterSubclass() below.
440
441 The signature of the generator is:
442 BOOL <name>(JSContext *context, JSObject *inObject, <class>** outObject)
443 If it returns NO, inObject is of the wrong class and an error has been
444 raised. Otherwise, outObject is either a native object of the specified
445 class (or a subclass) or nil.
446*/
447#ifndef NDEBUG
448#define DEFINE_JS_OBJECT_GETTER(NAME, JSCLASS, JSPROTO, OBJCCLASSNAME) \
449static BOOL NAME(JSContext *context, JSObject *inObject, OBJCCLASSNAME **outObject) GCC_ATTR((unused)); \
450static BOOL NAME(JSContext *context, JSObject *inObject, OBJCCLASSNAME **outObject) \
451{ \
452 NSCParameterAssert(outObject != NULL); \
453 static Class cls = Nil; \
454 if (EXPECT_NOT(cls == Nil)) cls = [OBJCCLASSNAME class]; \
455 return OOJSObjectGetterImplPRIVATE(context, inObject, JSCLASS, cls, #NAME, (id *)outObject); \
456}
457#else
458#define DEFINE_JS_OBJECT_GETTER(NAME, JSCLASS, JSPROTO, OBJCCLASSNAME) \
459OOINLINE BOOL NAME(JSContext *context, JSObject *inObject, OBJCCLASSNAME **outObject) \
460{ \
461 return OOJSObjectGetterImplPRIVATE(context, inObject, JSCLASS, (id *)outObject); \
462}
463#endif
464
465// For DEFINE_JS_OBJECT_GETTER()'s use.
466#ifndef NDEBUG
467BOOL OOJSObjectGetterImplPRIVATE(JSContext *context, JSObject *object, JSClass *requiredJSClass, Class requiredObjCClass, const char *name, id *outObject);
468#else
469BOOL OOJSObjectGetterImplPRIVATE(JSContext *context, JSObject *object, JSClass *requiredJSClass, id *outObject);
470#endif
471
472
473/*
474 Subclass relationships.
475
476 JSAPI doesn't have a concept of subclassing, as JavaScript doesn't have a
477 concept of classes, but Oolite reflects part of its class hierarchy as
478 related JSClasses whose prototypes inherit each other. For instance,
479 JS Entity methods work on JS Ships. In order for this to work,
480 OOJSEntityGetEntity() must be able to know that Ship is a subclass of
481 Entity. This is done using OOJSIsSubclass().
482
483 void OOJSRegisterSubclass(JSClass *subclass, JSClass *superclass)
484 Register subclass as a subclass of superclass. Subclass must not previously
485 have been registered as a subclass of any class (i.e., single inheritance
486 is required).
487
488 BOOL OOJSIsSubclass(JSClass *putativeSubclass, JSClass *superclass)
489 Test whether putativeSubclass is a equal to superclass or a registered
490 subclass of superclass, recursively.
491*/
492void OOJSRegisterSubclass(JSClass *subclass, JSClass *superclass);
493BOOL OOJSIsSubclass(JSClass *putativeSubclass, JSClass *superclass);
494OOINLINE BOOL OOJSIsMemberOfSubclass(JSContext *context, JSObject *object, JSClass *superclass)
495{
496 return OOJSIsSubclass(OOJSGetClass(context, object), superclass);
497}
498
499
500/* Support for OOJSNativeObjectFromJSValue() family
501
502 OOJSClassConverterCallback specifies the prototype for a callback function
503 which converts a JavaScript object to an Objective-C object.
504
505 OOJSBasicPrivateObjectConverter() is a OOJSClassConverterCallback which
506 returns the JS object's private storage value. It automatically unpacks
507 OOWeakReferences if relevant.
508
509 OOJSRegisterObjectConverter() registers a callback for a specific JS class.
510 It is not automatically propagated to subclasses.
511*/
512typedef id (*OOJSClassConverterCallback)(JSContext *context, JSObject *object);
513id OOJSBasicPrivateObjectConverter(JSContext *context, JSObject *object);
514
515void OOJSRegisterObjectConverter(JSClass *theClass, OOJSClassConverterCallback converter);
516
517
518/* JS root handling
519
520 The name parameter to JS_AddNamed*Root is assigned with no overhead, not
521 copied, but the strings serve no purpose in a release build so we may as
522 well strip them out.
523
524 In debug builds, this will deliberately cause an error if name is not a
525 string literal.
526*/
527#ifdef NDEBUG
528#define OOJSAddGCValueRoot(context, root, name) JS_AddValueRoot((context), (root))
529#define OOJSAddGCStringRoot(context, root, name) JS_AddStringRoot((context), (root))
530#define OOJSAddGCObjectRoot(context, root, name) JS_AddObjectRoot((context), (root))
531#define OOJSAddGCThingRoot(context, root, name) JS_AddGCThingRoot((context), (root))
532#else
533#define OOJSAddGCValueRoot(context, root, name) JS_AddNamedValueRoot((context), (root), "" name)
534#define OOJSAddGCStringRoot(context, root, name) JS_AddNamedStringRoot((context), (root), "" name)
535#define OOJSAddGCObjectRoot(context, root, name) JS_AddNamedObjectRoot((context), (root), "" name)
536#define OOJSAddGCThingRoot(context, root, name) JS_AddNamedGCThingRoot((context), (root), "" name)
537#endif
538
539
540#if OOJSENGINE_MONITOR_SUPPORT
541
542/* Protocol for debugging "monitor" object.
543 The monitor is an object -- in Oolite, or via Distributed Objects -- which
544 is provided with debugging information by the OOJavaScriptEngine.
545*/
546
547@protocol OOJavaScriptEngineMonitor <NSObject>
548
549// Sent for JS errors or warnings.
550- (oneway void)jsEngine:(in byref OOJavaScriptEngine *)engine
551 context:(in JSContext *)context
552 error:(in JSErrorReport *)errorReport
553 stackSkip:(in unsigned)stackSkip
554 showingLocation:(in BOOL)showLocation
555 withMessage:(in NSString *)message;
556
557// Sent for JS log messages. Note: messageClass will be nil if Log() is used rather than LogWithClass().
558- (oneway void)jsEngine:(in byref OOJavaScriptEngine *)engine
559 context:(in JSContext *)context
560 logMessage:(in NSString *)message
561 ofClass:(in NSString *)messageClass;
562
563@end
564
565
566@interface OOJavaScriptEngine (OOMonitorSupport)
567
568- (void)setMonitor:(id<OOJavaScriptEngineMonitor>)monitor;
569
570@end
571
572#endif
573
574
576
577/* See comments on time limiter in OOJSEngineTimeManagement.h.
578*/
579void OOJSPauseTimeLimiter(void);
580void OOJSResumeTimeLimiter(void);
581
582
583/* OOJSDumpStack()
584 Write JavaScript stack to log.
585
586 OOJSDescribeLocation()
587 Get script and line number for a stack frame.
588
589 OOJSMarkConsoleEvalLocation()
590 Specify that a given stack frame identifies eval()ed code from the debug
591 console, so that matching locations can be described specially by
592 OOJSDescribeLocation().
593*/
594#ifndef NDEBUG
595void OOJSDumpStack(JSContext *context);
596
597NSString *OOJSDescribeLocation(JSContext *context, JSStackFrame *stackFrame);
598void OOJSMarkConsoleEvalLocation(JSContext *context, JSStackFrame *stackFrame);
599#else
600#define OOJSDumpStack(cx) do {} while (0)
601#define OOJSDescribeLocation(cx, frame) do {} while (0)
602#define OOJSMarkConsoleEvalLocation(cx, frame) do {} while (0)
603#endif
604
605
606
607
608/***** Reusable JS callbacks ****/
609
610/* OOJSUnconstructableConstruct
611
612 Constructor callback for pseudo-classes which can't be constructed.
613*/
614JSBool OOJSUnconstructableConstruct(JSContext *context, uintN argc, jsval *vp);
615
616
617/* OOJSObjectWrapperFinalize
618
619 Finalizer for JS classes whose private storage is a retained object
620 reference (generally an OOWeakReference, but doesn't have to be).
621*/
622void OOJSObjectWrapperFinalize(JSContext *context, JSObject *this);
623
624
625/* OOJSObjectWrapperToString
626
627 Implementation of toString() for JS classes whose private storage is an
628 Objective-C object reference (generally an OOWeakReference).
629
630 Calls -oo_jsDescription and, if that fails, -description.
631*/
632JSBool OOJSObjectWrapperToString(JSContext *context, uintN argc, jsval *vp);
633
634
635
636/***** Appropriate flags for host-defined read/write and read-only properties *****/
637
638// Slot-based (defined with JS_Define{Property/Object/Function}() and no callbacks)
639#define OOJS_PROP_READWRITE (JSPROP_PERMANENT | JSPROP_ENUMERATE)
640#define OOJS_PROP_READONLY (JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY)
641
642// Non-enumerable properties
643#define OOJS_PROP_HIDDEN_READWRITE (JSPROP_PERMANENT)
644#define OOJS_PROP_HIDDEN_READONLY (JSPROP_PERMANENT | JSPROP_READONLY)
645
646// Methods should be non-enumerable
647#define OOJS_METHOD_READONLY OOJS_PROP_HIDDEN_READONLY
648
649// Callback-based (includes all properties specified in JSPropertySpecs)
650#define OOJS_PROP_READWRITE_CB (OOJS_PROP_READWRITE | JSPROP_SHARED)
651#define OOJS_PROP_READONLY_CB (OOJS_PROP_READONLY | JSPROP_SHARED)
652
653#define OOJS_PROP_HIDDEN_READWRITE_CB (OOJS_PROP_HIDDEN_READWRITE | JSPROP_SHARED)
654#define OOJS_PROP_HIDDEN_READONLY_CB (OOJS_PROP_HIDDEN_READONLY | JSPROP_SHARED)
655
656
657
658
659/***** Helpers for native callbacks. *****/
660#define OOJS_THIS JS_THIS_OBJECT(context, vp)
661#define OOJS_ARGV JS_ARGV(context, vp)
662#define OOJS_RVAL JS_RVAL(context, vp)
663#define OOJS_SET_RVAL(v) JS_SET_RVAL(context, vp, v)
664
665#define OOJS_RETURN(v) do { OOJS_SET_RVAL(v); return YES; } while (0)
666#define OOJS_RETURN_JSOBJECT(o) OOJS_RETURN(OBJECT_TO_JSVAL(o))
667#define OOJS_RETURN_VOID OOJS_RETURN(JSVAL_VOID)
668#define OOJS_RETURN_NULL OOJS_RETURN(JSVAL_NULL)
669#define OOJS_RETURN_BOOL(v) OOJS_RETURN(OOJSValueFromBOOL(v))
670#define OOJS_RETURN_INT(v) OOJS_RETURN(INT_TO_JSVAL(v))
671#define OOJS_RETURN_OBJECT(o) OOJS_RETURN(OOJSValueFromNativeObject(context, o))
672
673#define OOJS_RETURN_WITH_HELPER(helper, value) \
674do { \
675 jsval jsresult; \
676 BOOL OK = helper(context, value, &jsresult); \
677 JS_SET_RVAL(context, vp, jsresult); return OK; \
678} while (0)
679
680#define OOJS_RETURN_VECTOR(value) OOJS_RETURN_WITH_HELPER(VectorToJSValue, value)
681#define OOJS_RETURN_HPVECTOR(value) OOJS_RETURN_WITH_HELPER(HPVectorToJSValue, value)
682#define OOJS_RETURN_QUATERNION(value) OOJS_RETURN_WITH_HELPER(QuaternionToJSValue, value)
683#define OOJS_RETURN_DOUBLE(value) OOJS_RETURN_WITH_HELPER(JS_NewNumberValue, value)
#define ALWAYS_INLINE_FUNC
#define INLINE_CONST_FUNC
#define OOINLINE
void OOJSPauseTimeLimiter(void)
id OOJSNativeObjectFromJSValue(JSContext *context, jsval value)
jsid OOJSIDFromString(NSString *string)
BOOL JSEntityIsDemoShipPredicate(Entity *entity, void *parameter)
BOOL OOJSArgumentListGetNumberNoError(JSContext *context, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed)
void OOJSReportWarning(JSContext *context, NSString *format,...)
BOOL OOJSArgumentListGetNumber(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed)
JSBool OOJSObjectWrapperToString(JSContext *context, uintN argc, jsval *vp)
BOOL OOJSObjectGetterImplPRIVATE(JSContext *context, JSObject *object, JSClass *requiredJSClass, Class requiredObjCClass, const char *name, id *outObject)
BOOL JSEntityIsJavaScriptSearchablePredicate(Entity *entity, void *parameter)
NSString *const kOOJavaScriptEngineWillResetNotification
void OOJSReportWarningWithArguments(JSContext *context, NSString *format, va_list args)
NSString *const kOOJavaScriptEngineDidResetNotification
NSString * OOStringFromJSPropertyIDAndSpec(JSContext *context, jsid propID, JSPropertySpec *propertySpec)
#define JS_IsInRequest(context)
NSString * OOStringFromJSID(jsid propID)
OOINLINE BOOL OOJSValueIsArray(JSContext *context, jsval value)
void OOJSRegisterObjectConverter(JSClass *theClass, OOJSClassConverterCallback converter)
void OOJSSetWarningOrErrorStackSkip(unsigned skip)
BOOL JSFunctionPredicate(Entity *entity, void *parameter)
OOINLINE jsval OOJSValueFromNativeObject(JSContext *context, id object)
id OOJSNativeObjectFromJSObject(JSContext *context, JSObject *object)
void OOJSObjectWrapperFinalize(JSContext *context, JSObject *this)
void OOJSReportBadPropertySelector(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec)
OOINLINE BOOL OOJSIsMemberOfSubclass(JSContext *context, JSObject *object, JSClass *superclass)
NSDictionary * OOJSDictionaryFromJSValue(JSContext *context, jsval value)
void OOJSReportWarningForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format,...)
void OOJSReportErrorForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format,...)
NSDictionary * OOJSDictionaryFromJSObject(JSContext *context, JSObject *object)
void OOJSMarkConsoleEvalLocation(JSContext *context, JSStackFrame *stackFrame)
id OOJSNativeObjectOfClassFromJSValue(JSContext *context, jsval value, Class requiredClass)
NSString * OOStringFromJSValue(JSContext *context, jsval value)
JSBool OOJSUnconstructableConstruct(JSContext *context, uintN argc, jsval *vp)
OOINLINE BOOL OOJSValueIsFunction(JSContext *context, jsval value)
void OOJSRegisterSubclass(JSClass *subclass, JSClass *superclass)
JSObject * OOJSObjectFromNativeObject(JSContext *context, id object)
OOINLINE JSContext * OOJSAcquireContext(void)
NSString * OOJSDescribeValue(JSContext *context, jsval value, BOOL abbreviateObjects)
void OOJSReportError(JSContext *context, NSString *format,...)
OOINLINE jsval OOJSValueFromBOOL(int b) INLINE_CONST_FUNC
#define JS_BeginRequest(context)
NSString * OOStringFromJSValueEvenIfNull(JSContext *context, jsval value)
OOINLINE void OOJSRelinquishContext(JSContext *context)
id(* OOJSClassConverterCallback)(JSContext *context, JSObject *object)
void OOJSReportBadPropertyValue(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec, jsval value)
id OOJSBasicPrivateObjectConverter(JSContext *context, JSObject *object)
void OOJSReportBadArguments(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, NSString *message, NSString *expectedArgsDescription)
#define JS_EndRequest(context)
NSDictionary * OOJSDictionaryFromStringTable(JSContext *context, jsval value)
void OOJSReportErrorWithArguments(JSContext *context, NSString *format, va_list args)
void OOJSResumeTimeLimiter(void)
BOOL JSEntityIsJavaScriptVisiblePredicate(Entity *entity, void *parameter)
NSString * OOJSDescribeLocation(JSContext *context, JSStackFrame *stackFrame)
BOOL OOJSIsSubclass(JSClass *putativeSubclass, JSClass *superclass)
void OOJSDumpStack(JSContext *context)
NSString * OOStringFromJSString(JSContext *context, JSString *string)
OOINLINE JSClass * OOJSGetClass(JSContext *cx, JSObject *obj) ALWAYS_INLINE_FUNC
void OOJSStrLiteralCachePRIVATE(const char *string, jsval *strCache, BOOL *inited)
id OOJSNativeObjectOfClassFromJSObject(JSContext *context, JSObject *object, Class requiredClass)
JSContext * gOOJSMainThreadContext
return nil
NSString * oo_jsDescription()
NSString * oo_jsClassName()