Esempio n. 1
0
 final XML ecmaToXml(Object object) {
   //    See ECMA357 10.3
   if (object == null || object == Undefined.instance) {
     throw ScriptRuntime.typeError("Cannot convert " + object + " to XML");
   }
   if (object instanceof XML) return (XML) object;
   if (object instanceof XMLList) {
     XMLList list = (XMLList) object;
     if (list.getXML() != null) {
       return list.getXML();
     } else {
       throw ScriptRuntime.typeError("Cannot convert list of >1 element to XML");
     }
   }
   //    TODO    Technically we should fail on anything except a String, Number or Boolean
   //            See ECMA357 10.3
   // Extension: if object is a DOM node, use that to construct the XML
   // object.
   if (object instanceof Wrapper) {
     object = ((Wrapper) object).unwrap();
   }
   if (object instanceof org.w3c.dom.Node) {
     org.w3c.dom.Node node = (org.w3c.dom.Node) object;
     return newXML(XmlNode.createElementFromNode(node));
   }
   //    Instead we just blindly cast to a String and let them convert anything.
   String s = ScriptRuntime.toString(object);
   //    TODO    Could this get any uglier?
   if (s.length() > 0 && s.charAt(0) == '<') {
     return parse(s);
   } else {
     return newXML(XmlNode.createText(options, s));
   }
 }
Esempio n. 2
0
  private Object applyOrCall(
      boolean isApply, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
    String methodName = isApply ? "apply" : "call";
    if (!(thisObj instanceof XMLList) || ((XMLList) thisObj).targetProperty == null)
      throw ScriptRuntime.typeError1("msg.isnt.function", methodName);

    return ScriptRuntime.applyOrCall(isApply, cx, scope, thisObj, args);
  }
Esempio n. 3
0
  @Override
  void putXMLProperty(XMLName xmlName, Object value) {
    // Log("put property: " + name);

    // Special-case checks for undefined and null
    if (value == null) {
      value = "null";
    } else if (value instanceof Undefined) {
      value = "undefined";
    }

    if (length() > 1) {
      throw ScriptRuntime.typeError("Assignment to lists with more than one item is not supported");
    } else if (length() == 0) {
      // Secret sauce for super-expandos.
      // We set an element here, and then add ourselves to our target.
      if (targetObject != null
          && targetProperty != null
          && targetProperty.getLocalName() != null
          && targetProperty.getLocalName().length() > 0) {
        // Add an empty element with our targetProperty name and
        // then set it.
        XML xmlValue = newTextElementXML(null, targetProperty, null);
        addToList(xmlValue);

        if (xmlName.isAttributeName()) {
          setAttribute(xmlName, value);
        } else {
          XML xml = item(0);
          xml.putXMLProperty(xmlName, value);

          // Update the list with the new item at location 0.
          replace(0, item(0));
        }

        // Now add us to our parent
        XMLName name2 =
            XMLName.formProperty(
                targetProperty.getNamespace().getUri(), targetProperty.getLocalName());
        targetObject.putXMLProperty(name2, this);
        replace(0, targetObject.getXML().getLastXmlChild());
      } else {
        throw ScriptRuntime.typeError("Assignment to empty XMLList without targets not supported");
      }
    } else if (xmlName.isAttributeName()) {
      setAttribute(xmlName, value);
    } else {
      XML xml = item(0);
      xml.putXMLProperty(xmlName, value);

      // Update the list with the new item at location 0.
      replace(0, item(0));
    }
  }
Esempio n. 4
0
 private static RuntimeException badXMLName(Object value) {
   String msg;
   if (value instanceof Number) {
     msg = "Can not construct XML name from number: ";
   } else if (value instanceof Boolean) {
     msg = "Can not construct XML name from boolean: ";
   } else if (value == Undefined.instance || value == null) {
     msg = "Can not construct XML name from ";
   } else {
     throw new IllegalArgumentException(value.toString());
   }
   return ScriptRuntime.typeError(msg + ScriptRuntime.toString(value));
 }
