TiGlobalContextRef TiContextGetGlobalContext(TiContextRef ctx) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); return toGlobalRef(exec->lexicalGlobalObject()->globalExec()); }
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()); }
TiObjectRef TiContextGetGlobalObject(TiContextRef ctx) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); // It is necessary to call toThisObject to get the wrapper object when used with WebCore. return toRef(exec->lexicalGlobalObject()->toThisObject(exec)); }
void JSReportExtraMemoryCost(TiContextRef ctx, size_t size) { TiExcState* exec = toJS(ctx); exec->globalData().heap.registerThread(); TiLock lock(exec); exec->globalData().heap.reportExtraMemoryCost(size); }
bool TiValueIsDate(TiContextRef ctx, TiValueRef value) { TiExcState* exec = toJS(ctx); exec->globalData().heap.registerThread(); TiLock lock(exec); TiValue jsValue = toJS(exec, value); return jsValue.inherits(&DateInstance::info); }
TiGlobalContextRef TiGlobalContextRetain(TiGlobalContextRef ctx) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiGlobalData& globalData = exec->globalData(); gcProtect(exec->dynamicGlobalObject()); globalData.ref(); return ctx; }
TiStringRef TiContextCreateBacktrace(TiContextRef ctx, unsigned maxStackSize) { TiExcState* exec = toJS(ctx); TiLock lock(exec); unsigned count = 0; UStringBuilder builder; CallFrame* callFrame = exec; UString functionName; if (exec->callee()) { if (asObject(exec->callee())->inherits(&InternalFunction::s_info)) { functionName = asInternalFunction(exec->callee())->name(exec); builder.append("#0 "); builder.append(functionName); builder.append("() "); count++; } } while (true) { ASSERT(callFrame); int signedLineNumber; intptr_t sourceID; UString urlString; TiValue function; UString levelStr = UString::number(count); exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function); if (function) functionName = asFunction(function)->name(exec); else { // Caller is unknown, but if frame is empty we should still add the frame, because // something called us, and gave us arguments. if (count) break; } unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0; if (!builder.isEmpty()) builder.append("\n"); builder.append("#"); builder.append(levelStr); builder.append(" "); builder.append(functionName); builder.append("() at "); builder.append(urlString); builder.append(":"); builder.append(UString::number(lineNumber)); if (!function || ++count == maxStackSize) break; callFrame = callFrame->callerFrame(); } return OpaqueTiString::create(builder.toUString()).leakRef(); }
TiObjectRef TiValueToObject(TiContextRef ctx, TiValueRef value, TiValueRef* exception) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiValue jsValue = toJS(exec, value); TiObjectRef objectRef = toRef(jsValue.toObject(exec)); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); objectRef = 0; } return objectRef; }
TiStringRef TiValueToStringCopy(TiContextRef ctx, TiValueRef value, TiValueRef* exception) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiValue jsValue = toJS(exec, value); RefPtr<OpaqueTiString> stringRef(OpaqueTiString::create(jsValue.toString(exec))); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); stringRef.clear(); } return stringRef.release().releaseRef(); }
double TiValueToNumber(TiContextRef ctx, TiValueRef value, TiValueRef* exception) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiValue jsValue = toJS(exec, value); double number = jsValue.toNumber(exec); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); number = NaN; } return number; }
TiStringRef TiValueCreateJSONString(TiContextRef ctx, TiValueRef apiValue, unsigned indent, TiValueRef* exception) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiValue value = toJS(exec, apiValue); UString result = JSONStringify(exec, value, indent); if (exception) *exception = 0; if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); return 0; } return OpaqueTiString::create(result).releaseRef(); }
bool TiValueIsEqual(TiContextRef ctx, TiValueRef a, TiValueRef b, TiValueRef* exception) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiValue jsA = toJS(exec, a); TiValue jsB = toJS(exec, b); bool result = TiValue::equal(exec, jsA, jsB); // false if an exception is thrown if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); } return result; }
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; }
bool TiValueIsInstanceOfConstructor(TiContextRef ctx, TiValueRef value, TiObjectRef constructor, TiValueRef* exception) { TiExcState* exec = toJS(ctx); APIEntryShim entryShim(exec); TiValue jsValue = toJS(exec, value); TiObject* jsConstructor = toJS(constructor); if (!jsConstructor->structure()->typeInfo().implementsHasInstance()) return false; bool result = jsConstructor->hasInstance(exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); } return result; }
void TiGarbageCollect(TiContextRef ctx) { // We used to recommend passing NULL as an argument here, which caused the only heap to be collected. // As there is no longer a shared heap, the previously recommended usage became a no-op (but the GC // will happen when the context group is destroyed). // Because the function argument was originally ignored, some clients may pass their released context here, // in which case there is a risk of crashing if another thread performs GC on the same heap in between. if (!ctx) return; TiExcState* exec = toJS(ctx); TiGlobalData& globalData = exec->globalData(); TiLock lock(globalData.isSharedInstance ? LockForReal : SilenceAssertionsOnly); if (!globalData.heap.isBusy()) globalData.heap.collect(); // FIXME: Perhaps we should trigger a second mark and sweep // once the garbage collector is done if this is called when // the collector is busy. }
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); }
TiContextGroupRef TiContextGetGroup(TiContextRef ctx) { TiExcState* exec = toJS(ctx); return toRef(&exec->globalData()); }