/// <summary> /// Compiles /// <code>source</code> /// and returns the transformed and optimized /// <see cref="Rhino.Ast.ScriptNode">Rhino.Ast.ScriptNode</see> /// </summary> protected internal virtual ScriptNode Compile(CharSequence source) { string mainMethodClassName = "Main"; string scriptClassName = "Main"; CompilerEnvirons compilerEnv = new CompilerEnvirons(); compilerEnv.InitFromContext(cx); ErrorReporter compilationErrorReporter = compilerEnv.GetErrorReporter(); Parser p = new Parser(compilerEnv, compilationErrorReporter); AstRoot ast = p.Parse(source.ToString(), "<eval>", 1); IRFactory irf = new IRFactory(compilerEnv); ScriptNode tree = irf.TransformTree(ast); Codegen codegen = new Codegen(); codegen.SetMainMethodClass(mainMethodClassName); codegen.CompileToClassFile(compilerEnv, scriptClassName, tree, tree.GetEncodedSource(), false); return tree; }
/// <exception cref="System.IO.IOException"></exception> private object CompileImpl(Scriptable scope, TextReader sourceReader, string sourceString, string sourceName, int lineno, object securityDomain, bool returnFunction, Evaluator compiler, ErrorReporter compilationErrorReporter) { if (sourceName == null) { sourceName = "unnamed script"; } if (securityDomain != null && GetSecurityController() == null) { throw new ArgumentException("securityDomain should be null if setSecurityController() was never called"); } // One of sourceReader or sourceString has to be null if (!(sourceReader == null ^ sourceString == null)) { Kit.CodeBug(); } // scope should be given if and only if compiling function if (!(scope == null ^ returnFunction)) { Kit.CodeBug(); } CompilerEnvirons compilerEnv = new CompilerEnvirons(); compilerEnv.InitFromContext(this); if (compilationErrorReporter == null) { compilationErrorReporter = compilerEnv.GetErrorReporter(); } if (debugger != null) { if (sourceReader != null) { sourceString = Kit.ReadReader(sourceReader); sourceReader = null; } } Parser p = new Parser(compilerEnv, compilationErrorReporter); if (returnFunction) { p.calledByCompileFunction = true; } AstRoot ast; if (sourceString != null) { ast = p.Parse(sourceString, sourceName, lineno); } else { ast = p.Parse(sourceReader, sourceName, lineno); } if (returnFunction) { // parser no longer adds function to script node if (!(ast.GetFirstChild() != null && ast.GetFirstChild().GetType() == Token.FUNCTION)) { // XXX: the check just looks for the first child // and allows for more nodes after it for compatibility // with sources like function() {};;; throw new ArgumentException("compileFunction only accepts source with single JS function: " + sourceString); } } IRFactory irf = new IRFactory(compilerEnv, compilationErrorReporter); ScriptNode tree = irf.TransformTree(ast); // discard everything but the IR tree p = null; ast = null; irf = null; if (compiler == null) { compiler = CreateCompiler(); } object bytecode = compiler.Compile(compilerEnv, tree, tree.GetEncodedSource(), returnFunction); if (debugger != null) { if (sourceString == null) { Kit.CodeBug(); } if (bytecode is DebuggableScript) { DebuggableScript dscript = (DebuggableScript)bytecode; NotifyDebugger_r(this, dscript, sourceString); } else { throw new Exception("NOT SUPPORTED"); } } object result; if (returnFunction) { result = compiler.CreateFunctionObject(this, scope, bytecode, securityDomain); } else { result = compiler.CreateScriptObject(bytecode, securityDomain); } return result; }
/// <summary>Compile JavaScript source into one or more Java class files.</summary> /// <remarks> /// Compile JavaScript source into one or more Java class files. /// The first compiled class will have name mainClassName. /// If the results of /// <see cref="GetTargetExtends()">GetTargetExtends()</see> /// or /// <see cref="GetTargetImplements()">GetTargetImplements()</see> /// are not null, then the first compiled /// class will extend the specified super class and implement /// specified interfaces. /// </remarks> /// <returns> /// array where elements with even indexes specifies class name /// and the following odd index gives class file body as byte[] /// array. The initial element of the array always holds /// mainClassName and array[1] holds its byte code. /// </returns> public virtual object[] CompileToClassFiles(string source, string sourceLocation, int lineno, string mainClassName) { Parser p = new Parser(compilerEnv); AstRoot ast = p.Parse(source, sourceLocation, lineno); IRFactory irf = new IRFactory(compilerEnv); ScriptNode tree = irf.TransformTree(ast); // release reference to original parse tree & parser irf = null; ast = null; p = null; Type superClass = GetTargetExtends(); Type[] interfaces = GetTargetImplements(); string scriptClassName; bool isPrimary = (interfaces == null && superClass == null); if (isPrimary) { scriptClassName = mainClassName; } else { scriptClassName = MakeAuxiliaryClassName(mainClassName, "1"); } Codegen codegen = new Codegen(); codegen.SetMainMethodClass(mainMethodClassName); byte[] scriptClassBytes = codegen.CompileToClassFile(compilerEnv, scriptClassName, tree, tree.GetEncodedSource(), false); if (isPrimary) { return new object[] { scriptClassName, scriptClassBytes }; } int functionCount = tree.GetFunctionCount(); ObjToIntMap functionNames = new ObjToIntMap(functionCount); for (int i = 0; i != functionCount; ++i) { FunctionNode ofn = tree.GetFunctionNode(i); string name = ofn.GetName(); if (name != null && name.Length != 0) { functionNames.Put(name, ofn.GetParamCount()); } } if (superClass == null) { superClass = ScriptRuntime.ObjectClass; } byte[] mainClassBytes = JavaAdapter.CreateAdapterCode(functionNames, mainClassName, superClass, interfaces, scriptClassName); return new object[] { mainClassName, mainClassBytes, scriptClassName, scriptClassBytes }; }