Using JSContextGroupSetExecutionTimeLimit in iOS
Asked Answered
N

1

3

I need to stop the execution of Javascript in a JSContext object? I found the following method which exactly what I need

@function
@abstract Sets the script execution time limit.
@param group The JavaScript context group that this time limit applies to.
@param limit The time limit of allowed script execution time in seconds.
@param callback The callback function that will be invoked when the time limit
 has been reached. This will give you a chance to decide if you want to
 terminate the script or not. If you pass a NULL callback, the script will be
 terminated unconditionally when the time limit has been reached.
@param context User data that you can provide to be passed back to you
 in your callback.

 In order to guarantee that the execution time limit will take effect, you will
 need to call JSContextGroupSetExecutionTimeLimit before you start executing
 any scripts.
*/
JS_EXPORT void JSContextGroupSetExecutionTimeLimit(JSContextGroupRef, double limit, JSShouldTerminateCallback, void* context) AVAILABLE_IN_WEBKIT_VERSION_4_0;

Unfortunately the method is not well documented and I can't figure out how I can use it.

My code is

JSContextGroupRef group = JSContextGroupCreate();
JSGlobalContextRef context = JSGlobalContextCreateInGroup(group, NULL);
NSString *code = @"while(1){}";
JSStringRef script = JSStringCreateWithCFString((__bridge CFStringRef)code);
JSContextGroupSetExecutionTimeLimit(group,.200f,nil,0);
JSValueRef error = NULL;
JSValueRef value = JSEvaluateScript(context, script, NULL, NULL, 0, &error);

when I try to to call to JSContextGroupSetExecutionTimeLimit I get compilation error.

Implicit declaration of function "JSContextGroupSetExecutionTimeLimit" is invalid in C99,

seems like the call comes from JSContextRefPrivate.h, the question how I can add this header to my project and where is the implementation.

any advice how can I handle this. thanks

Nova answered 24/9, 2016 at 11:40 Comment(1)
This is an undocumented method that might cause apple to reject the appAndris
M
2

It's actually pretty trivial: Just copy the declarations of the relevant functions (and the JSShouldTerminateCallback typedef) into your source code. This tells the compiler the exact signatures with which the functions will be available at runtime.

As JavascriptCore is part of the open source WebKit project, the function declarations are available even with useful descriptions in the WebKit repository. The relevant parts are:

typedef bool
(*JSShouldTerminateCallback) (JSContextRef ctx, void* context);

JS_EXPORT void JSContextGroupSetExecutionTimeLimit(JSContextGroupRef group,
                                                   double limit, JSShouldTerminateCallback callback, void* context) CF_AVAILABLE(10_6, 7_0);

JS_EXPORT void JSContextGroupClearExecutionTimeLimit(JSContextGroupRef group) CF_AVAILABLE(10_6, 7_0);

Also, you don't have to create a group yourself, as according to the JavascriptCore documentation, every JSContextRef you create is assigned a new JSContextGroup. You can get the group of a context using the public JSContextGetGroup function.

An example using the private JSContextGroupSetExecutionTimeLimit API is available in the WebKit tests.

IMPORTANT: As already pointed out, an app using this private API is likely to be rejected from the App Store.

Meadowsweet answered 18/12, 2018 at 18:27 Comment(1)
Do you know how to terminate the evaluation of JSContext (Objective-C object)? I tried JSGlobalContextRef contextRef = [jscontext JSGlobalContextRef]; with the WebKit tests same way, but doesn't work, any idea? Thank you!Sheepwalk

© 2022 - 2024 — McMap. All rights reserved.