public CodeSourceUnit(string /*!*/ code, PhpSourceFile /*!*/ sourceFile, Encoding /*!*/ encoding, Lexer.LexicalStates initialState) : base(sourceFile, encoding, Text.LineBreaks.Create(code)) { this.code = code; this.initialState = initialState; }
public SourceUnit(PhpSourceFile/*!*/ sourceFile, Encoding/*!*/ encoding) { Debug.Assert(sourceFile != null && encoding != null); this.sourceFile = sourceFile; this.encoding = encoding; }
/// <summary> /// Initializes the script context for a PHP console application. /// </summary> /// <param name="appContext">Application context.</param> /// <param name="mainScript">The main script's type or a <B>null</B> reference for a pure application.</param> /// <param name="relativeSourcePath">A path to the main script source file.</param> /// <param name="sourceRoot">A source root within which an application has been compiler.</param> /// <returns> /// A new instance of <see cref="ScriptContext"/> with its own copy of local configuration /// to be used by the application. /// </returns> /// <exception cref="System.Configuration.ConfigurationErrorsException"> /// Web configuration is invalid. The context is not initialized then. /// </exception> /// <remarks> /// Use this method if you want to initialize application in the same way the PHP console/Windows /// application is initialized. The returned script context is initialized as follows: /// <list type="bullet"> /// <term>The application's source root is set.</term> /// <term>The main script of the application is defined.</term> /// <term>Output and input streams are set to standard output and input, respectively.</term> /// <term>Current culture it set to <see cref="CultureInfo.InvariantCulture"/>.</term> /// <term>Auto-global variables ($_GET, $_SET, etc.) are initialized.</term> /// <term>Working directory is set tothe current working directory.</term> /// </list> /// </remarks> public static ScriptContext /*!*/ InitApplication(ApplicationContext /*!*/ appContext, Type mainScript, string relativeSourcePath, string sourceRoot) { // loads configuration into the given application context // (applies only if the config has not been loaded yet by the current thread): Configuration.Load(appContext); ApplicationConfiguration app_config = Configuration.Application; if (mainScript != null) { if (relativeSourcePath == null) { throw new ArgumentNullException("relativeSourcePath"); } if (sourceRoot == null) { throw new ArgumentNullException("sourceRoot"); } // overrides source root configuration if not explicitly specified in config file: if (!app_config.Compiler.SourceRootSet) { app_config.Compiler.SourceRoot = new FullPath(sourceRoot); } } // takes a writable copy of a global configuration: LocalConfiguration config = (LocalConfiguration)Configuration.DefaultLocal.DeepCopy(); // sets invariant culture as a default one: Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; ScriptContext result = new ScriptContext(appContext, config, Console.Out, Console.OpenStandardOutput()); result.IsOutputBuffered = result.config.OutputControl.OutputBuffering; result.AutoGlobals.Initialize(config, null); result.WorkingDirectory = Directory.GetCurrentDirectory(); result.ThrowExceptionOnError = true; result.config.ErrorControl.HtmlMessages = false; if (mainScript != null) { // converts relative path of the script source to full canonical path using source root from the configuration: PhpSourceFile main_source_file = new PhpSourceFile( app_config.Compiler.SourceRoot, new FullPath(relativeSourcePath, app_config.Compiler.SourceRoot) ); result.DefineMainScript(new ScriptInfo(mainScript), main_source_file); } ScriptContext.CurrentContext = result; Externals.BeginRequest(); return(result); }
/// <summary> /// Returns compiled module if exists. /// </summary> /// <param name="sourceFile">Source file.</param> /// <param name="ctx">A compilation context.</param> /// <returns>The <see cref="PhpModule"/> or a <B>null</B> reference.</returns> /// <remarks> /// Checks whether a module associated with a <paramref name="sourceFile"/> has already been compiled. /// If so returns the respective <see cref="PhpModule"/>. Otherwise a <B>null</B> reference is returned. /// Does no locking since application compiler is thread unsafe. /// </remarks> public PhpModule LockForCompiling(PhpSourceFile/*!*/ sourceFile, CompilationContext/*!*/ ctx) { // take a look into script library first if (applicationContext.ScriptLibraryDatabase.ContainsScript(sourceFile.FullPath)) { return applicationContext.ScriptLibraryDatabase.GetScriptModule(sourceFile.FullPath); } return assemblyBuilder.Assembly.GetModule(sourceFile); }
public SourceUnit(PhpSourceFile /*!*/ sourceFile, Encoding /*!*/ encoding, ILineBreaks /*!*/ lineBreaks) { Debug.Assert(sourceFile != null && encoding != null); Debug.Assert(lineBreaks != null); this.sourceFile = sourceFile; this.encoding = encoding; this.innerLineBreaks = lineBreaks; this.naming = new NamingContext(null, null); }
/// <summary> /// Returns compiled module if exists. /// </summary> /// <param name="sourceFile">Source file.</param> /// <param name="ctx">A compilation context.</param> /// <returns>The <see cref="PhpModule"/> or a <B>null</B> reference.</returns> /// <remarks> /// Checks whether a module associated with a <paramref name="sourceFile"/> has already been compiled. /// If so returns the respective <see cref="PhpModule"/>. Otherwise a <B>null</B> reference is returned. /// Does no locking since application compiler is thread unsafe. /// </remarks> public PhpModule LockForCompiling(PhpSourceFile /*!*/ sourceFile, CompilationContext /*!*/ ctx) { // take a look into script library first if (applicationContext.ScriptLibraryDatabase.ContainsScript(sourceFile.FullPath)) { return(applicationContext.ScriptLibraryDatabase.GetScriptModule(sourceFile.FullPath)); } return(assemblyBuilder.Assembly.GetModule(sourceFile)); }
/// <summary> /// Loads a script type dynamically. /// </summary> /// <param name="sourceFile">Script's source file.</param> private ScriptInfo LoadDynamicScriptType(PhpSourceFile /*!*/ sourceFile) { Debug.WriteLine("SC", "LoadDynamicScriptType: '{0}'", sourceFile); // runtime compiler manages: // - 1. script library // - 2. optionally bin/WebPages.dll // - 3. compiles file from file system if allowed return(this.ApplicationContext.RuntimeCompilerManager.GetCompiledScript(sourceFile, RequestContext.CurrentContext)); }
/// <summary> /// Creates source unit and parses given <paramref name="code"/>. /// </summary> /// <param name="code">Source code to be parsed.</param> /// <param name="sourceFile">Source file used for error reporting.</param> /// <param name="errors">Errors sink. Can be <c>null</c>.</param> /// <param name="reductionsSink">Reduction sink. Can be <c>null</c>.</param> /// <param name="features">Optional. Language features.</param> /// <param name="initialState"> /// Optional. Initial parser state. /// This allows e.g. to parse PHP code without encapsulating the code into opening and closing tags.</param> /// <returns></returns> public static SourceUnit /*!*/ ParseCode(string code, PhpSourceFile sourceFile, ErrorSink /*!*/ errors, IReductionsSink /*!*/ reductionsSink = null, LanguageFeatures features = LanguageFeatures.Php5, Lexer.LexicalStates initialState = Lexer.LexicalStates.INITIAL) { var /*!*/ unit = new CodeSourceUnit(code, sourceFile, Encoding.UTF8, initialState); unit.Parse(errors, reductionsSink, features); unit.Close(); // return(unit); }
/// <summary> /// Translates a source path to an assembly coded name. /// </summary> /// <param name="sourceFile">Source file.</param> /// <param name="config">The compiler configuration.</param> /// <returns> /// The code name consisting of significant configuration hashcode and source /// path relative to the application source root. /// Format of the name: <code>{relativized path}(~{level_count})?#{config hash}#</code> /// Backslashes and colons are replaced with underscores, underscores are doubled. /// </returns> public static string GetAssemblyCodedName(PhpSourceFile/*!*/ sourceFile, CompilerConfiguration/*!*/ config) { RelativePath rp = sourceFile.RelativePath; StringBuilder sb = new StringBuilder(rp.Path); if (rp.Level >= 0) { sb.Append('~'); sb.Append(rp.Level); } sb.Append('#'); sb.Append(config.Compiler.HashCode.ToString("x")); sb.Append('#'); return sb.Replace("_", "__").Replace('/', '_').Replace('\\', '_').Replace(':', '_').ToString(); }
public bool Equals(PhpSourceFile other) { if (ReferenceEquals(other, this)) { return(true); } if (other == null) { return(false); } // assuming full to relative conversion is faster: if (this.fullPath.IsEmpty || other.fullPath.IsEmpty) { return(this.root.Equals(other.root) && this.RelativePath.Equals(other.RelativePath)); } else { return(this.fullPath.Equals(other.fullPath)); } }
/// <summary> /// Performs PHP inclusion on a specified script. /// </summary> /// <param name="relativeSourcePath"> /// Path to the target script source file relative to the application source root /// (see <c>Configuration.Application.Compiler.SourceRoot</c>. /// </param> /// <param name="script"> /// Script type (i.e. type called <c>Default</c> representing the target script) or any type from /// the assembly where the target script is contained (useful for multi-script assemblies, where script types are /// not directly available from C# as they have mangled names). In the latter case, the script type is searched in the /// assembly using value of <paramref name="relativeSourcePath"/>. /// </param> /// <returns>The value returned by the global code of the target script.</returns> /// <remarks> /// <para> /// The inclusion inheres in adding the target to the list of included scripts on the current script context /// (see <c>ScriptContext.Scripts</c> and in a call to the global code of the target script. /// </para> /// </remarks> /// <exception cref="InvalidOperationException">Request context has been disposed.</exception> /// <exception cref="ArgumentNullException"><paramref name="relativeSourcePath"/> or <paramref name="script"/> are <B>null</B> references.</exception> /// <exception cref="ArgumentException">Script type cannot be resolved.</exception> /// <exception cref="InvalidScriptAssemblyException">The target assembly is not a valid Phalanger compiled assembly.</exception> internal object IncludeScript(string /*!*/ relativeSourcePath, ScriptInfo /*!*/ script) { //if (type == null) // throw new ArgumentNullException("type"); if (relativeSourcePath == null) { throw new ArgumentNullException("relativeSourcePath"); } if (script == null) { throw new ArgumentException("script"); } FullPath source_root = Configuration.Application.Compiler.SourceRoot; PhpSourceFile source_file = new PhpSourceFile( new FullPath(source_root), new FullPath(Path.Combine(source_root, relativeSourcePath))); // the first script becomes the main one: if (MainScriptFile == null) { DefineMainScript(script, source_file); } return(GuardedCall((ScriptInfo scriptInfo) => { //return PhpScript.InvokeMainHelper( // (Type)scriptType, return scriptInfo.Main( this, null, // no local variables null, // no object context null, // no class context true); }, script, true)); }
/// <summary> /// Gets the script module contained in the assembly. /// </summary> /// <returns>The one and only script module of the assembly.</returns> public override ScriptModule GetScriptModule(PhpSourceFile dummy) { return script; }
/// <summary> /// Gets a full name of an assembly in which a specified source script is compiled. /// </summary> /// <param name="sourceFile">Source file.</param> /// <returns>The assembly full name.</returns> /// <remarks>A name of the assembly consists of a hexa-timestamp and a assembly coded name.</remarks> public AssemblyName GetAssemblyFullName(PhpSourceFile/*!*/ sourceFile) { // timestamp ensures there won't be two loaded assemblies of the same name: // (consider editing of a source file) string stamp = requestTimestamp.Ticks.ToString("x16"); AssemblyName result = new AssemblyName(); result.Name = GetAssemblyCodedName(sourceFile, config) + stamp; result.Version = new Version(1, 0, 0, 0); return result; }
public static PhpAssemblyBuilder/*!*/ Create(ApplicationContext/*!*/ applicationContext, AssemblyKinds kind, bool pure, FullPath outPath, FullPath docPath, PhpSourceFile entryPoint, Version version, StrongNameKeyPair key, Win32IconResource icon, ICollection<ResourceFileReference> resources, bool debug, bool force32bit) { string out_dir = Path.GetDirectoryName(outPath); string out_file = Path.GetFileName(outPath); AssemblyName assembly_name = new AssemblyName(); assembly_name.Name = Path.GetFileNameWithoutExtension(outPath); assembly_name.Version = version; assembly_name.KeyPair = key; if (pure) { return new PureAssemblyBuilder(applicationContext, assembly_name, out_dir, out_file, kind, resources, debug, force32bit, icon); } else { return new MultiScriptAssemblyBuilder(applicationContext, assembly_name, out_dir, out_file, kind, resources, debug, force32bit, icon, entryPoint); } }
/// <summary> /// Initializes the script context for a PHP console application. /// </summary> /// <param name="appContext">Application context.</param> /// <param name="mainScript">The main script's type or a <B>null</B> reference for a pure application.</param> /// <param name="relativeSourcePath">A path to the main script source file.</param> /// <param name="sourceRoot">A source root within which an application has been compiler.</param> /// <returns> /// A new instance of <see cref="ScriptContext"/> with its own copy of local configuration /// to be used by the application. /// </returns> /// <exception cref="System.Configuration.ConfigurationErrorsException"> /// Web configuration is invalid. The context is not initialized then. /// </exception> /// <remarks> /// Use this method if you want to initialize application in the same way the PHP console/Windows /// application is initialized. The returned script context is initialized as follows: /// <list type="bullet"> /// <term>The application's source root is set.</term> /// <term>The main script of the application is defined.</term> /// <term>Output and input streams are set to standard output and input, respectively.</term> /// <term>Current culture it set to <see cref="CultureInfo.InvariantCulture"/>.</term> /// <term>Auto-global variables ($_GET, $_SET, etc.) are initialized.</term> /// <term>Working directory is set tothe current working directory.</term> /// </list> /// </remarks> public static ScriptContext/*!*/ InitApplication(ApplicationContext/*!*/ appContext, Type mainScript, string relativeSourcePath, string sourceRoot) { // loads configuration into the given application context // (applies only if the config has not been loaded yet by the current thread): Configuration.Load(appContext); ApplicationConfiguration app_config = Configuration.Application; if (mainScript != null) { if (relativeSourcePath == null) throw new ArgumentNullException("relativeSourcePath"); if (sourceRoot == null) throw new ArgumentNullException("sourceRoot"); // overrides source root configuration if not explicitly specified in config file: if (!app_config.Compiler.SourceRootSet) app_config.Compiler.SourceRoot = new FullPath(sourceRoot); } // takes a writable copy of a global configuration: LocalConfiguration config = (LocalConfiguration)Configuration.DefaultLocal.DeepCopy(); // sets invariant culture as a default one: Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; ScriptContext result = new ScriptContext(appContext, config, Console.Out, Console.OpenStandardOutput()); result.IsOutputBuffered = result.config.OutputControl.OutputBuffering; result.AutoGlobals.Initialize(config, null); result.WorkingDirectory = Directory.GetCurrentDirectory(); result.ThrowExceptionOnError = true; result.config.ErrorControl.HtmlMessages = false; if (mainScript != null) { // converts relative path of the script source to full canonical path using source root from the configuration: PhpSourceFile main_source_file = new PhpSourceFile( app_config.Compiler.SourceRoot, new FullPath(relativeSourcePath, app_config.Compiler.SourceRoot) ); result.DefineMainScript(new ScriptInfo(mainScript), main_source_file); } ScriptContext.CurrentContext = result; Externals.BeginRequest(); return result; }
/// <summary> /// Gets a script type stored in a specified single-script assembly. /// </summary> public override Type GetScriptType(PhpSourceFile dummy) { return GetScriptType(); }
/// <summary> /// Translates a source path to an assembly coded name. /// </summary> public string GetAssemblyCodedName(PhpSourceFile/*!*/ sourceFile) { return GetAssemblyCodedName(sourceFile, config); }
/// <summary> /// Checks whether a specified source file needs to be (re)compiled and if so locks /// it so that any other compiler from the current app domain will wait until this compilation finishes. /// </summary> /// <param name="sourceFile">Source file.</param> /// <param name="ctx">Compilation context.</param> /// <returns> /// A compiled module associated with the <paramref name="sourceFile"/> or a <B>null</B> reference /// if a compilation of that file is needed. /// </returns> public PhpModule LockForCompiling(PhpSourceFile/*!*/ sourceFile, CompilationContext/*!*/ ctx) { Debug.Assert(ctx is WebCompilationContext); WebCompilationContext context = (WebCompilationContext)ctx; // take a look into script library first if (applicationContext.ScriptLibraryDatabase.ContainsScript(sourceFile.FullPath)) { return applicationContext.ScriptLibraryDatabase.GetScriptModule(sourceFile.FullPath); } for (int i = 0; i < AttemptsToGetCompiledAssembly; i++) { string ns = ScriptModule.GetSubnamespace(sourceFile.RelativePath, false); CacheEntry cache_entry; // TODO: Single script assemblies can be loaded and reflected // but this still have to be done for MSAs if (TryLoadCachedEntry(ns, sourceFile, out cache_entry) && !cache_entry.ScriptAssembly.IsMultiScript) return cache_entry.ScriptAssembly.GetModule(sourceFile); // compilation is in progress or not started yet // ManualResetEvent compilation_finished; lock (eventsMutex) { // if compilation of the target file has not started yet: if (!events.TryGetValue(sourceFile, out compilation_finished)) { // adds event which others wait on: events.Add(sourceFile, new ManualResetEvent(false)); return null; } } // waits until compilation is finished and assembly has been persisted: compilation_finished.WaitOne(CompilationTimeout, false); } return null; }
/// <summary> /// Called by compiler when information about compiling progress is available. /// </summary> /// <remarks>Ignored by this manager.</remarks> public void Info(PhpSourceFile/*!*/ sourceFile, CompilationContext ctx) { // nop // }
/// <summary> /// Triggered by the compiler on events such are start of compilation, end of compilation etc. /// </summary> /// <param name="sourceFile">A source path to a script being processed.</param> /// <param name="ctx">A compilation context.</param> public void Info(PhpSourceFile/*!*/ sourceFile, CompilationContext/*!*/ ctx) { Console.WriteLine(sourceFile.RelativePath); }
/// <summary> /// Retrives a compiled script. /// /// The method check scripts in following order: /// 1. Script Library database. /// 2. Modified source file on the file system. /// 3. Unmodified source file in precompiled WebPages.dll. /// </summary> /// <param name="sourceFile">Script source file.</param> /// <param name="requestContext">The current HTTP context. Can be <c>null</c> in case of desktop app.</param> /// <returns>The script type or a <B>null</B> reference on failure.</returns> /// <remarks>The method do check the script library database.</remarks> public ScriptInfo GetCompiledScript(PhpSourceFile/*!*/ sourceFile, RequestContext requestContext) { Debug.Assert(sourceFile != null); // try to get the script from precompiled script library first var scriptLibraryModule = applicationContext.ScriptLibraryDatabase.GetScriptModule(sourceFile.FullPath); if (scriptLibraryModule != null) return scriptLibraryModule.ScriptInfo; // loads precompiled assembly if exists and not loaded yet: GetPrecompiledAssembly(); // enables source code watcher if not enabled yet: if (watcher != null && !watcher.EnableRaisingEvents) { Debug.WriteLine("WSSM", "Source code watcher is starting."); watcher.EnableRaisingEvents = true; } string ns = ScriptModule.GetSubnamespace(sourceFile.RelativePath, false); CacheEntry cache_entry; if (Configuration.Application.Compiler.OnlyPrecompiledCode) { // Load script from cache (WebPages.dll) if (TryGetCachedEntry(ns, out cache_entry)) return cache_entry.ScriptInfo; else return null; } else { // Load script from cache or from ASP.NET Temporary files if (TryLoadCachedEntry(ns, sourceFile, out cache_entry)) return cache_entry.ScriptInfo; lock (this) { // double checked lock, CompileScript should not be called on more threads if (TryGetCachedEntry(ns, out cache_entry)) return cache_entry.ScriptInfo; Debug.WriteLine("WSSM", "Compile script '{0}'.", sourceFile.ToString()); return CompileScriptNoLock(ns, sourceFile, requestContext); } } }
/// <summary> /// Remembers whether compilation has been successful. /// </summary> /// <param name="sourceFile">Source file.</param> /// <param name="successful">Whether compilation was successful.</param> /// <param name="ctx">A compilation context.</param> public void UnlockForCompiling(PhpSourceFile/*!*/ sourceFile, bool successful, CompilationContext/*!*/ ctx) { this.successful &= successful; }
internal bool ScriptExists(FullPath fullPath) { PhpSourceFile source_file = new PhpSourceFile(Configuration.Application.Compiler.SourceRoot, fullPath); return GetScriptType(source_file) != null; }
/// <summary> /// Gets a full qualified name of a script type given a sub-namespace. /// </summary> /// <param name="sourceFile">Source file.</param> /// <returns>The qualified name.</returns> public string GetQualifiedScriptTypeName(PhpSourceFile/*!*/ sourceFile) { Debug.Assert(sourceFile != null); return GetQualifiedScriptTypeName(ScriptModule.GetSubnamespace(sourceFile)); }
/// <summary> /// Gets a script type stored in a specified multi-script assembly. /// </summary> /// <param name="sourceFile">Source file.</param> /// <returns>The script type.</returns> public override Type GetScriptType(PhpSourceFile/*!*/ sourceFile) { Debug.Assert(sourceFile != null); return module.GetType(GetQualifiedScriptTypeName(sourceFile), false, true); }
/// <summary> /// Gets a script module associated with a specified source file. /// </summary> public override ScriptModule GetScriptModule(PhpSourceFile/*!*/ sourceFile) { ScriptModule result; scripts.TryGetValue(sourceFile, out result); return result; }
/// <summary> /// Compiles a script. /// Called when the script cannot be loaded from pre-compiled assembly and it should be compiled. /// </summary> /// <returns>The compiled script type.</returns> private ScriptInfo CompileScriptNoLock(string ns, PhpSourceFile/*!*/ sourceFile, RequestContext requestContext) { Debug.Assert(sourceFile != null); CompilerConfiguration config = new CompilerConfiguration(Configuration.Application); WebCompilationContext context = new WebCompilationContext(applicationContext, this, config, sourceFile.Directory, (requestContext != null) ? requestContext.HttpContext.Timestamp : DateTime.UtcNow); try { CacheEntry cache_entry; if (ScriptAssemblyBuilder.CompileScripts(new PhpSourceFile[] { sourceFile }, context)) { // assembly should be already added into the cache by Persist() method if (TryGetCachedEntry(ns, out cache_entry)) return cache_entry.ScriptInfo; } return null; } catch (CompilerException) { return null; } catch (Exception) { // record stack info to the message if the manager resides in a dedicated domain: throw; } }
/// <summary> /// Includes a specific script using current configuration. /// </summary> /// <param name="relativeSourcePath">Source root relative path to the script.</param> /// <param name="once">Specifies whether script should be included only once.</param> /// <returns>The value returned by the global code of the target script.</returns> public object Include(string /*!*/ relativeSourcePath, bool once) { ApplicationConfiguration app_config = Configuration.Application; // searches for file: FullPath included_full_path = SearchForIncludedFile(PhpError.Error, relativeSourcePath, FullPath.Empty); if (included_full_path.IsEmpty) { return(false); } ScriptInfo info; bool already_included = scripts.TryGetValue(included_full_path.ToString(), out info); // skips inclusion if script has already been included and inclusion's type is "once": if (already_included) { if (once) { return(ScriptModule.SkippedIncludeReturnValue); } // script type loaded, info cannot be null } else { PhpSourceFile included_source_file = new PhpSourceFile(app_config.Compiler.SourceRoot, included_full_path); // loads script type: info = LoadDynamicScriptType(included_source_file); // script not found: if (info == null) { return(false); } if (MainScriptFile == null) { // the first script becomes the main one: DefineMainScript(info, included_source_file); } else { // adds included file into the script list scripts.Add(included_full_path.ToString(), info); } } Debug.Assert(info != null); return(GuardedCall((ScriptInfo scriptInfo) => { //return PhpScript.InvokeMainHelper( // (Type)scriptType, return scriptInfo.Main( this, null, // no local variables null, // no object context null, // no class context true); }, info, true)); }
/// <summary> /// Wakes up threads waiting for a script compilation finish. /// </summary> /// <param name="sourceFile">The compiled script's source file.</param> /// <param name="successful">Whether compilation has been successful.</param> /// <param name="ctx">A compilation context.</param> /// <remarks>Should be called after <see cref="Persist"/>.</remarks> public void UnlockForCompiling(PhpSourceFile/*!*/ sourceFile, bool successful, CompilationContext ctx) { Debug.Assert(sourceFile != null && ctx is WebCompilationContext); ManualResetEvent compilation_finished; lock (eventsMutex) { if (events.TryGetValue(sourceFile, out compilation_finished)) events.Remove(sourceFile); } // any waiting thread can access the compiled assembly now: if (compilation_finished != null) compilation_finished.Set(); }
/// <summary> /// Triggered by the compiler on events such are start of compilation, end of compilation etc. /// </summary> /// <param name="sourceFile">A source path to a script being processed.</param> /// <param name="ctx">A compilation context.</param> public void Info(PhpSourceFile /*!*/ sourceFile, CompilationContext /*!*/ ctx) { Console.WriteLine(sourceFile.RelativePath); }
/// <summary> /// Loads script from cache (in-memory tables) or from /// previously compiled dll in ASP.NET Temporary files. /// </summary> private bool TryLoadCachedEntry(string/*!*/ ns, PhpSourceFile/*!*/ sourceFile, out CacheEntry cache_entry) { // first try in-memory cache if (TryGetCachedEntry(ns, out cache_entry)) { Debug.WriteLine("WSSM", "Cache hit."); if (CheckEntryFileTime(ns, cache_entry) || !Configuration.Application.Compiler.WatchSourceChanges) return true; } lock(tempLoadLocks[unchecked((uint)ns.GetHashCode()) % tempLoadLocks.Length]) { // double checked lock if (TryGetCachedEntry(ns, out cache_entry)) return true; // do not check source time, since it was currently created // try to find previously compiled assembly in temporary files if (TryLoadTemporaryCompiledNoLock(ns, sourceFile, out cache_entry)) { Debug.WriteLine("WSSM", "Loaded from Temporary files."); return true; } } return false; }
/// <summary> /// Performs PHP inclusion on a specified script. /// </summary> /// <param name="relativeSourcePath"> /// Path to the target script source file relative to the application source root /// (see <c>Configuration.Application.Compiler.SourceRoot</c>. /// </param> /// <param name="script"> /// Script type (i.e. type called <c>Default</c> representing the target script) or any type from /// the assembly where the target script is contained (useful for multi-script assemblies, where script types are /// not directly available from C# as they have mangled names). In the latter case, the script type is searched in the /// assembly using value of <paramref name="relativeSourcePath"/>. /// </param> /// <returns>The value returned by the global code of the target script.</returns> /// <remarks> /// <para> /// The inclusion inheres in adding the target to the list of included scripts on the current script context /// (see <c>ScriptContext.Scripts</c> and in a call to the global code of the target script. /// </para> /// </remarks> /// <exception cref="InvalidOperationException">Request context has been disposed.</exception> /// <exception cref="ArgumentNullException"><paramref name="relativeSourcePath"/> or <paramref name="script"/> are <B>null</B> references.</exception> /// <exception cref="ArgumentException">Script type cannot be resolved.</exception> /// <exception cref="InvalidScriptAssemblyException">The target assembly is not a valid Phalanger compiled assembly.</exception> internal object IncludeScript(string/*!*/ relativeSourcePath, ScriptInfo/*!*/ script) { //if (type == null) // throw new ArgumentNullException("type"); if (relativeSourcePath == null) throw new ArgumentNullException("relativeSourcePath"); if (script == null) throw new ArgumentException("script"); FullPath source_root = Configuration.Application.Compiler.SourceRoot; PhpSourceFile source_file = new PhpSourceFile( new FullPath(source_root), new FullPath(Path.Combine(source_root, relativeSourcePath))); // the first script becomes the main one: if (MainScriptFile == null) DefineMainScript(script, source_file); return GuardedCall((ScriptInfo scriptInfo) => { //return PhpScript.InvokeMainHelper( // (Type)scriptType, return scriptInfo.Main( this, null, // no local variables null, // no object context null, // no class context true); }, script, true); }
/// <summary> /// Tries to load script from ASP.NET Temporary files - this is useful when /// web is not precompiled (so it is compiled into SSAs) and appdomain is reloaded /// (which means that we loose the cache) /// </summary> private bool TryLoadTemporaryCompiledNoLock(string ns, PhpSourceFile/*!*/ sourceFile, out CacheEntry cache_entry) { CompilerConfiguration config = new CompilerConfiguration(Configuration.Application); string name = WebCompilationContext.GetAssemblyCodedName(sourceFile, config); string sourcePath = sourceFile.FullPath.ToString(); bool sourceExists = File.Exists(sourcePath); DateTime sourceTime = sourceExists ? File.GetLastWriteTime(sourcePath) : DateTime.UtcNow.AddYears(1); // If file does not exist, fake the sourceTime to NOT load any SSA DLL. Delete them instead. DateTime configTime = Configuration.LastConfigurationModificationTime; // here find the max modification of all dependant files (configuration, script itself, other DLLs): long sourceStamp = Math.Max(Math.Max(sourceTime.Ticks, configTime.Ticks), appCodeAssemblyCreated.Ticks); // Find specified file in temporary files if (Directory.Exists(outDir)) foreach (string file in Directory.GetFiles(outDir, name + "*.dll")) { Match match = reFileStamp.Match(file); if (!match.Success) continue; long fileStamp; if (!Int64.TryParse((string)match.Groups["Stamp"].Value, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out fileStamp)) continue; // File is up-to-date if (sourceStamp < fileStamp) { Debug.WriteLine("WSSM", "Loading from ASP.NET Temporary files."); return LoadSSA(ns, file, out cache_entry); } else { // do "some" cleanup: try { File.Delete(file); File.Delete(Path.ChangeExtension(file, ".pdb")); } catch{ /*nop*/ } } } cache_entry = default(CacheEntry); return false; }
/// <summary> /// Remembers whether compilation has been successful. /// </summary> /// <param name="sourceFile">Source file.</param> /// <param name="successful">Whether compilation was successful.</param> /// <param name="ctx">A compilation context.</param> public void UnlockForCompiling(PhpSourceFile /*!*/ sourceFile, bool successful, CompilationContext /*!*/ ctx) { this.successful &= successful; }
/// <summary> /// Get the precompiled script from several locations - script library database, precompiled SSA, precompiled MSA (WebPages.dll). /// </summary> /// <param name="sourceFile">The source file of the script to retrieve.</param> /// <returns>The <see cref="ScriptInfo"/> of required script or null if such script cannot be obtained.</returns> internal ScriptInfo GetCompiledScript(PhpSourceFile /*!*/ sourceFile) { return(scriptContext.ApplicationContext.RuntimeCompilerManager.GetCompiledScript(sourceFile, this)); }
public bool Equals(PhpSourceFile other) { if (ReferenceEquals(other, this)) return true; if (other == null) return false; // assuming full to relative conversion is faster: if (this.fullPath.IsEmpty || other.fullPath.IsEmpty) return this.root.Equals(other.root) && this.RelativePath.Equals(other.RelativePath); else return this.fullPath.Equals(other.fullPath); }
/// <summary> /// Creates an instance of of multi-script assembly builder. /// </summary> /// <param name="applicationContext">Application context.</param> /// <param name="assemblyName">Name of the assembly.</param> /// <param name="directory">Directory where assembly will be stored.</param> /// <param name="fileName">Name of the assembly file including an extension.</param> /// <param name="kind">Assembly file kind.</param> /// <param name="debug">Whether to include debug information.</param> /// <param name="force32bit">Whether to force 32bit execution of generated assembly.</param> /// <param name="entryPoint">Entry point.</param> /// <param name="icon">Icon.</param> /// <param name="resources">Resources to embed</param> public MultiScriptAssemblyBuilder(ApplicationContext/*!*/ applicationContext, AssemblyName assemblyName, string directory, string fileName, AssemblyKinds kind, ICollection<ResourceFileReference> resources, bool debug, bool force32bit, Win32IconResource icon, PhpSourceFile entryPoint) : base(new MultiScriptAssembly(applicationContext), assemblyName, directory, fileName, kind, resources, debug, force32bit, false, icon) { this.entryPoint = entryPoint; }
/// <summary> /// Get the precompiled script from several locations - script library database, precompiled SSA, precompiled MSA (WebPages.dll). /// </summary> /// <param name="sourceFile">The source file of the script to retrieve.</param> /// <returns>The <see cref="ScriptInfo"/> of required script or null if such script cannot be obtained.</returns> internal ScriptInfo GetCompiledScript(PhpSourceFile/*!*/ sourceFile) { return scriptContext.ApplicationContext.RuntimeCompilerManager.GetCompiledScript(sourceFile, this); }
/// <summary> /// Includes a specific script using current configuration. /// </summary> /// <param name="relativeSourcePath">Source root relative path to the script.</param> /// <param name="once">Specifies whether script should be included only once.</param> /// <returns>The value returned by the global code of the target script.</returns> public object Include(string/*!*/ relativeSourcePath, bool once) { ApplicationConfiguration app_config = Configuration.Application; // searches for file: FullPath included_full_path = SearchForIncludedFile(PhpError.Error, relativeSourcePath, FullPath.Empty); if (included_full_path.IsEmpty) return false; ScriptInfo info; bool already_included = scripts.TryGetValue(included_full_path.ToString(), out info); // skips inclusion if script has already been included and inclusion's type is "once": if (already_included) { if(once) return ScriptModule.SkippedIncludeReturnValue; // script type loaded, info cannot be null } else { PhpSourceFile included_source_file = new PhpSourceFile(app_config.Compiler.SourceRoot, included_full_path); // loads script type: info = LoadDynamicScriptType(included_source_file); // script not found: if (info == null) return false; if (MainScriptFile == null) // the first script becomes the main one: DefineMainScript(info, included_source_file); else // adds included file into the script list scripts.Add(included_full_path.ToString(), info); } Debug.Assert(info != null); return GuardedCall((ScriptInfo scriptInfo) => { //return PhpScript.InvokeMainHelper( // (Type)scriptType, return scriptInfo.Main( this, null, // no local variables null, // no object context null, // no class context true); }, info, true); }
public abstract Type GetScriptType(PhpSourceFile sourceFile);
/// <summary> /// Loads a script type dynamically. /// </summary> /// <param name="sourceFile">Script's source file.</param> private ScriptInfo LoadDynamicScriptType(PhpSourceFile/*!*/ sourceFile) { Debug.WriteLine("SC", "LoadDynamicScriptType: '{0}'", sourceFile); // runtime compiler manages: // - 1. script library // - 2. optionally bin/WebPages.dll // - 3. compiles file from file system if allowed return this.ApplicationContext.RuntimeCompilerManager.GetCompiledScript(sourceFile, RequestContext.CurrentContext); }
public static PhpAssemblyBuilder/*!*/ Create(ApplicationContext/*!*/ applicationContext, AssemblyKinds kind, bool pure, FullPath outPath, FullPath docPath, string duckPath, string duckNs, PhpSourceFile entryPoint, Version version, StrongNameKeyPair key, Win32IconResource icon, ICollection<ResourceFileReference> resources, bool debug) { string out_dir = Path.GetDirectoryName(outPath); string out_file = Path.GetFileName(outPath); AssemblyName assembly_name = new AssemblyName(); assembly_name.Name = Path.GetFileNameWithoutExtension(outPath); assembly_name.Version = version; assembly_name.KeyPair = key; if (pure) { // This is primarilly supported for non-pure mode, but it could be extended.. if (duckPath != null) throw new NotSupportedException("Generation of duck type interfaces isn't supported for pure assemblies!"); return new PureAssemblyBuilder(applicationContext, assembly_name, out_dir, out_file, kind, resources, debug, icon); } else return new MultiScriptAssemblyBuilder(applicationContext, assembly_name, out_dir, out_file, duckPath, duckNs, kind, resources, debug, icon, entryPoint); }