Esempio n. 5
0
 private String getStringProperty(Scriptable obj, String name, String defaultValue) {
   Object value = ScriptableObject.getProperty(obj, name);
   if (value != null && value != ScriptableObject.NOT_FOUND) {
     return ScriptRuntime.toString(value);
   }
   return defaultValue;
 }
 private static int printSourceNumber(String source, int offset, StringBuffer sb) {
   double number = 0.0;
   char type = source.charAt(offset);
   ++offset;
   if (type == 'S') {
     if (sb != null) {
       number = source.charAt(offset);
     }
     ++offset;
   } else if (type == 'J' || type == 'D') {
     if (sb != null) {
       long lbits;
       lbits = (long) source.charAt(offset) << 48;
       lbits |= (long) source.charAt(offset + 1) << 32;
       lbits |= (long) source.charAt(offset + 2) << 16;
       lbits |= (long) source.charAt(offset + 3);
       if (type == 'J') {
         number = lbits;
       } else {
         number = Double.longBitsToDouble(lbits);
       }
     }
     offset += 4;
   } else {
     // Bad source
     throw new RuntimeException();
   }
   if (sb != null) {
     sb.append(ScriptRuntime.numberToString(number, 10));
   }
   return offset;
 }
Esempio n. 7
0
  XmlNode.QName toNodeQName(Context cx, Object namespaceValue, Object nameValue) {
    // This is duplication of constructQName(cx, namespaceValue, nameValue)
    // but for XMLName

    String localName;

    if (nameValue instanceof QName) {
      QName qname = (QName) nameValue;
      localName = qname.localName();
    } else {
      localName = ScriptRuntime.toString(nameValue);
    }

    XmlNode.Namespace ns;
    if (namespaceValue == Undefined.instance) {
      if ("*".equals(localName)) {
        ns = null;
      } else {
        ns = getDefaultNamespace(cx).getDelegate();
      }
    } else if (namespaceValue == null) {
      ns = null;
    } else if (namespaceValue instanceof Namespace) {
      ns = ((Namespace) namespaceValue).getDelegate();
    } else {
      ns = this.namespacePrototype.constructNamespace(namespaceValue).getDelegate();
    }

    if (localName != null && localName.equals("*")) localName = null;
    return XmlNode.QName.create(ns, localName);
  }
Esempio n. 8
0
 private XML parse(String frag) {
   try {
     return newXML(
         XmlNode.createElement(
             options, getDefaultNamespaceURI(Context.getCurrentContext()), frag));
   } catch (SAXException e) {
     throw ScriptRuntime.typeError("Cannot parse XML: " + e.getMessage());
   }
 }
Esempio n. 9
0
  /**
   * If value represents Uint32 index, make it available through ScriptRuntime.lastUint32Result(cx)
   * and return null. Otherwise return the same value as toXMLName(cx, value).
   */
  XMLName toXMLNameOrIndex(Context cx, Object value) {
    XMLName result;

    if (value instanceof XMLName) {
      result = (XMLName) value;
    } else if (value instanceof String) {
      String str = (String) value;
      long test = ScriptRuntime.testUint32String(str);
      if (test >= 0) {
        ScriptRuntime.storeUint32Result(cx, test);
        result = null;
      } else {
        result = toXMLNameFromString(cx, str);
      }
    } else if (value instanceof Number) {
      double d = ((Number) value).doubleValue();
      long l = (long) d;
      if (l == d && 0 <= l && l <= 0xFFFFFFFFL) {
        ScriptRuntime.storeUint32Result(cx, l);
        result = null;
      } else {
        throw badXMLName(value);
      }
    } else if (value instanceof QName) {
      QName qname = (QName) value;
      String uri = qname.uri();
      boolean number = false;
      result = null;
      if (uri != null && uri.length() == 0) {
        // Only in this case qname.toString() can resemble uint32
        long test = ScriptRuntime.testUint32String(uri);
        if (test >= 0) {
          ScriptRuntime.storeUint32Result(cx, test);
          number = true;
        }
      }
      if (!number) {
        result = XMLName.formProperty(uri, qname.localName());
      }
    } else if (value instanceof Boolean || value == Undefined.instance || value == null) {
      throw badXMLName(value);
    } else {
      String str = ScriptRuntime.toString(value);
      long test = ScriptRuntime.testUint32String(str);
      if (test >= 0) {
        ScriptRuntime.storeUint32Result(cx, test);
        result = null;
      } else {
        result = toXMLNameFromString(cx, str);
      }
    }

    return result;
  }
