/// <summary> /// Creates a new PHP stack frame. /// </summary> /// <param name="context">A script context.</param> /// <param name="frame">The respective CLR frame.</param> /// <param name="kind">A kind of the frame.</param> internal PhpStackFrame(ScriptContext /*!*/ context, StackFrame /*!*/ frame, FrameKinds kind) { Debug.Assert(context != null && frame != null && kind != FrameKinds.Invisible); this.frame = frame; this.kind = kind; MethodBase method = frame.GetMethod(); if (kind == FrameKinds.ClassLibraryFunction) { this.name = ImplementsFunctionAttribute.Reflect(method).Name; SetDebugInfo(frame); } else { Type type = method.DeclaringType; int eval_id = TransientAssembly.InvalidEvalId; if (type != null && context.ApplicationContext.IsTransientRealType(type)) { // gets [PhpEvalId] attribute defined on the type: object[] attrs = type.GetCustomAttributes(typeof(PhpEvalIdAttribute), false); eval_id = ((PhpEvalIdAttribute)attrs[0]).Id; ErrorStackInfo info = new ErrorStackInfo(); PhpStackTrace.FillEvalStackInfo(context, eval_id, ref info, false); this.line = info.Line; this.column = info.Column; this.file = info.File; this.name = info.Caller; } else { SetDebugInfo(frame); } // the caller has already been set by FillEvalStackInfo // if it is not an eval main: if (!(eval_id != TransientAssembly.InvalidEvalId && PhpScript.IsScriptType(type) && kind == FrameKinds.Main)) { if (this.name == ScriptModule.MainHelperName) { this.name = "{main}"; } else { int j; PhpScript.ParseMDeclName(method.Name, out this.name, out j); } } } }
/// <summary> /// Determines whether a specified method whose declaring type is a script type is a Main helper. /// </summary> /// <param name="method">The method.</param> /// <param name="parameters">GetUserEntryPoint parameters (optimization). Can be <B>null</B> reference.</param> /// <returns>Whether a specified method is an arg-less stub.</returns> internal static bool IsMainHelper(MethodInfo /*!*/ method, ParameterInfo[] parameters) { Debug.Assert(method != null && PhpScript.IsScriptType(method.DeclaringType)); if (method.Name != ScriptModule.MainHelperName) { return(false); } if (parameters == null) { parameters = method.GetParameters(); } return(parameters.Length == 5 && parameters[4].ParameterType == Emit.Types.Bool[0]); }
/// <summary> /// Traces the calling stack to discover current PHP class context. /// </summary> /// <returns><see cref="Type"/> of the PHP class that represents current class context for this thread or /// <B>null</B> if this thread is executing in a function or startup Main context.</returns> public static DTypeDesc GetClassContext() { // SILVERLIGHT: Todo Todo .. ? what to do here ? #if !SILVERLIGHT StackTrace stack_trace = new StackTrace(1); int frame_count = stack_trace.FrameCount; for (int i = 0; i < frame_count; i++) { StackFrame stack_frame = stack_trace.GetFrame(i); MethodBase method = stack_frame.GetMethod(); Type type = method.DeclaringType; if (type != null) { if (PhpType.IsPhpRealType(type)) { return(DTypeDesc.Create(type)); } MethodInfo minfo = method as MethodInfo; if (minfo != null) { ParameterInfo[] parameters = minfo.GetParameters(); if (!PhpFunctionUtils.IsArglessStub(minfo, parameters) && PhpScript.IsScriptType(minfo.DeclaringType) && !PhpScript.IsMainHelper(minfo, parameters)) { return(null); } // if the method is a helper method (Main, an arg-less overload, a constructor, etc.), // continue with the trace } } } #endif return(null); }