private object CompileImpl(IScriptable scope, StreamReader sourceReader, string sourceString, string sourceName, int lineno, object securityDomain, bool returnFunction, Interpreter compiler, ErrorReporter compilationErrorReporter) { if (securityDomain != null && securityController == 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)) Context.CodeBug (); // scope should be given if and only if compiling function if (!(scope == null ^ returnFunction)) Context.CodeBug (); CompilerEnvirons compilerEnv = new CompilerEnvirons (); compilerEnv.initFromContext (this); if (compilationErrorReporter == null) { compilationErrorReporter = compilerEnv.getErrorReporter (); } if (m_Debugger != null) { if (sourceReader != null) { sourceString = sourceReader.ReadToEnd (); sourceReader = null; } } Parser p = new Parser (compilerEnv, compilationErrorReporter); if (returnFunction) { p.calledByCompileFunction = true; } ScriptOrFnNode tree; if (sourceString != null) { tree = p.Parse (sourceString, sourceName, lineno); } else { tree = p.Parse (sourceReader, sourceName, lineno); } if (returnFunction) { if (!(tree.FunctionCount == 1 && tree.FirstChild != null && tree.FirstChild.Type == Token.FUNCTION)) { // TODO: the check just look for the first child // TODO: and allows for more nodes after it for compatibility // TODO: with sources like function() {};;; throw new ArgumentException ("compileFunction only accepts source with single JS function: " + sourceString); } } if (compiler == null) { compiler = new Interpreter (); //compiler = new Compiler(); } string encodedSource = p.EncodedSource; object bytecode = compiler.Compile (compilerEnv, tree, encodedSource, returnFunction); if (m_Debugger != null) { if (sourceString == null) Context.CodeBug (); if (bytecode is DebuggableScript) { DebuggableScript dscript = (DebuggableScript)bytecode; NotifyDebugger (this, dscript, sourceString); } else { throw new ApplicationException ("NOT SUPPORTED"); } } object result; if (returnFunction) { result = compiler.CreateFunctionObject (this, scope, bytecode, securityDomain); } else { result = compiler.CreateScriptObject (bytecode, securityDomain); } return result; }
private static ArrayList Parse(StreamReader stream, ErrorReporter reporter) { var compilerEnvirons = new CompilerEnvirons(); var parser = new Parser(compilerEnvirons, reporter); parser.Parse(stream, null, 1); string source = parser.EncodedSource; int offset = 0; int length = source.Length; var tokens = new ArrayList(); var stringBuilder = new StringBuilder(); while (offset < length) { int tt = source[offset++]; switch (tt) { case Token.CONDCOMMENT: case Token.KEEPCOMMENT: case Token.NAME: case Token.REGEXP: case Token.STRING: stringBuilder.Length = 0; offset = PrintSourceString(source, offset, stringBuilder); tokens.Add(new JavaScriptToken(tt, stringBuilder.ToString())); break; case Token.NUMBER: stringBuilder.Length = 0; offset = PrintSourceNumber(source, offset, stringBuilder); tokens.Add(new JavaScriptToken(tt, stringBuilder.ToString())); break; default: var literal = (string) Literals[tt]; if (literal != null) { tokens.Add(new JavaScriptToken(tt, literal)); } break; } } return tokens; }
/// <summary> Check whether a string is ready to be compiled. /// <p> /// stringIsCompilableUnit is intended to support interactive compilation of /// javascript. If compiling the string would result in an error /// that might be fixed by appending more source, this method /// returns false. In every other case, it returns true. /// <p> /// Interactive shells may accumulate source lines, using this /// method after each new line is appended to check whether the /// statement being entered is complete. /// /// </summary> /// <param name="source">the source buffer to check /// </param> /// <returns> whether the source is ready for compilation /// </returns> public ScriptOrFnNode IsCompilableUnit(string source) { ScriptOrFnNode ret = null; bool errorseen = false; CompilerEnvirons compilerEnv = new CompilerEnvirons (); compilerEnv.initFromContext (this); // no source name or source text manager, because we're just // going to throw away the result. compilerEnv.setGeneratingSource (false); Parser p = new Parser (compilerEnv, DefaultErrorReporter.instance); try { ret = p.Parse (source, null, 1); } catch (EcmaScriptRuntimeException) { errorseen = true; } // Return false only if an error occurred as a result of reading past // the end of the file, i.e. if the source could be fixed by // appending more source. if (!(errorseen && p.Eof)) return ret; return null; }