private static Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException { if (script == null) { return null; } final Global oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != ctxtGlobal); try { if (globalChanged) { Context.setGlobal(ctxtGlobal); } ctxtGlobal.setScriptContext(ctxt); return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal)); } catch (final Exception e) { throwAsScriptException(e, ctxtGlobal); throw new AssertionError("should not reach here"); } finally { if (globalChanged) { Context.setGlobal(oldGlobal); } } }
/** * Dump all Nashorn debug mode counters. Calling this may be better if * you want to print all counters. This way you can avoid too many callsites * due to counter access itself!! * @param self self reference * @return undefined */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) public static Object dumpCounters(final Object self) { final PrintWriter out = Context.getCurrentErr(); out.println("ScriptObject count " + ScriptObject.getCount()); out.println("Scope count " + Scope.getScopeCount()); out.println("ScriptObject listeners added " + PropertyListeners.getListenersAdded()); out.println("ScriptObject listeners removed " + PropertyListeners.getListenersRemoved()); out.println("ScriptFunction constructor calls " + ScriptFunction.getConstructorCount()); out.println("ScriptFunction invokes " + ScriptFunction.getInvokes()); out.println("ScriptFunction allocations " + ScriptFunction.getAllocations()); out.println("PropertyMap count " + PropertyMap.getCount()); out.println("PropertyMap cloned " + PropertyMap.getClonedCount()); out.println("PropertyMap history hit " + PropertyMap.getHistoryHit()); out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations()); out.println("PropertyMap proto history hit " + PropertyMap.getProtoHistoryHit()); out.println("PropertyMap setProtoNewMapCount " + PropertyMap.getSetProtoNewMapCount()); out.println("Callsite count " + LinkerCallSite.getCount()); out.println("Callsite misses " + LinkerCallSite.getMissCount()); out.println("Callsite misses by site at " + LinkerCallSite.getMissSamplingPercentage() + "%"); LinkerCallSite.getMissCounts(out); return UNDEFINED; }
private ScriptFunction compileImpl(final Source source, final Global newGlobal) throws ScriptException { final Global oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != newGlobal); try { if (globalChanged) { Context.setGlobal(newGlobal); } return nashornContext.compileScript(source, newGlobal); } catch (final Exception e) { throwAsScriptException(e, newGlobal); throw new AssertionError("should not reach here"); } finally { if (globalChanged) { Context.setGlobal(oldGlobal); } } }
private static boolean isInterfaceImplemented(final Class<?> iface, final ScriptObject sobj) { for (final Method method : iface.getMethods()) { // ignore methods of java.lang.Object class if (method.getDeclaringClass() == Object.class) { continue; } // skip check for default methods - non-abstract, interface methods if (! Modifier.isAbstract(method.getModifiers())) { continue; } final Object obj = sobj.get(method.getName()); if (! (obj instanceof ScriptFunction)) { return false; } } return true; }
/** * ECMA 15.5.4.11 String.prototype.replace (searchValue, replaceValue) * @param self self reference * @param string item to replace * @param replacement item to replace it with * @return string after replacement * @throws Throwable if replacement fails */ @Function(attributes = Attribute.NOT_ENUMERABLE) public static String replace(final Object self, final Object string, final Object replacement) throws Throwable { final String str = checkObjectToString(self); final NativeRegExp nativeRegExp; if (string instanceof NativeRegExp) { nativeRegExp = (NativeRegExp) string; } else { nativeRegExp = NativeRegExp.flatRegExp(JSType.toString(string)); } if (replacement instanceof ScriptFunction) { return nativeRegExp.replace(str, "", (ScriptFunction)replacement); } return nativeRegExp.replace(str, JSType.toString(replacement), null); }
@Override public Iterator<String> propertyIterator() { // Try __getIds__ first, if not found then try __getKeys__ // In jdk6, we had added "__getIds__" so this is just for compatibility. Object func = adaptee.get(__getIds__); if (!(func instanceof ScriptFunction)) { func = adaptee.get(__getKeys__); } Object obj; if (func instanceof ScriptFunction) { obj = ScriptRuntime.apply((ScriptFunction)func, adaptee); } else { obj = new NativeArray(0); } final List<String> array = new ArrayList<>(); for (final Iterator<Object> iter = ArrayLikeIterator.arrayLikeIterator(obj); iter.hasNext(); ) { array.add((String)iter.next()); } return array.iterator(); }
private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) { final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>(); list.addAll(Arrays.asList(func.getMap().getProperties())); if (func instanceof ScriptFunction) { final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func); if (proto != null) { list.addAll(Arrays.asList(proto.getMap().getProperties())); } } final jdk.nashorn.internal.runtime.Property prop = getProperty(name); if (prop != null) { list.add(prop); } return list; }
@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); } }
MethodType getCallSiteType(final FunctionNode functionNode) { final Type[] types = paramTypeMap.get(functionNode.getId()); if (types == null) { return null; } MethodType mt = MethodType.methodType(returnTypeMap.get(functionNode.getId()).getTypeClass()); if (needsCallee) { mt = mt.appendParameterTypes(ScriptFunction.class); } mt = mt.appendParameterTypes(Object.class); //this for (final Type type : types) { if (type == null) { return null; // not all parameter information is supplied } mt = mt.appendParameterTypes(type.getTypeClass()); } return mt; }
/** * ECMA 15.3.2.1 new Function (p1, p2, ... , pn, body) * * Constructor * * @param newObj is the new operator used for constructing this function * @param self self reference * @param args arguments * @return new NativeFunction */ @Constructor(arity = 1) public static ScriptFunction function(final boolean newObj, final Object self, final Object... args) { final StringBuilder sb = new StringBuilder(); sb.append("(function ("); final String funcBody; if (args.length > 0) { final StringBuilder paramListBuf = new StringBuilder(); for (int i = 0; i < args.length - 1; i++) { paramListBuf.append(JSType.toString(args[i])); if (i < args.length - 2) { paramListBuf.append(","); } } // now convert function body to a string funcBody = JSType.toString(args[args.length - 1]); final String paramList = paramListBuf.toString(); if (!paramList.isEmpty()) { checkFunctionParameters(paramList); sb.append(paramList); } } else { funcBody = null; } sb.append(") {\n"); if (args.length > 0) { checkFunctionBody(funcBody); sb.append(funcBody); sb.append('\n'); } sb.append("})"); final Global global = Global.instance(); final Context context = global.getContext(); return (ScriptFunction)context.eval(global, sb.toString(), global, "<function>"); }
/** * ECMA 15.3.4.2 Function.prototype.toString ( ) * * @param self self reference * @return string representation of Function */ @Function(attributes = Attribute.NOT_ENUMERABLE) public static String toString(final Object self) { if (!(self instanceof ScriptFunction)) { throw typeError("not.a.function", ScriptRuntime.safeToString(self)); } return ((ScriptFunction)self).toSource(); }
/** * ECMA 15.3.4.3 Function.prototype.apply (thisArg, argArray) * * @param self self reference * @param thiz {@code this} arg for apply * @param array array of argument for apply * @return result of apply */ @Function(attributes = Attribute.NOT_ENUMERABLE) public static Object apply(final Object self, final Object thiz, final Object array) { checkCallable(self); final Object[] args = toApplyArgs(array); if (self instanceof ScriptFunction) { return ScriptRuntime.apply((ScriptFunction)self, thiz, args); } else if (self instanceof JSObject) { return ((JSObject)self).call(thiz, args); } throw new AssertionError("Should not reach here"); }
/** * Adds jjs shell interactive mode builtin functions to global scope. */ public void addShellBuiltins() { Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT); addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT); addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); }
/** * ECMA 15.3.2.1 new Function (p1, p2, ... , pn, body) * * Constructor * * @param newObj is the new operator used for constructing this function * @param self self reference * @param args arguments * @return new NativeFunction */ @Constructor(arity = 1) public static ScriptFunction function(final boolean newObj, final Object self, final Object... args) { final StringBuilder sb = new StringBuilder(); sb.append("(function ("); final String funcBody; if (args.length > 0) { final StringBuilder paramListBuf = new StringBuilder(); for (int i = 0; i < args.length - 1; i++) { paramListBuf.append(JSType.toString(args[i])); if (i < args.length - 2) { paramListBuf.append(","); } } // now convert function body to a string funcBody = JSType.toString(args[args.length - 1]); final String paramList = paramListBuf.toString(); if (!paramList.isEmpty()) { checkFunctionParameters(paramList); sb.append(paramList); } } else { funcBody = null; } sb.append(") {\n"); if (args.length > 0) { checkFunctionBody(funcBody); sb.append(funcBody); sb.append('\n'); } sb.append("})"); final Global global = Global.instance(); return (ScriptFunction)Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext()); }
/** * Nashorn extension: Error.captureStackTrace. Capture stack trace at the point of call into the Error object provided. * * @param self self reference * @param errorObj the error object * @return undefined */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) public static Object captureStackTrace(final Object self, final Object errorObj) { final ScriptObject sobj = Global.checkObject(errorObj); initException(sobj); sobj.delete(STACK, false); if (! sobj.has("stack")) { final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK); final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK); sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); } return UNDEFINED; }
/** * Returns if the given object is a "callable" * @param obj object to be checked for callability * @return true if the obj is callable */ public static boolean isCallable(final Object obj) { if (obj == ScriptRuntime.UNDEFINED || obj == null) { return false; } return obj instanceof ScriptFunction || isJSObjectFunction(obj) || BeansLinker.isDynamicMethod(obj) || obj instanceof BoundCallable || isFunctionalInterfaceObject(obj) || obj instanceof StaticClass; }
/** * Returns synchronized wrapper version of the given ECMAScript function. * @param self not used * @param func the ECMAScript function whose synchronized version is returned. * @param obj the object (i.e, lock) on which the function synchronizes. * @return synchronized wrapper version of the given ECMAScript function. */ @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) public static Object synchronizedFunc(final Object self, final Object func, final Object obj) { if (func instanceof ScriptFunction) { return ((ScriptFunction)func).createSynchronized(obj); } throw typeError("not.a.function", ScriptRuntime.safeToString(func)); }
/** * Returns true if the given object is a strict callable * @param callable the callable object to be checked for strictness * @return true if the obj is a strict callable, false if it is a non-strict callable. * @throws ECMAException with {@code TypeError} if the object is not a callable. */ public static boolean isStrictCallable(final Object callable) { if (callable instanceof ScriptFunction) { return ((ScriptFunction)callable).isStrict(); } else if (isJSObjectFunction(callable)) { return ((JSObject)callable).isStrictFunction(); } else if (callable instanceof BoundCallable) { return isStrictCallable(((BoundCallable)callable).getCallable()); } else if (BeansLinker.isDynamicMethod(callable) || callable instanceof StaticClass || isFunctionalInterfaceObject(callable)) { return false; } throw notFunction(callable); }
private static boolean isBuiltinFunctionProperty(final String name) { final Global instance = Global.instance(); final ScriptFunction builtinFunction = instance.getBuiltinFunction(); if (builtinFunction == null) { return false; //conservative for compile-only mode } final boolean isBuiltinFunction = instance.function == builtinFunction; return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin(); }
@Override public Object call(final Object thiz, final Object... args) { final Global oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != global); try { if (globalChanged) { Context.setGlobal(global); } if (sobj instanceof ScriptFunction) { final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args; final Object self = globalChanged? wrapLikeMe(thiz, oldGlobal) : thiz; return wrapLikeMe(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global))); } throw new RuntimeException("not a function: " + toString()); } catch (final NashornException ne) { throw ne.initEcmaError(global); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { throw new RuntimeException(t); } finally { if (globalChanged) { Context.setGlobal(oldGlobal); } } }
private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException { if (script == null) { return null; } final Global oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != ctxtGlobal); try { if (globalChanged) { Context.setGlobal(ctxtGlobal); } final ScriptContext oldCtxt = ctxtGlobal.getScriptContext(); ctxtGlobal.setScriptContext(ctxt); try { return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal)); } finally { ctxtGlobal.setScriptContext(oldCtxt); } } catch (final Exception e) { throwAsScriptException(e, ctxtGlobal); throw new AssertionError("should not reach here"); } finally { if (globalChanged) { Context.setGlobal(oldGlobal); } } }
private void initTypedArray() { this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); }
/** * Returns synchronized wrapper version of the given ECMAScript function. * @param self not used * @param func the ECMAScript function whose synchronized version is returned. * @param obj the object (i.e, lock) on which the function synchronizes. * @return synchronized wrapper version of the given ECMAScript function. */ @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) public static Object synchronizedFunc(final Object self, final Object func, final Object obj) { if (func instanceof ScriptFunction) { return ((ScriptFunction)func).makeSynchronizedFunction(obj); } throw typeError("not.a.function", ScriptRuntime.safeToString(func)); }
@SuppressWarnings("unused") private static boolean isJSAdapter(final Object self, final Object adaptee, final MethodHandle getter, final Object where, final ScriptFunction func) { final boolean res = self instanceof NativeJSAdapter && ((NativeJSAdapter)self).getAdaptee() == adaptee; if (res && getter != null) { try { return getter.invokeExact(where) == func; } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { throw new RuntimeException(t); } } return res; }
private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) { final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags); func.setPrototype(UNDEFINED); // Non-constructor built-in functions do not have "prototype" property func.deleteOwnProperty(func.getMap().findProperty("prototype")); return func; }
private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) { try { // Assuming class name pattern for built-in JS constructors. final StringBuilder sb = new StringBuilder(PACKAGE_PREFIX); sb.append("Native"); sb.append(name); sb.append("$Constructor"); final Class<?> funcClass = Class.forName(sb.toString()); final T res = clazz.cast(funcClass.getDeclaredConstructor().newInstance()); if (res instanceof ScriptFunction) { // All global constructor prototypes are not-writable, // not-enumerable and not-configurable. final ScriptFunction func = (ScriptFunction)res; func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT); } if (res.getProto() == null) { res.setInitialProto(getObjectPrototype()); } res.setIsBuiltin(); return res; } catch (final Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException)e; } else { throw new RuntimeException(e); } } }
private void compileJSFile(final File file, final TestFilter filter) { if (VERBOSE) { log("Begin compiling " + file.getAbsolutePath()); } final Global oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != global); try { final char[] buffer = readFully(file); boolean excluded = false; if (filter != null) { final String content = new String(buffer); excluded = filter.exclude(file, content); } if (excluded) { if (VERBOSE) { log("Skipping " + file.getAbsolutePath()); } skipped++; return; } if (globalChanged) { Context.setGlobal(global); } final Source source = sourceFor(file.getAbsolutePath(), buffer); final ScriptFunction script = context.compileScript(source, global); if (script == null || context.getErrorManager().getNumberOfErrors() > 0) { log("Compile failed: " + file.getAbsolutePath()); failed++; } else { passed++; } } catch (final Throwable t) { log("Compile failed: " + file.getAbsolutePath() + " : " + t); if (VERBOSE) { t.printStackTrace(System.out); } failed++; } finally { if (globalChanged) { Context.setGlobal(oldGlobal); } } if (VERBOSE) { log("Done compiling " + file.getAbsolutePath()); } }
private synchronized ScriptFunction getBuiltinInt32Array() { if (this.builtinInt32Array == null) { this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); } return this.builtinInt32Array; }
ScriptObject getErrorPrototype() { return ScriptFunction.getPrototype(builtinError); }
ScriptObject getURIErrorPrototype() { return ScriptFunction.getPrototype(getBuiltinURIError()); }
private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt) throws ScriptException { return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt)); }
@Override public int run(final OutputStream out, final OutputStream err, final String[] args) throws IOException { final Global oldGlobal = Context.getGlobal(); try { ctxOut.setDelegatee(out); ctxErr.setDelegatee(err); final ErrorManager errors = context.getErrorManager(); final Global global = context.createGlobal(); Context.setGlobal(global); // For each file on the command line. for (final String fileName : args) { if (fileName.startsWith("-")) { // ignore options in shared context mode (which was initialized upfront!) continue; } final File file = new File(fileName); final ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global); if (script == null || errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; } try { ScriptRuntime.apply(script, global); } catch (final NashornException e) { errors.error(e.toString()); if (context.getEnv()._dump_on_error) { e.printStackTrace(context.getErr()); } return RUNTIME_ERROR; } } } finally { context.getOut().flush(); context.getErr().flush(); Context.setGlobal(oldGlobal); } return SUCCESS; }
@Override public ScriptFunction getSetter() { return (set instanceof ScriptFunction) ? (ScriptFunction)set : null; }
ScriptObject getDataViewPrototype() { return ScriptFunction.getPrototype(getBuiltinDataView()); }
private static void checkCallable(final Object self) { if (!(self instanceof ScriptFunction || (self instanceof JSObject && ((JSObject)self).isFunction()))) { throw typeError("not.a.function", ScriptRuntime.safeToString(self)); } }