Oolite 1.91.0.7645-241119-222d325
Loading...
Searching...
No Matches
OOJSScript.m
Go to the documentation of this file.
1/*
2
3OOJSScript.m
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#ifndef OO_CACHE_JS_SCRIPTS
26#define OO_CACHE_JS_SCRIPTS 1
27#endif
28
29
30#import "OOJSScript.h"
33
34#import "OOLogging.h"
35#import "OOConstToString.h"
36#import "Entity.h"
39#import "OOConstToJSString.h"
42#import "OOPListParsing.h"
43#import "OODebugStandards.h"
44
45#if OO_CACHE_JS_SCRIPTS
46#include <jsxdrapi.h>
47#import "OOCacheManager.h"
48#endif
49
50
53{
56};
57
58
59static JSObject *sScriptPrototype;
61
62
63static void AddStackToArrayReversed(NSMutableArray *array, RunningStack *stack);
64
65static JSScript *LoadScriptWithName(JSContext *context, NSString *path, JSObject *object, JSObject **outScriptObject, NSString **outErrorMessage);
66
67#if OO_CACHE_JS_SCRIPTS
68static NSData *CompiledScriptData(JSContext *context, JSScript *script);
69static JSScript *ScriptWithCompiledData(JSContext *context, NSData *data);
70#endif
71
72static NSString *StrippedName(NSString *string);
73
74
75static JSBool ScriptAddProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
76
77
78static JSClass sScriptClass =
79{
80 "Script",
81 JSCLASS_HAS_PRIVATE,
82
84 JS_PropertyStub,
85 JS_PropertyStub,
86 JS_StrictPropertyStub,
87 JS_EnumerateStub,
88 JS_ResolveStub,
89 JS_ConvertStub,
91};
92
93
94static JSFunctionSpec sScriptMethods[] =
95{
96 // JS name Function min args
97 { "toString", OOJSObjectWrapperToString, 0, },
98 { 0 }
99};
100
101
102@interface OOJSScript (OOPrivate)
103
104- (NSString *)scriptNameFromPath:(NSString *)path;
105- (NSDictionary *)defaultPropertiesFromPath:(NSString *)path;
106
107@end
108
109
110@implementation OOJSScript
111
112+ (id) scriptWithPath:(NSString *)path properties:(NSDictionary *)properties
113{
114 return [[[self alloc] initWithPath:path properties:properties] autorelease];
115}
116
117
118- (id) initWithPath:(NSString *)path properties:(NSDictionary *)properties
119{
120 JSContext *context = NULL;
121 NSString *problem = nil; // Acts as error flag.
122 JSScript *script = NULL;
123 JSObject *scriptObject = NULL;
124 jsval returnValue = JSVAL_VOID;
125 NSEnumerator *keyEnum = nil;
126 NSString *key = nil;
127 id property = nil;
128
129 self = [super init];
130 if (self == nil) problem = @"allocation failure";
131 else
132 {
133 context = OOJSAcquireContext();
134
135 if (JS_IsExceptionPending(context))
136 {
137 JS_ClearPendingException(context);
138 OOLogERR(@"script.javaScript.load.waitingException", @"Prior to loading script %@, there was a pending JavaScript exception, which has been cleared. This is an internal error, please report it.", path);
139 }
140
141 // Set up JS object
142 if (!problem)
143 {
144 _jsSelf = JS_NewObject(context, &sScriptClass, sScriptPrototype, NULL);
145 if (_jsSelf == NULL) problem = @"allocation failure";
146 }
147
148 if (!problem && !OOJSAddGCObjectRoot(context, &_jsSelf, "Script object"))
149 {
150 problem = @"could not add JavaScript root object";
151 }
152
153 if (!problem && !OOJSAddGCObjectRoot(context, &scriptObject, "Script GC holder"))
154 {
155 problem = @"could not add JavaScript root object";
156 }
157
158 if (!problem)
159 {
160 if (!JS_SetPrivate(context, _jsSelf, OOConsumeReference([self weakRetain])))
161 {
162 problem = @"could not set private backreference";
163 }
164 }
165
166 // Push self on stack of running scripts.
167 RunningStack stackElement =
168 {
169 .back = sRunningStack,
170 .current = self
171 };
172 sRunningStack = &stackElement;
173
174 filePath = [path retain];
175
176 if (!problem)
177 {
178 OOLog(@"script.javaScript.willLoad", @"About to load JavaScript %@", path);
179 script = LoadScriptWithName(context, path, _jsSelf, &scriptObject, &problem);
180 }
181 OOLogIndentIf(@"script.javaScript.willLoad");
182
183 // Set default properties from manifest.plist
184 NSDictionary *defaultProperties = [self defaultPropertiesFromPath:path];
185 for (keyEnum = [defaultProperties keyEnumerator]; (key = [keyEnum nextObject]); )
186 {
187 if ([key isKindOfClass:[NSString class]])
188 {
189 property = [defaultProperties objectForKey:key];
190 if ([key isEqualToString:kLocalManifestProperty])
191 {
192 // this must not be editable
193 [self defineProperty:property named:key];
194 }
195 else
196 {
197 // can be overwritten by script itself
198 [self setProperty:property named:key];
199 }
200 }
201 }
202
203 // Set properties. (read-only)
204 if (!problem && properties != nil)
205 {
206 for (keyEnum = [properties keyEnumerator]; (key = [keyEnum nextObject]); )
207 {
208 if ([key isKindOfClass:[NSString class]])
209 {
210 property = [properties objectForKey:key];
211 [self defineProperty:property named:key];
212 }
213 }
214 }
215
216 /* Set initial name (in case of script error during initial run).
217 The "name" ivar is not set here, so the property can be fetched from JS
218 if we fail during setup. However, the "name" ivar is set later so that
219 the script object can't be renamed after the initial run. This could
220 probably also be achieved by fiddling with JS property attributes.
221 */
222 jsid nameID = OOJSID("name");
223 [self setProperty:[self scriptNameFromPath:path] withID:nameID inContext:context];
224
225 // Run the script (allowing it to set up the properties we need, as well as setting up those event handlers)
226 if (!problem)
227 {
229 if (!JS_ExecuteScript(context, _jsSelf, script, &returnValue))
230 {
231 problem = @"could not run script";
232 }
234
235 // We don't need the script any more - the event handlers hang around as long as the JS object exists.
236 JS_DestroyScript(context, script);
237 }
238
239 JS_RemoveObjectRoot(context, &scriptObject);
240
241 sRunningStack = stackElement.back;
242
243 if (!problem)
244 {
245 // Get display attributes from script
246 DESTROY(name);
247 name = [StrippedName([[self propertyWithID:nameID inContext:context] description]) copy];
248 if (name == nil)
249 {
250 name = [[self scriptNameFromPath:path] retain];
251 [self setProperty:name withID:nameID inContext:context];
252 }
253
254 version = [[[self propertyWithID:OOJSID("version") inContext:context] description] copy];
255 description = [[[self propertyWithID:OOJSID("description") inContext:context] description] copy];
256
257 OOLog(@"script.javaScript.load.success", @"Loaded JavaScript: %@ -- %@", [self displayName], description ? description : (NSString *)@"(no description)");
258 }
259
260 OOLogOutdentIf(@"script.javaScript.willLoad");
261
262 DESTROY(filePath); // Only used for error reporting during startup.
263 }
264
265 if (problem)
266 {
267 OOLog(@"script.javaScript.load.failed", @"***** Error loading JavaScript script %@ -- %@", path, problem);
268 JS_ReportPendingException(context);
269 DESTROY(self);
270 }
271
272 OOJSRelinquishContext(context);
273
274 if (self != nil)
275 {
276 [[NSNotificationCenter defaultCenter] addObserver:self
277 selector:@selector(javaScriptEngineWillReset:)
278 name:kOOJavaScriptEngineWillResetNotification
280 }
281
282 return self;
283}
284
285
286- (void) dealloc
287{
288 [[NSNotificationCenter defaultCenter] removeObserver:self
289 name:kOOJavaScriptEngineWillResetNotification
291
292 DESTROY(name);
293 DESTROY(description);
294 DESTROY(version);
295 DESTROY(filePath);
296
297 if (_jsSelf != NULL)
298 {
299 JSContext *context = OOJSAcquireContext();
300
301 OOJSObjectWrapperFinalize(context, _jsSelf); // Release weakref to self
302 JS_RemoveObjectRoot(context, &_jsSelf); // Unroot jsSelf
303
304 OOJSRelinquishContext(context);
305 }
306
307 [weakSelf weakRefDrop];
308
309 [super dealloc];
310}
311
312
313- (NSString *) oo_jsClassName
314{
315 return @"Script";
316}
317
318
319- (NSString *)descriptionComponents
320{
321 if (_jsSelf != NULL) return [super descriptionComponents];
322 else return @"invalid script";
323}
324
325
326- (void) javaScriptEngineWillReset:(NSNotification *)notification
327{
328 // All scripts become invalid when the JS engine resets.
329 if (_jsSelf != NULL)
330 {
331 _jsSelf = NULL;
332 JSContext *context = OOJSAcquireContext();
333 JS_RemoveObjectRoot(context, &_jsSelf);
334 OOJSRelinquishContext(context);
335 }
336}
337
338
339+ (OOJSScript *) currentlyRunningScript
340{
341 if (sRunningStack == NULL) return NULL;
342 return sRunningStack->current;
343}
344
345
346+ (NSArray *) scriptStack
347{
348 NSMutableArray *result = nil;
349
350 result = [NSMutableArray array];
352 return result;
353}
354
355
356- (id) weakRetain
357{
358 if (weakSelf == nil) weakSelf = [OOWeakReference weakRefWithObject:self];
359 return [weakSelf retain];
360}
361
362
363- (void) weakRefDied:(OOWeakReference *)weakRef
364{
365 if (weakRef == weakSelf) weakSelf = nil;
366}
367
368
369- (NSString *) name
370{
371 if (name == nil) name = [[self propertyNamed:@"name"] copy];
372 if (name == nil) return [self scriptNameFromPath:filePath]; // Special case for parse errors during load.
373 return name;
374}
375
376
377- (NSString *) scriptDescription
378{
379 return description;
380}
381
382
383- (NSString *) version
384{
385 return version;
386}
387
388
389- (void)runWithTarget:(Entity *)target
390{
391
392}
393
394
395- (BOOL) callMethod:(jsid)methodID
396 inContext:(JSContext *)context
397 withArguments:(jsval *)argv count:(intN)argc
398 result:(jsval *)outResult
399{
400 NSParameterAssert(name != NULL && (argv != NULL || argc == 0) && context != NULL && JS_IsInRequest(context));
401 if (_jsSelf == NULL) return NO;
402
403 JSObject *root = NULL;
404 BOOL OK = NO;
405 jsval method;
406 jsval ignoredResult = JSVAL_VOID;
407
408 if (outResult == NULL) outResult = &ignoredResult;
409 OOJSAddGCObjectRoot(context, &root, "OOJSScript method root");
410
411 if (EXPECT(JS_GetMethodById(context, _jsSelf, methodID, &root, &method) && !JSVAL_IS_VOID(method)))
412 {
413#ifndef NDEBUG
414 if (JS_IsExceptionPending(context))
415 {
416 OOLog(@"script.internalBug", @"Exception pending on context before calling method in %s, clearing. This is an internal error, please report it.", __PRETTY_FUNCTION__);
417 JS_ClearPendingException(context);
418 }
419
420 OOLog(@"script.javaScript.call", @"Calling [%@].%@()", [self name], OOStringFromJSID(methodID));
421 OOLogIndentIf(@"script.javaScript.call");
422#endif
423
424 // Push self on stack of running scripts.
425 RunningStack stackElement =
426 {
427 .back = sRunningStack,
428 .current = self
429 };
430 sRunningStack = &stackElement;
431
432 // Call the method.
434 OK = JS_CallFunctionValue(context, _jsSelf, method, argc, argv, outResult);
436
437 if (JS_IsExceptionPending(context))
438 {
439 JS_ReportPendingException(context);
440 OK = NO;
441 }
442
443 // Pop running scripts stack
444 sRunningStack = stackElement.back;
445
446#ifndef NDEBUG
447 OOLogOutdentIf(@"script.javaScript.call");
448#endif
449 }
450
451 JS_RemoveObjectRoot(context, &root);
452
453 return OK;
454}
455
456
457- (id) propertyWithID:(jsid)propID inContext:(JSContext *)context
458{
459 NSParameterAssert(context != NULL && JS_IsInRequest(context));
460 if (_jsSelf == NULL) return nil;
461
462 jsval jsValue = JSVAL_VOID;
463 if (JS_GetPropertyById(context, _jsSelf, propID, &jsValue))
464 {
465 return OOJSNativeObjectFromJSValue(context, jsValue);
466 }
467 return nil;
468}
469
470
471- (BOOL) setProperty:(id)value withID:(jsid)propID inContext:(JSContext *)context
472{
473 NSParameterAssert(context != NULL && JS_IsInRequest(context));
474 if (_jsSelf == NULL) return NO;
475
476 jsval jsValue = OOJSValueFromNativeObject(context, value);
477 return JS_SetPropertyById(context, _jsSelf, propID, &jsValue);
478}
479
480
481- (BOOL) defineProperty:(id)value withID:(jsid)propID inContext:(JSContext *)context
482{
483 NSParameterAssert(context != NULL && JS_IsInRequest(context));
484 if (_jsSelf == NULL) return NO;
485
486 jsval jsValue = OOJSValueFromNativeObject(context, value);
487 return JS_DefinePropertyById(context, _jsSelf, propID, jsValue, NULL, NULL, OOJS_PROP_READONLY);
488}
489
490
491- (id) propertyNamed:(NSString *)propName
492{
493 if (propName == nil) return nil;
494 if (_jsSelf == NULL) return nil;
495
496 JSContext *context = OOJSAcquireContext();
497 id result = [self propertyWithID:OOJSIDFromString(propName) inContext:context];
498 OOJSRelinquishContext(context);
499
500 return result;
501}
502
503
504- (BOOL) setProperty:(id)value named:(NSString *)propName
505{
506 if (value == nil || propName == nil) return NO;
507 if (_jsSelf == NULL) return NO;
508
509 JSContext *context = OOJSAcquireContext();
510 BOOL result = [self setProperty:value withID:OOJSIDFromString(propName) inContext:context];
511 OOJSRelinquishContext(context);
512
513 return result;
514}
515
516
517- (BOOL) defineProperty:(id)value named:(NSString *)propName
518{
519 if (value == nil || propName == nil) return NO;
520 if (_jsSelf == NULL) return NO;
521
522 JSContext *context = OOJSAcquireContext();
523 BOOL result = [self defineProperty:value withID:OOJSIDFromString(propName) inContext:context];
524 OOJSRelinquishContext(context);
525
526 return result;
527}
528
529
530- (jsval)oo_jsValueInContext:(JSContext *)context
531{
532 if (_jsSelf == NULL) return JSVAL_VOID;
533 return OBJECT_TO_JSVAL(_jsSelf);
534}
535
536
537+ (void)pushScript:(OOJSScript *)script
538{
539 RunningStack *element = NULL;
540
541 element = malloc(sizeof *element);
542 if (element == NULL) exit(EXIT_FAILURE);
543
544 element->back = sRunningStack;
545 element->current = script;
546 sRunningStack = element;
547}
548
549
550+ (void)popScript:(OOJSScript *)script
551{
552 RunningStack *element = NULL;
553
554 assert(sRunningStack->current == script);
555
556 element = sRunningStack;
558 free(element);
559}
560
561@end
562
563
564@implementation OOJSScript (OOPrivate)
565
566
567
568/* Generate default name for script which doesn't set its name property when
569 first run.
570
571 The generated name is <name>.anon-script, where <name> is selected as
572 follows:
573 * If path is nil (futureproofing), use the address of the script object.
574 * If the file's name is something other than script.*, use the file name.
575 * If the containing directory is something other than Config, use the
576 containing directory's name.
577 * Otherwise, use the containing directory's parent (which will generally
578 be an OXP root directory).
579 * If either of the two previous steps results in an empty string, fall
580 back on the full path.
581*/
582- (NSString *)scriptNameFromPath:(NSString *)path
583{
584 NSString *lastComponent = nil;
585 NSString *truncatedPath = nil;
586 NSString *theName = nil;
587
588 if (path == nil) theName = [NSString stringWithFormat:@"%p", self];
589 else
590 {
591 lastComponent = [path lastPathComponent];
592 if (![lastComponent hasPrefix:@"script."]) theName = lastComponent;
593 else
594 {
595 truncatedPath = [path stringByDeletingLastPathComponent];
596 if (NSOrderedSame == [[truncatedPath lastPathComponent] caseInsensitiveCompare:@"Config"])
597 {
598 truncatedPath = [truncatedPath stringByDeletingLastPathComponent];
599 }
600 if (NSOrderedSame == [[truncatedPath pathExtension] caseInsensitiveCompare:@"oxp"])
601 {
602 truncatedPath = [truncatedPath stringByDeletingPathExtension];
603 }
604
605 lastComponent = [truncatedPath lastPathComponent];
606 theName = lastComponent;
607 }
608 }
609
610 if (0 == [theName length]) theName = path;
611
612 return StrippedName([theName stringByAppendingString:@".anon-script"]);
613}
614
615
616- (NSDictionary *) defaultPropertiesFromPath:(NSString *)path
617{
618 // remove file name, remove OXP subfolder, add manifest.plist
619 NSString *manifestPath = [[[path stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"manifest.plist"];
620 NSDictionary *manifest = OODictionaryFromFile(manifestPath);
621 NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithCapacity:3];
622 /* __oolite.tmp.* is allocated for OXPs without manifests. Its
623 * values are meaningless and shouldn't be used here */
624 if (manifest != nil && ![[manifest oo_stringForKey:kOOManifestIdentifier] hasPrefix:@"__oolite.tmp."])
625 {
626 if ([manifest objectForKey:kOOManifestVersion] != nil)
627 {
628 [properties setObject:[manifest oo_stringForKey:kOOManifestVersion] forKey:@"version"];
629 }
630 if ([manifest objectForKey:kOOManifestIdentifier] != nil)
631 {
632 // used for system info
633 [properties setObject:[manifest oo_stringForKey:kOOManifestIdentifier] forKey:kLocalManifestProperty];
634 }
635 if ([manifest objectForKey:kOOManifestAuthor] != nil)
636 {
637 [properties setObject:[manifest oo_stringForKey:kOOManifestAuthor] forKey:@"author"];
638 }
639 if ([manifest objectForKey:kOOManifestLicense] != nil)
640 {
641 [properties setObject:[manifest oo_stringForKey:kOOManifestLicense] forKey:@"license"];
642 }
643 }
644 return properties;
645}
646
647@end
648
649
650@implementation OOScript (JavaScriptEvents)
651
652- (BOOL) callMethod:(jsid)methodID
653 inContext:(JSContext *)context
654 withArguments:(jsval *)argv count:(intN)argc
655 result:(jsval *)outResult
656{
657 return NO;
658}
659
660@end
661
662
663void InitOOJSScript(JSContext *context, JSObject *global)
664{
665 sScriptPrototype = JS_InitClass(context, global, NULL, &sScriptClass, OOJSUnconstructableConstruct, 0, NULL, sScriptMethods, NULL, NULL);
667}
668
669
670static JSBool ScriptAddProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
671{
672 // Complain about attempts to set the property tickle.
673 if (JSID_IS_STRING(propID))
674 {
675 JSString *propName = JSID_TO_STRING(propID);
676 JSBool match;
677 if (JS_StringEqualsAscii(context, propName, "tickle", &match) && match)
678 {
679 OOJSScript *thisScript = OOJSNativeObjectOfClassFromJSObject(context, this, [OOJSScript class]);
680 OOJSReportWarning(context, @"Script %@ appears to use the tickle() event handler, which is no longer supported.", [thisScript name]);
681 }
682 }
683
684 return YES;
685}
686
687
688static void AddStackToArrayReversed(NSMutableArray *array, RunningStack *stack)
689{
690 if (stack != NULL)
691 {
692 AddStackToArrayReversed(array, stack->back);
693 [array addObject:stack->current];
694 }
695}
696
697
698static JSScript *LoadScriptWithName(JSContext *context, NSString *path, JSObject *object, JSObject **outScriptObject, NSString **outErrorMessage)
699{
700#if OO_CACHE_JS_SCRIPTS
701 OOCacheManager *cache = nil;
702#endif
703 NSString *fileContents = nil;
704 NSData *data = nil;
705 JSScript *script = NULL;
706
707 NSCParameterAssert(outScriptObject != NULL && outErrorMessage != NULL);
708 *outErrorMessage = nil;
709
710#if OO_CACHE_JS_SCRIPTS
711 // Look for cached compiled script
712 cache = [OOCacheManager sharedCache];
713 data = [cache objectForKey:path inCache:@"compiled JavaScript scripts"];
714 if (data != nil)
715 {
716 script = ScriptWithCompiledData(context, data);
717 }
718#endif
719
720 if (script == NULL)
721 {
722 fileContents = [NSString stringWithContentsOfUnicodeFile:path];
723
724 if (fileContents != nil)
725 {
726#ifndef NDEBUG
727 /* FIXME: this isn't strictly the right test, since strict
728 * mode can be enabled with this string within a function
729 * definition, but it seems unlikely anyone is actually doing
730 * that here. */
731 if ([fileContents rangeOfString:@"\"use strict\";"].location == NSNotFound && [fileContents rangeOfString:@"'use strict';"].location == NSNotFound)
732 {
733 OOStandardsDeprecated([NSString stringWithFormat:@"Script %@ does not \"use strict\";",path]);
734 if (OOEnforceStandards())
735 {
736 // prepend it anyway
737 // TODO: some time after 1.82, make this required
738 fileContents = [@"\"use strict\";\n" stringByAppendingString:fileContents];
739 }
740 }
741#endif
742 data = [fileContents utf16DataWithBOM:NO];
743 }
744 if (data == nil) *outErrorMessage = @"could not load file";
745 else
746 {
747 script = JS_CompileUCScript(context, object, [data bytes], [data length] / sizeof(unichar), [path UTF8String], 1);
748 if (script != NULL) *outScriptObject = JS_NewScriptObject(context, script);
749 else *outErrorMessage = @"compilation failed";
750 }
751
752#if OO_CACHE_JS_SCRIPTS
753 if (script != NULL)
754 {
755 // Write compiled script to cache
756 data = CompiledScriptData(context, script);
757 [cache setObject:data forKey:path inCache:@"compiled JavaScript scripts"];
758 }
759#endif
760 }
761
762 return script;
763}
764
765
766#if OO_CACHE_JS_SCRIPTS
767static NSData *CompiledScriptData(JSContext *context, JSScript *script)
768{
769 JSXDRState *xdr = NULL;
770 NSData *result = nil;
771 uint32 length;
772 void *bytes = NULL;
773
774 xdr = JS_XDRNewMem(context, JSXDR_ENCODE);
775 if (xdr != NULL)
776 {
777 if (JS_XDRScript(xdr, &script))
778 {
779 bytes = JS_XDRMemGetData(xdr, &length);
780 if (bytes != NULL)
781 {
782 result = [NSData dataWithBytes:bytes length:length];
783 }
784 }
785 JS_XDRDestroy(xdr);
786 }
787
788 return result;
789}
790
791
792static JSScript *ScriptWithCompiledData(JSContext *context, NSData *data)
793{
794 JSXDRState *xdr = NULL;
795 JSScript *result = NULL;
796
797 if (data == nil) return NULL;
798
799 xdr = JS_XDRNewMem(context, JSXDR_DECODE);
800 if (xdr != NULL)
801 {
802 NSUInteger length = [data length];
803 if (EXPECT_NOT(length > UINT32_MAX)) return NULL;
804
805 JS_XDRMemSetData(xdr, (void *)[data bytes], (uint32_t)length);
806 if (!JS_XDRScript(xdr, &result)) result = NULL;
807
808 JS_XDRMemSetData(xdr, NULL, 0); // Don't let it be freed by XDRDestroy
809 JS_XDRDestroy(xdr);
810 }
811
812 return result;
813}
814#endif
815
816
817static NSString *StrippedName(NSString *string)
818{
819 static NSCharacterSet *invalidSet = nil;
820 if (invalidSet == nil) invalidSet = [[NSCharacterSet characterSetWithCharactersInString:@"_ \t\n\r\v"] retain];
821
822 return [string stringByTrimmingCharactersInSet:invalidSet];
823}
#define DESTROY(x)
Definition OOCocoa.h:77
id OOConsumeReference(id OO_NS_CONSUMED value)
Definition OOCocoa.m:93
void OOStandardsDeprecated(NSString *message)
BOOL OOEnforceStandards(void)
#define EXPECT_NOT(x)
#define EXPECT(x)
#define OOJSStopTimeLimiter()
#define OOJSStartTimeLimiter()
#define kOOJSLongTimeLimit
#define OOJSStartTimeLimiterWithTimeLimit(limit)
#define OOJSID(str)
Definition OOJSPropID.h:38
void InitOOJSScript(JSContext *context, JSObject *global)
Definition OOJSScript.m:663
static NSString *const kLocalManifestProperty
Definition OOJSScript.h:29
static NSString * StrippedName(NSString *string)
Definition OOJSScript.m:817
static JSBool ScriptAddProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
Definition OOJSScript.m:670
static NSData * CompiledScriptData(JSContext *context, JSScript *script)
Definition OOJSScript.m:767
static JSObject * sScriptPrototype
Definition OOJSScript.m:59
static RunningStack * sRunningStack
Definition OOJSScript.m:60
static JSFunctionSpec sScriptMethods[]
Definition OOJSScript.m:94
static JSClass sScriptClass
Definition OOJSScript.m:78
static JSScript * LoadScriptWithName(JSContext *context, NSString *path, JSObject *object, JSObject **outScriptObject, NSString **outErrorMessage)
Definition OOJSScript.m:698
static void AddStackToArrayReversed(NSMutableArray *array, RunningStack *stack)
Definition OOJSScript.m:688
static JSScript * ScriptWithCompiledData(JSContext *context, NSData *data)
Definition OOJSScript.m:792
id OOJSNativeObjectFromJSValue(JSContext *context, jsval value)
void OOJSReportWarning(JSContext *context, NSString *format,...)
JSBool OOJSObjectWrapperToString(JSContext *context, uintN argc, jsval *vp)
#define JS_IsInRequest(context)
NSString * OOStringFromJSID(jsid propID)
void OOJSRegisterObjectConverter(JSClass *theClass, OOJSClassConverterCallback converter)
OOINLINE jsval OOJSValueFromNativeObject(JSContext *context, id object)
void OOJSObjectWrapperFinalize(JSContext *context, JSObject *this)
JSBool OOJSUnconstructableConstruct(JSContext *context, uintN argc, jsval *vp)
#define OOJS_PROP_READONLY
OOINLINE JSContext * OOJSAcquireContext(void)
#define OOJSAddGCObjectRoot(context, root, name)
OOINLINE void OOJSRelinquishContext(JSContext *context)
id OOJSBasicPrivateObjectConverter(JSContext *context, JSObject *object)
id OOJSNativeObjectOfClassFromJSObject(JSContext *context, JSObject *object, Class requiredClass)
#define OOLogERR(class, format,...)
Definition OOLogging.h:112
#define OOLogOutdentIf(class)
Definition OOLogging.h:102
#define OOLog(class, format,...)
Definition OOLogging.h:88
#define OOLogIndentIf(class)
Definition OOLogging.h:101
static NSString *const kOOManifestLicense
static NSString *const kOOManifestIdentifier
static NSString *const kOOManifestVersion
static NSString *const kOOManifestAuthor
NSDictionary * OODictionaryFromFile(NSString *path)
return nil
void setObject:forKey:inCache:(id inElement,[forKey] NSString *inKey,[inCache] NSString *inCacheKey)
id objectForKey:inCache:(NSString *inKey,[inCache] NSString *inCacheKey)
OOCacheManager * sharedCache()
OOJavaScriptEngine * sharedEngine()
id weakRefWithObject:(id< OOWeakReferenceSupport > object)
RunningStack * back
Definition OOJSScript.m:54
OOJSScript * current
Definition OOJSScript.m:55