Esempio n. 10
0
 /*
  * Analog of match_glob() in jsstr.c
  */
 private static void match_glob(
     GlobData mdata, Context cx, Scriptable scope, int count, RegExpImpl reImpl) {
   if (mdata.arrayobj == null) {
     Scriptable s = ScriptableObject.getTopLevelScope(scope);
     mdata.arrayobj = ScriptRuntime.newObject(cx, s, "Array", null);
   }
   SubString matchsub = reImpl.lastMatch;
   String matchstr = matchsub.toString();
   mdata.arrayobj.put(count, mdata.arrayobj, matchstr);
 }
Esempio n. 11
0
  public Object action(
      Context cx, Scriptable scope, Scriptable thisObj, Object[] args, int actionType) {
    GlobData data = new GlobData();
    data.mode = actionType;

    switch (actionType) {
      case RA_MATCH:
        {
          Object rval;
          data.optarg = 1;
          rval = matchOrReplace(cx, scope, thisObj, args, this, data, false);
          return data.arrayobj == null ? rval : data.arrayobj;
        }

      case RA_SEARCH:
        data.optarg = 1;
        return matchOrReplace(cx, scope, thisObj, args, this, data, false);

      case RA_REPLACE:
        {
          Object arg1 = args.length < 2 ? Undefined.instance : args[1];
          String repstr = null;
          Function lambda = null;
          if (arg1 instanceof Function) {
            lambda = (Function) arg1;
          } else {
            repstr = ScriptRuntime.toString(arg1);
          }

          data.optarg = 2;
          data.lambda = lambda;
          data.repstr = repstr;
          data.dollar = repstr == null ? -1 : repstr.indexOf('$');
          data.charBuf = null;
          data.leftIndex = 0;
          Object val = matchOrReplace(cx, scope, thisObj, args, this, data, true);
          SubString rc = this.rightContext;

          if (data.charBuf == null) {
            if (data.global || val == null || !val.equals(Boolean.TRUE)) {
              /* Didn't match even once. */
              return data.str;
            }
            SubString lc = this.leftContext;
            replace_glob(data, cx, scope, this, lc.index, lc.length);
          }
          data.charBuf.append(rc.charArray, rc.index, rc.length);
          return data.charBuf.toString();
        }

      default:
        throw Kit.codeBug();
    }
  }
Esempio n. 12
0
 @Override
 boolean propertyIsEnumerable(Object name) {
   long index;
   if (name instanceof Integer) {
     index = ((Integer) name).intValue();
   } else if (name instanceof Number) {
     double x = ((Number) name).doubleValue();
     index = (long) x;
     if (index != x) {
       return false;
     }
     if (index == 0 && 1.0 / x < 0) {
       // Negative 0
       return false;
     }
   } else {
     String s = ScriptRuntime.toString(name);
     index = ScriptRuntime.testUint32String(s);
   }
   return (0 <= index && index < length());
 }
Esempio n. 13
0
    private Scriptable alloc(Context cx, Object[] args) {
      ScriptableObject obj = objArg(args, 0, ScriptableObject.class, true);
      int size = intArg(args, 1);
      Object typeObj = objArg(args, 2, Object.class, false);
      int type;

      if ((typeObj == null) || Undefined.instance.equals(typeObj)) {
        type = 2;
      } else {
        type = ScriptRuntime.toInt32(typeObj);
      }

      if (obj.getExternalArrayData() != null) {
        throw Utils.makeTypeError(cx, this, "object already has external array data");
      }

      ExternalArrayData array;
      // Switch needs to match constants in smalloc.js
      switch (type) {
        case 1:
          array = new NativeInt8Array(size);
          break;
        case 2:
          array = new NativeUint8Array(size);
          break;
        case 3:
          array = new NativeInt16Array(size);
          break;
        case 4:
          array = new NativeUint16Array(size);
          break;
        case 5:
          array = new NativeInt32Array(size);
          break;
        case 6:
          array = new NativeUint32Array(size);
          break;
        case 7:
          array = new NativeFloat32Array(size);
          break;
        case 8:
          array = new NativeFloat64Array(size);
          break;
        case 9:
          array = new NativeUint8ClampedArray(size);
          break;
        default:
          throw Utils.makeError(cx, this, "Invalid array type");
      }

      obj.setExternalArrayData(array);
      return obj;
    }
