/** * Construct a parser. * * @param env script environment * @param source source to parse * @param errors error manager * @param strict parser created with strict mode enabled. * @param lineOffset line offset to start counting lines from * @param log debug logger if one is needed */ public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) { super(source, errors, strict, lineOffset); this.env = env; this.namespace = new Namespace(env.getNamespace()); this.scripting = env._scripting; if (this.scripting) { this.lineInfoReceiver = new Lexer.LineInfoReceiver() { @Override public void lineInfo(final int receiverLine, final int receiverLinePosition) { // update the parser maintained line information Parser.this.line = receiverLine; Parser.this.linePosition = receiverLinePosition; } }; } else { // non-scripting mode script can't have multi-line literals this.lineInfoReceiver = null; } this.log = log == null ? DebugLogger.DISABLED_LOGGER : log; }
/** * Construct a parser. * * @param env script environment * @param source source to parse * @param errors error manager * @param strict parser created with strict mode enabled. * @param lineOffset line offset to start counting lines from * @param log debug logger if one is needed */ public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) { super(source, errors, strict, lineOffset); this.lc = new ParserContext(); this.defaultNames = new ArrayDeque<>(); this.env = env; this.namespace = new Namespace(env.getNamespace()); this.scripting = env._scripting; if (this.scripting) { this.lineInfoReceiver = new Lexer.LineInfoReceiver() { @Override public void lineInfo(final int receiverLine, final int receiverLinePosition) { // update the parser maintained line information Parser.this.line = receiverLine; Parser.this.linePosition = receiverLinePosition; } }; } else { // non-scripting mode script can't have multi-line literals this.lineInfoReceiver = null; } this.log = log == null ? DebugLogger.DISABLED_LOGGER : log; }
@Test public void evalTest() { final Options options = new Options(""); final ErrorManager errors = new ErrorManager(); final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader()); final Global oldGlobal = Context.getGlobal(); Context.setGlobal(cx.createGlobal()); try { String code = "22 + 10"; assertTrue(32.0 == ((Number)(eval(cx, "<evalTest>", code))).doubleValue()); code = "obj = { js: 'nashorn' }; obj.js"; assertEquals(eval(cx, "<evalTest2>", code), "nashorn"); } finally { Context.setGlobal(oldGlobal); } }
@Test public void compileErrorTest() { final Options options = new Options(""); final ErrorManager errors = new ErrorManager(); final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader()); final Global oldGlobal = Context.getGlobal(); Context.setGlobal(cx.createGlobal()); try { final ScriptFunction script = cx.compileScript(sourceFor("<evalCompileErrorTest>", "*/"), Context.getGlobal()); if (script != null) { fail("Invalid script compiled without errors"); } if (errors.getNumberOfErrors() != 1) { fail("Wrong number of errors: " + errors.getNumberOfErrors()); } } finally { Context.setGlobal(oldGlobal); } }
@BeforeClass public void setupTest() { final Options options = new Options("nashorn"); options.set("compile.only", true); options.set("print.ast", true); options.set("print.parse", true); options.set("scripting", true); options.set("const.as.var", true); options.set("verify.code", true); final ErrorManager errors = new ErrorManager() { @Override public void error(final String msg) { log(msg); } }; final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); this.context = new Context(options, errors, pw, pw, Thread.currentThread().getContextClassLoader()); this.global = context.createGlobal(); }
@BeforeClass public void setupTest() { final Options options = new Options("nashorn"); options.set("anon.functions", true); options.set("compile.only", true); options.set("print.ast", true); options.set("print.parse", true); options.set("scripting", true); options.set("const.as.var", true); options.set("verify.code", true); final ErrorManager errors = new ErrorManager() { @Override public void error(final String msg) { log(msg); } }; final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); this.context = new Context(options, errors, pw, pw, Thread.currentThread().getContextClassLoader()); this.global = context.createGlobal(); }
/** * Constructor. * * @throws LanguageAdapterException * In case of an initialization error */ public NashornAdapter() throws LanguageAdapterException { super( "Nashorn", Version.version(), "JavaScript", new NashornScriptEngineFactory().getLanguageVersion(), Arrays.asList( "js", "javascript", "nashorn" ), "js", Arrays.asList( "javascript", "js", "nashorn" ), "nashorn" ); try { System.setProperty( "nashorn.persistent.code.cache", getCacheDir().getCanonicalPath() ); } catch( IOException x ) { throw new LanguageAdapterException( NashornAdapter.class, "Could not access cache directory: " + getCacheDir(), x ); } PrintWriter out = new PrintWriter( new ExecutionContextWriter(), true ); PrintWriter err = new PrintWriter( new ExecutionContextErrorWriter(), true ); // See: jdk.nashorn.internal.runtime.ScriptEnvironment Options options = new Options( "nashorn", err ); options.set( "print.no.newline", true ); options.set( "persistent.code.cache", true ); ErrorManager errors = new ErrorManager( err ); context = new Context( options, errors, out, err, getClass().getClassLoader() ); }
/** * Construct a parser. * * @param env script environment * @param source source to parse * @param errors error manager * @param strict parser created with strict mode enabled. */ public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict) { super(source, errors, strict); this.env = env; this.namespace = new Namespace(env.getNamespace()); this.scripting = env._scripting; if (this.scripting) { this.lineInfoReceiver = new Lexer.LineInfoReceiver() { @Override public void lineInfo(final int receiverLine, final int receiverLinePosition) { // update the parser maintained line information Parser.this.line = receiverLine; Parser.this.linePosition = receiverLinePosition; } }; } else { // non-scripting mode script can't have multi-line literals this.lineInfoReceiver = null; } }
@BeforeClass public void setupTest() { final Options options = new Options("nashorn"); options.set("anon.functions", true); options.set("compile.only", true); options.set("print.ast", true); options.set("print.parse", true); options.set("scripting", true); final ErrorManager errors = new ErrorManager() { @Override public void error(final String msg) { log(msg); } }; final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); this.context = new Context(options, errors, pw, pw, Thread.currentThread().getContextClassLoader()); this.global = context.createGlobal(); }
/** * Construct a parser. * * @param source Source to parse. * @param errors Error reporting manager. * @param strict True if we are in strict mode * @param lineOffset Offset from which lines should be counted */ protected AbstractParser(final Source source, final ErrorManager errors, final boolean strict, final int lineOffset) { this.source = source; this.errors = errors; this.k = -1; this.token = Token.toDesc(EOL, 0, 1); this.type = EOL; this.last = EOL; this.isStrictMode = strict; this.lineOffset = lineOffset; }
/** * Report an error. * * @param errorType The error type * @param message Error message. * @return ParserException upon failure. Caller should throw and not ignore */ protected final ParserException error(final JSErrorType errorType, final String message) { // TODO - column needs to account for tabs. final int position = Token.descPosition(token); final int column = position - linePosition; final String formatted = ErrorManager.format(message, source, line, column, token); return new ParserException(errorType, formatted, source, line, column, token); }
private void throwParserException(final String message, final Node origin) { if (origin == null) { throw new ParserException(message); } final Source source = compiler.getSource(); final long token = origin.getToken(); final int line = source.getLine(origin.getStart()); final int column = source.getColumn(origin.getStart()); final String formatted = ErrorManager.format(message, source, line, column, token); throw new ParserException(JSErrorType.SYNTAX_ERROR, formatted, source, line, column, token); }
/** * Constructor * * @param context context * @param env script environment * @param installer code installer * @param source source to compile * @param errors error manager * @param isStrict is this a strict compilation * @param isOnDemand is this an on demand compilation * @param compiledFunction compiled function, if any * @param types parameter and return value type information, if any is known * @param invalidatedProgramPoints invalidated program points for recompilation * @param typeInformationFile descriptor of the location where type information is persisted * @param continuationEntryPoints continuation entry points for restof method * @param runtimeScope runtime scope for recompilation type lookup in {@code TypeEvaluator} */ @SuppressWarnings("unused") public Compiler( final Context context, final ScriptEnvironment env, final CodeInstaller<ScriptEnvironment> installer, final Source source, final ErrorManager errors, final boolean isStrict, final boolean isOnDemand, final RecompilableScriptFunctionData compiledFunction, final TypeMap types, final Map<Integer, Type> invalidatedProgramPoints, final Object typeInformationFile, final int[] continuationEntryPoints, final ScriptObject runtimeScope) { this.context = context; this.env = env; this.installer = installer; this.constantData = new ConstantData(); this.compileUnits = CompileUnit.createCompileUnitSet(); this.bytecode = new LinkedHashMap<>(); this.log = initLogger(context); this.source = source; this.errors = errors; this.sourceName = FunctionNode.getSourceName(source); this.onDemand = isOnDemand; this.compiledFunction = compiledFunction; this.types = types; this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new HashMap<Integer, Type>() : invalidatedProgramPoints; this.typeInformationFile = typeInformationFile; this.continuationEntryPoints = continuationEntryPoints == null ? null: continuationEntryPoints.clone(); this.typeEvaluator = new TypeEvaluator(this, runtimeScope); this.firstCompileUnitName = firstCompileUnitName(); this.strict = isStrict; this.optimistic = env._optimistic_types; }
/** * Construct a parser. * * @param source Source to parse. * @param errors Error reporting manager. * @param strict True if we are in strict mode * @param lineOffset Offset from which lines should be counted */ protected AbstractParser(final Source source, final ErrorManager errors, final boolean strict, final int lineOffset) { if (source.getLength() > Token.LENGTH_MASK) { throw new RuntimeException("Source exceeds size limit of " + Token.LENGTH_MASK + " bytes"); } this.source = source; this.errors = errors; this.k = -1; this.token = Token.toDesc(EOL, 0, 1); this.type = EOL; this.last = EOL; this.isStrictMode = strict; this.lineOffset = lineOffset; }
ParserException error(final String message, final int start, final int length) throws ParserException { final long token = Token.toDesc(STRING, start, length); final int pos = Token.descPosition(token); final Source src = Source.sourceFor("<json>", source); final int lineNum = src.getLine(pos); final int columnNum = src.getColumn(pos); final String formatted = ErrorManager.format(message, src, lineNum, columnNum, token); return new ParserException(JSErrorType.SYNTAX_ERROR, formatted, src, lineNum, columnNum, token); }
private void throwNotImplementedYet(final String msgId, final Node node) { final long token = node.getToken(); final int line = source.getLine(node.getStart()); final int column = source.getColumn(node.getStart()); final String message = ECMAErrors.getMessage("unimplemented." + msgId); final String formatted = ErrorManager.format(message, source, line, column, token); throw new RuntimeException(formatted); }
/** * Convenience constructor for non on-demand compiler instances. */ private Compiler( final Context context, final CodeInstaller installer, final Source source, final ErrorManager errors, final boolean isStrict) { this(context, installer, source, errors, isStrict, false, null, null, null, null, null, null); }
private Compiler( final Context context, final CodeInstaller installer, final Source source, final ErrorManager errors, final boolean isStrict, final boolean isOnDemand, final RecompilableScriptFunctionData compiledFunction, final TypeMap types, final Map<Integer, Type> invalidatedProgramPoints, final Object typeInformationFile, final int[] continuationEntryPoints, final ScriptObject runtimeScope) { this.context = context; this.env = context.getEnv(); this.installer = installer; this.constantData = new ConstantData(); this.compileUnits = CompileUnit.createCompileUnitSet(); this.bytecode = new LinkedHashMap<>(); this.log = initLogger(context); this.source = source; this.errors = errors; this.sourceName = FunctionNode.getSourceName(source); this.onDemand = isOnDemand; this.compiledFunction = compiledFunction; this.types = types; this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new HashMap<>() : invalidatedProgramPoints; this.typeInformationFile = typeInformationFile; this.continuationEntryPoints = continuationEntryPoints == null ? null: continuationEntryPoints.clone(); this.typeEvaluator = new TypeEvaluator(this, runtimeScope); this.firstCompileUnitName = firstCompileUnitName(); this.strict = isStrict; this.optimistic = env._optimistic_types; }