ScriptEnvironment.java revision 1088:7e62d98d4625
1/*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.nashorn.internal.runtime;
27
28import java.io.PrintWriter;
29import java.util.HashMap;
30import java.util.List;
31import java.util.Locale;
32import java.util.Map;
33import java.util.StringTokenizer;
34import java.util.TimeZone;
35import java.util.logging.Level;
36import jdk.nashorn.internal.codegen.Namespace;
37import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
38import jdk.nashorn.internal.runtime.options.KeyValueOption;
39import jdk.nashorn.internal.runtime.options.LoggingOption;
40import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
41import jdk.nashorn.internal.runtime.options.Option;
42import jdk.nashorn.internal.runtime.options.Options;
43
44/**
45 * Script environment consists of command line options, arguments, script files
46 * and output and error writers, top level Namespace etc.
47 */
48public final class ScriptEnvironment {
49    /** Output writer for this environment */
50    private final PrintWriter out;
51
52    /** Error writer for this environment */
53    private final PrintWriter err;
54
55    /** Top level namespace. */
56    private final Namespace namespace;
57
58    /** Current Options object. */
59    private final Options options;
60
61    /** Size of the per-global Class cache size */
62    public final int     _class_cache_size;
63
64    /** Only compile script, do not run it or generate other ScriptObjects */
65    public final boolean _compile_only;
66
67    /** Accept "const" keyword and treat it as variable. Interim feature */
68    public final boolean _const_as_var;
69
70    /** Accumulated callsite flags that will be used when bootstrapping script callsites */
71    public final int     _callsite_flags;
72
73    /** Generate line number table in class files */
74    public final boolean _debug_lines;
75
76    /** Package to which generated class files are added */
77    public final String  _dest_dir;
78
79    /** Display stack trace upon error, default is false */
80    public final boolean _dump_on_error;
81
82    /** Invalid lvalue expressions should be reported as early errors */
83    public final boolean _early_lvalue_error;
84
85    /** Empty statements should be preserved in the AST */
86    public final boolean _empty_statements;
87
88    /** Show full Nashorn version */
89    public final boolean _fullversion;
90
91    /** Launch using as fx application */
92    public final boolean _fx;
93
94    /** Use single Global instance per jsr223 engine instance. */
95    public final boolean _global_per_engine;
96
97    /** Enable experimental ECMAScript 6 features. */
98    public final boolean _es6;
99
100    /** Argument passed to compile only if optimistic compilation should take place */
101    public static final String COMPILE_ONLY_OPTIMISTIC_ARG = "optimistic";
102
103    /**
104     *  Behavior when encountering a function declaration in a lexical context where only statements are acceptable
105     * (function declarations are source elements, but not statements).
106     */
107    public enum FunctionStatementBehavior {
108        /**
109         * Accept the function declaration silently and treat it as if it were a function expression assigned to a local
110         * variable.
111         */
112        ACCEPT,
113        /**
114         * Log a parser warning, but accept the function declaration and treat it as if it were a function expression
115         * assigned to a local variable.
116         */
117        WARNING,
118        /**
119         * Raise a {@code SyntaxError}.
120         */
121        ERROR
122    }
123
124    /**
125     * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
126     * (function declarations are source elements, but not statements).
127     */
128    public final FunctionStatementBehavior _function_statement;
129
130    /** Should lazy compilation take place */
131    public final boolean _lazy_compilation;
132
133    /** Should optimistic types be used */
134    public final boolean _optimistic_types;
135
136    /** Create a new class loaded for each compilation */
137    public final boolean _loader_per_compile;
138
139    /** Do not support Java support extensions. */
140    public final boolean _no_java;
141
142    /** Do not support non-standard syntax extensions. */
143    public final boolean _no_syntax_extensions;
144
145    /** Do not support typed arrays. */
146    public final boolean _no_typed_arrays;
147
148    /** Only parse the source code, do not compile */
149    public final boolean _parse_only;
150
151    /** Enable disk cache for compiled scripts */
152    public final boolean _persistent_cache;
153
154    /** Print the AST before lowering */
155    public final boolean _print_ast;
156
157    /** Print the AST after lowering */
158    public final boolean _print_lower_ast;
159
160    /** Print resulting bytecode for script */
161    public final boolean _print_code;
162
163    /** Directory (optional) to print files to */
164    public final String _print_code_dir;
165
166    /** List of functions to write to the print code dir, optional */
167    public final String _print_code_func;
168
169    /** Print memory usage for IR after each phase */
170    public final boolean _print_mem_usage;
171
172    /** Print function will no print newline characters */
173    public final boolean _print_no_newline;
174
175    /** Print AST in more human readable form */
176    public final boolean _print_parse;
177
178    /** Print AST in more human readable form after Lowering */
179    public final boolean _print_lower_parse;
180
181    /** print symbols and their contents for the script */
182    public final boolean _print_symbols;
183
184    /** is this environment in scripting mode? */
185    public final boolean _scripting;
186
187    /** is this environment in strict mode? */
188    public final boolean _strict;
189
190    /** print version info of Nashorn */
191    public final boolean _version;
192
193    /** should code verification be done of generated bytecode */
194    public final boolean _verify_code;
195
196    /** time zone for this environment */
197    public final TimeZone _timezone;
198
199    /** Local for error messages */
200    public final Locale _locale;
201
202    /** Logging */
203    public final Map<String, LoggerInfo> _loggers;
204
205    /** Timing */
206    public final Timing _timing;
207
208    /**
209     * Constructor
210     *
211     * @param options a Options object
212     * @param out output print writer
213     * @param err error print writer
214     */
215    @SuppressWarnings("unused")
216    public ScriptEnvironment(final Options options, final PrintWriter out, final PrintWriter err) {
217        this.out = out;
218        this.err = err;
219        this.namespace = new Namespace();
220        this.options = options;
221
222        _class_cache_size     = options.getInteger("class.cache.size");
223        _compile_only         = options.getBoolean("compile.only");
224        _const_as_var         = options.getBoolean("const.as.var");
225        _debug_lines          = options.getBoolean("debug.lines");
226        _dest_dir             = options.getString("d");
227        _dump_on_error        = options.getBoolean("doe");
228        _early_lvalue_error   = options.getBoolean("early.lvalue.error");
229        _empty_statements     = options.getBoolean("empty.statements");
230        _fullversion          = options.getBoolean("fullversion");
231        if (options.getBoolean("function.statement.error")) {
232            _function_statement = FunctionStatementBehavior.ERROR;
233        } else if (options.getBoolean("function.statement.warning")) {
234            _function_statement = FunctionStatementBehavior.WARNING;
235        } else {
236            _function_statement = FunctionStatementBehavior.ACCEPT;
237        }
238        _fx                   = options.getBoolean("fx");
239        _global_per_engine    = options.getBoolean("global.per.engine");
240        _lazy_compilation     = options.getBoolean("lazy.compilation");
241        _optimistic_types     = options.getBoolean("optimistic.types");
242        _loader_per_compile   = options.getBoolean("loader.per.compile");
243        _no_java              = options.getBoolean("no.java");
244        _no_syntax_extensions = options.getBoolean("no.syntax.extensions");
245        _no_typed_arrays      = options.getBoolean("no.typed.arrays");
246        _parse_only           = options.getBoolean("parse.only");
247        _persistent_cache     = options.getBoolean("persistent.code.cache");
248        _print_ast            = options.getBoolean("print.ast");
249        _print_lower_ast      = options.getBoolean("print.lower.ast");
250        _print_code           = options.getString("print.code") != null;
251        _print_mem_usage      = options.getBoolean("print.mem.usage");
252        _print_no_newline     = options.getBoolean("print.no.newline");
253        _print_parse          = options.getBoolean("print.parse");
254        _print_lower_parse    = options.getBoolean("print.lower.parse");
255        _print_symbols        = options.getBoolean("print.symbols");
256        _scripting            = options.getBoolean("scripting");
257        _strict               = options.getBoolean("strict");
258        _version              = options.getBoolean("version");
259        _verify_code          = options.getBoolean("verify.code");
260
261        final String language = options.getString("language");
262        if (language == null || language.equals("es5")) {
263            _es6 = false;
264        } else if (language.equals("es6")) {
265            _es6 = true;
266        } else {
267            throw new RuntimeException("Unsupported language: " + language);
268        }
269
270        String dir = null;
271        String func = null;
272        final String pc = options.getString("print.code");
273        if (pc != null) {
274            final StringTokenizer st = new StringTokenizer(pc, ",");
275            while (st.hasMoreTokens()) {
276                final StringTokenizer st2 = new StringTokenizer(st.nextToken(), ":");
277                while (st2.hasMoreTokens()) {
278                    final String cmd = st2.nextToken();
279                    if ("dir".equals(cmd)) {
280                        dir = st2.nextToken();
281                    } else if ("function".equals(cmd)) {
282                        func = st2.nextToken();
283                    }
284                }
285            }
286        }
287        _print_code_dir = dir;
288        _print_code_func = func;
289
290        int callSiteFlags = 0;
291        if (options.getBoolean("profile.callsites")) {
292            callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_PROFILE;
293        }
294
295        if (options.get("trace.callsites") instanceof KeyValueOption) {
296            callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE;
297            final KeyValueOption kv = (KeyValueOption)options.get("trace.callsites");
298            if (kv.hasValue("miss")) {
299                callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES;
300            }
301            if (kv.hasValue("enterexit") || (callSiteFlags & NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES) == 0) {
302                callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT;
303            }
304            if (kv.hasValue("objects")) {
305                callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
306            }
307        }
308        this._callsite_flags = callSiteFlags;
309
310        final Option<?> timezoneOption = options.get("timezone");
311        if (timezoneOption != null) {
312            this._timezone = (TimeZone)timezoneOption.getValue();
313        } else {
314            this._timezone  = TimeZone.getDefault();
315        }
316
317        final Option<?> localeOption = options.get("locale");
318        if (localeOption != null) {
319            this._locale = (Locale)localeOption.getValue();
320        } else {
321            this._locale = Locale.getDefault();
322        }
323
324        final LoggingOption loggingOption = (LoggingOption)options.get("log");
325        this._loggers = loggingOption == null ? new HashMap<String, LoggerInfo>() : loggingOption.getLoggers();
326
327        final LoggerInfo timeLoggerInfo = _loggers.get(Timing.getLoggerName());
328        this._timing = new Timing(timeLoggerInfo != null && timeLoggerInfo.getLevel() != Level.OFF);
329    }
330
331    /**
332     * Get the output stream for this environment
333     * @return output print writer
334     */
335    public PrintWriter getOut() {
336        return out;
337    }
338
339    /**
340     * Get the error stream for this environment
341     * @return error print writer
342     */
343    public PrintWriter getErr() {
344        return err;
345    }
346
347    /**
348     * Get the namespace for this environment
349     * @return namespace
350     */
351    public Namespace getNamespace() {
352        return namespace;
353    }
354
355    /**
356     * Return the JavaScript files passed to the program
357     *
358     * @return a list of files
359     */
360    public List<String> getFiles() {
361        return options.getFiles();
362    }
363
364    /**
365     * Return the user arguments to the program, i.e. those trailing "--" after
366     * the filename
367     *
368     * @return a list of user arguments
369     */
370    public List<String> getArguments() {
371        return options.getArguments();
372    }
373
374    /**
375     * Check if there is a logger registered for a particular name: typically
376     * the "name" attribute of a Loggable annotation on a class
377     *
378     * @param name logger name
379     * @return true, if a logger exists for that name, false otherwise
380     */
381    public boolean hasLogger(final String name) {
382        return _loggers.get(name) != null;
383    }
384
385    /**
386     * Check if compilation/runtime timings are enabled
387     * @return true if enabled
388     */
389    public boolean isTimingEnabled() {
390        return _timing != null ? _timing.isEnabled() : false;
391    }
392
393}
394