Esempio n. 14
0
  /* TODO: Can this can be replaced by ecmaToXml below?
   */
  final XML newXMLFromJs(Object inputObject) {
    String frag;

    if (inputObject == null || inputObject == Undefined.instance) {
      frag = "";
    } else if (inputObject instanceof XMLObjectImpl) {
      // todo: faster way for XMLObjects?
      frag = ((XMLObjectImpl) inputObject).toXMLString();
    } else {
      frag = ScriptRuntime.toString(inputObject);
    }

    if (frag.trim().startsWith("<>")) {
      throw ScriptRuntime.typeError("Invalid use of XML object anonymous tags <></>.");
    }

    if (frag.indexOf("<") == -1) {
      //    Solo text node
      return newXML(XmlNode.createText(options, frag));
    }
    return parse(frag);
  }
Esempio n. 15
0
  final XMLList newXMLListFrom(Object inputObject) {
    XMLList rv = newXMLList();

    if (inputObject == null || inputObject instanceof Undefined) {
      return rv;
    } else if (inputObject instanceof XML) {
      XML xml = (XML) inputObject;
      rv.getNodeList().add(xml);
      return rv;
    } else if (inputObject instanceof XMLList) {
      XMLList xmll = (XMLList) inputObject;
      rv.getNodeList().add(xmll.getNodeList());
      return rv;
    } else {
      String frag = ScriptRuntime.toString(inputObject).trim();

      if (!frag.startsWith("<>")) {
        frag = "<>" + frag + "</>";
      }

      frag = "<fragment>" + frag.substring(2);
      if (!frag.endsWith("</>")) {
        throw ScriptRuntime.typeError("XML with anonymous tag missing end anonymous tag");
      }

      frag = frag.substring(0, frag.length() - 3) + "</fragment>";

      XML orgXML = newXMLFromJs(frag);

      // Now orphan the children and add them to our XMLList.
      XMLList children = orgXML.children();

      for (int i = 0; i < children.getNodeList().length(); i++) {
        // Copy here is so that they'll be orphaned (parent() will be undefined)
        rv.getNodeList().add(((XML) children.item(i).copy()));
      }
      return rv;
    }
  }
  /** {@inheritDoc} */
  @Override
  public String getIdentifier(final Object entry) {
    // should be final but cannot be for sake of exception handling
    String identifier;

    if (entry instanceof Scriptable) {
      final Context cx = Context.enter();
      try {
        final Object toString = ScriptableObject.getProperty((Scriptable) entry, "toString");
        if (toString instanceof Function) {
          final Object toStringResult =
              ((Function) toString).call(cx, (Scriptable) entry, (Scriptable) entry, new Object[0]);
          identifier = ScriptRuntime.toString(toStringResult);
        } else if (toString != Scriptable.NOT_FOUND) {
          identifier = ScriptRuntime.toString(toString);
        } else if (entry instanceof BaseFunction) {
          final String functionName = ((BaseFunction) entry).getFunctionName();
          identifier =
              functionName != null && functionName.length() != 0 ? functionName : entry.toString();
        } else {
          identifier = entry.toString();
        }
      } catch (final RhinoException ex) {
        LOGGER.debug(
            "Exception determining entry identifier via Rhino - falling back to simple toString",
            ex);
        identifier = entry.toString();
      } finally {
        Context.exit();
      }
    } else if (entry != null) {
      identifier = entry.toString();
    } else {
      identifier = null;
    }

    return identifier;
  }
