Var JavascriptExternalFunction::ExternalFunctionThunk(RecyclableObject* function, CallInfo callInfo, ...) { ARGUMENTS(args, callInfo); JavascriptExternalFunction* externalFunction = static_cast<JavascriptExternalFunction*>(function); ScriptContext * scriptContext = externalFunction->type->GetScriptContext(); #ifdef ENABLE_DIRECTCALL_TELEMETRY DirectCallTelemetry::AutoLogger logger(scriptContext, externalFunction, &args); #endif externalFunction->PrepareExternalCall(&args); #if ENABLE_TTD Var result = nullptr; if(scriptContext->ShouldPerformRecordOrReplayAction()) { result = JavascriptExternalFunction::HandleRecordReplayExternalFunction_Thunk(externalFunction, callInfo, args, scriptContext); } else { BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext) { // Don't do stack probe since BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION does that for us already result = externalFunction->nativeMethod(function, callInfo, args.Values); } END_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext); } #else Var result = nullptr; BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext) { // Don't do stack probe since BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION does that for us already result = externalFunction->nativeMethod(function, callInfo, args.Values); } END_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext); #endif if (result == nullptr) { #pragma warning(push) #pragma warning(disable:6011) // scriptContext cannot be null here result = scriptContext->GetLibrary()->GetUndefined(); #pragma warning(pop) } else { result = CrossSite::MarshalVar(scriptContext, result); } return result; }
Var JavascriptExternalFunction::ExternalFunctionThunk(RecyclableObject* function, CallInfo callInfo, ...) { RUNTIME_ARGUMENTS(args, callInfo); JavascriptExternalFunction* externalFunction = static_cast<JavascriptExternalFunction*>(function); // Deferred constructors which are not callable fall back to using the RecyclableObject::DefaultEntryPoint. In order to call // this function we have to be inside script so all this and return before doing any of the external call preparation. if (externalFunction->nativeMethod == Js::RecyclableObject::DefaultExternalEntryPoint) { return Js::RecyclableObject::DefaultExternalEntryPoint(function, callInfo, args.Values); } ScriptContext * scriptContext = externalFunction->type->GetScriptContext(); #ifdef ENABLE_DIRECTCALL_TELEMETRY DirectCallTelemetry::AutoLogger logger(scriptContext, externalFunction, &args); #endif externalFunction->PrepareExternalCall(&args); Var result = nullptr; BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext) { // Don't do stack probe since BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION does that for us already result = externalFunction->nativeMethod(function, callInfo, args.Values); } END_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext); return externalFunction->FinishExternalCall(result); }
Var JavascriptExternalFunction::HandleRecordReplayExternalFunction_Thunk(Js::JavascriptFunction* function, CallInfo& callInfo, Arguments& args, ScriptContext* scriptContext) { JavascriptExternalFunction* externalFunction = static_cast<JavascriptExternalFunction*>(function); Var result = nullptr; if(scriptContext->ShouldPerformReplayAction()) { TTD::TTDNestingDepthAutoAdjuster logPopper(scriptContext->GetThreadContext()); scriptContext->GetThreadContext()->TTDLog->ReplayExternalCallEvent(externalFunction, args, &result); } else { TTDAssert(scriptContext->ShouldPerformRecordAction(), "Check either record/replay before calling!!!"); TTD::EventLog* elog = scriptContext->GetThreadContext()->TTDLog; TTD::TTDNestingDepthAutoAdjuster logPopper(scriptContext->GetThreadContext()); TTD::NSLogEvents::EventLogEntry* callEvent = elog->RecordExternalCallEvent(externalFunction, scriptContext->GetThreadContext()->TTDRootNestingCount, args, false); BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext) { // Don't do stack probe since BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION does that for us already result = externalFunction->nativeMethod(function, callInfo, args.Values); } END_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext); //Exceptions should be prohibited so no need to do extra work elog->RecordExternalCallEvent_Complete(externalFunction, callEvent, result); } return result; }