Exemple #1
0
        /// <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);
                    }
                }
            }
        }
Exemple #2
0
		private static bool FunctionsCallback(MethodInfo method, ImplementsFunctionAttribute ifa, object result)
		{
			if ((ifa.Options & FunctionImplOptions.Internal) == 0 && (ifa.Options & FunctionImplOptions.NotSupported) == 0)
			{
				PhpArray array = (PhpArray)result;
				((PhpArray)array["name"]).Add(ifa.Name);
				((PhpArray)array["type"]).Add(method.DeclaringType.FullName);
				((PhpArray)array["method"]).Add(method.Name);
			}
			return true;
		}
Exemple #3
0
		/// <summary>
		/// A callback used by <see cref="GetExtensionFunctions"/> method. Adds a function to the resulting array as a key.
		/// </summary>
		private static bool AddFunctionToHashtable(MethodInfo info, ImplementsFunctionAttribute ifa, object result)
		{
			if ((ifa.Options & FunctionImplOptions.NotSupported) == 0)
				((Hashtable)result)[ifa.Name] = null;

			return true;
		}
Exemple #4
0
        /// <summary>
        /// Traces up the stack frame containing the method call that has caused an error.
        /// </summary>
        /// <returns>Found stack info.</returns>
        /// <remarks>
        /// Starts with a frame of a calling method and ends with the first frame belonging to user routine.
        /// If there was <see cref="ImplementsFunctionAttribute"/> found during the walk the last one's value
        /// is considered as the caller.
        /// If there was not such attribute found (error occured in an operator, directly in the code etc.)
        /// the last inspected method's debug info is returned.
        /// If the trace ends up with a function or method inside transient assembly an eval hierarchy is inspected
        /// and added to the resulting source position information.
        /// </remarks>
        internal static ErrorStackInfo TraceErrorFrame(ScriptContext /*!*/ context, bool lazy)
        {
            Debug.Assert(context != null);

            ErrorStackInfo result           = new ErrorStackInfo();
            int            cl_function_idx  = -1;
            string         cl_function_name = null;
            StackFrame     frame;
            int            eval_id = TransientAssembly.InvalidEvalId;

            // stack trace without debug info is constructed:
#if !SILVERLIGHT
            StackTrace trace = new StackTrace(1, false);

            // note: method stack frame contains a debug info about the call to the callee
            // hence if we find a method that reported the error we should look the next frame
            // to obtain a debug info

            int i = 0;
            for (; ;)
            {
                // gets frame:
                frame = trace.GetFrame(i++);

                // error has been thrown directly by Core without intermediary user code (all frames are invisible):
                if (frame == null)
                {
                    // cl_function_idx can be non-minus-one here because a callback can be called directly from Core
                    // (e.g. output buffer filter targeting class library function):
                    if (cl_function_idx != -1)
                    {
                        result.Caller        = cl_function_name;
                        result.LibraryCaller = true;
                    }

                    return(result);
                }

                MethodBase method = frame.GetMethod();
                if (lazy)
                {
                    if (method.Name == "Throw" && method.DeclaringType == typeof(PhpException))
                    {
                        lazy = false;
                    }
                    continue;
                }

                FrameKinds frame_kind = GetFrameKind(frame);

                if (frame_kind == FrameKinds.Visible || frame_kind == FrameKinds.Main)
                {
                    int eid = TransientModule.GetEvalId(context.ApplicationContext, method);

                    if (eval_id == TransientAssembly.InvalidEvalId)
                    {
                        eval_id = eid;
                    }

                    if (eid == TransientAssembly.InvalidEvalId)
                    {
                        break;
                    }
                }
                else if (frame_kind == FrameKinds.ClassLibraryFunction)
                {
                    cl_function_idx  = i;
                    cl_function_name = ImplementsFunctionAttribute.Reflect(method).Name;
                }
            }

            // skips i frames (the very first frame has been skipped in the previous
            // trace construction and we want to skip i-1 frames from that trace => i frames totally):
            frame = new StackFrame(1 + i - 1, true);

            // extracts a source info (file & position):
            if (eval_id != TransientAssembly.InvalidEvalId)
            {
                FillEvalStackInfo(context, eval_id, ref result, false);
            }
            else
            {
                result.Line   = frame.GetFileLineNumber();
                result.Column = frame.GetFileColumnNumber();
                result.File   = frame.GetFileName();
            }

            // determines a caller (either a library function or a user function/method):
            if (cl_function_idx >= 0)
            {
                result.Caller        = cl_function_name;
                result.LibraryCaller = true;
            }
            //else
            //{
            //  MethodBase method = frame.GetMethod();
            //  Type type = method.DeclaringType;

            //  // the caller has already been set by FillEvalStackInfo
            //  // if we are in eval and the function is Main helper of the script type:
            //  if (eval_id == TransientAssembly.InvalidEvalId)
            //  {
            //    result.LibraryCaller = false;

            //    if (type != null)
            //    {
            //      result.Caller = String.Concat(DTypeDesc.MakeFullName(type), "::", DRoutineDesc.MakeFullName(method));
            //    }
            //    else
            //    {
            //      result.Caller = DRoutineDesc.MakeFullName(method);
            //    }
            //  }
            //}
#endif

            // add missing info about file and line
            context.LastErrorLine = result.Line;
            context.LastErrorFile = result.File;

            //
            return(result);
        }