Esempio n. 17
0
 /**
  * Take an object from the scripting layer and convert it to an int.
  *
  * @param obj
  * @return int
  */
 private int toInt(Object obj) {
   int result = 0;
   if (obj instanceof String) {
     result = Integer.parseInt((String) obj);
   } else if (obj instanceof Number) {
     result = ((Number) obj).intValue();
   } else if (obj instanceof Scriptable) {
     Scriptable sobj = (Scriptable) obj;
     if (sobj.getClassName().equals("Number")) {
       result = (int) ScriptRuntime.toNumber(sobj);
     }
   }
   return result;
 }
Esempio n. 18
0
  public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
    // This XMLList is being called as a Function.
    // Let's find the real Function object.
    if (targetProperty == null) throw ScriptRuntime.notFunctionError(this);

    String methodName = targetProperty.getLocalName();

    boolean isApply = methodName.equals("apply");
    if (isApply || methodName.equals("call")) return applyOrCall(isApply, cx, scope, thisObj, args);

    if (!(thisObj instanceof XMLObject)) {
      throw ScriptRuntime.typeError1("msg.incompat.call", methodName);
    }
    Object func = null;
    Scriptable sobj = thisObj;

    while (sobj instanceof XMLObject) {
      XMLObject xmlObject = (XMLObject) sobj;
      func = xmlObject.getFunctionProperty(cx, methodName);
      if (func != Scriptable.NOT_FOUND) {
        break;
      }
      sobj = xmlObject.getExtraMethodSource(cx);
      if (sobj != null) {
        thisObj = sobj;
        if (!(sobj instanceof XMLObject)) {
          func = ScriptableObject.getProperty(sobj, methodName);
        }
      }
    }

    if (!(func instanceof Callable)) {
      throw ScriptRuntime.notFunctionError(thisObj, func, methodName);
    }
    return ((Callable) func).call(cx, scope, thisObj, args);
  }
Esempio n. 19
0
 /*
    TODO: Too general; this should be split into overloaded methods.
    Is that possible?
 */
 XmlNode.QName toNodeQName(Context cx, Object nameValue, boolean attribute) {
   if (nameValue instanceof XMLName) {
     return ((XMLName) nameValue).toQname();
   } else if (nameValue instanceof QName) {
     QName qname = (QName) nameValue;
     return qname.getDelegate();
   } else if (nameValue instanceof Boolean
       || nameValue instanceof Number
       || nameValue == Undefined.instance
       || nameValue == null) {
     throw badXMLName(nameValue);
   } else {
     String local = null;
     if (nameValue instanceof String) {
       local = (String) nameValue;
     } else {
       local = ScriptRuntime.toString(nameValue);
     }
     return toNodeQName(cx, local, attribute);
   }
 }
Esempio n. 20
0
  Namespace getDefaultNamespace(Context cx) {
    if (cx == null) {
      cx = Context.getCurrentContext();
      if (cx == null) {
        return namespacePrototype;
      }
    }

    Object ns = ScriptRuntime.searchDefaultNamespace(cx);
    if (ns == null) {
      return namespacePrototype;
    } else {
      if (ns instanceof Namespace) {
        return (Namespace) ns;
      } else {
        //    TODO    Clarify or remove the following comment
        // Should not happen but for now it could
        // due to bad searchDefaultNamespace implementation.
        return namespacePrototype;
      }
    }
  }
Esempio n. 21
0
  /* TODO: Marked deprecated by original author */
  XMLName toXMLName(Context cx, Object nameValue) {
    XMLName result;

    if (nameValue instanceof XMLName) {
      result = (XMLName) nameValue;
    } else if (nameValue instanceof QName) {
      QName qname = (QName) nameValue;
      result = XMLName.formProperty(qname.uri(), qname.localName());
    } else if (nameValue instanceof String) {
      result = toXMLNameFromString(cx, (String) nameValue);
    } else if (nameValue instanceof Boolean
        || nameValue instanceof Number
        || nameValue == Undefined.instance
        || nameValue == null) {
      throw badXMLName(nameValue);
    } else {
      String name = ScriptRuntime.toString(nameValue);
      result = toXMLNameFromString(cx, name);
    }

    return result;
  }
