139
140 @Override
141 public void verify(final byte[] code) {
142 context.verify(code);
143 }
144
145 @Override
146 public long getUniqueScriptId() {
147 return context.getUniqueScriptId();
148 }
149
150 @Override
151 public long getUniqueEvalId() {
152 return context.getUniqueEvalId();
153 }
154 }
155
156 /** Is Context global debug mode enabled ? */
157 public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
158
159 private static final ThreadLocal<ScriptObject> currentGlobal = new ThreadLocal<>();
160
161 // class cache
162 private ClassCache classCache;
163
164 /**
165 * Get the current global scope
166 * @return the current global scope
167 */
168 public static ScriptObject getGlobal() {
169 // This class in a package.access protected package.
170 // Trusted code only can call this method.
171 return getGlobalTrusted();
172 }
173
174 /**
175 * Set the current global scope
176 * @param global the global scope
177 */
178 public static void setGlobal(final ScriptObject global) {
179 if (global != null && !(global instanceof Global)) {
180 throw new IllegalArgumentException("global is not an instance of Global!");
181 }
182
183 setGlobalTrusted(global);
184 }
185
186 /**
187 * Get context of the current global
188 * @return current global scope's context.
189 */
190 public static Context getContext() {
191 final SecurityManager sm = System.getSecurityManager();
192 if (sm != null) {
193 sm.checkPermission(new RuntimePermission(NASHORN_GET_CONTEXT));
194 }
195 return getContextTrusted();
196 }
197
198 /**
199 * Get current context's error writer
200 *
201 * @return error writer of the current context
202 */
203 public static PrintWriter getCurrentErr() {
204 final ScriptObject global = getGlobalTrusted();
205 return (global != null)? global.getContext().getErr() : new PrintWriter(System.err);
206 }
207
208 /**
209 * Output text to this Context's error stream
210 * @param str text to write
211 */
212 public static void err(final String str) {
213 err(str, true);
214 }
215
216 /**
217 * Output text to this Context's error stream, optionally with
218 * a newline afterwards
219 *
220 * @param str text to write
221 * @param crlf write a carriage return/new line after text
222 */
223 @SuppressWarnings("resource")
224 public static void err(final String str, final boolean crlf) {
389 * Get the output stream for this context
390 * @return output print writer
391 */
392 public PrintWriter getOut() {
393 return env.getOut();
394 }
395
396 /**
397 * Get the error stream for this context
398 * @return error print writer
399 */
400 public PrintWriter getErr() {
401 return env.getErr();
402 }
403
404 /**
405 * Get the PropertyMap of the current global scope
406 * @return the property map of the current global scope
407 */
408 public static PropertyMap getGlobalMap() {
409 return Context.getGlobalTrusted().getMap();
410 }
411
412 /**
413 * Compile a top level script.
414 *
415 * @param source the source
416 * @param scope the scope
417 *
418 * @return top level function for script
419 */
420 public ScriptFunction compileScript(final Source source, final ScriptObject scope) {
421 return compileScript(source, scope, this.errors);
422 }
423
424 /**
425 * Entry point for {@code eval}
426 *
427 * @param initialScope The scope of this eval call
428 * @param string Evaluated code as a String
429 * @param callThis "this" to be passed to the evaluated code
430 * @param location location of the eval call
431 * @param strict is this {@code eval} call from a strict mode code?
432 *
433 * @return the return value of the {@code eval}
434 */
435 public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) {
436 final String file = (location == UNDEFINED || location == null) ? "<eval>" : location.toString();
437 final Source source = new Source(file, string);
438 final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval?
439 final ScriptObject global = Context.getGlobalTrusted();
440
441 ScriptObject scope = initialScope;
442
443 // ECMA section 10.1.1 point 2 says eval code is strict if it begins
444 // with "use strict" directive or eval direct call itself is made
445 // from from strict mode code. We are passed with caller's strict mode.
446 boolean strictFlag = directEval && strict;
447
448 Class<?> clazz = null;
449 try {
450 clazz = compile(source, new ThrowErrorManager(), strictFlag);
451 } catch (final ParserException e) {
452 e.throwAsEcmaException(global);
453 return null;
454 }
455
456 if (!strictFlag) {
457 // We need to get strict mode flag from compiled class. This is
458 // because eval code may start with "use strict" directive.
459 try {
460 strictFlag = clazz.getField(STRICT_MODE.symbolName()).getBoolean(null);
461 } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
462 //ignored
463 strictFlag = false;
464 }
465 }
466
467 // In strict mode, eval does not instantiate variables and functions
468 // in the caller's environment. A new environment is created!
469 if (strictFlag) {
470 // Create a new scope object
471 final ScriptObject strictEvalScope = ((GlobalObject)global).newObject();
472
473 // bless it as a "scope"
474 strictEvalScope.setIsScope();
475
476 // set given scope to be it's proto so that eval can still
477 // access caller environment vars in the new environment.
478 strictEvalScope.setProto(scope);
479 scope = strictEvalScope;
480 }
481
482 ScriptFunction func = getRunScriptFunction(clazz, scope);
483 Object evalThis;
484 if (directEval) {
485 evalThis = (callThis instanceof ScriptObject || strictFlag) ? callThis : global;
486 } else {
487 evalThis = global;
488 }
489
490 return ScriptRuntime.apply(func, evalThis);
491 }
576
577 if (source != null) {
578 return evaluateSource(source, scope, scope);
579 }
580
581 throw typeError("cant.load.script", ScriptRuntime.safeToString(from));
582 }
583
584 /**
585 * Implementation of {@code loadWithNewGlobal} Nashorn extension. Load a script file from a source
586 * expression, after creating a new global scope.
587 *
588 * @param from source expression for script
589 * @param args (optional) arguments to be passed to the loaded script
590 *
591 * @return return value for load call (undefined)
592 *
593 * @throws IOException if source cannot be found or loaded
594 */
595 public Object loadWithNewGlobal(final Object from, final Object...args) throws IOException {
596 final ScriptObject oldGlobal = getGlobalTrusted();
597 final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
598 @Override
599 public ScriptObject run() {
600 try {
601 return newGlobal();
602 } catch (final RuntimeException e) {
603 if (Context.DEBUG) {
604 e.printStackTrace();
605 }
606 throw e;
607 }
608 }
609 }, CREATE_GLOBAL_ACC_CTXT);
610 // initialize newly created Global instance
611 initGlobal(newGlobal);
612 setGlobalTrusted(newGlobal);
613
614 final Object[] wrapped = args == null? ScriptRuntime.EMPTY_ARRAY : ScriptObjectMirror.wrapArray(args, oldGlobal);
615 newGlobal.put("arguments", ((GlobalObject)newGlobal).wrapAsObject(wrapped), env._strict);
616
617 try {
618 // wrap objects from newGlobal's world as mirrors - but if result
619 // is from oldGlobal's world, unwrap it!
620 return ScriptObjectMirror.unwrap(ScriptObjectMirror.wrap(load(newGlobal, from), newGlobal), oldGlobal);
621 } finally {
622 setGlobalTrusted(oldGlobal);
623 }
624 }
625
626 /**
627 * Load or get a structure class. Structure class names are based on the number of parameter fields
628 * and {@link AccessorProperty} fields in them. Structure classes are used to represent ScriptObjects
629 *
630 * @see ObjectClassGenerator
631 * @see AccessorProperty
632 * @see ScriptObject
633 *
634 * @param fullName full name of class, e.g. jdk.nashorn.internal.objects.JO2P1 contains 2 fields and 1 parameter.
635 *
636 * @return the {@code Class<?>} for this structure
637 *
638 * @throws ClassNotFoundException if structure class cannot be resolved
639 */
640 public static Class<?> forStructureClass(final String fullName) throws ClassNotFoundException {
641 if (System.getSecurityManager() != null && !StructureLoader.isStructureClass(fullName)) {
642 throw new ClassNotFoundException(fullName);
777 * user specified verify option. We check it here even though caller
778 * may have already checked that flag
779 *
780 * @param bytecode bytecode to verify
781 */
782 public void verify(final byte[] bytecode) {
783 if (env._verify_code) {
784 // No verification when security manager is around as verifier
785 // may load further classes - which should be avoided.
786 if (System.getSecurityManager() == null) {
787 CheckClassAdapter.verify(new ClassReader(bytecode), sharedLoader, false, new PrintWriter(System.err, true));
788 }
789 }
790 }
791
792 /**
793 * Create and initialize a new global scope object.
794 *
795 * @return the initialized global scope object.
796 */
797 public ScriptObject createGlobal() {
798 return initGlobal(newGlobal());
799 }
800
801 /**
802 * Create a new uninitialized global scope object
803 * @return the global script object
804 */
805 public ScriptObject newGlobal() {
806 return new Global(this);
807 }
808
809 /**
810 * Initialize given global scope object.
811 *
812 * @param global the global
813 * @return the initialized global scope object.
814 */
815 public ScriptObject initGlobal(final ScriptObject global) {
816 if (! (global instanceof GlobalObject)) {
817 throw new IllegalArgumentException("not a global object!");
818 }
819
820 // Need only minimal global object, if we are just compiling.
821 if (!env._compile_only) {
822 final ScriptObject oldGlobal = Context.getGlobalTrusted();
823 try {
824 Context.setGlobalTrusted(global);
825 // initialize global scope with builtin global objects
826 ((GlobalObject)global).initBuiltinObjects();
827 } finally {
828 Context.setGlobalTrusted(oldGlobal);
829 }
830 }
831
832 return global;
833 }
834
835 /**
836 * Trusted variants - package-private
837 */
838
839 /**
840 * Return the current global scope
841 * @return current global scope
842 */
843 static ScriptObject getGlobalTrusted() {
844 return currentGlobal.get();
845 }
846
847 /**
848 * Set the current global scope
849 */
850 static void setGlobalTrusted(ScriptObject global) {
851 currentGlobal.set(global);
852 }
853
854 /**
855 * Return the current global's context
856 * @return current global's context
857 */
858 static Context getContextTrusted() {
859 return Context.getGlobalTrusted().getContext();
860 }
861
862 /**
863 * Try to infer Context instance from the Class. If we cannot,
864 * then get it from the thread local variable.
865 *
866 * @param clazz the class
867 * @return context
868 */
869 static Context fromClass(final Class<?> clazz) {
870 final ClassLoader loader = clazz.getClassLoader();
871
872 if (loader instanceof ScriptLoader) {
873 return ((ScriptLoader)loader).getContext();
874 }
875
876 return Context.getContextTrusted();
877 }
878
879 private URL getResourceURL(final String resName) {
908 // Get run method - the entry point to the script
909 final MethodHandle runMethodHandle =
910 MH.findStatic(
911 MethodHandles.lookup(),
912 script,
913 RUN_SCRIPT.symbolName(),
914 MH.type(
915 Object.class,
916 ScriptFunction.class,
917 Object.class));
918
919 boolean strict;
920
921 try {
922 strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null);
923 } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
924 strict = false;
925 }
926
927 // Package as a JavaScript function and pass function back to shell.
928 return ((GlobalObject)Context.getGlobalTrusted()).newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
929 }
930
931 private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
932 return getRunScriptFunction(compile(source, errMan, this._strict), scope);
933 }
934
935 private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
936 // start with no errors, no warnings.
937 errMan.reset();
938
939 Class<?> script = findCachedClass(source);
940 if (script != null) {
941 Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
942 return script;
943 }
944
945 final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
946 if (errors.hasErrors()) {
947 return null;
948 }
|
139
140 @Override
141 public void verify(final byte[] code) {
142 context.verify(code);
143 }
144
145 @Override
146 public long getUniqueScriptId() {
147 return context.getUniqueScriptId();
148 }
149
150 @Override
151 public long getUniqueEvalId() {
152 return context.getUniqueEvalId();
153 }
154 }
155
156 /** Is Context global debug mode enabled ? */
157 public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
158
159 private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>();
160
161 // class cache
162 private ClassCache classCache;
163
164 /**
165 * Get the current global scope
166 * @return the current global scope
167 */
168 public static Global getGlobal() {
169 // This class in a package.access protected package.
170 // Trusted code only can call this method.
171 return currentGlobal.get();
172 }
173
174 /**
175 * Set the current global scope
176 * @param global the global scope
177 */
178 public static void setGlobal(final ScriptObject global) {
179 if (global != null && !(global instanceof Global)) {
180 throw new IllegalArgumentException("not a global!");
181 }
182 setGlobal((Global)global);
183 }
184
185 /**
186 * Set the current global scope
187 * @param global the global scope
188 */
189 public static void setGlobal(final Global global) {
190 // This class in a package.access protected package.
191 // Trusted code only can call this method.
192 currentGlobal.set(global);
193 }
194
195 /**
196 * Get context of the current global
197 * @return current global scope's context.
198 */
199 public static Context getContext() {
200 final SecurityManager sm = System.getSecurityManager();
201 if (sm != null) {
202 sm.checkPermission(new RuntimePermission(NASHORN_GET_CONTEXT));
203 }
204 return getContextTrusted();
205 }
206
207 /**
208 * Get current context's error writer
209 *
210 * @return error writer of the current context
211 */
212 public static PrintWriter getCurrentErr() {
213 final ScriptObject global = getGlobal();
214 return (global != null)? global.getContext().getErr() : new PrintWriter(System.err);
215 }
216
217 /**
218 * Output text to this Context's error stream
219 * @param str text to write
220 */
221 public static void err(final String str) {
222 err(str, true);
223 }
224
225 /**
226 * Output text to this Context's error stream, optionally with
227 * a newline afterwards
228 *
229 * @param str text to write
230 * @param crlf write a carriage return/new line after text
231 */
232 @SuppressWarnings("resource")
233 public static void err(final String str, final boolean crlf) {
398 * Get the output stream for this context
399 * @return output print writer
400 */
401 public PrintWriter getOut() {
402 return env.getOut();
403 }
404
405 /**
406 * Get the error stream for this context
407 * @return error print writer
408 */
409 public PrintWriter getErr() {
410 return env.getErr();
411 }
412
413 /**
414 * Get the PropertyMap of the current global scope
415 * @return the property map of the current global scope
416 */
417 public static PropertyMap getGlobalMap() {
418 return Context.getGlobal().getMap();
419 }
420
421 /**
422 * Compile a top level script.
423 *
424 * @param source the source
425 * @param scope the scope
426 *
427 * @return top level function for script
428 */
429 public ScriptFunction compileScript(final Source source, final ScriptObject scope) {
430 return compileScript(source, scope, this.errors);
431 }
432
433 /**
434 * Entry point for {@code eval}
435 *
436 * @param initialScope The scope of this eval call
437 * @param string Evaluated code as a String
438 * @param callThis "this" to be passed to the evaluated code
439 * @param location location of the eval call
440 * @param strict is this {@code eval} call from a strict mode code?
441 *
442 * @return the return value of the {@code eval}
443 */
444 public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) {
445 final String file = (location == UNDEFINED || location == null) ? "<eval>" : location.toString();
446 final Source source = new Source(file, string);
447 final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval?
448 final Global global = Context.getGlobal();
449
450 ScriptObject scope = initialScope;
451
452 // ECMA section 10.1.1 point 2 says eval code is strict if it begins
453 // with "use strict" directive or eval direct call itself is made
454 // from from strict mode code. We are passed with caller's strict mode.
455 boolean strictFlag = directEval && strict;
456
457 Class<?> clazz = null;
458 try {
459 clazz = compile(source, new ThrowErrorManager(), strictFlag);
460 } catch (final ParserException e) {
461 e.throwAsEcmaException(global);
462 return null;
463 }
464
465 if (!strictFlag) {
466 // We need to get strict mode flag from compiled class. This is
467 // because eval code may start with "use strict" directive.
468 try {
469 strictFlag = clazz.getField(STRICT_MODE.symbolName()).getBoolean(null);
470 } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
471 //ignored
472 strictFlag = false;
473 }
474 }
475
476 // In strict mode, eval does not instantiate variables and functions
477 // in the caller's environment. A new environment is created!
478 if (strictFlag) {
479 // Create a new scope object
480 final ScriptObject strictEvalScope = global.newObject();
481
482 // bless it as a "scope"
483 strictEvalScope.setIsScope();
484
485 // set given scope to be it's proto so that eval can still
486 // access caller environment vars in the new environment.
487 strictEvalScope.setProto(scope);
488 scope = strictEvalScope;
489 }
490
491 ScriptFunction func = getRunScriptFunction(clazz, scope);
492 Object evalThis;
493 if (directEval) {
494 evalThis = (callThis instanceof ScriptObject || strictFlag) ? callThis : global;
495 } else {
496 evalThis = global;
497 }
498
499 return ScriptRuntime.apply(func, evalThis);
500 }
585
586 if (source != null) {
587 return evaluateSource(source, scope, scope);
588 }
589
590 throw typeError("cant.load.script", ScriptRuntime.safeToString(from));
591 }
592
593 /**
594 * Implementation of {@code loadWithNewGlobal} Nashorn extension. Load a script file from a source
595 * expression, after creating a new global scope.
596 *
597 * @param from source expression for script
598 * @param args (optional) arguments to be passed to the loaded script
599 *
600 * @return return value for load call (undefined)
601 *
602 * @throws IOException if source cannot be found or loaded
603 */
604 public Object loadWithNewGlobal(final Object from, final Object...args) throws IOException {
605 final Global oldGlobal = getGlobal();
606 final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
607 @Override
608 public Global run() {
609 try {
610 return newGlobal();
611 } catch (final RuntimeException e) {
612 if (Context.DEBUG) {
613 e.printStackTrace();
614 }
615 throw e;
616 }
617 }
618 }, CREATE_GLOBAL_ACC_CTXT);
619 // initialize newly created Global instance
620 initGlobal(newGlobal);
621 setGlobal(newGlobal);
622
623 final Object[] wrapped = args == null? ScriptRuntime.EMPTY_ARRAY : ScriptObjectMirror.wrapArray(args, oldGlobal);
624 newGlobal.put("arguments", newGlobal.wrapAsObject(wrapped), env._strict);
625
626 try {
627 // wrap objects from newGlobal's world as mirrors - but if result
628 // is from oldGlobal's world, unwrap it!
629 return ScriptObjectMirror.unwrap(ScriptObjectMirror.wrap(load(newGlobal, from), newGlobal), oldGlobal);
630 } finally {
631 setGlobal(oldGlobal);
632 }
633 }
634
635 /**
636 * Load or get a structure class. Structure class names are based on the number of parameter fields
637 * and {@link AccessorProperty} fields in them. Structure classes are used to represent ScriptObjects
638 *
639 * @see ObjectClassGenerator
640 * @see AccessorProperty
641 * @see ScriptObject
642 *
643 * @param fullName full name of class, e.g. jdk.nashorn.internal.objects.JO2P1 contains 2 fields and 1 parameter.
644 *
645 * @return the {@code Class<?>} for this structure
646 *
647 * @throws ClassNotFoundException if structure class cannot be resolved
648 */
649 public static Class<?> forStructureClass(final String fullName) throws ClassNotFoundException {
650 if (System.getSecurityManager() != null && !StructureLoader.isStructureClass(fullName)) {
651 throw new ClassNotFoundException(fullName);
786 * user specified verify option. We check it here even though caller
787 * may have already checked that flag
788 *
789 * @param bytecode bytecode to verify
790 */
791 public void verify(final byte[] bytecode) {
792 if (env._verify_code) {
793 // No verification when security manager is around as verifier
794 // may load further classes - which should be avoided.
795 if (System.getSecurityManager() == null) {
796 CheckClassAdapter.verify(new ClassReader(bytecode), sharedLoader, false, new PrintWriter(System.err, true));
797 }
798 }
799 }
800
801 /**
802 * Create and initialize a new global scope object.
803 *
804 * @return the initialized global scope object.
805 */
806 public Global createGlobal() {
807 return initGlobal(newGlobal());
808 }
809
810 /**
811 * Create a new uninitialized global scope object
812 * @return the global script object
813 */
814 public Global newGlobal() {
815 return new Global(this);
816 }
817
818 /**
819 * Initialize given global scope object.
820 *
821 * @param global the global
822 * @return the initialized global scope object.
823 */
824 public Global initGlobal(final Global global) {
825 // Need only minimal global object, if we are just compiling.
826 if (!env._compile_only) {
827 final Global oldGlobal = Context.getGlobal();
828 try {
829 Context.setGlobal(global);
830 // initialize global scope with builtin global objects
831 global.initBuiltinObjects();
832 } finally {
833 Context.setGlobal(oldGlobal);
834 }
835 }
836
837 return global;
838 }
839
840 /**
841 * Trusted variant - package-private
842 */
843
844 /**
845 * Return the current global's context
846 * @return current global's context
847 */
848 static Context getContextTrusted() {
849 return ((ScriptObject)Context.getGlobal()).getContext();
850 }
851
852 /**
853 * Try to infer Context instance from the Class. If we cannot,
854 * then get it from the thread local variable.
855 *
856 * @param clazz the class
857 * @return context
858 */
859 static Context fromClass(final Class<?> clazz) {
860 final ClassLoader loader = clazz.getClassLoader();
861
862 if (loader instanceof ScriptLoader) {
863 return ((ScriptLoader)loader).getContext();
864 }
865
866 return Context.getContextTrusted();
867 }
868
869 private URL getResourceURL(final String resName) {
898 // Get run method - the entry point to the script
899 final MethodHandle runMethodHandle =
900 MH.findStatic(
901 MethodHandles.lookup(),
902 script,
903 RUN_SCRIPT.symbolName(),
904 MH.type(
905 Object.class,
906 ScriptFunction.class,
907 Object.class));
908
909 boolean strict;
910
911 try {
912 strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null);
913 } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
914 strict = false;
915 }
916
917 // Package as a JavaScript function and pass function back to shell.
918 return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
919 }
920
921 private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
922 return getRunScriptFunction(compile(source, errMan, this._strict), scope);
923 }
924
925 private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
926 // start with no errors, no warnings.
927 errMan.reset();
928
929 Class<?> script = findCachedClass(source);
930 if (script != null) {
931 Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
932 return script;
933 }
934
935 final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
936 if (errors.hasErrors()) {
937 return null;
938 }
|