Tue, 07 May 2013 14:43:17 +0200
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
Reviewed-by: jlaskey, attila
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 */
26 package jdk.nashorn.internal.runtime;
28 import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
29 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
30 import static jdk.nashorn.internal.lookup.Lookup.MH;
31 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
34 import java.io.File;
35 import java.io.IOException;
36 import java.io.PrintWriter;
37 import java.lang.invoke.MethodHandle;
38 import java.lang.invoke.MethodHandles;
39 import java.lang.reflect.Constructor;
40 import java.net.MalformedURLException;
41 import java.net.URL;
42 import java.security.AccessControlContext;
43 import java.security.AccessController;
44 import java.security.CodeSigner;
45 import java.security.CodeSource;
46 import java.security.Permissions;
47 import java.security.PrivilegedAction;
48 import java.security.ProtectionDomain;
49 import jdk.internal.org.objectweb.asm.ClassReader;
50 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
51 import jdk.nashorn.internal.codegen.Compiler;
52 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
53 import jdk.nashorn.internal.ir.FunctionNode;
54 import jdk.nashorn.internal.ir.debug.ASTWriter;
55 import jdk.nashorn.internal.ir.debug.PrintVisitor;
56 import jdk.nashorn.internal.parser.Parser;
57 import jdk.nashorn.internal.runtime.options.Options;
59 /**
60 * This class manages the global state of execution. Context is immutable.
61 */
62 public final class Context {
64 /**
65 * ContextCodeInstaller that has the privilege of installing classes in the Context.
66 * Can only be instantiated from inside the context and is opaque to other classes
67 */
68 public static class ContextCodeInstaller implements CodeInstaller<ScriptEnvironment> {
69 private final Context context;
70 private final ScriptLoader loader;
71 private final CodeSource codeSource;
73 private ContextCodeInstaller(final Context context, final ScriptLoader loader, final CodeSource codeSource) {
74 this.context = context;
75 this.loader = loader;
76 this.codeSource = codeSource;
77 }
79 /**
80 * Return the context for this installer
81 * @return ScriptEnvironment
82 */
83 @Override
84 public ScriptEnvironment getOwner() {
85 return context.env;
86 }
88 @Override
89 public Class<?> install(final String className, final byte[] bytecode) {
90 return loader.installClass(className, bytecode, codeSource);
91 }
93 @Override
94 public void verify(final byte[] code) {
95 context.verify(code);
96 }
97 }
99 /** Is Context global debug mode enabled ? */
100 public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
102 private static final ThreadLocal<ScriptObject> currentGlobal =
103 new ThreadLocal<ScriptObject>() {
104 @Override
105 protected ScriptObject initialValue() {
106 return null;
107 }
108 };
110 /**
111 * Get the current global scope
112 * @return the current global scope
113 */
114 public static ScriptObject getGlobal() {
115 // This class in a package.access protected package.
116 // Trusted code only can call this method.
117 return getGlobalTrusted();
118 }
120 /**
121 * Set the current global scope
122 * @param global the global scope
123 */
124 public static void setGlobal(final ScriptObject global) {
125 final SecurityManager sm = System.getSecurityManager();
126 if (sm != null) {
127 sm.checkPermission(new RuntimePermission("nashorn.setGlobal"));
128 }
130 if (global != null && !(global instanceof GlobalObject)) {
131 throw new IllegalArgumentException("global does not implement GlobalObject!");
132 }
134 setGlobalTrusted(global);
135 }
137 /**
138 * Get context of the current global
139 * @return current global scope's context.
140 */
141 public static Context getContext() {
142 final SecurityManager sm = System.getSecurityManager();
143 if (sm != null) {
144 sm.checkPermission(new RuntimePermission("nashorn.getContext"));
145 }
146 return getContextTrusted();
147 }
149 /**
150 * Get current context's error writer
151 *
152 * @return error writer of the current context
153 */
154 public static PrintWriter getCurrentErr() {
155 final ScriptObject global = getGlobalTrusted();
156 return (global != null)? global.getContext().getErr() : new PrintWriter(System.err);
157 }
159 /**
160 * Output text to this Context's error stream
161 * @param str text to write
162 */
163 public static void err(final String str) {
164 err(str, true);
165 }
167 /**
168 * Output text to this Context's error stream, optionally with
169 * a newline afterwards
170 *
171 * @param str text to write
172 * @param crlf write a carriage return/new line after text
173 */
174 @SuppressWarnings("resource")
175 public static void err(final String str, final boolean crlf) {
176 final PrintWriter err = Context.getCurrentErr();
177 if (err != null) {
178 if (crlf) {
179 err.println(str);
180 } else {
181 err.print(str);
182 }
183 }
184 }
186 /** Current environment. */
187 private final ScriptEnvironment env;
189 /** is this context in strict mode? Cached from env. as this is used heavily. */
190 public final boolean _strict;
192 /** class loader to resolve classes from script. */
193 private final ClassLoader appLoader;
195 /** Class loader to load classes from -classpath option, if set. */
196 private final ClassLoader classPathLoader;
198 /** Class loader to load classes compiled from scripts. */
199 private final ScriptLoader scriptLoader;
201 /** Current error manager. */
202 private final ErrorManager errors;
204 private static final ClassLoader myLoader = Context.class.getClassLoader();
205 private static final StructureLoader sharedLoader;
207 static {
208 sharedLoader = AccessController.doPrivileged(new PrivilegedAction<StructureLoader>() {
209 @Override
210 public StructureLoader run() {
211 return new StructureLoader(myLoader, null);
212 }
213 });
214 }
216 /**
217 * ThrowErrorManager that throws ParserException upon error conditions.
218 */
219 public static class ThrowErrorManager extends ErrorManager {
220 @Override
221 public void error(final String message) {
222 throw new ParserException(message);
223 }
225 @Override
226 public void error(final ParserException e) {
227 throw e;
228 }
229 }
231 /**
232 * Constructor
233 *
234 * @param options options from command line or Context creator
235 * @param errors error manger
236 * @param appLoader application class loader
237 */
238 public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader) {
239 this(options, errors, new PrintWriter(System.out, true), new PrintWriter(System.err, true), appLoader);
240 }
242 /**
243 * Constructor
244 *
245 * @param options options from command line or Context creator
246 * @param errors error manger
247 * @param out output writer for this Context
248 * @param err error writer for this Context
249 * @param appLoader application class loader
250 */
251 public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader) {
252 final SecurityManager sm = System.getSecurityManager();
253 if (sm != null) {
254 sm.checkPermission(new RuntimePermission("nashorn.createContext"));
255 }
257 this.env = new ScriptEnvironment(options, out, err);
258 this._strict = env._strict;
259 this.appLoader = appLoader;
260 this.scriptLoader = (ScriptLoader)AccessController.doPrivileged(
261 new PrivilegedAction<ClassLoader>() {
262 @Override
263 public ClassLoader run() {
264 final StructureLoader structureLoader = new StructureLoader(sharedLoader, Context.this);
265 return new ScriptLoader(structureLoader, Context.this);
266 }
267 });
268 this.errors = errors;
270 // if user passed -classpath option, make a class loader with that and set it as
271 // thread context class loader so that script can access classes from that path.
272 final String classPath = options.getString("classpath");
273 if (! env._compile_only && classPath != null && !classPath.isEmpty()) {
274 // make sure that caller can create a class loader.
275 if (sm != null) {
276 sm.checkPermission(new RuntimePermission("createClassLoader"));
277 }
278 this.classPathLoader = NashornLoader.createClassLoader(classPath);
279 } else {
280 this.classPathLoader = null;
281 }
283 // print version info if asked.
284 if (env._version) {
285 getErr().println("nashorn " + Version.version());
286 }
288 if (env._fullversion) {
289 getErr().println("nashorn full version " + Version.fullVersion());
290 }
291 }
293 /**
294 * Get the error manager for this context
295 * @return error manger
296 */
297 public ErrorManager getErrorManager() {
298 return errors;
299 }
301 /**
302 * Get the script environment for this context
303 * @return script environment
304 */
305 public ScriptEnvironment getEnv() {
306 return env;
307 }
309 /**
310 * Get the output stream for this context
311 * @return output print writer
312 */
313 public PrintWriter getOut() {
314 return env.getOut();
315 }
317 /**
318 * Get the error stream for this context
319 * @return error print writer
320 */
321 public PrintWriter getErr() {
322 return env.getErr();
323 }
325 /**
326 * Get the PropertyMap of the current global scope
327 * @return the property map of the current global scope
328 */
329 public static PropertyMap getGlobalMap() {
330 return Context.getGlobalTrusted().getMap();
331 }
333 /**
334 * Compile a top level script.
335 *
336 * @param source the source
337 * @param scope the scope
338 *
339 * @return top level function for script
340 */
341 public ScriptFunction compileScript(final Source source, final ScriptObject scope) {
342 return compileScript(source, scope, this.errors);
343 }
345 /**
346 * Entry point for {@code eval}
347 *
348 * @param initialScope The scope of this eval call
349 * @param string Evaluated code as a String
350 * @param callThis "this" to be passed to the evaluated code
351 * @param location location of the eval call
352 * @param strict is this {@code eval} call from a strict mode code?
353 *
354 * @return the return value of the {@code eval}
355 */
356 public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) {
357 final String file = (location == UNDEFINED || location == null) ? "<eval>" : location.toString();
358 final Source source = new Source(file, string);
359 final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval?
360 final ScriptObject global = Context.getGlobalTrusted();
362 ScriptObject scope = initialScope;
364 // ECMA section 10.1.1 point 2 says eval code is strict if it begins
365 // with "use strict" directive or eval direct call itself is made
366 // from from strict mode code. We are passed with caller's strict mode.
367 boolean strictFlag = directEval && strict;
369 Class<?> clazz = null;
370 try {
371 clazz = compile(source, new ThrowErrorManager(), strictFlag);
372 } catch (final ParserException e) {
373 e.throwAsEcmaException(global);
374 return null;
375 }
377 if (!strictFlag) {
378 // We need to get strict mode flag from compiled class. This is
379 // because eval code may start with "use strict" directive.
380 try {
381 strictFlag = clazz.getField(STRICT_MODE.symbolName()).getBoolean(null);
382 } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
383 //ignored
384 strictFlag = false;
385 }
386 }
388 // In strict mode, eval does not instantiate variables and functions
389 // in the caller's environment. A new environment is created!
390 if (strictFlag) {
391 // Create a new scope object
392 final ScriptObject strictEvalScope = ((GlobalObject)global).newObject();
394 // bless it as a "scope"
395 strictEvalScope.setIsScope();
397 // set given scope to be it's proto so that eval can still
398 // access caller environment vars in the new environment.
399 strictEvalScope.setProto(scope);
400 scope = strictEvalScope;
401 }
403 ScriptFunction func = getRunScriptFunction(clazz, scope);
404 Object evalThis;
405 if (directEval) {
406 evalThis = (callThis instanceof ScriptObject || strictFlag) ? callThis : global;
407 } else {
408 evalThis = global;
409 }
411 return ScriptRuntime.apply(func, evalThis);
412 }
414 private static Source loadInternal(final String srcStr, final String prefix, final String resourcePath) {
415 if (srcStr.startsWith(prefix)) {
416 final String resource = resourcePath + srcStr.substring(prefix.length());
417 // NOTE: even sandbox scripts should be able to load scripts in nashorn: scheme
418 // These scripts are always available and are loaded from nashorn.jar's resources.
419 return AccessController.doPrivileged(
420 new PrivilegedAction<Source>() {
421 @Override
422 public Source run() {
423 try {
424 final URL resURL = Context.class.getResource(resource);
425 return (resURL != null)? new Source(srcStr, resURL) : null;
426 } catch (final IOException exp) {
427 return null;
428 }
429 }
430 });
431 }
433 return null;
434 }
436 /**
437 * Implementation of {@code load} Nashorn extension. Load a script file from a source
438 * expression
439 *
440 * @param scope the scope
441 * @param from source expression for script
442 *
443 * @return return value for load call (undefined)
444 *
445 * @throws IOException if source cannot be found or loaded
446 */
447 public Object load(final ScriptObject scope, final Object from) throws IOException {
448 final Object src = (from instanceof ConsString)? from.toString() : from;
449 Source source = null;
451 // load accepts a String (which could be a URL or a file name), a File, a URL
452 // or a ScriptObject that has "name" and "source" (string valued) properties.
453 if (src instanceof String) {
454 final String srcStr = (String)src;
455 final File file = new File(srcStr);
456 if (srcStr.indexOf(':') != -1) {
457 if ((source = loadInternal(srcStr, "nashorn:", "resources/")) == null &&
458 (source = loadInternal(srcStr, "fx:", "resources/fx/")) == null) {
459 URL url;
460 try {
461 //check for malformed url. if malformed, it may still be a valid file
462 url = new URL(srcStr);
463 } catch (final MalformedURLException e) {
464 url = file.toURI().toURL();
465 }
466 source = new Source(url.toString(), url);
467 }
468 } else if (file.isFile()) {
469 source = new Source(srcStr, file);
470 }
471 } else if (src instanceof File && ((File)src).isFile()) {
472 final File file = (File)src;
473 source = new Source(file.getName(), file);
474 } else if (src instanceof URL) {
475 final URL url = (URL)src;
476 source = new Source(url.toString(), url);
477 } else if (src instanceof ScriptObject) {
478 final ScriptObject sobj = (ScriptObject)src;
479 if (sobj.has("script") && sobj.has("name")) {
480 final String script = JSType.toString(sobj.get("script"));
481 final String name = JSType.toString(sobj.get("name"));
482 source = new Source(name, script);
483 }
484 }
486 if (source != null) {
487 return evaluateSource(source, scope, scope);
488 }
490 throw typeError("cant.load.script", ScriptRuntime.safeToString(from));
491 }
493 /**
494 * Load or get a structure class. Structure class names are based on the number of parameter fields
495 * and {@link AccessorProperty} fields in them. Structure classes are used to represent ScriptObjects
496 *
497 * @see ObjectClassGenerator
498 * @see AccessorProperty
499 * @see ScriptObject
500 *
501 * @param fullName full name of class, e.g. jdk.nashorn.internal.objects.JO2P1 contains 2 fields and 1 parameter.
502 *
503 * @return the {@code Class<?>} for this structure
504 *
505 * @throws ClassNotFoundException if structure class cannot be resolved
506 */
507 public static Class<?> forStructureClass(final String fullName) throws ClassNotFoundException {
508 return Class.forName(fullName, true, sharedLoader);
509 }
511 /**
512 * Lookup a Java class. This is used for JSR-223 stuff linking in from
513 * {@code jdk.nashorn.internal.objects.NativeJava} and {@code jdk.nashorn.internal.runtime.NativeJavaPackage}
514 *
515 * @param fullName full name of class to load
516 *
517 * @return the {@code Class<?>} for the name
518 *
519 * @throws ClassNotFoundException if class cannot be resolved
520 */
521 public Class<?> findClass(final String fullName) throws ClassNotFoundException {
522 // check package access as soon as possible!
523 final int index = fullName.lastIndexOf('.');
524 if (index != -1) {
525 final SecurityManager sm = System.getSecurityManager();
526 if (sm != null) {
527 AccessController.doPrivileged(new PrivilegedAction<Void>() {
528 @Override
529 public Void run() {
530 sm.checkPackageAccess(fullName.substring(0, index));
531 return null;
532 }
533 }, createNoPermissionsContext());
534 }
535 }
537 // try the script -classpath loader, if that is set
538 if (classPathLoader != null) {
539 try {
540 return Class.forName(fullName, true, classPathLoader);
541 } catch (final ClassNotFoundException ignored) {
542 // ignore, continue search
543 }
544 }
546 // Try finding using the "app" loader.
547 return Class.forName(fullName, true, appLoader);
548 }
550 /**
551 * Hook to print stack trace for a {@link Throwable} that occurred during
552 * execution
553 *
554 * @param t throwable for which to dump stack
555 */
556 public static void printStackTrace(final Throwable t) {
557 if (Context.DEBUG) {
558 t.printStackTrace(Context.getCurrentErr());
559 }
560 }
562 /**
563 * Verify generated bytecode before emission. This is called back from the
564 * {@link ObjectClassGenerator} or the {@link Compiler}. If the "--verify-code" parameter
565 * hasn't been given, this is a nop
566 *
567 * Note that verification may load classes -- we don't want to do that unless
568 * user specified verify option. We check it here even though caller
569 * may have already checked that flag
570 *
571 * @param bytecode bytecode to verify
572 */
573 public void verify(final byte[] bytecode) {
574 if (env._verify_code) {
575 // No verification when security manager is around as verifier
576 // may load further classes - which should be avoided.
577 if (System.getSecurityManager() == null) {
578 CheckClassAdapter.verify(new ClassReader(bytecode), scriptLoader, false, new PrintWriter(System.err, true));
579 }
580 }
581 }
583 /**
584 * Create and initialize a new global scope object.
585 *
586 * @return the initialized global scope object.
587 */
588 public ScriptObject createGlobal() {
589 return initGlobal(newGlobal());
590 }
592 /**
593 * Create a new uninitialized global scope object
594 * @return the global script object
595 */
596 public ScriptObject newGlobal() {
597 final SecurityManager sm = System.getSecurityManager();
598 if (sm != null) {
599 sm.checkPermission(new RuntimePermission("nashorn.newGlobal"));
600 }
602 return newGlobalTrusted();
603 }
605 /**
606 * Initialize given global scope object.
607 *
608 * @param global the global
609 * @return the initialized global scope object.
610 */
611 public ScriptObject initGlobal(final ScriptObject global) {
612 if (! (global instanceof GlobalObject)) {
613 throw new IllegalArgumentException("not a global object!");
614 }
616 // Need only minimal global object, if we are just compiling.
617 if (!env._compile_only) {
618 final ScriptObject oldGlobal = Context.getGlobalTrusted();
619 try {
620 Context.setGlobalTrusted(global);
621 // initialize global scope with builtin global objects
622 ((GlobalObject)global).initBuiltinObjects();
623 } finally {
624 Context.setGlobalTrusted(oldGlobal);
625 }
626 }
628 return global;
629 }
631 /**
632 * Trusted variants - package-private
633 */
635 /**
636 * Return the current global scope
637 * @return current global scope
638 */
639 static ScriptObject getGlobalTrusted() {
640 return currentGlobal.get();
641 }
643 /**
644 * Set the current global scope
645 */
646 static void setGlobalTrusted(ScriptObject global) {
647 currentGlobal.set(global);
648 }
650 /**
651 * Return the current global's context
652 * @return current global's context
653 */
654 static Context getContextTrusted() {
655 return Context.getGlobalTrusted().getContext();
656 }
658 /**
659 * Try to infer Context instance from the Class. If we cannot,
660 * then get it from the thread local variable.
661 *
662 * @param clazz the class
663 * @return context
664 */
665 static Context fromClass(final Class<?> clazz) {
666 final ClassLoader loader = clazz.getClassLoader();
668 Context context = null;
669 if (loader instanceof NashornLoader) {
670 context = ((NashornLoader)loader).getContext();
671 }
673 return (context != null) ? context : Context.getContextTrusted();
674 }
676 private static AccessControlContext createNoPermissionsContext() {
677 return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, new Permissions()) });
678 }
680 private Object evaluateSource(final Source source, final ScriptObject scope, final ScriptObject thiz) {
681 ScriptFunction script = null;
683 try {
684 script = compileScript(source, scope, new Context.ThrowErrorManager());
685 } catch (final ParserException e) {
686 e.throwAsEcmaException();
687 }
689 return ScriptRuntime.apply(script, thiz);
690 }
692 private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) {
693 if (script == null) {
694 return null;
695 }
697 // Get run method - the entry point to the script
698 final MethodHandle runMethodHandle =
699 MH.findStatic(
700 MethodHandles.lookup(),
701 script,
702 RUN_SCRIPT.symbolName(),
703 MH.type(
704 Object.class,
705 ScriptFunction.class,
706 Object.class));
708 boolean strict;
710 try {
711 strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null);
712 } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
713 strict = false;
714 }
716 // Package as a JavaScript function and pass function back to shell.
717 return ((GlobalObject)Context.getGlobalTrusted()).newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
718 }
720 private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
721 return getRunScriptFunction(compile(source, errMan, this._strict), scope);
722 }
724 private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
725 // start with no errors, no warnings.
726 errMan.reset();
728 GlobalObject global = null;
729 Class<?> script;
731 if (env._class_cache_size > 0) {
732 global = (GlobalObject)Context.getGlobalTrusted();
733 script = global.findCachedClass(source);
734 if (script != null) {
735 Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
736 return script;
737 }
738 }
740 final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
741 if (errors.hasErrors()) {
742 return null;
743 }
745 if (env._print_ast) {
746 getErr().println(new ASTWriter(functionNode));
747 }
749 if (env._print_parse) {
750 getErr().println(new PrintVisitor(functionNode));
751 }
753 if (env._parse_only) {
754 return null;
755 }
757 final URL url = source.getURL();
758 final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
759 final CodeSource cs = url == null ? null : new CodeSource(url, (CodeSigner[])null);
760 final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
762 final Compiler compiler = new Compiler(installer, strict);
764 final FunctionNode newFunctionNode = compiler.compile(functionNode);
765 script = compiler.install(newFunctionNode);
767 if (global != null) {
768 global.cacheClass(source, script);
769 }
771 return script;
772 }
774 private ScriptLoader createNewLoader() {
775 return AccessController.doPrivileged(
776 new PrivilegedAction<ScriptLoader>() {
777 @Override
778 public ScriptLoader run() {
779 // Generated code won't refer to any class generated by context
780 // script loader and so parent loader can be the structure
781 // loader -- which is parent of the context script loader.
782 return new ScriptLoader((StructureLoader)scriptLoader.getParent(), Context.this);
783 }
784 });
785 }
787 private ScriptObject newGlobalTrusted() {
788 try {
789 final Class<?> clazz = Class.forName("jdk.nashorn.internal.objects.Global", true, scriptLoader);
790 final Constructor<?> cstr = clazz.getConstructor(Context.class);
791 return (ScriptObject) cstr.newInstance(this);
792 } catch (final Exception e) {
793 printStackTrace(e);
794 if (e instanceof RuntimeException) {
795 throw (RuntimeException)e;
796 }
797 throw new RuntimeException(e);
798 }
799 }
800 }