Esempio n. 22
0
 /** @deprecated */
 XMLName toAttributeName(Context cx, Object nameValue) {
   if (nameValue instanceof XMLName) {
     //    TODO    Will this always be an XMLName of type attribute name?
     return (XMLName) nameValue;
   } else if (nameValue instanceof QName) {
     return XMLName.create(((QName) nameValue).getDelegate(), true, false);
   } else if (nameValue instanceof Boolean
       || nameValue instanceof Number
       || nameValue == Undefined.instance
       || nameValue == null) {
     throw badXMLName(nameValue);
   } else {
     //    TODO    Not 100% sure that putting these in global namespace is the right thing to do
     String localName = null;
     if (nameValue instanceof String) {
       localName = (String) nameValue;
     } else {
       localName = ScriptRuntime.toString(nameValue);
     }
     if (localName != null && localName.equals("*")) localName = null;
     return XMLName.create(
         XmlNode.QName.create(XmlNode.Namespace.create(""), localName), true, false);
   }
 }
Esempio n. 23
0
  @Override
  public synchronized Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
    Transaction previousTransaction = Transaction.currentTransaction();
    Transaction.startTransaction();
    String filename = (String) args[0];
    if (filename.startsWith(".")) filename = currentJslibPath + filename;
    filename = Pattern.compile("\\.\\./[^.]*/").matcher(filename).replaceAll("/");
    filename = filename.replace("./", "");
    InputStream inStream;
    ScriptableObject exportObject;
    String oldJsLibPath = currentJslibPath;
    try {
      File jslibFile = jslibFiles.get(filename);
      if (jslibFile == null && !filename.endsWith(".js")) {
        filename += ".js";
        jslibFile = jslibFiles.get(filename);
      }
      if (jslibFile == null)
        throw ScriptRuntime.constructError("Error", "File not found " + filename);
      exportObject = exports.get(filename);
      Long lastTimeStamp = lastTimeStamps.get(filename);
      if (lastTimeStamp == null || lastTimeStamp < jslibFile.lastModified()) {
        lastTimeStamps.put(filename, jslibFile.lastModified());
        inStream = new FileInputStream(jslibFile);
        exportObject = new NativeObject();
        ScriptRuntime.setObjectProtoAndParent((ScriptableObject) exportObject, global);
        // setup the module scope
        ScriptableObject moduleScope = new NativeObject();
        moduleScope.setParentScope(global);
        int lastSlash = filename.lastIndexOf('/');
        currentJslibPath = lastSlash == -1 ? "" : filename.substring(0, lastSlash + 1);
        moduleScope.put("exports", moduleScope, exportObject);
        // memoize
        exports.put(filename, exportObject);
        // evaluate the script
        try {
          cx.evaluateString(moduleScope, IOUtils.toString(inStream, "UTF-8"), filename, 1, null);
        } catch (RuntimeException e) {
          // revert
          exports.remove(filename);
          jslibFiles.put(filename, jslibFile);
          throw e;
        }
        // re-retrieve it in case the library changed it
        exportObject = (ScriptableObject) moduleScope.get("exports", moduleScope);
        exports.put(filename, exportObject);

        if ("jsgi-app.js".equals(filename)) {
          // handle jackconfig.js, setting up the app if it is there
          global.put("app", global, exportObject.get("app", exportObject));
        }
        // freeze it
        // exportObject.sealObject();
      }
      Transaction.currentTransaction().commit();
    } catch (IOException e) {
      throw ScriptRuntime.constructError("Error", e.getMessage());
    } finally {
      currentJslibPath = oldJsLibPath;
      previousTransaction.enterTransaction();
    }
    return exportObject;
  }
Esempio n. 24
0
 public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
   throw ScriptRuntime.typeError1("msg.not.ctor", "XMLList");
 }
