/// <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> /// Searches for a file in the script library, current directory, included paths, and web application root respectively. /// </summary> /// <param name="errorSeverity">A severity of an error (if occures).</param> /// <param name="includedPath">A source path to the included script.</param> /// <param name="includerFullPath">Full source path to the including script.</param> /// <returns>Full path to the file or <B>null</B> path if not found.</returns> private FullPath SearchForIncludedFile(PhpError errorSeverity, string includedPath, FullPath includerFullPath) { FullPath result; string message; // // construct the delegate checking the script existance // var file_exists = applicationContext.BuildFileExistsDelegate(); // // try to find the script // if (file_exists != null) { string includer_directory = includerFullPath.IsEmpty ? WorkingDirectory : Path.GetDirectoryName(includerFullPath); // searches for file in the following order: // - incomplete absolute path => combines with RootOf(WorkingDirectory) // - relative path => searches in FileSystem.IncludePaths then in the includer source directory result = PhpScript.FindInclusionTargetPath( new InclusionResolutionContext( applicationContext, includer_directory, WorkingDirectory, config.FileSystem.IncludePaths ), includedPath, file_exists, out message); } else { message = "Script cannot be included with current configuration."; // there is no precompiled MSA available on non-web application result = FullPath.Empty; } // failure: if (result.IsEmpty) { PhpException.Throw(errorSeverity, CoreResources.GetString("script_inclusion_failed", includedPath, message, config.FileSystem.IncludePaths, WorkingDirectory)); } return(result); }
/// <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); }