Object get(Scriptable scope, String name, Object javaObject, boolean isStatic) { Map<String, Object> ht = isStatic ? staticMembers : members; Object member = ht.get(name); if (!isStatic && member == null) { // Try to get static member from instance (LC3) member = staticMembers.get(name); } if (member == null) { member = this.getExplicitFunction(scope, name, javaObject, isStatic); if (member == null) return Scriptable.NOT_FOUND; } if (member instanceof Scriptable) { return member; } Context cx = Context.getContext(); Object rval; Class<?> type; try { if (member instanceof BeanProperty) { BeanProperty bp = (BeanProperty) member; if (bp.getter == null) return Scriptable.NOT_FOUND; rval = bp.getter.invoke(javaObject, Context.emptyArgs); type = bp.getter.method().getReturnType(); } else { Field field = (Field) member; rval = field.get(isStatic ? null : javaObject); type = field.getType(); } } catch (Exception ex) { throw Context.throwAsScriptRuntimeEx(ex); } // Need to wrap the object before we return it. scope = ScriptableObject.getTopLevelScope(scope); return cx.getWrapFactory().wrap(cx, scope, rval, type); }
private static Object doCall( Context cx, Scriptable scope, Scriptable thisObj, Function f, Object[] args, long argsToWrap) { // Wrap the rest of objects for (int i = 0; i != args.length; ++i) { if (0 != (argsToWrap & (1 << i))) { Object arg = args[i]; if (!(arg instanceof Scriptable)) { args[i] = cx.getWrapFactory().wrap(cx, scope, arg, null); } } } return f.call(cx, scope, thisObj, args); }
@Override public Object getDefaultValue(Class<?> hint) { if (hint == ScriptRuntime.FunctionClass) return this; Object rval; Class<?> type; try { rval = field.get(javaObject); type = field.getType(); } catch (IllegalAccessException accEx) { throw Context.reportRuntimeError1("msg.java.internal.private", field.getName()); } Context cx = Context.getContext(); rval = cx.getWrapFactory().wrap(cx, this, rval, type); if (rval instanceof Scriptable) { rval = ((Scriptable) rval).getDefaultValue(hint); } return rval; }
synchronized Object getPkgProperty(String name, Scriptable start, boolean createPkg) { Object cached = super.get(name, start); if (cached != NOT_FOUND) return cached; if (negativeCache != null && negativeCache.contains(name)) { // Performance optimization: see bug 421071 return null; } String className = (packageName.length() == 0) ? name : packageName + '.' + name; Context cx = Context.getContext(); ClassShutter shutter = cx.getClassShutter(); Scriptable newValue = null; if (shutter == null || shutter.visibleToScripts(className)) { Class<?> cl = null; if (classLoader != null) { cl = Kit.classOrNull(classLoader, className); } else { cl = Kit.classOrNull(className); } if (cl != null) { WrapFactory wrapFactory = cx.getWrapFactory(); newValue = wrapFactory.wrapJavaClass(cx, getTopLevelScope(this), cl); newValue.setPrototype(getPrototype()); } } if (newValue == null) { if (createPkg) { NativeJavaPackage pkg; pkg = new NativeJavaPackage(true, className, classLoader); ScriptRuntime.setObjectProtoAndParent(pkg, getParentScope()); newValue = pkg; } else { // add to negative cache if (negativeCache == null) negativeCache = new HashSet<String>(); negativeCache.add(name); } } if (newValue != null) { // Make it available for fast lookup and sharing of // lazily-reflected constructors and static members. super.put(name, start, newValue); } return newValue; }
/* The JavaScript constructor */ private static Object jsConstructor( Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (args.length == 0 || args[0] == null || args[0] == Undefined.instance) { Object argument = args.length == 0 ? Undefined.instance : args[0]; throw ScriptRuntime.typeError1("msg.no.properties", ScriptRuntime.toString(argument)); } Scriptable obj = ScriptRuntime.toObject(scope, args[0]); boolean keyOnly = args.length > 1 && ScriptRuntime.toBoolean(args[1]); if (thisObj != null) { // Called as a function. Convert to iterator if possible. // For objects that implement java.lang.Iterable or // java.util.Iterator, have JavaScript Iterator call the underlying // iteration methods Iterator<?> iterator = VMBridge.instance.getJavaIterator(cx, scope, obj); if (iterator != null) { scope = ScriptableObject.getTopLevelScope(scope); return cx.getWrapFactory() .wrap(cx, scope, new WrappedJavaIterator(iterator, scope), WrappedJavaIterator.class); } // Otherwise, just call the runtime routine Scriptable jsIterator = ScriptRuntime.toIterator(cx, scope, obj, keyOnly); if (jsIterator != null) { return jsIterator; } } // Otherwise, just set up to iterate over the properties of the object. // Do not call __iterator__ method. Object objectIterator = ScriptRuntime.enumInit( obj, cx, keyOnly ? ScriptRuntime.ENUMERATE_KEYS_NO_ITERATOR : ScriptRuntime.ENUMERATE_ARRAY_NO_ITERATOR); ScriptRuntime.setEnumNumbers(objectIterator, true); NativeIterator result = new NativeIterator(objectIterator); result.setPrototype(ScriptableObject.getClassPrototype(scope, result.getClassName())); result.setParentScope(scope); return result; }
Object invokeImpl(Context cx, Object target, Scriptable topScope, Method method, Object[] args) { int N = (args == null) ? 0 : args.length; Callable function = (Callable) target; Scriptable thisObj = topScope; Object[] jsargs = new Object[N + 1]; jsargs[N] = method.getName(); if (N != 0) { WrapFactory wf = cx.getWrapFactory(); for (int i = 0; i != N; ++i) { jsargs[i] = wf.wrap(cx, topScope, args[i], null); } } Object result = function.call(cx, topScope, thisObj, jsargs); Class<?> javaResultType = method.getReturnType(); if (javaResultType == Void.TYPE) { result = null; } else { result = Context.jsToJava(result, javaResultType); } return result; }
@Override public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { // Find a method that matches the types given. if (methods.length == 0) { throw new RuntimeException("No methods defined for call"); } int index = findFunction(cx, methods, args); if (index < 0) { Class<?> c = methods[0].method().getDeclaringClass(); String sig = c.getName() + '.' + getFunctionName() + '(' + scriptSignature(args) + ')'; throw Context.reportRuntimeError1("msg.java.no_such_method", sig); } MemberBox meth = methods[index]; Class<?>[] argTypes = meth.argTypes; if (meth.vararg) { // marshall the explicit parameters Object[] newArgs = new Object[argTypes.length]; for (int i = 0; i < argTypes.length - 1; i++) { newArgs[i] = Context.jsToJava(args[i], argTypes[i]); } Object varArgs; // Handle special situation where a single variable parameter // is given and it is a Java or ECMA array or is null. if (args.length == argTypes.length && (args[args.length - 1] == null || args[args.length - 1] instanceof NativeArray || args[args.length - 1] instanceof NativeJavaArray)) { // convert the ECMA array into a native array varArgs = Context.jsToJava(args[args.length - 1], argTypes[argTypes.length - 1]); } else { // marshall the variable parameters Class<?> componentType = argTypes[argTypes.length - 1].getComponentType(); varArgs = Array.newInstance(componentType, args.length - argTypes.length + 1); for (int i = 0; i < Array.getLength(varArgs); i++) { Object value = Context.jsToJava(args[argTypes.length - 1 + i], componentType); Array.set(varArgs, i, value); } } // add varargs newArgs[argTypes.length - 1] = varArgs; // replace the original args with the new one args = newArgs; } else { // First, we marshall the args. Object[] origArgs = args; for (int i = 0; i < args.length; i++) { Object arg = args[i]; Object coerced = Context.jsToJava(arg, argTypes[i]); if (coerced != arg) { if (origArgs == args) { args = args.clone(); } args[i] = coerced; } } } Object javaObject; if (meth.isStatic()) { javaObject = null; // don't need an object } else { Scriptable o = thisObj; Class<?> c = meth.getDeclaringClass(); for (; ; ) { if (o == null) { throw Context.reportRuntimeError3( "msg.nonjava.method", getFunctionName(), ScriptRuntime.toString(thisObj), c.getName()); } if (o instanceof Wrapper) { javaObject = ((Wrapper) o).unwrap(); if (c.isInstance(javaObject)) { break; } } o = o.getPrototype(); } } if (debug) { printDebug("Calling ", meth, args); } Object retval = meth.invoke(javaObject, args); Class<?> staticType = meth.method().getReturnType(); if (debug) { Class<?> actualType = (retval == null) ? null : retval.getClass(); System.err.println( " ----- Returned " + retval + " actual = " + actualType + " expect = " + staticType); } Object wrapped = cx.getWrapFactory() .wrap( cx, scope, retval, staticType); if (debug) { Class<?> actualType = (wrapped == null) ? null : wrapped.getClass(); System.err.println(" ----- Wrapped as " + wrapped + " class = " + actualType); } if (wrapped == null && staticType == Void.TYPE) { wrapped = Undefined.instance; } return wrapped; }
/** * Performs conversions on argument types if needed and invokes the underlying Java method or * constructor. * * <p>Implements Function.call. * * @see gov.nbcs.rp.common.js.javascript.Function#call( Context, Scriptable, Scriptable, Object[]) */ public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { Object result; boolean checkMethodResult = false; if (parmsLength < 0) { if (parmsLength == VARARGS_METHOD) { Object[] invokeArgs = {cx, thisObj, args, this}; result = member.invoke(null, invokeArgs); checkMethodResult = true; } else { boolean inNewExpr = (thisObj == null); Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE; Object[] invokeArgs = {cx, args, this, b}; result = (member.isCtor()) ? member.newInstance(invokeArgs) : member.invoke(null, invokeArgs); } } else { if (!isStatic) { Class clazz = member.getDeclaringClass(); if (!clazz.isInstance(thisObj)) { boolean compatible = false; if (thisObj == scope) { Scriptable parentScope = getParentScope(); if (scope != parentScope) { // Call with dynamic scope for standalone function, // use parentScope as thisObj compatible = clazz.isInstance(parentScope); if (compatible) { thisObj = parentScope; } } } if (!compatible) { // Couldn't find an object to call this on. throw ScriptRuntime.typeError1("msg.incompat.call", functionName); } } } Object[] invokeArgs; if (parmsLength == args.length) { // Do not allocate new argument array if java arguments are // the same as the original js ones. invokeArgs = args; for (int i = 0; i != parmsLength; ++i) { Object arg = args[i]; Object converted = convertArg(cx, scope, arg, typeTags[i]); if (arg != converted) { if (invokeArgs == args) { invokeArgs = (Object[]) args.clone(); } invokeArgs[i] = converted; } } } else if (parmsLength == 0) { invokeArgs = ScriptRuntime.emptyArgs; } else { invokeArgs = new Object[parmsLength]; for (int i = 0; i != parmsLength; ++i) { Object arg = (i < args.length) ? args[i] : Undefined.instance; invokeArgs[i] = convertArg(cx, scope, arg, typeTags[i]); } } if (member.isMethod()) { result = member.invoke(thisObj, invokeArgs); checkMethodResult = true; } else { result = member.newInstance(invokeArgs); } } if (checkMethodResult) { if (hasVoidReturn) { result = Undefined.instance; } else if (returnTypeTag == JAVA_UNSUPPORTED_TYPE) { result = cx.getWrapFactory().wrap(cx, scope, result, null); } // XXX: the code assumes that if returnTypeTag == JAVA_OBJECT_TYPE // then the Java method did a proper job of converting the // result to JS primitive or Scriptable to avoid // potentially costly Context.javaToJS call. } return result; }
/** * @deprecated Use {@link Context#getWrapFactory()} together with calling {@link * WrapFactory#wrap(Context, Scriptable, Object, Class)} */ public static Object wrap(Scriptable scope, Object obj, Class<?> staticType) { Context cx = Context.getContext(); return cx.getWrapFactory().wrap(cx, scope, obj, staticType); }