Esempio n. 25
0
  /** Analog of C match_or_replace. */
  private static Object matchOrReplace(
      Context cx,
      Scriptable scope,
      Scriptable thisObj,
      Object[] args,
      RegExpImpl reImpl,
      GlobData data,
      boolean forceFlat) {
    NativeRegExp re;

    String str = ScriptRuntime.toString(thisObj);
    data.str = str;
    Scriptable topScope = ScriptableObject.getTopLevelScope(scope);

    if (args.length == 0) {
      Object compiled = NativeRegExp.compileRE(cx, "", "", false);
      re = new NativeRegExp(topScope, compiled);
    } else if (args[0] instanceof NativeRegExp) {
      re = (NativeRegExp) args[0];
    } else {
      String src = ScriptRuntime.toString(args[0]);
      String opt;
      if (data.optarg < args.length) {
        args[0] = src;
        opt = ScriptRuntime.toString(args[data.optarg]);
      } else {
        opt = null;
      }
      Object compiled = NativeRegExp.compileRE(cx, src, opt, forceFlat);
      re = new NativeRegExp(topScope, compiled);
    }
    data.regexp = re;

    data.global = (re.getFlags() & NativeRegExp.JSREG_GLOB) != 0;
    int[] indexp = {0};
    Object result = null;
    if (data.mode == RA_SEARCH) {
      result = re.executeRegExp(cx, scope, reImpl, str, indexp, NativeRegExp.TEST);
      if (result != null && result.equals(Boolean.TRUE))
        result = new Integer(reImpl.leftContext.length);
      else result = new Integer(-1);
    } else if (data.global) {
      re.lastIndex = 0;
      for (int count = 0; indexp[0] <= str.length(); count++) {
        result = re.executeRegExp(cx, scope, reImpl, str, indexp, NativeRegExp.TEST);
        if (result == null || !result.equals(Boolean.TRUE)) break;
        if (data.mode == RA_MATCH) {
          match_glob(data, cx, scope, count, reImpl);
        } else {
          if (data.mode != RA_REPLACE) Kit.codeBug();
          SubString lastMatch = reImpl.lastMatch;
          int leftIndex = data.leftIndex;
          int leftlen = lastMatch.index - leftIndex;
          data.leftIndex = lastMatch.index + lastMatch.length;
          replace_glob(data, cx, scope, reImpl, leftIndex, leftlen);
        }
        if (reImpl.lastMatch.length == 0) {
          if (indexp[0] == str.length()) break;
          indexp[0]++;
        }
      }
    } else {
      result =
          re.executeRegExp(
              cx,
              scope,
              reImpl,
              str,
              indexp,
              ((data.mode == RA_REPLACE) ? NativeRegExp.TEST : NativeRegExp.MATCH));
    }

    return result;
  }
Esempio n. 26
0
  /**
   * 对Scriptable对象转换成相应的Java对象
   *
   * <p>如果对象类型是数组,按下标数组和关联数组两种情况分别转换为Array和Map; 否则转换为对应的Java对象,或者是一个包含此对象所有属性的Map
   *
   * @param scriptObj 需要转换的Scriptable对象
   * @param context 上下文
   * @return return 转换后的Java对象
   */
  @SuppressWarnings({"rawtypes", "unchecked"})
  private static Object scriptableToJava(ScriptableObject scriptObj, Context context)
      throws IllegalAccessException, NoSuchFieldException {
    // Array & Arguments
    if (ScriptRuntime.isArrayObject(scriptObj)) {
      final Object[] arrayElements = (Object[]) context.getElements(scriptObj);
      // If scriptObj is a associative arry, arrayElements.length will
      // always 0
      // So if scriptObj is empty or index array, return true, else return
      // false
      if (scriptObj.getIds().length == 0 || arrayElements.length == scriptObj.getIds().length) {
        for (int i = 0; i < arrayElements.length; i++) {
          arrayElements[i] = jsToJava(arrayElements[i], context);
        }
        return arrayElements;
      } else {
        final Object[] ids = scriptObj.getIds();

        final HashMap map = new HashMap();
        for (int i = 0; i < ids.length; i++) {
          final String key = ids[i].toString();
          Object value = scriptObj.get(key, scriptObj);
          // if value is UniqueTag, means index is numeric,
          // should get its value by index
          if (value.getClass().equals(UniqueTag.class)) {
            value = scriptObj.get(Integer.parseInt(key), scriptObj);
          }
          map.put(ids[i], jsToJava(value, context));
        }
        return map;
      }
    } else {
      final String jsClassName = scriptObj.getClassName();
      // If jsClassName is 'Object', means scriptObj could't directly
      // convert to a normal java object, in this case we
      // return a map contains all properties in this scriptable object.
      if ("Object".equals(jsClassName)) {
        final Object[] ids = scriptObj.getIds();
        final HashMap map = new HashMap();
        for (int i = 0; i < ids.length; i++) {
          final String key = ids[i].toString();
          final Object value = scriptObj.get(key, scriptObj);
          map.put(key, jsToJava(value, context));
        }
        return map;
      }
      // If jsClassName is 'Funtion' & instanceof NativeFunction,
      // means scriptObj is a function defined in script,
      // in this case we return a String present source of this function
      else if ("Function".equals(jsClassName) && scriptObj instanceof NativeFunction) {
        final NativeFunction func = (NativeFunction) scriptObj;
        return Decompiler.decompile(
            func.getEncodedSource(), Decompiler.TO_SOURCE_FLAG, new UintMap());
      }
      // Else, we can covert it to a desired java object by
      // Context.jsToJava()
      else {
        final Class clazz =
            (Class) ScriptRuntime.class.getDeclaredField(jsClassName + "Class").get(scriptObj);
        return Context.jsToJava(scriptObj, clazz);
      }
    }
  }
