TiValueRef TiEvalScript(TiContextRef ctx, TiStringRef script, TiObjectRef thisObject, TiStringRef sourceURL, int startingLineNumber, TiValueRef* exception) { TiExcState* exec = toJS(ctx); exec->globalData().heap.registerThread(); TiLock lock(exec); TiObject* jsThisObject = toJS(thisObject); // evaluate sets "this" to the global object if it is NULL TiGlobalObject* globalObject = exec->dynamicGlobalObject(); SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber); Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), source, jsThisObject); if (completion.complType() == Throw) { if (exception) *exception = toRef(exec, completion.value()); return 0; } if (completion.value()) return toRef(exec, completion.value()); // happens, for example, when the only statement is an empty (';') statement return toRef(exec, jsUndefined()); }
TiGlobalContextRef TiGlobalContextRetain(TiGlobalContextRef ctx) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiGlobalData& globalData = exec->globalData(); gcProtect(exec->dynamicGlobalObject()); globalData.ref(); return ctx; }
bool TiCheckScriptSyntax(TiContextRef ctx, TiStringRef script, TiStringRef sourceURL, int startingLineNumber, TiValueRef* exception) { TiExcState* exec = toJS(ctx); exec->globalData().heap.registerThread(); TiLock lock(exec); SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber); Completion completion = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source); if (completion.complType() == Throw) { if (exception) *exception = toRef(exec, completion.value()); return false; } return true; }
void TiGlobalContextRelease(TiGlobalContextRef ctx) { TiExcState* exec = toJS(ctx); TiLock lock(exec); TiGlobalData& globalData = exec->globalData(); TiGlobalObject* dgo = exec->dynamicGlobalObject(); IdentifierTable* savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable); // One reference is held by TiGlobalObject, another added by TiGlobalContextRetain(). bool releasingContextGroup = globalData.refCount() == 2; bool releasingGlobalObject = Heap::heap(dgo)->unprotect(dgo); // If this is the last reference to a global data, it should also // be the only remaining reference to the global object too! ASSERT(!releasingContextGroup || releasingGlobalObject); // An API 'TiGlobalContextRef' retains two things - a global object and a // global data (or context group, in API terminology). // * If this is the last reference to any contexts in the given context group, // call destroy on the heap (the global data is being freed). // * If this was the last reference to the global object, then unprotecting // it may release a lot of GC memory - tickle the activity callback to // garbage collect soon. // * If there are more references remaining the the global object, then do nothing // (specifically that is more protects, which we assume come from other TiGlobalContextRefs). if (releasingContextGroup) { globalData.clearBuiltinStructures(); globalData.heap.destroy(); } else if (releasingGlobalObject) { globalData.heap.activityCallback()->synchronize(); (*globalData.heap.activityCallback())(); } globalData.deref(); wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable); }