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];
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;
129 if (
self ==
nil) problem =
@"allocation failure";
134 if (JS_IsExceptionPending(context))
136 JS_ClearPendingException(context);
137 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);
144 if (_jsSelf == NULL) problem =
@"allocation failure";
149 problem =
@"could not add JavaScript root object";
154 problem =
@"could not add JavaScript root object";
161 problem =
@"could not set private backreference";
173 filePath = [path retain];
177 OOLog(
@"script.javaScript.willLoad",
@"About to load JavaScript %@", path);
183 NSDictionary *defaultProperties = [
self defaultPropertiesFromPath:path];
186 if ([key isKindOfClass:[NSString class]])
188 property = [defaultProperties objectForKey:key];
192 [
self defineProperty:property named:key];
197 [
self setProperty:property named:key];
203 if (!problem && properties !=
nil)
207 if ([key isKindOfClass:[NSString class]])
209 property = [properties objectForKey:key];
210 [
self defineProperty:property named:key];
221 jsid nameID =
OOJSID(
"name");
222 [
self setProperty:[
self scriptNameFromPath:path] withID:nameID inContext:context];
228 if (!JS_ExecuteScript(context, _jsSelf, script, &returnValue))
230 problem =
@"could not run script";
235 JS_DestroyScript(context, script);
238 JS_RemoveObjectRoot(context, &scriptObject);
246 name = [StrippedName([[
self propertyWithID:nameID inContext:context] description]) copy];
249 name = [[
self scriptNameFromPath:path] retain];
250 [
self setProperty:name withID:nameID inContext:context];
253 version = [[[
self propertyWithID:OOJSID("version") inContext:context] description] copy];
254 description = [[[
self propertyWithID:OOJSID("description") inContext:context] description] copy];
256 OOLog(
@"script.javaScript.load.success",
@"Loaded JavaScript: %@ -- %@", [
self displayName], description ? description : (NSString *)
@"(no description)");
266 OOLog(
@"script.javaScript.load.failed",
@"***** Error loading JavaScript script %@ -- %@", path, problem);
267 JS_ReportPendingException(context);
275 [[NSNotificationCenter defaultCenter] addObserver:self
276 selector:@selector(javaScriptEngineWillReset:)
277 name:kOOJavaScriptEngineWillResetNotification
287 [[NSNotificationCenter defaultCenter] removeObserver:self
288 name:kOOJavaScriptEngineWillResetNotification
301 JS_RemoveObjectRoot(context, &_jsSelf);
306 [weakSelf weakRefDrop];
312- (NSString *) oo_jsClassName
318- (NSString *)descriptionComponents
320 if (_jsSelf != NULL)
return [
super descriptionComponents];
321 else return @"invalid script";
325- (void) javaScriptEngineWillReset:(NSNotification *)notification
332 JS_RemoveObjectRoot(context, &_jsSelf);
345+ (NSArray *) scriptStack
347 NSMutableArray *result =
nil;
349 result = [NSMutableArray array];
358 return [weakSelf retain];
364 if (weakRef == weakSelf) weakSelf =
nil;
370 if (name ==
nil) name = [[
self propertyNamed:@"name"] copy];
371 if (name ==
nil)
return [
self scriptNameFromPath:filePath];
376- (NSString *) scriptDescription
382- (NSString *) version
388- (void)runWithTarget:(
Entity *)target
394- (BOOL) callMethod:(jsid)methodID
395 inContext:(JSContext *)context
396 withArguments:(jsval *)argv count:(intN)argc
397 result:(jsval *)outResult
399 NSParameterAssert(name != NULL && (argv != NULL || argc == 0) && context != NULL &&
JS_IsInRequest(context));
400 if (_jsSelf == NULL)
return NO;
402 JSObject *root = NULL;
405 jsval ignoredResult = JSVAL_VOID;
407 if (outResult == NULL) outResult = &ignoredResult;
410 if (
EXPECT(JS_GetMethodById(context, _jsSelf, methodID, &root, &method) && !JSVAL_IS_VOID(method)))
413 if (JS_IsExceptionPending(context))
415 OOLog(
@"script.internalBug",
@"Exception pending on context before calling method in %s, clearing. This is an internal error, please report it.", __PRETTY_FUNCTION__);
416 JS_ClearPendingException(context);
433 OK = JS_CallFunctionValue(context, _jsSelf, method, argc, argv, outResult);
436 if (JS_IsExceptionPending(context))
438 JS_ReportPendingException(context);
450 JS_RemoveObjectRoot(context, &root);
697static JSScript *
LoadScriptWithName(JSContext *context, NSString *path, JSObject *
object, JSObject **outScriptObject, NSString **outErrorMessage)
699#if OO_CACHE_JS_SCRIPTS
702 NSString *fileContents =
nil;
704 JSScript *script = NULL;
706 NSCParameterAssert(outScriptObject != NULL && outErrorMessage != NULL);
707 *outErrorMessage =
nil;
709#if OO_CACHE_JS_SCRIPTS
721 fileContents = [NSString stringWithContentsOfUnicodeFile:path];
723 if (fileContents !=
nil)
730 if ([fileContents rangeOfString:
@"\"use strict\
";"].location == NSNotFound && [fileContents rangeOfString:@"'use strict';"].location == NSNotFound)
737 fileContents = [@"\"use strict\";\n" stringByAppendingString:fileContents];
741 data = [fileContents utf16DataWithBOM:NO];
743 if (data ==
nil) *outErrorMessage =
@"could not load file";
746 script = JS_CompileUCScript(context,
object, [data bytes], [data length] /
sizeof(unichar), [path UTF8String], 1);
747 if (script != NULL) *outScriptObject = JS_NewScriptObject(context, script);
748 else *outErrorMessage =
@"compilation failed";
751#if OO_CACHE_JS_SCRIPTS