Esempio n. 27
0
  /*
   * Analog of replace_glob() in jsstr.c
   */
  private static void replace_glob(
      GlobData rdata, Context cx, Scriptable scope, RegExpImpl reImpl, int leftIndex, int leftlen) {
    int replen;
    String lambdaStr;
    if (rdata.lambda != null) {
      // invoke lambda function with args lastMatch, $1, $2, ... $n,
      // leftContext.length, whole string.
      SubString[] parens = reImpl.parens;
      int parenCount = (parens == null) ? 0 : parens.length;
      Object[] args = new Object[parenCount + 3];
      args[0] = reImpl.lastMatch.toString();
      for (int i = 0; i < parenCount; i++) {
        SubString sub = parens[i];
        if (sub != null) {
          args[i + 1] = sub.toString();
        } else {
          args[i + 1] = Undefined.instance;
        }
      }
      args[parenCount + 1] = new Integer(reImpl.leftContext.length);
      args[parenCount + 2] = rdata.str;
      // This is a hack to prevent expose of reImpl data to
      // JS function which can run new regexps modifing
      // regexp that are used later by the engine.
      // TODO: redesign is necessary
      if (reImpl != ScriptRuntime.getRegExpProxy(cx)) Kit.codeBug();
      RegExpImpl re2 = new RegExpImpl();
      re2.multiline = reImpl.multiline;
      re2.input = reImpl.input;
      ScriptRuntime.setRegExpProxy(cx, re2);
      try {
        Scriptable parent = ScriptableObject.getTopLevelScope(scope);
        Object result = rdata.lambda.call(cx, parent, parent, args);
        lambdaStr = ScriptRuntime.toString(result);
      } finally {
        ScriptRuntime.setRegExpProxy(cx, reImpl);
      }
      replen = lambdaStr.length();
    } else {
      lambdaStr = null;
      replen = rdata.repstr.length();
      if (rdata.dollar >= 0) {
        int[] skip = new int[1];
        int dp = rdata.dollar;
        do {
          SubString sub = interpretDollar(cx, reImpl, rdata.repstr, dp, skip);
          if (sub != null) {
            replen += sub.length - skip[0];
            dp += skip[0];
          } else {
            ++dp;
          }
          dp = rdata.repstr.indexOf('$', dp);
        } while (dp >= 0);
      }
    }

    int growth = leftlen + replen + reImpl.rightContext.length;
    StringBuffer charBuf = rdata.charBuf;
    if (charBuf == null) {
      charBuf = new StringBuffer(growth);
      rdata.charBuf = charBuf;
    } else {
      charBuf.ensureCapacity(rdata.charBuf.length() + growth);
    }

    charBuf.append(reImpl.leftContext.charArray, leftIndex, leftlen);
    if (rdata.lambda != null) {
      charBuf.append(lambdaStr);
    } else {
      do_replace(rdata, cx, reImpl);
    }
  }