Ejemplo n.º 1
0
  private Ref xmlPrimaryReference(Context cx, XMLName xmlName, Scriptable scope) {
    XMLObjectImpl xmlObj;
    XMLObjectImpl firstXml = null;
    for (; ; ) {
      // XML object can only present on scope chain as a wrapper
      // of XMLWithScope
      if (scope instanceof XMLWithScope) {
        xmlObj = (XMLObjectImpl) scope.getPrototype();
        if (xmlObj.hasXMLProperty(xmlName)) {
          break;
        }
        if (firstXml == null) {
          firstXml = xmlObj;
        }
      }
      scope = scope.getParentScope();
      if (scope == null) {
        xmlObj = firstXml;
        break;
      }
    }

    // xmlObj == null corresponds to undefined as the target of
    // the reference
    if (xmlObj != null) {
      xmlName.initXMLObject(xmlObj);
    }
    return xmlName;
  }
Ejemplo n.º 2
0
  @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;
  }
Ejemplo n.º 3
0
  @Override
  public Object execIdCall(
      IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
    if (!f.hasTag(OBJECT_TAG)) {
      return super.execIdCall(f, cx, scope, thisObj, args);
    }
    int id = f.methodId();
    switch (id) {
      case Id_constructor:
        {
          if (thisObj != null) {
            // BaseFunction.construct will set up parent, proto
            return f.construct(cx, scope, args);
          }
          if (args.length == 0 || args[0] == null || args[0] == Undefined.instance) {
            return new NativeObject();
          }
          return ScriptRuntime.toObject(cx, scope, args[0]);
        }

      case Id_toLocaleString:
        {
          Object toString = ScriptableObject.getProperty(thisObj, "toString");
          if (!(toString instanceof Callable)) {
            throw ScriptRuntime.notFunctionError(toString);
          }
          Callable fun = (Callable) toString;
          return fun.call(cx, scope, thisObj, ScriptRuntime.emptyArgs);
        }

      case Id_toString:
        {
          if (cx.hasFeature(Context.FEATURE_TO_STRING_AS_SOURCE)) {
            String s =
                ScriptRuntime.defaultObjectToSource(
                    cx, scope,
                    thisObj, args);
            int L = s.length();
            if (L != 0 && s.charAt(0) == '(' && s.charAt(L - 1) == ')') {
              // Strip () that surrounds toSource
              s = s.substring(1, L - 1);
            }
            return s;
          }
          return ScriptRuntime.defaultObjectToString(thisObj);
        }

      case Id_valueOf:
        return thisObj;

      case Id_hasOwnProperty:
        {
          boolean result;
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          String s = ScriptRuntime.toStringIdOrIndex(cx, arg);
          if (s == null) {
            int index = ScriptRuntime.lastIndexResult(cx);
            result = thisObj.has(index, thisObj);
          } else {
            result = thisObj.has(s, thisObj);
          }
          return ScriptRuntime.wrapBoolean(result);
        }

      case Id_propertyIsEnumerable:
        {
          boolean result;
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          String s = ScriptRuntime.toStringIdOrIndex(cx, arg);
          if (s == null) {
            int index = ScriptRuntime.lastIndexResult(cx);
            result = thisObj.has(index, thisObj);
            if (result && thisObj instanceof ScriptableObject) {
              ScriptableObject so = (ScriptableObject) thisObj;
              int attrs = so.getAttributes(index);
              result = ((attrs & ScriptableObject.DONTENUM) == 0);
            }
          } else {
            result = thisObj.has(s, thisObj);
            if (result && thisObj instanceof ScriptableObject) {
              ScriptableObject so = (ScriptableObject) thisObj;
              int attrs = so.getAttributes(s);
              result = ((attrs & ScriptableObject.DONTENUM) == 0);
            }
          }
          return ScriptRuntime.wrapBoolean(result);
        }

      case Id_isPrototypeOf:
        {
          boolean result = false;
          if (args.length != 0 && args[0] instanceof Scriptable) {
            Scriptable v = (Scriptable) args[0];
            do {
              v = v.getPrototype();
              if (v == thisObj) {
                result = true;
                break;
              }
            } while (v != null);
          }
          return ScriptRuntime.wrapBoolean(result);
        }

      case Id_toSource:
        return ScriptRuntime.defaultObjectToSource(cx, scope, thisObj, args);
      case Id___defineGetter__:
      case Id___defineSetter__:
        {
          if (args.length < 2 || !(args[1] instanceof Callable)) {
            Object badArg = (args.length >= 2 ? args[1] : Undefined.instance);
            throw ScriptRuntime.notFunctionError(badArg);
          }
          if (!(thisObj instanceof ScriptableObject)) {
            throw Context.reportRuntimeError2(
                "msg.extend.scriptable", thisObj.getClass().getName(), String.valueOf(args[0]));
          }
          ScriptableObject so = (ScriptableObject) thisObj;
          String name = ScriptRuntime.toStringIdOrIndex(cx, args[0]);
          int index = (name != null ? 0 : ScriptRuntime.lastIndexResult(cx));
          Callable getterOrSetter = (Callable) args[1];
          boolean isSetter = (id == Id___defineSetter__);
          so.setGetterOrSetter(name, index, getterOrSetter, isSetter);
          if (so instanceof NativeArray) ((NativeArray) so).setDenseOnly(false);
        }
        return Undefined.instance;

      case Id___lookupGetter__:
      case Id___lookupSetter__:
        {
          if (args.length < 1 || !(thisObj instanceof ScriptableObject)) return Undefined.instance;

          ScriptableObject so = (ScriptableObject) thisObj;
          String name = ScriptRuntime.toStringIdOrIndex(cx, args[0]);
          int index = (name != null ? 0 : ScriptRuntime.lastIndexResult(cx));
          boolean isSetter = (id == Id___lookupSetter__);
          Object gs;
          for (; ; ) {
            gs = so.getGetterOrSetter(name, index, isSetter);
            if (gs != null) break;
            // If there is no getter or setter for the object itself,
            // how about the prototype?
            Scriptable v = so.getPrototype();
            if (v == null) break;
            if (v instanceof ScriptableObject) so = (ScriptableObject) v;
            else break;
          }
          if (gs != null) return gs;
        }
        return Undefined.instance;

      case ConstructorId_getPrototypeOf:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          Scriptable obj = ensureScriptable(arg);
          return obj.getPrototype();
        }
      case ConstructorId_keys:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          Scriptable obj = ensureScriptable(arg);
          Object[] ids = obj.getIds();
          for (int i = 0; i < ids.length; i++) {
            ids[i] = ScriptRuntime.toString(ids[i]);
          }
          return cx.newArray(scope, ids);
        }
      case ConstructorId_getOwnPropertyNames:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          ScriptableObject obj = ensureScriptableObject(arg);
          Object[] ids = obj.getAllIds();
          for (int i = 0; i < ids.length; i++) {
            ids[i] = ScriptRuntime.toString(ids[i]);
          }
          return cx.newArray(scope, ids);
        }
      case ConstructorId_getOwnPropertyDescriptor:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          // TODO(norris): There's a deeper issue here if
          // arg instanceof Scriptable. Should we create a new
          // interface to admit the new ECMAScript 5 operations?
          ScriptableObject obj = ensureScriptableObject(arg);
          Object nameArg = args.length < 2 ? Undefined.instance : args[1];
          String name = ScriptRuntime.toString(nameArg);
          Scriptable desc = obj.getOwnPropertyDescriptor(cx, name);
          return desc == null ? Undefined.instance : desc;
        }
      case ConstructorId_defineProperty:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          ScriptableObject obj = ensureScriptableObject(arg);
          Object name = args.length < 2 ? Undefined.instance : args[1];
          Object descArg = args.length < 3 ? Undefined.instance : args[2];
          ScriptableObject desc = ensureScriptableObject(descArg);
          obj.defineOwnProperty(cx, name, desc);
          return obj;
        }
      case ConstructorId_isExtensible:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          ScriptableObject obj = ensureScriptableObject(arg);
          return Boolean.valueOf(obj.isExtensible());
        }
      case ConstructorId_preventExtensions:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          ScriptableObject obj = ensureScriptableObject(arg);
          obj.preventExtensions();
          return obj;
        }
      case ConstructorId_defineProperties:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          ScriptableObject obj = ensureScriptableObject(arg);
          Object propsObj = args.length < 2 ? Undefined.instance : args[1];
          Scriptable props = Context.toObject(propsObj, getParentScope());
          obj.defineOwnProperties(cx, ensureScriptableObject(props));
          return obj;
        }
      case ConstructorId_create:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          Scriptable obj = (arg == null) ? null : ensureScriptable(arg);

          ScriptableObject newObject = new NativeObject();
          newObject.setParentScope(getParentScope());
          newObject.setPrototype(obj);

          if (args.length > 1 && args[1] != Undefined.instance) {
            Scriptable props = Context.toObject(args[1], getParentScope());
            newObject.defineOwnProperties(cx, ensureScriptableObject(props));
          }

          return newObject;
        }
      case ConstructorId_isSealed:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          ScriptableObject obj = ensureScriptableObject(arg);

          if (obj.isExtensible()) return Boolean.FALSE;

          for (Object name : obj.getAllIds()) {
            Object configurable = obj.getOwnPropertyDescriptor(cx, name).get("configurable");
            if (Boolean.TRUE.equals(configurable)) return Boolean.FALSE;
          }

          return Boolean.TRUE;
        }
      case ConstructorId_isFrozen:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          ScriptableObject obj = ensureScriptableObject(arg);

          if (obj.isExtensible()) return Boolean.FALSE;

          for (Object name : obj.getAllIds()) {
            ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name);
            if (Boolean.TRUE.equals(desc.get("configurable"))) return Boolean.FALSE;
            if (isDataDescriptor(desc) && Boolean.TRUE.equals(desc.get("writable")))
              return Boolean.FALSE;
          }

          return Boolean.TRUE;
        }
      case ConstructorId_seal:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          ScriptableObject obj = ensureScriptableObject(arg);

          for (Object name : obj.getAllIds()) {
            ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name);
            if (Boolean.TRUE.equals(desc.get("configurable"))) {
              desc.put("configurable", desc, Boolean.FALSE);
              obj.defineOwnProperty(cx, name, desc, false);
            }
          }
          obj.preventExtensions();

          return obj;
        }
      case ConstructorId_freeze:
        {
          Object arg = args.length < 1 ? Undefined.instance : args[0];
          ScriptableObject obj = ensureScriptableObject(arg);

          for (Object name : obj.getAllIds()) {
            ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name);
            if (isDataDescriptor(desc) && Boolean.TRUE.equals(desc.get("writable")))
              desc.put("writable", desc, Boolean.FALSE);
            if (Boolean.TRUE.equals(desc.get("configurable")))
              desc.put("configurable", desc, Boolean.FALSE);
            obj.defineOwnProperty(cx, name, desc, false);
          }
          obj.preventExtensions();

          return obj;
        }

      default:
        throw new IllegalArgumentException(String.valueOf(id));
    }
  }