25#ifndef OO_CACHE_JS_SCRIPTS
26#define OO_CACHE_JS_SCRIPTS 1
45#if OO_CACHE_JS_SCRIPTS
65static JSScript *
LoadScriptWithName(JSContext *context, NSString *path, JSObject *
object, JSObject **outScriptObject, NSString **outErrorMessage);
67#if OO_CACHE_JS_SCRIPTS
75static JSBool
ScriptAddProperty(JSContext *context, JSObject *
this, jsid propID, jsval *value);
86 JS_StrictPropertyStub,
102@interface OOJSScript (OOPrivate)
104- (NSString *)scriptNameFromPath:(NSString *)path;
105- (NSDictionary *)defaultPropertiesFromPath:(NSString *)path;
112+ (id) scriptWithPath:(NSString *)path properties:(NSDictionary *)properties
114 return [[[
self alloc] initWithPath:path properties:properties] autorelease];
112+ (id) scriptWithPath:(NSString *)path properties:(NSDictionary *)properties {
…}
118- (id) initWithPath:(NSString *)path properties:(NSDictionary *)properties
120 JSContext *context = NULL;
121 NSString *problem =
nil;
122 JSScript *script = NULL;
123 JSObject *scriptObject = NULL;
124 jsval returnValue = JSVAL_VOID;
125 NSEnumerator *keyEnum =
nil;
130 if (
self ==
nil) problem =
@"allocation failure";
135 if (JS_IsExceptionPending(context))
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);
145 if (
_jsSelf == NULL) problem =
@"allocation failure";
150 problem =
@"could not add JavaScript root object";
155 problem =
@"could not add JavaScript root object";
162 problem =
@"could not set private backreference";
178 OOLog(
@"script.javaScript.willLoad",
@"About to load JavaScript %@", path);
185 for (keyEnum = [defaultProperties keyEnumerator]; (key = [
keyEnum nextObject]); )
187 if ([key isKindOfClass:[NSString
class]])
204 if (!problem && properties !=
nil)
206 for (keyEnum = [properties keyEnumerator]; (key = [
keyEnum nextObject]); )
208 if ([key isKindOfClass:[NSString
class]])
222 jsid nameID =
OOJSID(
"name");
229 if (!JS_ExecuteScript(context,
_jsSelf, script, &returnValue))
231 problem =
@"could not run script";
236 JS_DestroyScript(context, script);
239 JS_RemoveObjectRoot(context, &scriptObject);
267 OOLog(
@"script.javaScript.load.failed",
@"***** Error loading JavaScript script %@ -- %@", path, problem);
268 JS_ReportPendingException(context);
277 selector:@selector(javaScriptEngineWillReset:)
278 name:kOOJavaScriptEngineWillResetNotification
118- (id) initWithPath:(NSString *)path properties:(NSDictionary *)properties {
…}
289 name:kOOJavaScriptEngineWillResetNotification
302 JS_RemoveObjectRoot(context, &
_jsSelf);
322 else return @"invalid script";
326- (void) javaScriptEngineWillReset:(NSNotification *)notification
333 JS_RemoveObjectRoot(context, &
_jsSelf);
326- (void) javaScriptEngineWillReset:(NSNotification *)notification {
…}
348 NSMutableArray *result =
nil;
395- (BOOL) callMethod:(jsid)methodID
396 inContext:(JSContext *)context
397 withArguments:(jsval *)argv count:(intN)argc
398 result:(jsval *)outResult
400 NSParameterAssert(
name != NULL && (argv != NULL || argc == 0) && context != NULL &&
JS_IsInRequest(context));
401 if (
_jsSelf == NULL)
return NO;
403 JSObject *root = NULL;
406 jsval ignoredResult = JSVAL_VOID;
408 if (outResult == NULL) outResult = &ignoredResult;
411 if (
EXPECT(JS_GetMethodById(context,
_jsSelf, methodID, &root, &method) && !JSVAL_IS_VOID(method)))
414 if (JS_IsExceptionPending(context))
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);
434 OK = JS_CallFunctionValue(context,
_jsSelf, method, argc, argv, outResult);
437 if (JS_IsExceptionPending(context))
439 JS_ReportPendingException(context);
451 JS_RemoveObjectRoot(context, &root);
395- (BOOL) callMethod:(jsid)methodID {
…}
457- (id) propertyWithID:(jsid)propID inContext:(JSContext *)context
462 jsval jsValue = JSVAL_VOID;
463 if (JS_GetPropertyById(context,
_jsSelf, propID, &jsValue))
457- (id) propertyWithID:(jsid)propID inContext:(JSContext *)context {
…}
471- (BOOL) setProperty:(
id)value withID:(jsid)propID inContext:(JSContext *)context
474 if (
_jsSelf == NULL)
return NO;
477 return JS_SetPropertyById(context,
_jsSelf, propID, &jsValue);
471- (BOOL) setProperty:(
id)value withID:(jsid)propID inContext:(JSContext *)context {
…}
481- (BOOL) defineProperty:(
id)value withID:(jsid)propID inContext:(JSContext *)context
484 if (
_jsSelf == NULL)
return NO;
481- (BOOL) defineProperty:(
id)value withID:(jsid)propID inContext:(JSContext *)context {
…}
491- (id) propertyNamed:(NSString *)propName
493 if (propName ==
nil)
return nil;
491- (id) propertyNamed:(NSString *)propName {
…}
504- (BOOL) setProperty:(
id)value named:(NSString *)propName
506 if (value ==
nil || propName ==
nil)
return NO;
507 if (
_jsSelf == NULL)
return NO;
504- (BOOL) setProperty:(
id)value named:(NSString *)propName {
…}
517- (BOOL) defineProperty:(
id)value named:(NSString *)propName
519 if (value ==
nil || propName ==
nil)
return NO;
520 if (
_jsSelf == NULL)
return NO;
517- (BOOL) defineProperty:(
id)value named:(NSString *)propName {
…}
530- (jsval)oo_jsValueInContext:(JSContext *)context
532 if (
_jsSelf == NULL)
return JSVAL_VOID;
533 return OBJECT_TO_JSVAL(
_jsSelf);
530- (jsval)oo_jsValueInContext:(JSContext *)context {
…}
541 element = malloc(
sizeof *element);
542 if (element == NULL) exit(EXIT_FAILURE);
564@implementation OOJSScript (OOPrivate)
582- (NSString *)scriptNameFromPath:(NSString *)path
584 NSString *lastComponent =
nil;
585 NSString *truncatedPath =
nil;
586 NSString *theName =
nil;
588 if (path ==
nil) theName = [
NSString stringWithFormat:@"%p",
self];
591 lastComponent = [
path lastPathComponent];
592 if (![lastComponent hasPrefix:
@"script."]) theName = lastComponent;
595 truncatedPath = [
path stringByDeletingLastPathComponent];
596 if (NSOrderedSame == [[truncatedPath lastPathComponent] caseInsensitiveCompare:
@"Config"])
598 truncatedPath = [
truncatedPath stringByDeletingLastPathComponent];
600 if (NSOrderedSame == [[truncatedPath pathExtension] caseInsensitiveCompare:
@"oxp"])
602 truncatedPath = [
truncatedPath stringByDeletingPathExtension];
606 theName = lastComponent;
610 if (0 == [theName length]) theName = path;
612 return StrippedName([theName stringByAppendingString:
@".anon-script"]);
582- (NSString *)scriptNameFromPath:(NSString *)path {
…}
616- (NSDictionary *) defaultPropertiesFromPath:(NSString *)path
619 NSString *manifestPath = [[[
path stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"manifest.plist"];
628 [
properties setObject:[
manifest oo_stringForKey:kOOManifestVersion] forKey:@"version"];
633 [
properties setObject:[
manifest oo_stringForKey:kOOManifestIdentifier] forKey:kLocalManifestProperty];
641 [
properties setObject:[
manifest oo_stringForKey:kOOManifestLicense] forKey:@"license"];
616- (NSDictionary *) defaultPropertiesFromPath:(NSString *)path {
…}
650@implementation OOScript (JavaScriptEvents)
652- (BOOL) callMethod:(jsid)methodID
653 inContext:(JSContext *)context
654 withArguments:(jsval *)argv count:(intN)argc
655 result:(jsval *)outResult
652- (BOOL) callMethod:(jsid)methodID {
…}
673 if (JSID_IS_STRING(propID))
675 JSString *propName = JSID_TO_STRING(propID);
677 if (JS_StringEqualsAscii(context, propName,
"tickle", &match) && match)
680 OOJSReportWarning(context,
@"Script %@ appears to use the tickle() event handler, which is no longer supported.", [thisScript name]);
693 [array addObject:stack->current];
698static JSScript *
LoadScriptWithName(JSContext *context, NSString *path, JSObject *
object, JSObject **outScriptObject, NSString **outErrorMessage)
700#if OO_CACHE_JS_SCRIPTS
703 NSString *fileContents =
nil;
705 JSScript *script = NULL;
707 NSCParameterAssert(outScriptObject != NULL && outErrorMessage != NULL);
708 *outErrorMessage =
nil;
710#if OO_CACHE_JS_SCRIPTS
722 fileContents = [NSString stringWithContentsOfUnicodeFile:path];
724 if (fileContents !=
nil)
731 if ([fileContents rangeOfString:
@"\"use strict\
";"].location == NSNotFound && [fileContents rangeOfString:
@"'use strict';"].location == NSNotFound)
738 fileContents = [@"\"use strict\";\n" stringByAppendingString:fileContents];
742 data = [fileContents utf16DataWithBOM:NO];
744 if (data ==
nil) *outErrorMessage =
@"could not load file";
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";
752#if OO_CACHE_JS_SCRIPTS
698static JSScript *
LoadScriptWithName(JSContext *context, NSString *path, JSObject *
object, JSObject **outScriptObject, NSString **outErrorMessage) {
…}
766#if OO_CACHE_JS_SCRIPTS
769 JSXDRState *xdr = NULL;
770 NSData *result =
nil;
774 xdr = JS_XDRNewMem(context, JSXDR_ENCODE);
777 if (JS_XDRScript(xdr, &script))
779 bytes = JS_XDRMemGetData(xdr, &length);
782 result = [NSData dataWithBytes:bytes length:length];
794 JSXDRState *xdr = NULL;
795 JSScript *result = NULL;
797 if (data ==
nil)
return NULL;
799 xdr = JS_XDRNewMem(context, JSXDR_DECODE);
802 NSUInteger length = [data length];
803 if (
EXPECT_NOT(length > UINT32_MAX))
return NULL;
805 JS_XDRMemSetData(xdr, (
void *)[data bytes], (uint32_t)length);
806 if (!JS_XDRScript(xdr, &result)) result = NULL;
808 JS_XDRMemSetData(xdr, NULL, 0);
819 static NSCharacterSet *invalidSet =
nil;
820 if (invalidSet ==
nil) invalidSet = [[NSCharacterSet characterSetWithCharactersInString:@"_ \t\n\r\v"] retain];
822 return [string stringByTrimmingCharactersInSet:invalidSet];
id OOConsumeReference(id OO_NS_CONSUMED value)
void OOStandardsDeprecated(NSString *message)
BOOL OOEnforceStandards(void)
#define OOJSStopTimeLimiter()
#define OOJSStartTimeLimiter()
#define kOOJSLongTimeLimit
#define OOJSStartTimeLimiterWithTimeLimit(limit)
void InitOOJSScript(JSContext *context, JSObject *global)
static NSString *const kLocalManifestProperty
static NSString * StrippedName(NSString *string)
static JSBool ScriptAddProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
static NSData * CompiledScriptData(JSContext *context, JSScript *script)
static JSObject * sScriptPrototype
static RunningStack * sRunningStack
static JSFunctionSpec sScriptMethods[]
static JSClass sScriptClass
static JSScript * LoadScriptWithName(JSContext *context, NSString *path, JSObject *object, JSObject **outScriptObject, NSString **outErrorMessage)
static void AddStackToArrayReversed(NSMutableArray *array, RunningStack *stack)
static JSScript * ScriptWithCompiledData(JSContext *context, NSData *data)
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,...)
#define OOLogOutdentIf(class)
#define OOLog(class, format,...)
#define OOLogIndentIf(class)
static NSString *const kOOManifestLicense
static NSString *const kOOManifestIdentifier
static NSString *const kOOManifestVersion
static NSString *const kOOManifestAuthor
NSDictionary * OODictionaryFromFile(NSString *path)
void setObject:forKey:inCache:(id inElement,[forKey] NSString *inKey,[inCache] NSString *inCacheKey)
id objectForKey:inCache:(NSString *inKey,[inCache] NSString *inCacheKey)
OOCacheManager * sharedCache()
BOOL defineProperty:named:(id value,[named] NSString *name)
BOOL setProperty:named:(id value,[named] NSString *name)
BOOL defineProperty:withID:inContext:(id value,[withID] jsid propID,[inContext] JSContext *context)
id propertyNamed:(NSString *name)
NSString * oo_jsClassName()
id propertyWithID:inContext:(jsid propID,[inContext] JSContext *context)
OOJSScript * currentlyRunningScript()
NSString * scriptNameFromPath:(NSString *path)
OOWeakReference * weakSelf
BOOL setProperty:withID:inContext:(id value,[withID] jsid propID,[inContext] JSContext *context)
NSString * descriptionComponents()
NSString * scriptDescription()
NSDictionary * defaultPropertiesFromPath:(NSString *path)
OOJavaScriptEngine * sharedEngine()
NSString * descriptionComponents()
id weakRefWithObject:(id< OOWeakReferenceSupport > object)