Пример #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);
                    }
                }
            }
        }
Пример #2
0
		/// <summary>
		/// Invoked when the instance is created (not called when unserialized).
		/// </summary>
		protected override void InstanceCreated(ScriptContext context)
		{
			base.InstanceCreated(context);

			PhpStackTrace trace = new PhpStackTrace(context, 1);
			PhpStackFrame frame = trace.GetFrame(0);
			Debug.Assert(frame != null);

			this.file.Value = frame.File;
			this.line.Value = frame.Line;
			this.column.Value = frame.Column;
			this.trace.Value = trace.GetUserTrace();
		}
Пример #3
0
        /// <summary>
        /// Attempts to bind this callback to its target.
        /// </summary>
        /// <param name="quiet"><B>true</B> of no errors should be thrown, <B>false</B> otherwise.</param>
        /// <param name="nameContext">Current <see cref="NamingContext"/> for function and class name resolution.</param>
        /// <param name="caller">Current class context or a <see cref="UnknownTypeDesc"/> if the class context
        /// should be determined ad-hoc.</param>
        /// <returns><B>True</B> if the callback was successfully bound, <B>false</B> if an error occured.</returns>
        public bool Bind(bool quiet, DTypeDesc caller, NamingContext nameContext)
        {
            if (IsInvalid)
            {
                return(false);
            }

            switch (state)
            {
            case State.UnboundFunction:
            {
                if (context == null)
                {
                    context = ScriptContext.CurrentContext;
                }

                routineDesc = context.ResolveFunction(targetName, nameContext, quiet);
                if (routineDesc == null)
                {
                    return(false);
                }

                state = State.Bound;
                return(true);
            }

            case State.UnboundStaticMethod:
            {
                if (context == null)
                {
                    context = ScriptContext.CurrentContext;
                }

                if (caller != null && caller.IsUnknown)
                {
                    callingContext = PhpStackTrace.GetClassContext();
                }
                else
                {
                    callingContext = caller;
                }

                // try to find the CLR method

                // find the class according to className
                ResolveTypeFlags flags = ResolveTypeFlags.UseAutoload;
                if (!quiet)
                {
                    flags |= ResolveTypeFlags.ThrowErrors;
                }

                DTypeDesc type = context.ResolveType(className, nameContext, callingContext, null, flags);
                if (type == null)
                {
                    return(false);
                }

                // find the method
                bool is_caller_method;
                lateStaticBindType = type;
                routineDesc        = Operators.GetStaticMethodDesc(type, targetName,
                                                                   ref instance, callingContext, context, quiet, false, out is_caller_method);

                if (routineDesc == null)
                {
                    return(false);
                }

                if (instance != null)
                {
                    dummyInstance = true;
                }
                state = is_caller_method ? State.BoundToCaller : State.Bound;
                return(true);
            }

            case State.UnboundInstanceMethod:
            {
                if (caller != null && caller.IsUnknown)
                {
                    callingContext = PhpStackTrace.GetClassContext();
                }
                else
                {
                    callingContext = caller;
                }

                // ask the instance for a handle to the method
                bool is_caller_method;
                routineDesc = instance.GetMethodDesc(targetName, callingContext, quiet, out is_caller_method);
                if (routineDesc == null)
                {
                    return(false);
                }

                state = (is_caller_method ? State.BoundToCaller : State.Bound);
                return(true);
            }
            }
            return(true);
        }
Пример #4
0
        /// <summary>
        /// Reports a PHP error.
        /// </summary>
        /// <param name="error">The error type</param>
        /// <param name="message">The error message.</param>
        public static void Throw(PhpError error, string message)
        {
            if (ThrowCallbackOverride != null)
            {
                ThrowCallbackOverride(error, message);
                return;
            }

            ErrorStackInfo info        = new ErrorStackInfo();
            bool           info_loaded = false;

            // gets the current script context and config:
            ScriptContext      context = ScriptContext.CurrentContext;
            LocalConfiguration config  = context.Config;

            // determines whether the error will be reported and whether it is handleable:
            bool is_error_reported   = ((PhpErrorSet)error & config.ErrorControl.ReportErrors) != 0 && !context.ErrorReportingDisabled;
            bool is_error_handleable = ((PhpErrorSet)error & PhpErrorSet.Handleable & (PhpErrorSet)config.ErrorControl.UserHandlerErrors) != 0;
            bool is_error_fatal      = ((PhpErrorSet)error & PhpErrorSet.Fatal) != 0;
            bool do_report           = true;

            // remember last error info
            context.LastErrorType    = error;
            context.LastErrorMessage = message;
            context.LastErrorFile    = null; // only if we are getting ErrorStackInfo, see PhpStackTrace.TraceErrorFrame
            context.LastErrorLine    = 0;    // only if we are getting ErrorStackInfo, see PhpStackTrace.TraceErrorFrame

            // calls a user defined handler if available:
            if (is_error_handleable && config.ErrorControl.UserHandler != null)
            {
                // loads stack info:
                Func <ErrorStackInfo> func = () =>
                {
                    if (!info_loaded)
                    {
                        info        = PhpStackTrace.TraceErrorFrame(context, true);
                        info_loaded = true;
                    }
                    return(info);
                };

                do_report = CallUserErrorHandler(context, error, func, message);
            }

            // reports error to output and logs:
            if (do_report && is_error_reported &&
                (config.ErrorControl.DisplayErrors || config.ErrorControl.EnableLogging))   // check if the error will be displayed to avoid stack trace loading
            {
                // loads stack info:
                if (!info_loaded)
                {
                    info = PhpStackTrace.TraceErrorFrame(context, false); info_loaded = true;
                }

                ReportError(config, context.Output, error, -1, info, message);
            }

            // Throws an exception if the error is fatal and throwing is enabled.
            // PhpError.UserError is also fatal, but can be cancelled by user handler => handler call must precede this line.
            // Error displaying must also precede this line because the error should be displayed before an exception is thrown.
            if (is_error_fatal && context.ThrowExceptionOnError)
            {
                // loads stack info:
                if (!info_loaded)
                {
                    info = PhpStackTrace.TraceErrorFrame(context, false); info_loaded = true;
                }

                throw new PhpException(error, message, info);
            }
        }