This commit was generated by cvs2svn to compensate for changes in r4,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
hns 2000-12-29 17:58:10 +00:00
parent af35ca5581
commit ee13186158
148 changed files with 34934 additions and 0 deletions

View file

@ -0,0 +1,185 @@
// ArrayObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import java.util.Hashtable;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
/**
* Implements the Array EcmaScript object. This is a singleton
*/
public class ArrayObject extends BuiltinFunctionObject {
private static final String JOINstring = ("join").intern();
private static final int JOINhash = JOINstring.hashCode();
private static final String LENGTHstring = ("length").intern();
private static final int LENGTHhash = LENGTHstring.hashCode();
private static final String ZEROstring = ("0").intern();
private static final int ZEROhash = ZEROstring.hashCode();
/**
* Create a new Array object - used by makeArrayObject
*
* @param prototype Must be an ArrayPrototype
* @param evaluator the evaluator
*/
private ArrayObject(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator, "Array", 1);
}
// overrides
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
return doConstruct(thisObject, arguments);
}
// overrides
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESObject ap = evaluator.getArrayPrototype();
ArrayPrototype theArray = new ArrayPrototype(ap, evaluator);
if (arguments.length > 1) {
for (int i=0; i<arguments.length; i++) {
String iString = Integer.toString(i);
theArray.putProperty(iString, arguments[i], iString.hashCode());
}
} else if (arguments.length == 1) {
ESValue firstArg = arguments[0];
// Not clear in standard:
if (firstArg.isNumberValue()) {
int length = (int) firstArg.toInt32();
theArray.putProperty(LENGTHstring, firstArg, LENGTHhash);
} else {
theArray.putProperty(ZEROstring, firstArg, ZEROhash);
}
}
return theArray;
}
/**
* Utility function to create the single Array object
*
* @param evaluator the Evaluator
* @param objectPrototype The Object prototype attached to the evaluator
* @param functionPrototype The Function prototype attached to the evaluator
*
* @return The Array singleton
*/
public static ArrayObject makeArrayObject(Evaluator evaluator,
ObjectPrototype objectPrototype,
FunctionPrototype functionPrototype) {
ArrayPrototype arrayPrototype = new ArrayPrototype(objectPrototype, evaluator);
ArrayObject arrayObject = new ArrayObject(functionPrototype, evaluator);
try {
// For arrayPrototype
class ArrayPrototypeToString extends BuiltinFunctionObject {
ArrayPrototypeToString(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
BuiltinFunctionObject join = (BuiltinFunctionObject)
thisObject.getProperty(JOINstring, JOINhash);
return join.callFunction(thisObject, new ESValue[0]);
}
}
class ArrayPrototypeJoin extends BuiltinFunctionObject {
ArrayPrototypeJoin(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
StringBuffer buffer = new StringBuffer();
String separator = ",";
if (arguments.length > 0) {
separator = arguments[0].toString();
}
int length = (thisObject.getProperty(ArrayObject.LENGTHstring, ArrayObject.LENGTHhash)).toInt32();
for (int i =0; i<length; i++) {
if (i>0) buffer.append(separator);
String iString = Integer.toString(i);
ESValue value = thisObject.getProperty(iString,iString.hashCode());
if (value!=ESUndefined.theUndefined && value!=ESNull.theNull) {
buffer.append(value.toString());
}
}
return new ESString(buffer.toString());
}
}
class ArrayPrototypeReverse extends BuiltinFunctionObject {
ArrayPrototypeReverse(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (!(thisObject instanceof ArrayPrototype)) {
throw new EcmaScriptException ("reverse only implemented for arrays");
}
return ((ArrayPrototype) thisObject).reverse();
}
}
class ArrayPrototypeSort extends BuiltinFunctionObject {
ArrayPrototypeSort(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (!(thisObject instanceof ArrayPrototype)) {
throw new EcmaScriptException ("sort only implemented for arrays");
}
ESValue compareFn = null;
if (arguments.length>0) compareFn = arguments[0];
return ((ArrayPrototype) thisObject).sort(compareFn);
}
}
arrayObject.putHiddenProperty("prototype",arrayPrototype);
arrayObject.putHiddenProperty(LENGTHstring,new ESNumber(1));
arrayPrototype.putHiddenProperty("constructor",arrayObject);
arrayPrototype.putHiddenProperty("toString",
new ArrayPrototypeToString("toString", evaluator, functionPrototype));
arrayPrototype.putHiddenProperty("join",
new ArrayPrototypeJoin("join", evaluator, functionPrototype));
arrayPrototype.putHiddenProperty("reverse",
new ArrayPrototypeReverse("reverse", evaluator, functionPrototype));
arrayPrototype.putHiddenProperty("sort",
new ArrayPrototypeSort("sort", evaluator, functionPrototype));
} catch (EcmaScriptException e) {
e.printStackTrace();
throw new ProgrammingError(e.getMessage());
}
evaluator.setArrayPrototype(arrayPrototype);
return arrayObject;
}
}

View file

@ -0,0 +1,585 @@
// ArrayPrototype.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import java.util.Vector;
import java.util.Enumeration;
import java.lang.reflect.Array;
/**
* Implements the prototype and is the class of all Array objects
*/
public class ArrayPrototype extends ESObject {
private static final String LENGTHstring = ("length").intern();
private static final int LENGTHhash = LENGTHstring.hashCode();
// The array value
// We could use a non synchronized vector or directly and array
protected Vector theArray = new Vector();
/**
* Create a new empty array
* @param prototype the ArrayPrototype
* @param evaluator The evaluator
*/
public ArrayPrototype(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator);
}
// overrides
public String getESClassName() {
return "Array";
}
/**
* Return a Java array object which is the object to pass to Java routines
* called by FESI.
* @ param componentType the type of the component of the array
* @return a java array object
*/
public Object toJavaArray(Class componentType) throws EcmaScriptException {
int l = size();
Object array = Array.newInstance(componentType, l);
if (l ==0) return array;
for (int i =0; i<l; i++) {
ESValue element = (ESValue) theArray.elementAt(i);
if (componentType==Integer.TYPE) {
if (element.isNumberValue()) {
double d = element.doubleValue();
int value = (int) d;
if (value != d) {
throw new EcmaScriptException("An element (" + element + ") of array is too large for class " + componentType);
}
Array.setInt(array,i,value);
} else {
throw new EcmaScriptException("An element (" + element + ") of array cannot be converted to class " + componentType);
}
} else if (componentType==Short.TYPE) {
if (element.isNumberValue()) {
double d = element.doubleValue();
short value = (short) d;
if (value != d) {
throw new EcmaScriptException("An element (" + element + ") of array is too large for class " + componentType);
}
Array.setShort(array,i,value);
} else {
throw new EcmaScriptException("An element (" + element + ") of array cannot be converted to class " + componentType);
}
} else if (componentType==Byte.TYPE) {
if (element.isNumberValue()) {
double d = element.doubleValue();
byte value = (byte) d;
if (value != d) {
throw new EcmaScriptException("An element (" + element + ") of array is too large for class " + componentType);
}
Array.setByte(array,i,value);
} else {
throw new EcmaScriptException("An element (" + element + ") of array cannot be converted to class " + componentType);
}
} else if (componentType==Long.TYPE) {
if (element.isNumberValue()) {
double d = element.doubleValue();
long value = (long) d;
if (value != d) {
throw new EcmaScriptException("An element (" + element + ") of array is too large for class " + componentType);
}
Array.setLong(array,i,value);
} else {
throw new EcmaScriptException("An element (" + element + ") of array cannot be converted to class " + componentType);
}
} else if (componentType==Float.TYPE) {
if (element.isNumberValue()) {
double d = element.doubleValue();
float value = (float) d;
if (value != d) {
throw new EcmaScriptException("An element (" + element + ") of array is too large for class " + componentType);
}
Array.setFloat(array,i,value);
} else {
throw new EcmaScriptException("An element (" + element + ") of array cannot be converted to class " + componentType);
}
} else if (componentType==Double.TYPE) {
if (element.isNumberValue()) {
double d = element.doubleValue();
Array.setDouble(array,i,d);
} else {
throw new EcmaScriptException("An element (" + element + ") of array cannot be converted to class " + componentType);
}
} else if (componentType==Boolean.TYPE) {
if (element.isBooleanValue()) {
boolean b = element.booleanValue();
Array.setBoolean(array,i,b);
} else {
throw new EcmaScriptException("An element (" + element + ") of array cannot be converted to class " + componentType);
}
} else if (componentType==Character.TYPE) {
if (element.isStringValue()) {
String s = element.toString();
if (s.length()!=1) {
throw new EcmaScriptException("A string (" + element + ") of array is not of size 1 for conversion to Character");
}
Array.setChar(array,i,s.charAt(0));
} else {
throw new EcmaScriptException("An element (" + element + ") of array cannot be converted to class " + componentType);
}
} else {
Object o = element.toJavaObject();
if (o==null) {
Array.set(array,i,o);
} else {
Class sourceClass = o.getClass();
if (componentType.isAssignableFrom(sourceClass)) {
Array.set(array,i,o);
} else {
throw new EcmaScriptException("An element (" + element + ") of array cannot be converted to class " + componentType);
}
}
}
}
return array;
}
// overrides
public String toDetailString() {
return "ES:[" + getESClassName() + ":" + this.getClass().getName() +"]";
}
/**
* Return the size of the array
* @return the size as an int
*/
public int size() {
return theArray.size();
}
/**
* Set the size of the array, truncating if needed
* @param size the new size 90 or positive)
*/
public void setSize(int size) {
theArray.setSize(size);
}
/**
* Set the value of a specific element
*
* @param theElement the new element value
* @param index the index of the element
*/
public void setElementAt(ESValue theElement, int index) {
theArray.setElementAt(theElement, index);
}
/**
* Reverse the orders of the elements in an array
* @return the reversed array (which is the same as this one)
*/
public ESValue reverse() throws EcmaScriptException {
int size = theArray.size();
if (size>0) {
Vector reversed = new Vector(size);
reversed.setSize(size);
for (int i = 0, j=size-1; i<size; i++, j--) {
reversed.setElementAt(theArray.elementAt(j),i);
}
theArray = reversed;
}
return this;
}
// This routines are taken from Java examples in a nutshell
static interface Comparer {
/**
* Compare objects and return a value that indicates their relative order:
* if (a > b) return a number > 0;
* if (a == b) return 0;
* if (a < b) return a number < 0.
**/
int compare(ESValue a, ESValue b) throws EcmaScriptException;
}
static class DefaultComparer implements Comparer {
public int compare(ESValue v1, ESValue v2) throws EcmaScriptException {
ESValue v1p = v1.toESPrimitive(ESValue.EStypeNumber);
ESValue v2p = v2.toESPrimitive(ESValue.EStypeNumber);
if (v1p == ESUndefined.theUndefined && v2p == ESUndefined.theUndefined) return 0;
if (v1p == ESUndefined.theUndefined ) return 1;
if (v2p == ESUndefined.theUndefined ) return -1;
//System.out.println("v1p = " + v1 + " v2p = " + v2);
String s1 = v1.toString();
String s2 = v2.toString();
//System.out.println("s1 = " + s1 + " s2 = " + s2);
return s1.compareTo(s2);
}
}
/**
* This is the main sort() routine. It performs a quicksort on the elements
* of array a between the element from and the element to.
* The Comparer argument c is used to perform
* comparisons between elements of the array.
**/
private void sort(int from, int to,
Comparer c) throws EcmaScriptException
{
// If there is nothing to sort, return
if (theArray.size() < 2) return;
// This is the basic quicksort algorithm, stripped of frills that can make
// it faster but even more confusing than it already is. You should
// understand what the code does, but don't have to understand just
// why it is guaranteed to sort the array...
// Note the use of the compare() method of the Comparer object.
int i = from, j = to;
ESValue center = (ESValue) theArray.elementAt((from + to) / 2);
do {
ESValue ai = (ESValue) theArray.elementAt(i);
ESValue aj = (ESValue) theArray.elementAt(j);
while((i < to) && (c.compare(center, ai) > 0)) { i++; ai = (ESValue) theArray.elementAt(i);}
while((j > from) && (c.compare(center, aj) < 0)) {j--; aj = (ESValue) theArray.elementAt(j);}
if (i < j) {
Object tmp = ai; theArray.setElementAt(aj,i); theArray.setElementAt(tmp, j);
}
if (i <= j) { i++; j--; }
} while(i <= j);
if (from < j) sort(from, j, c); // recursively sort the rest
if (i < to) sort(i, to, c);
}
/**
* Sort the array with a specified compare routine
* @param compareFn A function returning a comparer
* @return the sorted array (in place)
*/
public ESValue sort(ESValue compareFn) throws EcmaScriptException {
if ((compareFn != null) &&
(!(compareFn instanceof FunctionPrototype))) {
throw new EcmaScriptException("Compare function not a function: " + compareFn);
}
Comparer c = null;
if (compareFn != null)
c = new FunctionComparer((FunctionPrototype) compareFn);
else
c = new DefaultComparer();
sort(0, theArray.size()-1, c);
return this;
}
// overrides
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
if (hash==LENGTHhash && propertyName.equals(LENGTHstring)) {
int length = (int) (((ESPrimitive) propertyValue).doubleValue());
if (length<0) {
throw new EcmaScriptException("Invalid length value: " + propertyValue);
}
theArray.setSize(length);
} else {
int index = -1; // indicates not a valid index value
try {
index = Integer.parseInt(propertyName); // should be uint
} catch (NumberFormatException e) {
}
if (index<0) {
super.putProperty(propertyName, propertyValue, hash);
} else {
putProperty(index, propertyValue);
}
}
}
// overrides
public void putProperty(int index, ESValue propertyValue)
throws EcmaScriptException {
if (index>=theArray.size()) {
theArray.setSize(index+1);
}
theArray.setElementAt(propertyValue, index);
}
// overrides
public ESValue getPropertyInScope(String propertyName, ScopeChain previousScope, int hash)
throws EcmaScriptException {
if (hash==LENGTHhash && propertyName.equals(LENGTHstring)) {
return new ESNumber(theArray.size());
}
if (hasProperty(propertyName, hash)) {
return getProperty(propertyName, hash);
}
if (previousScope == null) {
throw new EcmaScriptException("global variable '" + propertyName + "' does not have a value");
} else {
return previousScope.getValue(propertyName, hash);
}
}
// overrides
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
if (hash==LENGTHhash && propertyName.equals(LENGTHstring)) {
return new ESNumber(theArray.size());
} else {
int index = -1; // indicates not a valid index value
try {
index = Integer.parseInt(propertyName); // should be uint
} catch (NumberFormatException e) {
}
if (index<0) {
return super.getProperty(propertyName, hash);
} else {
return getProperty(index);
}
}
}
// overrides
public ESValue getProperty(int index)
throws EcmaScriptException {
Object theElement = null;
if (index<theArray.size()) theElement = theArray.elementAt(index);
if (theElement == null) {
return ESUndefined.theUndefined;
} else {
return (ESValue) theElement;
}
}
// overrides
public boolean hasProperty(String propertyName, int hash)
throws EcmaScriptException {
if (hash==LENGTHhash && propertyName.equals(LENGTHstring)) {
return true;
} else {
int index = -1; // indicates not a valid index value
try {
index = Integer.parseInt(propertyName); // should be uint
} catch (NumberFormatException e) {
}
if (index<0) {
return super.hasProperty(propertyName, hash);
} else {
return index<theArray.size();
}
}
}
// overrides
// Skip elements which were never set (are null), as Netscape
/*
OLD - DID IGNORE THE NORMAL PROPERTIES OF AN ARRAY
public Enumeration getProperties() {
return new Enumeration() {
int nextIndex = 0;
public boolean hasMoreElements() {
while ( (nextIndex<theArray.size()) &&
(theArray.elementAt(nextIndex) == null))
nextIndex++;
return nextIndex<theArray.size();
}
public Object nextElement() {
if (hasMoreElements()) {
return new ESNumber(nextIndex++);
} else {
throw new java.util.NoSuchElementException();
}
}
};
}
*/
/**
* Returns an enumerator for the key elements of this object,
* that is all is enumerable properties and the (non hidden)
* ones of its prototype, etc... As used for the for in
* statement.
*<P> Skip elements which were never set (are null), as Netscape
* SHOULD USE SUPER INSTEAD !
* @return the enumerator
*/
public Enumeration getProperties() {
return new Enumeration() {
Enumeration props = properties.keys();
Object currentKey = null;
int currentHash = 0;
int nextIndex = 0;
boolean inside = false;
ESObject prototype = ArrayPrototype.this.getPrototype();
public boolean hasMoreElements() {
// Check if hasMoreElements was already called
if (currentKey != null) return true;
// Check if a numeric key is appropriate
while ( (nextIndex<theArray.size()) &&
(theArray.elementAt(nextIndex) == null)) {
nextIndex++;
}
if (nextIndex<theArray.size()) {
// Should it be an ESNumber?
currentKey = new ESNumber(nextIndex++);
return true;
}
while (props.hasMoreElements()) {
currentKey = props.nextElement();
currentHash = currentKey.hashCode();
if (inside) {
if (properties.containsKey((String) currentKey, currentHash)) continue;
} else {
if (isHiddenProperty((String) currentKey, currentHash)) continue;
}
return true;
}
if (!inside && prototype != null) {
inside = true;
props = prototype.getProperties();
while (props.hasMoreElements()) {
currentKey = props.nextElement();
currentHash = currentKey.hashCode();
if (properties.containsKey((String) currentKey, currentHash)) continue;
return true;
}
}
return false;
}
public Object nextElement() {
if (hasMoreElements()) {
Object key = currentKey;
currentKey = null;
return key;
} else {
throw new java.util.NoSuchElementException();
}
}
};
}
/**
* Get all properties (including hidden ones), for the command
* @listall of the interpreter. Include the visible properties of the
* prototype (that is the one added by the user) but not the
* hidden ones of the prototype (otherwise this would list
* all functions for any object).
* <P> Hidde elements which are null (as netscape)
*
* @return An enumeration of all properties (visible and hidden).
*/
public Enumeration getAllProperties() {
return new Enumeration() {
String [] specialProperties = getSpecialPropertyNames();
int specialEnumerator = 0;
Enumeration props = properties.keys(); // all of object properties
String currentKey = null;
int currentHash = 0;
boolean inside = false; // true when examing prototypes properties
int nextIndex = 0;
public boolean hasMoreElements() {
// OK if we already checked for a property and one exists
if (currentKey != null) return true;
// loop on idex properties
if (nextIndex<theArray.size()) {
while ( (nextIndex<theArray.size()) &&
(theArray.elementAt(nextIndex) == null))
nextIndex++;
if (nextIndex<theArray.size()) {
currentKey = Integer.toString(nextIndex);
currentHash = currentKey.hashCode();
nextIndex++;
return true;
}
}
// Loop on special properties first
if (specialEnumerator < specialProperties.length) {
currentKey = specialProperties[specialEnumerator];
currentHash = currentKey.hashCode();
specialEnumerator++;
return true;
}
// loop on standard or prototype properties
while (props.hasMoreElements()) {
currentKey = (String) props.nextElement();
currentHash = currentKey.hashCode();
if (inside) {
if (properties.containsKey(currentKey, currentHash)) continue;
// SHOULD CHECK IF NOT IN SPECIAL
}
return true;
}
// If prototype properties have not yet been examined, look for them
if (!inside && getPrototype() != null) {
inside = true;
props = getPrototype().getProperties();
while (props.hasMoreElements()) {
currentKey = (String) props.nextElement();
currentHash = currentKey.hashCode();
if (properties.containsKey(currentKey, currentHash)) continue;
return true;
}
}
return false;
}
public Object nextElement() {
if (hasMoreElements()) {
String key = currentKey;
currentKey = null;
return key;
} else {
throw new java.util.NoSuchElementException();
}
}
};
}
// overrides
public String[] getSpecialPropertyNames() {
String [] ns = {LENGTHstring};
return ns;
}
// Support of custom compare function for sort
class FunctionComparer implements Comparer {
FunctionPrototype compareFn;
ESValue arguments[];
ESObject thisObject;
public FunctionComparer (FunctionPrototype fn) {
this.compareFn = fn;
this.arguments = new ESValue[2];
this.thisObject = evaluator.getGlobalObject ();
}
public int compare(ESValue v1, ESValue v2) throws EcmaScriptException {
ESValue v1p = v1.toESPrimitive(ESValue.EStypeNumber);
ESValue v2p = v2.toESPrimitive(ESValue.EStypeNumber);
if (v1p == ESUndefined.theUndefined && v2p == ESUndefined.theUndefined) return 0;
if (v1p == ESUndefined.theUndefined ) return 1;
if (v2p == ESUndefined.theUndefined ) return -1;
arguments[0] = v1;
arguments[1] = v2;
ESValue compValue = compareFn.callFunction (thisObject, arguments);
return compValue.toInt32 ();
}
}
}

View file

@ -0,0 +1,123 @@
// BooleanObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
/**
* Implemements the EcmaScript Boolean singleton.
*/
public class BooleanObject extends BuiltinFunctionObject {
private BooleanObject(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator, "Boolean", 1);
}
// overrides
public String toString() {
return "<Boolean>";
}
// overrides
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length==0) {
return ESBoolean.makeBoolean(false);
} else {
return ESBoolean.makeBoolean(arguments[0].booleanValue());
}
}
// overrides
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
BooleanPrototype theObject = null;
ESObject bp = evaluator.getBooleanPrototype();
theObject= new BooleanPrototype(bp, evaluator);
if (arguments.length>0) {
theObject.value = ESBoolean.makeBoolean(arguments[0].booleanValue());
} else {
theObject.value = ESBoolean.makeBoolean(false);
}
return theObject;
}
/**
* Utility function to create the single Boolean object
*
* @param evaluator the Evaluator
* @param objectPrototype The Object prototype attached to the evaluator
* @param functionPrototype The Function prototype attached to the evaluator
*
* @return the Boolean singleton
*/
public static BooleanObject makeBooleanObject(Evaluator evaluator,
ObjectPrototype objectPrototype,
FunctionPrototype functionPrototype) {
BooleanPrototype booleanPrototype = new BooleanPrototype(objectPrototype, evaluator);
BooleanObject booleanObject = new BooleanObject(functionPrototype, evaluator);
try {
// For booleanPrototype
class BooleanPrototypeToString extends BuiltinFunctionObject {
BooleanPrototypeToString(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESValue v = ((BooleanPrototype) thisObject).value;
String s = v.toString();
return new ESString(s);
}
}
class BooleanPrototypeValueOf extends BuiltinFunctionObject {
BooleanPrototypeValueOf(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
return ((BooleanPrototype) thisObject).value;
}
}
booleanObject.putHiddenProperty("prototype",booleanPrototype);
booleanObject.putHiddenProperty("length",new ESNumber(1));
booleanPrototype.putHiddenProperty("constructor",booleanObject);
booleanPrototype.putHiddenProperty("toString",
new BooleanPrototypeToString("toString", evaluator, functionPrototype));
booleanPrototype.putHiddenProperty("valueOf",
new BooleanPrototypeValueOf("valueOf", evaluator, functionPrototype));
} catch (EcmaScriptException e) {
e.printStackTrace();
throw new ProgrammingError(e.getMessage());
}
evaluator.setBooleanPrototype(booleanPrototype);
return booleanObject;
}
}

View file

@ -0,0 +1,80 @@
// BooleanPrototype.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
/**
* Implements the prototype and is the class of all Boolean objects
*/
class BooleanPrototype extends ESObject {
// The value
protected ESBoolean value = ESBoolean.makeBoolean(false);
/** Create a new Boolean initialized to false
* @param prototype the BooleanPrototype
* @param evaluator the evaluator
*/
BooleanPrototype(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator);
}
// overrides
public String getESClassName() {
return "Boolean";
}
// overrides
public String toString(Evaluator evaluator) throws EcmaScriptException {
return value.toString();
}
// overrides
public double doubleValue() throws EcmaScriptException {
return value.doubleValue();
}
// overrides
public ESValue toESBoolean() throws EcmaScriptException {
return value;
}
// overrides
public boolean booleanValue() {
return value.booleanValue();
}
// overrides
public Object toJavaObject() {
return new Boolean(value.booleanValue());
}
// overrides
public String toDetailString() {
return "ES:[Object: builtin " + this.getClass().getName() + ":" +
((value == null) ? "null" : value.toString()) + "]";
}
// overrides
public boolean isBooleanValue() {
return true;
}
}

View file

@ -0,0 +1,70 @@
// BuiltinFunctionObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import java.util.Hashtable;
import java.util.Vector;
import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator;
/**
* Implement the common functionality of all built-in functions
*/
public abstract class BuiltinFunctionObject extends FunctionPrototype {
protected BuiltinFunctionObject(ESObject functionPrototype,
Evaluator evaluator,
String functionName,
int length) {
super(functionPrototype, evaluator, functionName, length);
}
// overrides
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
if (!propertyName.equals("prototype")) {
super.putProperty(propertyName, propertyValue, hash);
} // Allowed via putHiddenProperty, used internally !
}
/**
* get the string defining the function
* @return a string indicating that the function is native
*/
public String getFunctionImplementationString() {
return "{[native: " + this.getClass().getName() + "]}";
}
/**
* Get the function parameter description as a string
*
* @return the function parameter string as (a,b,c)
*/
public String getFunctionParametersString() {
return "(<" + getLengthProperty()+ " args>)";
}
// overrides
public String toString() {
return "<" + this.getFunctionName() + ":" + this.getClass().getName() +">";
}
}

View file

@ -0,0 +1,83 @@
// ESLoader.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
/**
* Descripe the compatibility of a method, allowing to
* postpone the choice of the method to call until all
* potentially compatible ones have been examined.
*/
class CompatibilityDescriptor {
int distance;
boolean [] convertToChar = null; // flag to indicate if conversion to char is needed
Object [] convertedArrays = null; // Converted array if any needed
/*
* Create a new descrptor (note that there is a predefined one for
* incompatible parameters).
* @param distance -1 if incompatible, or evaluation of conversion distance
* @param convertToChar Optional flag for each parameter
* @param convertedArrays Optional list of converted arrays
*/
CompatibilityDescriptor(int distance,
boolean[] convertedToChar,
Object[] convertedArrays) {
this.distance = distance;
if (distance>=0) {
this.convertToChar = convertedToChar;
this.convertedArrays = convertedArrays;
}
}
/** Return true if the method is compatible with the parameters */
public boolean isCompatible() {
return distance>=0;
}
/** Return the distance between perfect compatibility and this one */
public int getDistance() {
return distance;
}
/** Convert the parameters for this method call */
public void convert(Object params[]) {
if (params != null && distance>=0) {
// Modify the parameters
int n = params.length;
if (convertToChar!=null) {
for (int i=0; i<n; i++) {
if (convertToChar[i]) {
String s = (String) params[i];
Character c = new Character(s.charAt(0));
params[i] = c;
}
}
}
if (convertedArrays!=null) {
for (int i=0; i<n; i++) {
if (convertedArrays[i] != null) {
params[i] = convertedArrays[i];
}
}
}
}
} // convert
} // class CompatibilityDescriptor

View file

@ -0,0 +1,256 @@
// ConstructedFunctionObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import java.util.Hashtable;
import java.util.Vector;
import FESI.Exceptions.*;
import FESI.AST.ASTStatementList;
import FESI.Interpreter.*;
/**
* Implements functions constructed from source text
*/
public class ConstructedFunctionObject extends FunctionPrototype {
private static final String PROTOTYPEstring = new String("prototype").intern();
private static final int PROTOTYPEhash=PROTOTYPEstring.hashCode();
private ASTStatementList theFunctionAST;
private String [] theArguments;
private Vector localVariableNames;
private EvaluationSource evaluationSource = null;
private String functionSource = null;
private ESValue currentArguments = ESNull.theNull;
private ConstructedFunctionObject(FunctionPrototype functionPrototype,
Evaluator evaluator,
String functionName,
EvaluationSource evaluationSource,
String functionSource,
String [] arguments,
Vector localVariableNames,
ASTStatementList aFunctionAST) {
super(functionPrototype, evaluator, functionName, arguments.length);
this.evaluationSource = evaluationSource;
this.functionSource = functionSource;
theFunctionAST = aFunctionAST;
theArguments = arguments;
this.localVariableNames = localVariableNames;
//try {
// targetObject.putProperty(functionName, this);
//} catch (EcmaScriptException e) {
// throw new ProgrammingError(e.getMessage());
//}
}
/**
* get the string defining the function
* @return the source string
*/
public String getFunctionImplementationString() {
if (functionSource == null) {
StringBuffer str = new StringBuffer();
str.append("function ");
str.append(getFunctionName());
str.append("(");
for (int i=0; i<theArguments.length; i++) {
if (i>0) str.append(",");
str.append(theArguments[i]);
}
str.append(")");
str.append("function {<internal abstract syntax tree representation>}");
return str.toString();
} else {
return functionSource;
}
}
/**
* Get the list of local variables of the function as a vector
* @return the Vector of local variable name strings
*/
public Vector getLocalVariableNames() {
return localVariableNames;
}
/**
* Get the function parameter description as a string
*
* @return the function parameter string as (a,b,c)
*/
public String getFunctionParametersString() {
StringBuffer str = new StringBuffer();
str.append("(");
for (int i=0; i<theArguments.length; i++) {
if (i>0) str.append(",");
str.append(theArguments[i]);
}
str.append(")");
return str.toString();
}
// overrides
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESValue value = null;
ESArguments args = ESArguments.makeNewESArguments(evaluator,
this,
theArguments,
arguments);
ESValue oldArguments = currentArguments;
currentArguments = args;
try {
value = evaluator.evaluateFunction(theFunctionAST,
evaluationSource,
args,
localVariableNames,
thisObject);
} finally {
currentArguments = oldArguments;
}
return value;
}
// overrides
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESValue prototype = getProperty(PROTOTYPEstring, PROTOTYPEhash);
ESObject op = evaluator.getObjectPrototype();
if (!(prototype instanceof ESObject)) prototype = op;
ESObject obj = new ObjectPrototype((ESObject) prototype, evaluator);
ESValue result = callFunction(obj, arguments);
// The next line was probably a misinterpretation of // 15.3.2.1 (18)
// which returned an other object if the function returned an object
// if (result instanceof ESObject) obj = (ESObject) result;
return obj;
}
// overrides
public String toString () {
return getFunctionImplementationString();
}
// overrides
public String toDetailString() {
StringBuffer str = new StringBuffer();
str.append("<Function: ");
str.append(getFunctionName());
str.append("(");
for (int i=0; i<theArguments.length; i++) {
if (i>0) str.append(",");
str.append(theArguments[i]);
}
str.append(")>");
return str.toString();
}
/**
* Utility function to create a function object. Used by the
* EcmaScript Function function to create new functions
*
* @param evaluator the Evaluator
* @param functionName the name of the new function
* @param evaluationSource An identification of the source of the function
* @param sourceString The source of the parsed function
* @param arguments The array of arguments
* @param localVariableNames the list of local variable declared by var
* @param aFunctionAST the parsed function
*
* @return A new function object
*/
public static ConstructedFunctionObject makeNewConstructedFunction(
Evaluator evaluator,
String functionName,
EvaluationSource evaluationSource,
String sourceString,
String [] arguments,
Vector localVariableNames,
ASTStatementList aFunctionAST) {
ConstructedFunctionObject theNewFunction = null;
try {
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
theNewFunction = new ConstructedFunctionObject (
fp,
evaluator,
functionName,
evaluationSource,
sourceString,
arguments,
localVariableNames,
aFunctionAST);
ObjectPrototype thePrototype = ObjectObject.createObject(evaluator);
theNewFunction.putHiddenProperty("prototype",thePrototype);
thePrototype.putHiddenProperty("constructor",theNewFunction);
} catch (EcmaScriptException e) {
e.printStackTrace();
throw new ProgrammingError(e.getMessage());
}
return theNewFunction;
}
// overrides
public ESValue getPropertyInScope(String propertyName, ScopeChain previousScope, int hash)
throws EcmaScriptException {
if (propertyName.equals("arguments")) {
return currentArguments;
} else {
return super.getPropertyInScope(propertyName, previousScope, hash);
}
}
// overrides
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
if (propertyName.equals("arguments")) {
return currentArguments;
} else {
return super.getProperty(propertyName, hash);
}
}
// overrides
public boolean hasProperty(String propertyName, int hash)
throws EcmaScriptException {
if (propertyName.equals("arguments")) {
return true;
} else {
return super.hasProperty(propertyName, hash);
}
}
// overrides
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
if (!propertyName.equals("arguments")) {
super.putProperty(propertyName, propertyValue, hash);
} // Allowed via putHiddenProperty, used internally !
}
// public ESValue replaceCurrentArguments(ESObject newArguments) {
// ESValue oldArguments = currentArguments;
// currentArguments = newArguments;
// return oldArguments;
// }
}

View file

@ -0,0 +1,803 @@
// DateObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import java.util.Date;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.GregorianCalendar;
import java.text.DateFormat;
public class DateObject extends BuiltinFunctionObject {
private DateObject(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator, "Date", 7);
}
// overrides
public String toString() {
return "<Date>";
}
// overrides
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
return new ESString(new Date().toString());
}
// overrides
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype theObject = null;
ESObject dp = evaluator.getDatePrototype();
theObject= new DatePrototype(dp, evaluator);
int l = arguments.length;
if (l==2 || l == 0) {
theObject.date = new Date();
} else if (l==1) {
double d = arguments[0].doubleValue();
if (Double.isNaN(d)) {
theObject.date = null;
} else {
theObject.date = new Date((long) d);
}
} else {
int year = arguments[0].toInt32();
if (0 <= year && year<=99) year += 1900;
int month = arguments[1].toInt32();
int day = arguments[2].toInt32();
int hour = (l>3) ? arguments[3].toInt32() : 0;
int minute = (l>4) ? arguments[4].toInt32() : 0;
int second = (l>5) ? arguments[5].toInt32() : 0;
int ms = (l>6) ? arguments[6].toInt32() : 0;
// Using current current locale, set it to the specified time
// System.out.println("YEAR IS " + year);
GregorianCalendar cal =
new GregorianCalendar(year,month,day,hour,minute,second);
if (ms != 0) cal.set(Calendar.MILLISECOND, ms);
theObject.date = cal.getTime();
}
return theObject;
}
/**
* Utility function to create the single Date object
*
* @param evaluator the Evaluator
* @param objectPrototype The Object prototype attached to the evaluator
* @param functionPrototype The Function prototype attached to the evaluator
*
* @return the Date singleton
*/
public static DateObject makeDateObject(Evaluator evaluator,
ObjectPrototype objectPrototype,
FunctionPrototype functionPrototype) {
DatePrototype datePrototype = new DatePrototype(objectPrototype, evaluator);
DateObject dateObject = new DateObject(functionPrototype, evaluator);
try {
// For datePrototype
class DatePrototypeToString extends BuiltinFunctionObject {
DatePrototypeToString(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return (aDate.date == null) ?
new ESString("NaN"):
new ESString(aDate.date.toString());
}
}
class DatePrototypeValueOf extends BuiltinFunctionObject {
DatePrototypeValueOf(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
if (aDate.date == null) {
return new ESNumber(Double.NaN);
} else {
long t = aDate.date.getTime();
return new ESNumber((double) t);
}
}
}
class DatePrototypeToLocaleString extends BuiltinFunctionObject {
DatePrototypeToLocaleString(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
DateFormat df = DateFormat.getDateTimeInstance();
df.setTimeZone(TimeZone.getDefault());
return (aDate.date == null) ?
new ESString("NaN"):
new ESString(df.format(aDate.date));
}
}
class DatePrototypeToGMTString extends BuiltinFunctionObject {
DatePrototypeToGMTString(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
df.setTimeZone(TimeZone.getTimeZone("GMT"));
return (aDate.date == null) ?
new ESString("NaN"):
new ESString(df.format(aDate.date));
}
}
class DatePrototypeGetYear extends BuiltinFunctionObject {
DatePrototypeGetYear(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
ESValue v = aDate.get(Calendar.YEAR);
return new ESNumber(v.doubleValue());
}
}
class DatePrototypeGetFullYear extends BuiltinFunctionObject {
DatePrototypeGetFullYear(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.get(Calendar.YEAR);
}
}
class DatePrototypeGetUTCFullYear extends BuiltinFunctionObject {
DatePrototypeGetUTCFullYear(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.getUTC(Calendar.YEAR);
}
}
class DatePrototypeGetMonth extends BuiltinFunctionObject {
DatePrototypeGetMonth(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.get(Calendar.MONTH);
}
}
class DatePrototypeGetUTCMonth extends BuiltinFunctionObject {
DatePrototypeGetUTCMonth(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.getUTC(Calendar.MONTH);
}
}
class DatePrototypeGetDate extends BuiltinFunctionObject {
DatePrototypeGetDate(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.get(Calendar.DAY_OF_MONTH);
}
}
class DatePrototypeGetUTCDate extends BuiltinFunctionObject {
DatePrototypeGetUTCDate(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.getUTC(Calendar.DAY_OF_MONTH);
}
}
class DatePrototypeGetDay extends BuiltinFunctionObject {
DatePrototypeGetDay(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
// EcmaScript has SUNDAY=0, java SUNDAY=1 - converted in DatePrototype
return aDate.get(Calendar.DAY_OF_WEEK);
}
}
class DatePrototypeGetUTCDay extends BuiltinFunctionObject {
DatePrototypeGetUTCDay(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.getUTC(Calendar.DAY_OF_WEEK);
}
}
class DatePrototypeGetHours extends BuiltinFunctionObject {
DatePrototypeGetHours(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.get(Calendar.HOUR_OF_DAY);
}
}
class DatePrototypeGetUTCHours extends BuiltinFunctionObject {
DatePrototypeGetUTCHours(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.getUTC(Calendar.HOUR_OF_DAY);
}
}
class DatePrototypeGetMinutes extends BuiltinFunctionObject {
DatePrototypeGetMinutes(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.get(Calendar.MINUTE);
}
}
class DatePrototypeGetUTCMinutes extends BuiltinFunctionObject {
DatePrototypeGetUTCMinutes(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.getUTC(Calendar.MINUTE);
}
}
class DatePrototypeGetSeconds extends BuiltinFunctionObject {
DatePrototypeGetSeconds(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.get(Calendar.SECOND);
}
}
class DatePrototypeGetUTCSeconds extends BuiltinFunctionObject {
DatePrototypeGetUTCSeconds(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.getUTC(Calendar.SECOND);
}
}
class DatePrototypeGetMilliseconds extends BuiltinFunctionObject {
DatePrototypeGetMilliseconds(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.get(Calendar.MILLISECOND);
}
}
class DatePrototypeGetUTCMilliseconds extends BuiltinFunctionObject {
DatePrototypeGetUTCMilliseconds(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.getUTC(Calendar.MILLISECOND);
}
}
class DatePrototypeSetYear extends BuiltinFunctionObject {
DatePrototypeSetYear(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
ESValue v = aDate.get(Calendar.YEAR);
return aDate.setYear(arguments);
}
}
class DatePrototypeSetFullYear extends BuiltinFunctionObject {
DatePrototypeSetFullYear(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setTime(arguments,
new int [] {Calendar.YEAR,Calendar.MONTH,Calendar.DAY_OF_MONTH});
}
}
class DatePrototypeSetUTCFullYear extends BuiltinFunctionObject {
DatePrototypeSetUTCFullYear(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setUTCTime(arguments,
new int [] {Calendar.YEAR,Calendar.MONTH,Calendar.DAY_OF_MONTH});
}
}
class DatePrototypeSetMonth extends BuiltinFunctionObject {
DatePrototypeSetMonth(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setTime(arguments,
new int [] {Calendar.MONTH,Calendar.DAY_OF_MONTH});
}
}
class DatePrototypeSetUTCMonth extends BuiltinFunctionObject {
DatePrototypeSetUTCMonth(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setUTCTime(arguments,
new int [] {Calendar.MONTH,Calendar.DAY_OF_MONTH});
}
}
class DatePrototypeSetDate extends BuiltinFunctionObject {
DatePrototypeSetDate(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setTime(arguments,
new int [] {Calendar.DAY_OF_MONTH});
}
}
class DatePrototypeSetUTCDate extends BuiltinFunctionObject {
DatePrototypeSetUTCDate(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setUTCTime(arguments,
new int [] {Calendar.DAY_OF_MONTH});
}
}
class DatePrototypeSetHours extends BuiltinFunctionObject {
DatePrototypeSetHours(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setTime(arguments,
new int [] {Calendar.HOUR_OF_DAY,Calendar.MINUTE,Calendar.SECOND,Calendar.MILLISECOND});
}
}
class DatePrototypeSetUTCHours extends BuiltinFunctionObject {
DatePrototypeSetUTCHours(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setUTCTime(arguments,
new int [] {Calendar.HOUR_OF_DAY,Calendar.MINUTE,Calendar.SECOND,Calendar.MILLISECOND});
}
}
class DatePrototypeSetMinutes extends BuiltinFunctionObject {
DatePrototypeSetMinutes(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setTime(arguments,
new int [] {Calendar.MINUTE,Calendar.SECOND,Calendar.MILLISECOND});
}
}
class DatePrototypeSetUTCMinutes extends BuiltinFunctionObject {
DatePrototypeSetUTCMinutes(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setUTCTime(arguments,
new int [] {Calendar.MINUTE,Calendar.SECOND,Calendar.MILLISECOND});
}
}
class DatePrototypeSetSeconds extends BuiltinFunctionObject {
DatePrototypeSetSeconds(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setTime(arguments,
new int [] {Calendar.SECOND,Calendar.MILLISECOND});
}
}
class DatePrototypeSetUTCSeconds extends BuiltinFunctionObject {
DatePrototypeSetUTCSeconds(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setUTCTime(arguments,
new int [] {Calendar.SECOND,Calendar.MILLISECOND});
}
}
class DatePrototypeSetMilliseconds extends BuiltinFunctionObject {
DatePrototypeSetMilliseconds(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setTime(arguments, new int [] {Calendar.MILLISECOND});
}
}
class DatePrototypeSetUTCMilliseconds extends BuiltinFunctionObject {
DatePrototypeSetUTCMilliseconds(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
return aDate.setUTCTime(arguments, new int [] {Calendar.MILLISECOND});
}
}
class DatePrototypeGetTimezoneOffset extends BuiltinFunctionObject {
DatePrototypeGetTimezoneOffset(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
GregorianCalendar cal = new GregorianCalendar(TimeZone.getDefault());
cal.setTime(aDate.date);
TimeZone tz = cal.getTimeZone();
int offset = tz.getOffset(cal.get(Calendar.ERA),
cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH),
cal.get(Calendar.DATE),
cal.get(Calendar.DAY_OF_WEEK),
cal.get(Calendar.HOUR_OF_DAY) * 86400000
+ cal.get(Calendar.MINUTE) * 3600000
+ cal.get(Calendar.SECOND) * 1000);
// int offset = TimeZone.getDefault().getRawOffset();
//System.out.println("TimeZone.getDefault().getID(): " + TimeZone.getDefault().getID());
// System.out.println("TimeZone.getDefault().getRawOffset(): " + TimeZone.getDefault().getRawOffset());
int minutes = -(offset / 1000 / 60); // convert to minutes
return new ESNumber(minutes);
}
}
class DatePrototypeSetTime extends BuiltinFunctionObject {
DatePrototypeSetTime(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
DatePrototype aDate = (DatePrototype) thisObject;
double dateValue = Double.NaN;
if (arguments.length>0) {
dateValue = arguments[0].doubleValue();
}
if (Double.isNaN(dateValue)) {
aDate.date = null;
} else {
aDate.date = new Date((long) dateValue);
}
return new ESNumber(dateValue);
}
}
// For dateObject
class DateObjectParse extends BuiltinFunctionObject {
DateObjectParse(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length<=0) {
throw new EcmaScriptException("Missing argument");
}
String dateString = arguments[0].toString();
DateFormat df = DateFormat.getDateInstance();
ESValue dateValue = null;
try {
Date date = df.parse(dateString);
dateValue = new ESNumber(date.getTime());
} catch (java.text.ParseException e) {
dateValue = new ESNumber(Double.NaN);
}
return dateValue;
}
}
class DateObjectUTC extends BuiltinFunctionObject {
DateObjectUTC(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 7);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
int l = arguments.length;
if (l<=2) {
throw new EcmaScriptException("Missing argument");
}
int year = arguments[0].toInt32();
if (0 <= year && year<=99) year += 1900;
int month = arguments[1].toInt32();
int day = arguments[2].toInt32();
int hour = (l>3) ? arguments[3].toInt32() : 0;
int minute = (l>4) ? arguments[4].toInt32() : 0;
int second = (l>5) ? arguments[5].toInt32() : 0;
int ms = (l>6) ? arguments[6].toInt32() : 0;
Calendar cal =
new GregorianCalendar(TimeZone.getTimeZone("GMT"));
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DAY_OF_MONTH, day);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
cal.set(Calendar.MILLISECOND, ms );
long timeinms = cal.getTime().getTime();
return new ESNumber((double) timeinms);
}
}
dateObject.putHiddenProperty("prototype",datePrototype);
dateObject.putHiddenProperty("length",new ESNumber(7));
dateObject.putHiddenProperty("parse",
new DateObjectParse("parse", evaluator, functionPrototype));
dateObject.putHiddenProperty("UTC",
new DateObjectUTC("UTC", evaluator, functionPrototype));
datePrototype.putHiddenProperty("constructor",dateObject);
datePrototype.putHiddenProperty("toString",
new DatePrototypeToString("toString", evaluator, functionPrototype));
datePrototype.putHiddenProperty("toLocaleString",
new DatePrototypeToLocaleString("toLocaleString", evaluator, functionPrototype));
datePrototype.putHiddenProperty("toGMTString",
new DatePrototypeToGMTString("toGMTString", evaluator, functionPrototype));
datePrototype.putHiddenProperty("toUTCString",
new DatePrototypeToGMTString("toUTCString", evaluator, functionPrototype));
datePrototype.putHiddenProperty("valueOf",
new DatePrototypeValueOf("valueOf", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getTime",
new DatePrototypeValueOf("getTime", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getYear",
new DatePrototypeGetYear("getYear", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getFullYear",
new DatePrototypeGetFullYear("getFullYear", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getUTCFullYear",
new DatePrototypeGetUTCFullYear("getUTCFullYear", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getMonth",
new DatePrototypeGetMonth("getMonth", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getUTCMonth",
new DatePrototypeGetUTCMonth("getUTCMonth", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getDate",
new DatePrototypeGetDate("getDate", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getUTCDate",
new DatePrototypeGetUTCDate("getUTCDate", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getDay",
new DatePrototypeGetDay("getDay", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getUTCDay",
new DatePrototypeGetUTCDay("getUTCDay", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getHours",
new DatePrototypeGetHours("getHours", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getUTCHours",
new DatePrototypeGetUTCHours("getUTCHours", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getMinutes",
new DatePrototypeGetMinutes("getMinutes", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getUTCMinutes",
new DatePrototypeGetUTCMinutes("getUTCMinutes", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getSeconds",
new DatePrototypeGetSeconds("getSeconds", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getUTCSeconds",
new DatePrototypeGetUTCSeconds("getUTCSeconds", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getMilliseconds",
new DatePrototypeGetMilliseconds("getMilliseconds", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getUTCMilliseconds",
new DatePrototypeGetUTCMilliseconds("getUTCMilliseconds", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setYear",
new DatePrototypeSetYear("setYear", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setFullYear",
new DatePrototypeSetFullYear("setFullYear", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setUTCFullYear",
new DatePrototypeSetUTCFullYear("setUTCFullYear", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setMonth",
new DatePrototypeSetMonth("setMonth", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setUTCMonth",
new DatePrototypeSetUTCMonth("setUTCMonth", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setDate",
new DatePrototypeSetDate("setDate", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setUTCDate",
new DatePrototypeSetUTCDate("setUTCDate", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setHours",
new DatePrototypeSetHours("setHours", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setUTCHours",
new DatePrototypeSetUTCHours("setUTCHours", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setMinutes",
new DatePrototypeSetMinutes("setMinutes", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setUTCMinutes",
new DatePrototypeSetUTCMinutes("setUTCMinutes", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setSeconds",
new DatePrototypeSetSeconds("setSeconds", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setUTCSeconds",
new DatePrototypeSetUTCSeconds("setUTCSeconds", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setMilliseconds",
new DatePrototypeSetMilliseconds("setMilliseconds", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setUTCMilliseconds",
new DatePrototypeSetUTCMilliseconds("setUTCMilliseconds", evaluator, functionPrototype));
datePrototype.putHiddenProperty("getTimezoneOffset",
new DatePrototypeGetTimezoneOffset("getTimezoneOffset", evaluator, functionPrototype));
datePrototype.putHiddenProperty("setTime",
new DatePrototypeSetTime("setTime", evaluator, functionPrototype));
} catch (EcmaScriptException e) {
e.printStackTrace();
throw new ProgrammingError(e.getMessage());
}
evaluator.setDatePrototype(datePrototype);
return dateObject;
}
}

View file

@ -0,0 +1,225 @@
// DatePrototype.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
/**
* Implements the prototype and is the class of all Date objects
*/
public class DatePrototype extends ESObject {
// The value
protected Date date = null;
/**
* Create a new Date object with a null date
* @param prototype the Date prototype
* @param evaluator the Evaluator
*/
DatePrototype(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator);
date = new Date();
}
/**
* Create a new Date object with a specified date
* @param prototype the Date prototype
* @param evaluator the Evaluator
* @param date the Date
*/
public DatePrototype (Evaluator evaluator, Date aDate) {
super(evaluator.getDatePrototype(), evaluator);
date = new Date(aDate.getTime());
}
/**
* Create a new Date object with a specified date
* @param prototype the Date prototype
* @param evaluator the Evaluator
* @param time the Date
*/
public DatePrototype (Evaluator evaluator, long time) {
super(evaluator.getDatePrototype(), evaluator);
date = new Date(time);
}
// overrides
public String getESClassName() {
return "Date";
}
/**
* Set the year value of the date. BEWARE: Fixed as base 1900 !
* @param arguments The array of arguments, the first one being the year
* @return the new date as a number
*/
public ESValue setYear(ESValue[] arguments) throws EcmaScriptException {
if (date == null) {
return new ESNumber(Double.NaN);
} else {
if (arguments.length<=0) {
date = null;
return new ESNumber(Double.NaN);
}
GregorianCalendar cal = new GregorianCalendar(TimeZone.getDefault());
cal.setTime(date);
double d = arguments[0].doubleValue();
if (Double.isNaN(d)) {
date = null;
return new ESNumber(Double.NaN);
}
if (d <100) d+= 1900;
// System.out.println("SETYEAR to " + d);
cal.set(Calendar.YEAR, (int) d);
date = cal.getTime();
long t = date.getTime();
return new ESNumber((double) t);
}
}
/**
* Set the time value of the date based on the element type to change
* Assume that the time elements are in the local time zone
* @param arguments The array of arguments
* @para, argTypes The array of element type
* @return the new date as a number
*/
public ESValue setTime(ESValue[] arguments, int [] argTypes) throws EcmaScriptException {
if (date == null) {
return new ESNumber(Double.NaN);
} else {
if (arguments.length<=0) {
date = null;
return new ESNumber(Double.NaN);
}
GregorianCalendar cal = new GregorianCalendar(TimeZone.getDefault());
cal.setTime(date);
for (int iarg=0; (iarg<argTypes.length) && (iarg<arguments.length); iarg++) {
double d = arguments[iarg].doubleValue();
if (Double.isNaN(d)) {
date = null;
return new ESNumber(Double.NaN);
}
// System.out.println("SET " + argTypes[iarg] + " to " + d);
cal.set(argTypes[iarg], (int) d);
}
date = cal.getTime();
long t = date.getTime();
return new ESNumber((double) t);
}
}
/**
* Set the time value of the date based on the element type to change
* Assume that the time elements are in the UTC time zone
* @param arguments The array of arguments
* @para, argTypes The array of element type
* @return the new date as a number
*/
public ESValue setUTCTime(ESValue[] arguments, int [] argTypes) throws EcmaScriptException {
if (date == null) {
return new ESNumber(Double.NaN);
} else {
if (arguments.length<=0) {
date = null;
return new ESNumber(Double.NaN);
}
GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
cal.setTime(date);
for (int iarg=0; (iarg<argTypes.length) && (iarg<arguments.length); iarg++) {
double d = arguments[iarg].doubleValue();
if (Double.isNaN(d)) {
date = null;
return new ESNumber(Double.NaN);
}
// System.out.println("UTCSET " + argTypes[iarg] + " to " + d);
cal.set(argTypes[iarg], (int) d);
}
date = cal.getTime();
long t = date.getTime();
return new ESNumber((double) t);
}
}
/**
* Get an element of the date (in local time zone)
* @param element The type of the element
* @return the element as a value
*/
public ESValue get(int element) {
if (date == null) {
return new ESNumber(Double.NaN);
} else {
GregorianCalendar cal = new GregorianCalendar(TimeZone.getDefault());
cal.setTime(date);
long t = cal.get(element);
// EcmaScript has SUNDAY=0, java SUNDAY=1 - converted in DatePrototype
if (element == Calendar.DAY_OF_WEEK) t--;
return new ESNumber((double) t);
}
}
/**
* Get an element of the date (in UTC time zone)
* @param element The type of the element
* @return the element as a value
*/
public ESValue getUTC(int element) {
if (date == null) {
return new ESNumber(Double.NaN);
} else {
GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
cal.setTime(date);
long t = cal.get(element);
// EcmaScript has SUNDAY=0, java SUNDAY=1 - converted in DatePrototype
if (element == Calendar.DAY_OF_WEEK) t--;
return new ESNumber((double) t);
}
}
// overrides
public String toString() {
return (date==null ? "null" : date.toString());
}
// overrides
public String toDetailString() {
return "ES:[Object: builtin " + this.getClass().getName() + ":" +
((date == null) ? "null" : date.toString()) + "]";
}
// overrides
public Object toJavaObject() {
return date;
}
// overrides
public ESValue getDefaultValue()
throws EcmaScriptException {
return this.getDefaultValue(EStypeString);
}
}

View file

@ -0,0 +1,253 @@
// ESArguments.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
/**
* Implements the "arguments" object for function call
*/
public final class ESArguments extends ESObject {
private ESObject callee; // Called object
private int length; // Number of arguments
String [] argumentNames; // Argument names from 0 to n
// (not readily available) int [] hashCodes; // Argument hash codes from 0 to n
/**
* Create a new arguments object - only called by makeNewESArgument
* @param prototype The Object prototype
* @param evaluator The evaluator
* @param argumentNames The array of argument names
* @param length The number of arguments (max of names and values
* @param callee The called object
*/
private ESArguments(ESObject prototype,
Evaluator evaluator,
String [] argumentNames,
int length,
ESObject callee) {
super(prototype, evaluator, (length<3) ? 5 : 11 ); // limit space requirements
this.argumentNames = argumentNames;
this.length = length;
this.callee = callee;
}
// overrides
public ESValue getPropertyInScope(String propertyName,
ScopeChain previousScope,
int hash)
throws EcmaScriptException {
if (propertyName.equals("callee")) {
return callee;
} else if (propertyName.equals("arguments")) {
return this;
} else if (propertyName.equals("length")) {
return new ESNumber((double) length);
}
// directly test on get
if (super.hasProperty(propertyName, hash)) {
return (ESValue) super.getProperty(propertyName, hash);
}
int index = -1; // indicates not a valid index value
try {
char c = propertyName.charAt(0);
if ('0' <= c && c <= '9') {
index = Integer.parseInt(propertyName);
}
} catch (NumberFormatException e) {
} catch (StringIndexOutOfBoundsException e) { // for charAt
}
if (index>=0 && index<argumentNames.length) {
propertyName = argumentNames[index];
hash = propertyName.hashCode();
return super.getProperty(propertyName, hash); // will be defined
}
if (previousScope == null) {
throw new EcmaScriptException("global variable '" + propertyName + "' does not have a value");
} else {
return previousScope.getValue(propertyName, hash);
}
}
// overrides
public ESValue doIndirectCallInScope(Evaluator evaluator,
ScopeChain previousScope,
ESObject thisObject,
String functionName,
int hash,
ESValue[] arguments)
throws EcmaScriptException {
if (functionName.equals("callee")) {
return callee.callFunction(thisObject,arguments);
} else {
return super.doIndirectCallInScope(evaluator, previousScope, thisObject, functionName, hash, arguments);
}
}
// overrides
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
if (propertyName.equals("callee")) {
return callee;
} else if (propertyName.equals("arguments")) {
return this;
} else if (propertyName.equals("length")) {
return new ESNumber((double) length);
} else {
// Assume that it is more likely a name than a number
if (super.hasProperty(propertyName, hash)) {
return super.getProperty(propertyName, hash);
}
int index = -1; // indicates not a valid index value
try {
char c = propertyName.charAt(0);
if ('0' <= c && c <= '9') {
index = Integer.parseInt(propertyName);
}
} catch (NumberFormatException e) {
}
if (index>=0 && index<argumentNames.length) {
propertyName = argumentNames[index];
hash = propertyName.hashCode();
}
return super.getProperty(propertyName, hash);
}
}
// overrides
public ESValue getProperty(int index)
throws EcmaScriptException {
if (index>=0 && index<argumentNames.length) {
String propertyName = argumentNames[index];
return super.getProperty(propertyName, propertyName.hashCode());
} else {
String iString = Integer.toString(index);
return getProperty(iString, iString.hashCode());
}
}
// overrides
public boolean hasProperty(String propertyName, int hash)
throws EcmaScriptException {
if (propertyName.equals("callee")) {
return true;
} else if (propertyName.equals("arguments")) {
return true;
} else if (propertyName.equals("length")) {
return true;
} else if (super.hasProperty(propertyName, hash)) {
return true;
} else {
int index = -1; // indicates not a valid index value
try {
char c = propertyName.charAt(0);
if ('0' <= c && c <= '9') {
index = Integer.parseInt(propertyName);
} } catch (NumberFormatException e) {
}
if (index>=0 && index<argumentNames.length) {
return true;
}
return false;
}
}
/**
* Make a new ESArgument from names and values - the number
* of names and values do not have to be identical.
* @param evaluator theEvaluator
* @param callee the called function
* @param argumentNames the names of the arguments of the function
* @param agumentValues the values of the argument.
* @return the new ESArguments
*/
public static ESArguments makeNewESArguments(Evaluator evaluator,
ESObject callee,
String [] argumentNames,
ESValue[] argumentValues) {
ObjectPrototype op =
(ObjectPrototype) evaluator.getObjectPrototype();
ESArguments args = new ESArguments(op, evaluator, argumentNames,
Math.max(argumentValues.length, argumentNames.length),
callee);
try {
for (int i=0; i<argumentValues.length; i++) {
ESValue val = (i<argumentValues.length) ? argumentValues[i] :
ESUndefined.theUndefined;
if (i<argumentNames.length) {
args.putProperty(argumentNames[i], val, argumentNames[i].hashCode());
} else {
String iString = Integer.toString(i);
args.putProperty(iString, val, iString.hashCode()); // arguments after name use index as name
}
}
} catch (EcmaScriptException e) {
e.printStackTrace();
throw new ProgrammingError(e.getMessage());
}
return args;
}
// overrides
public boolean deleteProperty(String propertyName, int hash)
throws EcmaScriptException {
return !hasProperty(propertyName, hash); // none can be deleted...
}
// overrides
public ESValue getDefaultValue(Evaluator evaluator, int hint)
throws EcmaScriptException {
return callee.getDefaultValue(hint);
}
// overrides
public int getTypeOf() {
return callee.getTypeOf();
}
// overrides
public Object toJavaObject() {
return callee.toJavaObject();
}
// overrides
public String getTypeofString() {
return callee.getTypeofString();
}
// overrides
public String toString() {
return callee.toString();
}
// overrides
public String toDetailString() {
return callee.toDetailString();
}
// overrides
public String[] getSpecialPropertyNames() {
String [] ns = {"arguments","callee","length"};
return ns;
}
}

View file

@ -0,0 +1,319 @@
// ESArrayWrapper.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import java.util.Enumeration;
import java.util.Date;
import FESI.Interpreter.*;
import java.lang.reflect.*;
// Class to wrap a Java array as an EcmaScript object
public class ESArrayWrapper extends ESObject {
// The java array
protected Object javaArray;
/**
* Create a new array wrapper
* @param javaArray the java array to wrap
* @param evaluator the evaluator
*/
public ESArrayWrapper(Object javaArray, Evaluator evaluator) {
super(null, evaluator);
this.javaArray = javaArray;
if (!javaArray.getClass().isArray()) {
throw new ProgrammingError("Array wrapper used on non array object");
}
}
// overrides
public ESObject getPrototype() {
throw new ProgrammingError("Cannot get prototype of Array Wrapper");
}
// overrides
public String getESClassName() {
return "Java Array";
}
// overrides
public int getTypeOf() {
return EStypeObject;
}
// overrides
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
if (propertyName.equals("length")) {
int length = (int) (((ESPrimitive) propertyValue).doubleValue());
if (length<0) {
throw new EcmaScriptException("Invalid length value: " + propertyValue);
}
throw new EcmaScriptException("length of Java Arrays is immutable");
} else {
int index = -1; // indicates not a valid index value
try {
index = Integer.parseInt(propertyName); // should be uint
} catch (NumberFormatException e) {
}
if (index<0) {
throw new EcmaScriptException("Java Arrays accept only index properties");
} else {
putProperty(index, propertyValue);
}
}
}
// overrides
public void putProperty(int index, ESValue propertyValue)
throws EcmaScriptException {
int l = Array.getLength(javaArray);
if (index>=l || index<0) {
throw new EcmaScriptException("Index " + index + " outside of Java Arrays size of " + l);
}
Object obj = propertyValue.toJavaObject();
try {
Array.set(javaArray, index, obj);
} catch (IllegalArgumentException e) {
String type = "null";
if (obj!=null) type = ESLoader.typeName(obj.getClass());
throw new EcmaScriptException("Cannot store a " + type +
" in the java array " + ESLoader.typeName(javaArray.getClass()));
}
}
// overrides
public ESValue getPropertyInScope(String propertyName, ScopeChain previousScope, int hash)
throws EcmaScriptException {
if (propertyName.equals("length")) {
return new ESNumber(Array.getLength(javaArray));
}
// Do not examine the integer values...
if (previousScope == null) {
throw new EcmaScriptException("global variable '" + propertyName + "' does not have a value");
} else {
return previousScope.getValue(propertyName, hash);
}
}
// overrides
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
if (propertyName.equals("length")) {
return new ESNumber(Array.getLength(javaArray));
} else {
int index = -1; // indicates not a valid index value
try {
index = Integer.parseInt(propertyName); // should be uint
} catch (NumberFormatException e) {
}
if (index<0) {
throw new EcmaScriptException("Java Arrays accept only index properties");
} else {
return getProperty(index);
}
}
}
// overrides
public ESValue getProperty(int index)
throws EcmaScriptException {
Object theElement = null;
int l = Array.getLength(javaArray);
if (index>=l || index<0) {
throw new EcmaScriptException("Java Array index " + index + " is out of range " + l);
}
theElement = Array.get(javaArray,index);
return ESLoader.normalizeValue(theElement, evaluator);
}
// overrides
public boolean hasProperty(String propertyName, int hash)
throws EcmaScriptException {
if (propertyName.equals("length")) {
return true;
} else {
int index = -1; // indicates not a valid index value
try {
index = Integer.parseInt(propertyName); // should be uint
} catch (NumberFormatException e) {
}
if (index<0) {
return false;
} else {
return (index>=0) && (index<Array.getLength(javaArray));
}
}
}
// overrides
// Skip elements which were never set (are null), as Netscape
public Enumeration getProperties() {
return new Enumeration() {
int nextIndex = 0;
int length = Array.getLength(javaArray);
public boolean hasMoreElements() {
while ( (nextIndex<length) &&
(Array.get(javaArray,nextIndex) == null))
nextIndex++;
return nextIndex<length;
}
public Object nextElement() {
if (hasMoreElements()) {
return new ESNumber(nextIndex++);
} else {
throw new java.util.NoSuchElementException();
}
}
};
}
/**
* Get all properties (including hidden ones), for the command
* @listall of the interpreter.
* <P>An ESArrayWrapper has no prototype, but it has the hidden property LENGTH.
*
* @return An enumeration of all properties (visible and hidden).
*/
public Enumeration getAllProperties() {
return new Enumeration() {
String [] specialProperties = getSpecialPropertyNames();
int specialEnumerator = 0;
Enumeration props = properties.keys(); // all of object properties
String currentKey = null;
int currentHash = 0;
int nextIndex = 0;
int length = Array.getLength(javaArray);
public boolean hasMoreElements() {
// OK if we already checked for a property and one exists
if (currentKey != null) return true;
// loop on index properties
if (nextIndex<length) {
while ( (nextIndex<length) &&
(Array.get(javaArray,nextIndex) == null))
// ignore null entries
nextIndex++;
if (nextIndex<length) {
currentKey = Integer.toString(nextIndex);
currentHash = currentKey.hashCode();
nextIndex++;
return true;
}
}
// Loop on special properties first
if (specialEnumerator < specialProperties.length) {
currentKey = specialProperties[specialEnumerator];
currentHash = currentKey.hashCode();
specialEnumerator++;
return true;
}
// loop on standard or prototype properties
if (props.hasMoreElements()) {
currentKey = (String) props.nextElement();
currentHash = currentKey.hashCode();
return true;
}
return false;
}
public Object nextElement() {
if (hasMoreElements()) {
String key = currentKey;
currentKey = null;
return key;
} else {
throw new java.util.NoSuchElementException();
}
}
};
}
// overrides
public String[] getSpecialPropertyNames() {
String [] ns = {"length"};
return ns;
}
// overrides
public boolean isHiddenProperty(String propertyName, int hash) {
return false;
}
// overrides
public void putHiddenProperty(String propertyName, ESValue propertyValue)
throws EcmaScriptException {
throw new ProgrammingError("Cannot put hidden property in " + this);
}
// overrides
public boolean deleteProperty(String propertyName, int hash)
throws EcmaScriptException {
return !hasProperty(propertyName, hash); // none can be deleted
}
// overrides
public ESValue getDefaultValue(int hint)
throws EcmaScriptException {
if (hint == EStypeString) {
return new ESString(javaArray.toString());
} else {
throw new EcmaScriptException ("No default value for " + this +
" and hint " + hint);
}
}
public ESValue getDefaultValue()
throws EcmaScriptException {
return this.getDefaultValue(EStypeString);
}
// overrides
public double doubleValue() {
double d = Double.NaN;
return d;
}
// overrides
public boolean booleanValue() {
return true;
}
// overrides
public String toString() {
return (javaArray == null) ? "<?Array Wrapper to null?>" : "[object JavaArray]";
}
// overrides
public Object toJavaObject() {
return javaArray;
}
//public String getTypeofString() {
// return "JavaArray";
//}
// overrides
public String toDetailString() {
return "ES:[" + getESClassName() + ":" + javaArray.toString() + "]";
}
}

149
src/FESI/Data/ESBeans.java Normal file
View file

@ -0,0 +1,149 @@
// ESBeans.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import java.util.Date;
import java.util.Enumeration;
import java.lang.reflect.*;
import java.io.*;
import java.awt.event.*;
import java.util.EventListener;
import java.util.zip.*;
import java.beans.Beans;
/**
* Implements the beans loader
*/
public class ESBeans extends ESLoader {
/**
* Create the top level bean loader (object Bean)
* @param evaluator the evaluator
*/
public ESBeans(Evaluator evaluator) {
super(evaluator);
}
/**
* Create a new bean loader or package prefix
* @param packageName The extension of the package name
* @param previousPackage Represents the higher level package names
* @param classLoader the class loader to use for this loader
* @param evaluator the evaluator
*/
public ESBeans(String packageName,
ESBeans previousPackage,
LocalClassLoader classLoader,
Evaluator evaluator) {
super(packageName,previousPackage,classLoader,evaluator);
}
// overrides
public ESObject getPrototype() {
throw new ProgrammingError("Cannot get prototype of Beans");
}
// overrides
public String getESClassName() {
return "Beans";
}
// overrides
// Getting a property dynamically creates a new Beans prefix object
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
ESValue value = (ESValue) properties.get(propertyName, hash);
if (value == null) {
String packageName = buildPrefix();
value = new ESBeans(propertyName, this, classLoader, evaluator);
properties.put(propertyName, hash, false, false, value); // Cache it for faster retrievial
}
return value;
}
// overrides
// Establish a bean classloader
// The parameter is the directory or jar to load from
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (previousPackage == null && classLoader == null) {
// This is the Beans object
if (arguments.length<1) {
throw new EcmaScriptException("Missing class directory or jar file name");
}
String directoryOrJar = arguments[0].toString();
LocalClassLoader classLoader =
LocalClassLoader.makeLocalClassLoader(directoryOrJar);
return new ESBeans(null, null, classLoader, evaluator);
} else {
throw new EcmaScriptException("Java class not found: '" + buildPrefix() +"'");
}
}
// overrides
// instantiates a bean
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String beanName = buildPrefix();
ESObject value = null;
if (beanName == null) {
throw new EcmaScriptException("cannot create beans without a package name");
}
try {
Object bean = Beans.instantiate(classLoader, beanName);
if (debugJavaAccess) {
System.out.println(" ** Bean '" + beanName + "' created");
}
value = new ESWrapper(bean, evaluator, true);
} catch (ClassNotFoundException e) {
throw new EcmaScriptException("Bean '" + beanName + "' not found: " + e);
} catch (IOException e) {
throw new EcmaScriptException("IOexception loading bean '" + beanName + "': " + e);
}
return value;
}
// overrides
public String getTypeofString() {
return "JavaBeans";
}
// overrides
public String toDetailString() {
return "ES:<" + getESClassName() + ":'" + buildPrefix() + "'" +
((classLoader==null) ? "" : (",@" + classLoader)) + ">";
}
}

View file

@ -0,0 +1,106 @@
// ESBoolean.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator;
/**
* Boolean primitive value
*/
public final class ESBoolean extends ESPrimitive {
// There is only one true and one false value (allowing
// efficient comparisons)
private static ESBoolean trueValue = new ESBoolean();
private static ESBoolean falseValue = new ESBoolean();
private ESBoolean() {
}
/**
* Create a boolean primitive (either true or false)
* by returning the predefined (unique) true or false values
*
* @return either trueValue or falseValue
*/
static public ESBoolean makeBoolean(boolean value) {
return value ? trueValue: falseValue;
}
// overrides
public String toDetailString() {
return "ES:<" + (this==trueValue ? "true" : "false") + ">";
}
// overrides
public int getTypeOf() {
return EStypeBoolean;
}
// overrides
public String getTypeofString() {
return "boolean";
}
// overrides
public String toString() {
return this==trueValue ? "true" : "false";
}
// overrides
public double doubleValue() {
return this==trueValue ? 1 : 0;
}
// overrides
public boolean booleanValue() {
return this==trueValue;
}
// overrides
public ESValue toESBoolean() {
return this;
}
// overrides
public ESValue toESObject(Evaluator evaluator) throws EcmaScriptException {
BooleanPrototype theObject = null;
ESObject bp = evaluator.getBooleanPrototype();
theObject = new BooleanPrototype(bp, evaluator);
theObject.value = this;
return theObject;
}
// overrides
public Object toJavaObject() {
return new Boolean(this==trueValue);
}
// overrides
/**
* returns true as we implement booleanValue without an evaluator.
* @return true
*/
public boolean isBooleanValue() {
return true;
}
}

494
src/FESI/Data/ESLoader.java Normal file
View file

@ -0,0 +1,494 @@
// ESLoader.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import FESI.jslib.JSFunction;
import java.util.Date;
import java.util.Enumeration;
import java.lang.reflect.*;
import java.io.*;
import java.awt.event.*;
import java.util.EventListener;
import java.util.zip.*;
/**
* Implements the common functionality of package(object) and beans loaders
*/
public abstract class ESLoader extends ESObject {
// Debug support
static protected boolean debugJavaAccess = false;
public static void setDebugJavaAccess(boolean b) {
debugJavaAccess = b;
}
static public boolean isDebugJavaAccess() {
return debugJavaAccess;
}
static protected boolean debugLoader = false;
public static void setDebugLoader(boolean b) {
debugLoader = b;
}
static public boolean isDebugLoader() {
return debugLoader;
}
// Incremental package name
protected String packageName = null;
protected ESLoader previousPackage = null;
protected LocalClassLoader classLoader = null;
// the non compatible flag
static private CompatibilityDescriptor nonCompatible =
new CompatibilityDescriptor(-1, null, null);
/**
* To contruct the Bean or Package object
*/
public ESLoader(Evaluator evaluator) {
super(null, evaluator);
}
/**
* To construct a bean or package sub-object (with a specific
* partial or complete package name
* @param packageName The extension of the package name
* @param previousPackage Represents the higher level package names
* @param classLoader the class loader to use for this loader
* @param evaluator the evaluator
*/
public ESLoader(String packageName,
ESLoader previousPackage,
LocalClassLoader classLoader,
Evaluator evaluator) {
super(null, evaluator);
this.packageName = packageName;
this.previousPackage = previousPackage;
this.classLoader = classLoader;
}
/**
* Build the prefix name of the package, concatenating
* all upper level prefix separated by dots
* @return prefix of the current package name
*/
protected String buildPrefix() {
if (previousPackage == null) {
return null;
} else {
String prefix = previousPackage.buildPrefix();
if (prefix == null) {
return packageName;
} else {
return prefix + "." + packageName;
}
}
}
// overrides
public ESObject getPrototype() {
throw new ProgrammingError("Cannot get prototype of Package");
}
// overrides
public int getTypeOf() {
return EStypeObject;
}
// overrides
public ESValue getPropertyInScope(String propertyName, ScopeChain previousScope, int hash)
throws EcmaScriptException {
throw new EcmaScriptException("A loader object ("+this+") should not be part of a with statement");
}
// overrides
public boolean hasProperty(String propertyName, int hash)
throws EcmaScriptException {
return true; // So it can be dereferenced by scopechain
// and wont be created
}
// overrides
public boolean isHiddenProperty(String propertyName, int hash) {
return false;
}
// overrides
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
return; // None can be put by the user
}
// overrides
public void putHiddenProperty(String propertyName, ESValue propertyValue)
throws EcmaScriptException {
throw new ProgrammingError("Cannot put hidden property in " + this);
}
// overrides
public boolean deleteProperty(String propertyName, int hash)
throws EcmaScriptException {
// all possible package name do potentialy exists and
// cannot be deleted, as they are recreated at the first
// reference.
return false;
}
// overrides
public ESValue getDefaultValue(int hint)
throws EcmaScriptException {
if (hint == EStypeString) {
return new ESString(this.toString());
} else {
throw new EcmaScriptException ("No default value for " + this +
" and hint " + hint);
}
}
// overrides
public ESValue getDefaultValue()
throws EcmaScriptException {
return this.getDefaultValue(EStypeString);
}
// overrides
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException("No contructor for loader object: " + this);
}
// overrides
public double doubleValue() {
double d = Double.NaN;
return d;
}
// overrides
public boolean booleanValue() {
return true;
}
// overrides
public String toString() {
return this.toDetailString();
}
//---------------------------------------------------------------
// Tools for the java wrapper objects
//---------------------------------------------------------------
/**
* Returns true if it is a primitive type
* @param the Class to test
* @return true if primitive type
*/
static boolean isBasicClass(Class cls) {
return cls == String.class ||
cls == Character.class ||
cls == Byte.class ||
cls == Short.class ||
cls == Integer.class ||
cls == Long.class ||
cls == Float.class ||
cls == Double.class ||
cls == Boolean.class ||
cls == Date.class;
}
// With the Hop, all instances of Number (including java.math.BigXXX) are
// treated as native numbers, so this is not called by normalizeValue.
static boolean isPrimitiveNumberClass(Class cls) {
return cls == Byte.class ||
cls == Short.class ||
cls == Integer.class ||
cls == Long.class ||
cls == Float.class ||
cls == Double.class;
}
/**
* Transform a java object to an EcmaScript value (primitive if possible)
* @param obj the object to transform
* @param evaluator the evaluator
* @return the EcmaScript object
* @exception EcmaScriptException the normalization failed
*/
public static ESValue normalizeValue(Object obj, Evaluator evaluator)
throws EcmaScriptException {
if (obj == null) {
return ESNull.theNull;
} else if (obj instanceof String) {
return new ESString((String) obj);
} else if (obj instanceof Number) {
return new ESNumber(((Number) obj).doubleValue());
} else if (obj instanceof Boolean) {
return ESBoolean.makeBoolean(((Boolean) obj).booleanValue());
} else if (obj instanceof Character) {
return new ESNumber(((Character) obj).charValue());
} else if (obj instanceof JSFunction) {
return JSWrapper.wrapJSFunction(evaluator, (JSFunction) obj);
} else if (obj instanceof JSWrapper) {
return ((JSWrapper)obj).getESObject();
} else if (obj instanceof Date) {
return new DatePrototype(evaluator, (Date) obj);
} else if (obj instanceof ESWrapper) {
return (ESWrapper) obj; // A wrapper received externally
} else if (obj instanceof ESArrayWrapper) {
return (ESArrayWrapper) obj; // An array wrapper received externally
} else if (obj.getClass().isArray()) {
return new ESArrayWrapper(obj, evaluator);
}
return new ESWrapper(obj, evaluator);
}
/**
* Transform a java object to an EcmaScript object (not a primitive)
* @param obj the object to transform
* @param evaluator the evaluator
* @return the EcmaScript object
* @exception EcmaScriptException the normalization failed
*/
public static ESObject normalizeObject(Object obj, Evaluator evaluator)
throws EcmaScriptException {
ESValue value = normalizeValue(obj, evaluator);
return (ESObject) value.toESObject(evaluator);
}
/**
* Convert the primitive class types to their corresponding
* class types. Must be called for primitive classes only.
*
* @param target The primitive class to convert
* @return The converted class
*/
private static Class convertPrimitive(Class target) {
if (target==java.lang.Boolean.TYPE) {
target=Boolean.class;
} else if (target==java.lang.Character.TYPE) {
target=Character.class;
} else if (target==java.lang.Byte.TYPE) {
target=Byte.class;
} else if (target==java.lang.Short.TYPE) {
target=Short.class;
} else if (target==java.lang.Integer.TYPE) {
target=Integer.class;
} else if (target==java.lang.Long.TYPE) {
target=Long.class;
} else if (target==java.lang.Float.TYPE) {
target=Float.class;
} else if (target==java.lang.Double.TYPE) {
target=Double.class;
} else {
throw new ProgrammingError("Not a recognized primitive type: " + target);
}
return target;
}
/**
* Get a number correlated to the wideness of the class in some lousy sense
*/
static private int getNumberSize(Class cls) {
if (cls == Byte.class) {
return 1;
} else if (cls == Character.class) {
return 2;
} else if (cls == Short.class) { // short and char widen in the same way
return 2;
} else if (cls == Integer.class) {
return 3;
} else if (cls == Long.class) {
return 4;
} else if (cls == Float.class) {
return 5;
} else if (cls == Double.class) {
return 6;
} else {
throw new ProgrammingError("Unexpected number class");
}
}
/**
* Check that each object in the paremeter array can be converted
* to the type specified by the target array and convert them if needed.
* <P>Even if the parameters are compatible with an EcmaScript value,
* some may have to be converted to an intermediate type. For example
* an EcmaScript string of 1 character long is compatible with a Java
* Character, but some conversion is needed. Arrays need a similar
* special processing.
* <P> The parameters have been converted to java Objects by the routine
* toJavaObject. Wrapped objects (java objects given to an EcmaScript
* routine and given back as parameters) have been unwrapped, so they
* are their original object again (including arrays), we do therefore
* not have ESWrapped objects as parameters.
* ESObjects have been wrapped in a JSObject, including Array objects.
* The handling of array is more delicate as they
* could not be converted to a cannonical form - we must know the element
* type to understand if they are convertible.
* <P> The target classes which are primitive are converted to their
* object counterpart, as only object can be given as parameter and the
* invoke mechanism will convert them back to primitive if needed.
* <P>All the conversion needed are described in the returned
* compatibilityDescriptor and will only be applied for the selected
* routine.
* <P>The distance is a metric on how "far" a parameter list is
* from the immediate value (used currntly only for simple value
* widening). It allows to select the routine having the nearest
* parameter list. This is not totally full proof and multiple routine
* can have the same distance (including 0, because of the conversion
* of primitive type to the corresponding objects).
* <P>The tracing must allow to find the logic of the conversion.
* @param target The class objects of the target routine
* @param parms The EcmaScript objects converted to Java objects (IN/OUT)
* @return a compatibility descriptor.
*/
static CompatibilityDescriptor areParametersCompatible(Class target[], Object params[]) {
int n = target.length;
if (n!=params.length) return nonCompatible; // Ensure we have the same number
boolean [] convertToChar = null; // flag to indicate if conversion to char is needed
Object [] convertedArrays = null; // Converted array if any needed
int distance = 0; // For perfect match, something added for widening
for (int i=0; i<n; i++) {
boolean accepted = false;
Class targetClass = target[i];
Class sourceClass = null;
String debugInfo = " not accepted";
if (params[i] == null) {
// A null parameter is of type Object, so we check
// that whatever is the target class be an object
if (targetClass.isPrimitive()) { // or: Object.class.isAssignableFrom(targetClass)
accepted = false;
debugInfo = " rejected (null cannot be assigned to primitive)";
} else {
accepted = true;
debugInfo = " accepted (null to Object)";
}
} else {
// We consider all primitive types as they object
// equivallent, as the parameter can only be done as
// object anyhow. Invoke will convert back if needed.
if (targetClass.isPrimitive()) {
// To accept long by Long, etc... - must be done after test of assigning null to object
targetClass = convertPrimitive(targetClass);
}
// The simplest case is direct object compatibility
sourceClass = params[i].getClass();
accepted = targetClass.isAssignableFrom(sourceClass);
debugInfo = " accepted (subclassing)";
if (!accepted) {
// If we do not have direct object compatibility, we check various
// allowed conversions.
// Handle number and number widening
if ((isPrimitiveNumberClass(sourceClass) ||
sourceClass == Character.class)
&& isPrimitiveNumberClass(targetClass)) {
// Can be widened ?
int targetSize = getNumberSize(targetClass);
int sourceSize = getNumberSize(sourceClass);
if (targetSize>sourceSize) {
accepted = true; // if == already accepted because same class
// or must be rejected (because char != short)
distance += Math.abs(targetSize-sourceSize);
debugInfo = " accepted (number widening: " + distance + ")";
} else {
debugInfo = " rejected (not widening numbers)";
}
// Handle String of length 1 as a Char, which can be converted to a number
} else if ((targetClass == Character.class ||
targetClass == Integer.class ||
targetClass == Long.class ||
targetClass == Float.class ||
targetClass == Double.class)
&& params[i] instanceof String) {
if (((String) params[i]).length()==1) {
accepted = true; // will require conversion of parameter
if (convertToChar == null) {
convertToChar = new boolean[n];
}
convertToChar[i] = true;
debugInfo = " accepted (String(1) as Character)";
} else {
debugInfo = " rejected (String not of length 1)";
}
// Handle array conversion if not from a native java array
} else if (targetClass.isArray()) {
if (params[i] instanceof JSWrapper) {
ESObject esArray = ((JSWrapper) params[i]).getESObject();
if (esArray instanceof ArrayPrototype) {
Object array = null;
try {
// We convert to the orginal class (possibly a primitive type)
array = ((ArrayPrototype) esArray).toJavaArray(targetClass.getComponentType());
accepted = true;
debugInfo = " accepted (array converted)";
if (convertedArrays == null) {
convertedArrays = new Object[n];
}
convertedArrays[i] = array; // save it for replacement at end
} catch (EcmaScriptException e) {
// ignore
debugInfo = " rejected ("+e.getMessage()+")";
}
} else {
debugInfo = " rejected (EcmaScript object is not an array)";
}
} else {
debugInfo = " rejected (only same native array or EcmaScript Array can be assigned to array)";
}
} else {
debugInfo = " rejected (incompatible types)";
}
} // if ! acccepted
} // if ! null
if (debugJavaAccess) System.out.println (" Assign " + sourceClass +
" to " + target[i] +
debugInfo);
if (!accepted) return nonCompatible;
} // for
// Compatible, return appropriate descriptor for future
// processing of conversion of the "nearest" method
return new CompatibilityDescriptor(distance,convertToChar,convertedArrays);
}
// overrides
static public String typeName(Class t) {
String brackets = "";
while (t.isArray()) {
brackets += "[]";
t = t.getComponentType();
}
return t.getName() + brackets;
}
}

72
src/FESI/Data/ESNull.java Normal file
View file

@ -0,0 +1,72 @@
// ESNull.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
/**
* Implements the NULL EcmaScript primitive value
* <P> There is only one value of this type which is referenced
* by ESNull.theNull. In general it is not identical for a routine
* to return ESNull, ESUndefined or the java null. They all have
* different purposes.
*/
public final class ESNull extends ESPrimitive {
/**
* the READ-ONLY null value
*/
public static ESNull theNull = new ESNull();
private ESNull() {
}
// overrides
public String toDetailString() {
return "ES:<null>";
}
// overrides
public int getTypeOf() {
return EStypeNull;
}
// overrides
public String toString() {
return "null";
}
// overrides
public String getTypeofString() {
return "object";
}
// overrides
public double doubleValue() {
return 0;
}
// overrides
public boolean booleanValue() {
return false;
}
// overrides
public Object toJavaObject() {
return null;
}
}

115
src/FESI/Data/ESNumber.java Normal file
View file

@ -0,0 +1,115 @@
// ESNumber.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator;
/**
* Implements the number primitive value as a double
*/
public final class ESNumber extends ESPrimitive {
// The value
private double value;
/**
* Create a new double with a specific value
*
* @param value The (immutable) value
*/
public ESNumber(double value) {
this.value = value;
}
// overrides
public int getTypeOf() {
return EStypeNumber;
}
// overrides
public String getTypeofString() {
return "number";
}
// overrides
public boolean isNumberValue() {
return true;
}
// overrides
public double doubleValue() {
return value;
}
// overrides
public boolean booleanValue() {
return !(Double.isNaN(value) || value==0.0);
}
// overrides
public String toString() {
long intValue = (long) value;
if (((double) intValue) == value) {
return Long.toString(intValue);
} else {
return Double.toString(value);
}
}
// overrides
public ESValue toESObject(Evaluator evaluator) throws EcmaScriptException {
NumberPrototype theObject = null;
ESObject np = evaluator.getNumberPrototype();
theObject = new NumberPrototype(np, evaluator);
theObject.value = this;
return theObject;
}
// overrides
public ESValue toESNumber() {
return this;
}
// overrides
public Object toJavaObject() {
long longValue = (long) value;
Object o = null;
if (((double) longValue) == value) {
if (((byte) longValue) == longValue) {
o = new Byte((byte) longValue);
} else if (((short) longValue) == longValue) {
o = new Short((short) longValue);
} else if (((int) longValue) == longValue) {
o = new Integer((int) longValue);
} else {
o = new Long(longValue);
}
} else {
o= new Double(value);
}
return o;
}
// overrides
public String toDetailString() {
return "ES:#'" + Double.toString(value)+"'";
}
}

775
src/FESI/Data/ESObject.java Normal file
View file

@ -0,0 +1,775 @@
// ESObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator;
import FESI.Interpreter.FesiHashtable;
import FESI.Interpreter.ScopeChain;
import java.util.Enumeration;
public abstract class ESObject extends ESValue {
/** Contains the properties of this object */
protected FesiHashtable properties;
/** The evaluator owning this object */
protected Evaluator evaluator;
/**
* The prototype of this object ([[prototype]] in the standard,
* not the "prototype" property of functions!)
*/
private ESObject prototype = null;
// Prepare common names and their hash value
static private final String TOSTRINGstring = ("toString").intern();
static private final int TOSTRINGhash = TOSTRINGstring.hashCode();
static private final String VALUEOFstring = ("valueOf").intern();
static private final int VALUEOFhash = VALUEOFstring.hashCode();
/**
* Create an object with a specific prototype (which may be null)
* in the context of a specific evaluator (which may not be null)
* Uses the default hashTable size.
*
* @param prototype The prototype ESObject - may be null
* @param evaluator The evaluator - must not be null
*/
protected ESObject(ESObject prototype, Evaluator evaluator) {
this.prototype = prototype;
this.properties = new FesiHashtable();
this.evaluator = evaluator; // It will crash somewhere if null...
}
/**
* Create an object with a specific prototype (which may be null)
* in the context of a specific evaluator (which may not be null)
* Uses the specified hashTable size, which should be a prime.
* size is usefull for very small (arguments) or very large objects.
*
* @param prototype The prototype ESObject - may be null
* @param evaluator The evaluator - must not be null
*/
protected ESObject(ESObject prototype, Evaluator evaluator, int initialSize) {
this.prototype = prototype;
this.properties = new FesiHashtable(initialSize);
this.evaluator = evaluator; // It will crash somewhere if null...
}
/**
* Get the evaluator for this object
*
* @return the evaluator
*/
public final Evaluator getEvaluator() {
return evaluator;
}
/**
* All objects and thir subclasses are non primitive
*
* @return false
*/
public final boolean isPrimitive() {
return false;
}
/**
* Implements the [[prototype]] property (see 8.6.2)
*
* @return The prototype object or null
*/
public ESObject getPrototype() {
return prototype;
}
/**
* Return the name of the class of objects ([[class]]), as used in the default toString
* method of objects (15.2.4.2)
*
* @return the [[Class]] property of this object
*/
public String getESClassName() {
return "Object";
}
/**
* Return a code indicating the type of the object for the implementation
* of the "==" operator.
*
* @return A type code
*/
public int getTypeOf() {
return EStypeObject;
}
/**
* Either return the property value of the specified property
* in the current object, or lookup the next object in the scope chain
* if there is one. If there is nones, generate an error message.
* <P>This routine must be overriden by subclass which change the
* implementation of getProperty.
*
* @param propertyName The property to look for
* @param previousScope The previous scope or null
* @param hash The hashCode of propertyName
* @return The value of the specified variable
* @exception EcmaScriptException if not found in any scope
*/
public ESValue getPropertyInScope(String propertyName,
ScopeChain previousScope,
int hash)
throws EcmaScriptException {
ESValue value = (ESValue) properties.get(propertyName, hash);
if (value == null) {
if (previousScope == null) {
// Return null for undefined global variables.
// throw new EcmaScriptException("global variable '" + propertyName + "' does not have a value");
value = ESNull.theNull;
} else {
value = previousScope.getValue(propertyName, hash);
}
}
return value;
}
/**
* Get the property by name (see 8.6.2.1) propagating to
* the prototype if required
*
* @param propertyName The string naming the property
* @param hash The hashCode of propertyName
* @return The property or <em>undefined</em>
* @exception EcmaScriptException Error in host objects ?
*/
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
ESValue value = (ESValue) properties.get(propertyName, hash);
if (value == null) {
if (prototype == null) {
value = ESUndefined.theUndefined;
} else {
value = prototype.getProperty(propertyName, hash);
}
}
return value;
}
/**
* Get the property by index value. By default the index is
* converted to a string, but this can be optimized for arrays.
* <P>This is not the same as the indexed properties of the first
* version of JavaScript and does not allow to access named
* properties other than the property using the integer string
* representation as a name.
*
* @param index The property name as an integer.
* @return The property or <em>undefined</em>
* @exception EcmaScriptException Error in host objects ?
*/
public ESValue getProperty(int index)
throws EcmaScriptException {
String iString = Integer.toString(index);
return getProperty(iString, iString.hashCode());
}
public boolean hasProperty(String propertyName, int hash)
throws EcmaScriptException {
boolean found = properties.containsKey(propertyName, hash);
if (!found && prototype != null) {
found = prototype.hasProperty(propertyName, hash);
}
return found;
}
public boolean isHiddenProperty(String propertyName, int hash) {
return properties.isHidden(propertyName, hash);
}
/**
* Indicates that the getProperties return an enumerator to the
* index rather rather than to the value index (see ESWrapper).
*
* @return false
*/
public boolean isDirectEnumerator() {
return false;
}
/**
* Returns an enumerator for the key elements of this object,
* that is all is enumerable properties and the (non hidden)
* ones of its prototype, etc... As used for the for in
* statement.
*
* @return the enumerator
*/
public Enumeration getProperties() {
return new Enumeration() {
Enumeration props = properties.keys();
String currentKey = null;
int currentHash = 0;
boolean inside = false;
public boolean hasMoreElements() {
if (currentKey != null) return true;
while (props.hasMoreElements()) {
currentKey = (String) props.nextElement();
currentHash = currentKey.hashCode();
if (inside) {
if (properties.containsKey(currentKey, currentHash)) continue;
} else {
if (isHiddenProperty(currentKey, currentHash)) continue;
}
return true;
}
if (!inside && prototype != null) {
inside = true;
props = prototype.getProperties();
while (props.hasMoreElements()) {
currentKey = (String) props.nextElement();
currentHash = currentKey.hashCode();
if (properties.containsKey(currentKey, currentHash)) continue;
return true;
}
}
return false;
}
public Object nextElement() {
if (hasMoreElements()) {
String key = currentKey;
currentKey = null;
return key;
} else {
throw new java.util.NoSuchElementException();
}
}
};
}
/**
* Get all properties (including hidden ones), for the command
* @listall of the interpreter. Include the visible properties of the
* prototype (that is the one added by the user) but not the
* hidden ones of the prototype (otherwise this would list
* all functions for any object).
*
* @return An enumeration of all properties (visible and hidden).
*/
public Enumeration getAllProperties() {
return new Enumeration() {
String [] specialProperties = getSpecialPropertyNames();
int specialEnumerator = 0;
Enumeration props = properties.keys(); // all of object properties
String currentKey = null;
int currentHash = 0;
boolean inside = false; // true when examing prototypes properties
public boolean hasMoreElements() {
// OK if we already checked for a property and one exists
if (currentKey != null) return true;
// Loop on special properties first
if (specialEnumerator < specialProperties.length) {
currentKey = specialProperties[specialEnumerator];
currentHash = currentKey.hashCode();
specialEnumerator++;
return true;
}
// loop on standard or prototype properties
while (props.hasMoreElements()) {
currentKey = (String) props.nextElement();
currentHash = currentKey.hashCode();
if (inside) {
if (properties.containsKey(currentKey, currentHash)) continue;
// SHOULD CHECK IF NOT IN SPECIAL
}
return true;
}
// If prototype properties have not yet been examined, look for them
if (!inside && prototype != null) {
inside = true;
props = prototype.getProperties();
while (props.hasMoreElements()) {
currentKey = (String) props.nextElement();
currentHash = currentKey.hashCode();
if (properties.containsKey(currentKey, currentHash)) continue;
return true;
}
}
return false;
}
public Object nextElement() {
if (hasMoreElements()) {
String key = currentKey;
currentKey = null;
return key;
} else {
throw new java.util.NoSuchElementException();
}
}
};
}
/**
* Put the property by name (see 8.6.2.2), ignoring if
* read only (integrate functionality of canPut) and
* creating it if needed and possible.
* <P>The routine implement the functionality of the canPut attribute.
*
* @param propertyName The string naming the property
* @param propertyValue The value to put
* @exception EcmaScriptException Error in host objects ?
*/
public void putProperty(String propertyName,
ESValue propertyValue,
int hash)
throws EcmaScriptException {
properties.put(propertyName, hash, false, false, propertyValue);
}
/**
* Put the property by index value. By default the index is
* converted to a string, but this can be optimized for arrays.
* <P>This is not the same as the indexed properties of the first
* version of JavaScript and does not allow to access named
* properties other than the property using the integer string
* representation as a name.
*
* @param index The property name as an integer.
* @param propertyValue The value to put
* @exception EcmaScriptException Error in host objects ?
*/
public void putProperty(int index, ESValue propertyValue)
throws EcmaScriptException {
String iString = Integer.toString(index);
putProperty(iString, propertyValue, iString.hashCode());
}
/**
* Put the property as hidden. This is mostly used by initialization
* code, so a hash value is computed localy and the string is interned.
*
* @param propertyName The name of the property
* @param propertyValue Its value
* @exception EcmaScriptException Not used
*/
public void putHiddenProperty(String propertyName,
ESValue propertyValue)
throws EcmaScriptException {
propertyName = propertyName.intern();
int hash = propertyName.hashCode();
properties.put(propertyName, hash, true, false, propertyValue);
}
/**
* Implements the [[delete]] function (8.6.2.5), only
* called by the DELETE operator. Should return true if
* the propery does not exist any more (or did not exist
* at all) after the return.
* <P>This routine must implement the DontDelete attribue too.
*
* @param propertyName The name of the property
* @return true if the property is not present anymore
* @exception EcmaScriptException Not used
*/
public boolean deleteProperty(String propertyName, int hash)
throws EcmaScriptException {
properties.remove(propertyName, hash);
return true; // either it did not exist or was deleted !
}
/**
* Implements [[DefaultValue]] with hint
*
* @param hint A type hint (only string or number)
* @exception EcmaScriptException Propagated or bad hint
* @return the default value of this object
*/
public ESValue getDefaultValue(int hint)
throws EcmaScriptException {
ESValue theResult = null;
ESValue theFunction = null;
if (hint == ESValue.EStypeString) {
theFunction = this.getProperty(TOSTRINGstring,TOSTRINGhash);
if (theFunction instanceof ESObject) {
theResult = theFunction.callFunction(this, new ESValue[0]);
if (theResult.isPrimitive()) {
return theResult;
}
}
theFunction = this.getProperty(VALUEOFstring,VALUEOFhash);
if (theFunction instanceof ESObject) {
theResult = theFunction.callFunction(this, new ESValue[0]);
if (theResult.isPrimitive()) {
return theResult;
}
}
// Throw errror on super to avoid evaluating this with as a string,
// as this is exactly what we cannot do.
throw new EcmaScriptException ("No default value for " + super.toString() + " and hint " + hint);
} else if (hint == ESValue.EStypeNumber) {
theFunction = this.getProperty(VALUEOFstring,VALUEOFhash);
if (theFunction instanceof ESObject) {
theResult = theFunction.callFunction(this, new ESValue[0]);
if (theResult.isPrimitive()) {
return theResult;
}
}
theFunction = this.getProperty(TOSTRINGstring,TOSTRINGhash);
if (theFunction instanceof ESObject) {
theResult = theFunction.callFunction(this, new ESValue[0]);
if (theResult.isPrimitive()) {
return theResult;
}
}
}
throw new EcmaScriptException ("No default value for " + this + " and hint " + hint);
}
/**
* Implements [[DefaultValue]] with no hint
* <P> The default is different for dates
*
* @exception EcmaScriptException Propagated
* @return the default value of this object
*/
public ESValue getDefaultValue()
throws EcmaScriptException {
return this.getDefaultValue(EStypeNumber);
}
/**
* Call a function object - not implemented for default objecr
*
* @param thisObject The current object
* @param arguments The arguments to the function
* @return The calculated value
* @exception EcmaScriptException thrown because the function is not implemented
*/
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException("No function defined on: " + this);
}
/**
* A construct as thisObject.functionName() was detected,
* The functionName is looked up, then a call is made.
* This avoid creating a dummy function object when one does not
* exists, like for the ESWrapper objects (where functions are
* really java methods).
* <P>Only method which do not use the standard EcmaScript
* function evaluation mechanism need to override this method.
*
* @param evaluator The evaluator
* @param target The original target (for recursive calls)
* @param functionName The name of the function property
* @param arguments The arguments of the function
* @return The result of calling the function
* @exception EcmaScriptException Function not defined
* @exception NoSuchMethodException Method not found
*/
public ESValue doIndirectCall(Evaluator evaluator,
ESObject target,
String functionName,
ESValue[] arguments)
throws EcmaScriptException, NoSuchMethodException {
ESValue theFunction = (ESValue) properties.get(functionName, functionName.hashCode());
if (theFunction == null) {
if (prototype == null) {
throw new EcmaScriptException("The function '"+functionName+
"' is not defined for object '"+target.toString()+"'");
} else {
return prototype.doIndirectCall(evaluator, target, functionName, arguments);
}
} else {
return theFunction.callFunction(target,arguments);
}
}
// A routine which may return a function as the value of a builtin
// property must override this function
public ESValue doIndirectCallInScope(Evaluator evaluator,
ScopeChain previousScope,
ESObject thisObject,
String functionName,
int hash,
ESValue[] arguments)
throws EcmaScriptException {
ESValue theFunction = (ESValue) properties.get(functionName, hash);
if (theFunction == null) {
if (previousScope == null) {
throw new EcmaScriptException("no global function named '" + functionName + "'");
} else {
return previousScope.doIndirectCall(evaluator, thisObject, functionName, hash, arguments);
}
}
return theFunction.callFunction(thisObject,arguments);
}
/**
* Call the constructor - not implemented on default object
*
* @param thisObject The current object
* @param arguments Arguments to new
* @return The created obbjecr
* @exception EcmaScriptException thrown because this function is not implemented
*/
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException("No constructor defined on: " + this);
}
/**
* Return a double value for this object if possible
*
* @return The double value
* @exception EcmaScriptException If not a suitable primitive
*/
public double doubleValue() throws EcmaScriptException {
ESValue value = ESUndefined.theUndefined;
double d = Double.NaN;
try {
value = toESPrimitive(EStypeNumber);
d = value.doubleValue();
} catch (EcmaScriptException e) {
throw new ProgrammingError(e.getMessage());
}
return d;
}
/**
* Return the boolean value of this object if possible
*
* @return the boolean value
* @exception EcmaScriptException If not a suitable primitive
*/
public boolean booleanValue() throws EcmaScriptException {
return true;
}
public String toString() {
ESValue value = ESUndefined.theUndefined;
String string = null;
try {
value = toESPrimitive(EStypeString);
} catch (EcmaScriptException e) {
return this.toDetailString();
}
string = value.toString();
return string;
}
/**
* Convert to an object
*
* @param evaluator The evaluator
* @return This
* @exception EcmaScriptException not thrown
*/
public final ESValue toESObject(Evaluator evaluator) throws EcmaScriptException {
return this;
}
/**
* Convert to a primitive
*
* @param preferedType For string or number
* @return The primitive value
* @exception EcmaScriptException If no suitable default value
*/
public final ESValue toESPrimitive(int preferedType) throws EcmaScriptException {
return getDefaultValue(preferedType);
}
/**
* Convert to a primitive
*
* @return The primitive value
* @exception EcmaScriptException If no suitable default value
*/
public final ESValue toESPrimitive() throws EcmaScriptException {
return getDefaultValue();
}
/**
* Return a Java object which is the object to pass to Java routines
* called by FESI. By default wrap the ESObject in a wrapper object,
* used by the jslib. Overriden by subclass if a better type can be found.
*
* @return a wrapper object over this ESObject.
*/
public Object toJavaObject() {
return new JSWrapper(this, evaluator);
}
/**
* Return the name of the type of the object for the typeof operator
*
* @return The name of the type as a String
*/
public String getTypeofString() {
return "object";
}
public String toDetailString() {
return "ES:[" + getESClassName() + "]";
}
/**
* Return true to indicate that this value is composite.
*
* @return true
*/
public boolean isComposite() {return true; }
/**
* Return the list of proprties which are not listed by getAll,
* that is all special properties handled directly by getProperty,
* which are not in the property hash table (they are considered
* hidden)
* Must be overriden by a subclass which overrides getProperty!
*
* return The array of special property names
*/
public String[] getSpecialPropertyNames() {
return new String[0];
}
/**
* Get an enumeration of the description of various aspects
* of the object, including all properties.
*/
public Enumeration getAllDescriptions() {
return new Enumeration() {
String [] specialProperties = getSpecialPropertyNames();
int specialEnumerator = 0;
Enumeration props = properties.keys();
String currentKey = null;
int currentHash = 0;
boolean inside = false;
boolean inSpecial = true;
public boolean hasMoreElements() {
// If we have one already, send it
if (currentKey != null) return true;
// Loop on special properties first
if (specialEnumerator < specialProperties.length) {
currentKey = specialProperties[specialEnumerator];
currentHash = currentKey.hashCode();
specialEnumerator++;
return true;
}
inSpecial = false;
// Otherwise check in current enumeration
while (props.hasMoreElements()) {
currentKey = (String) props.nextElement();
currentHash = currentKey.hashCode();
//if (inside) {
// if (properties.containsKey(currentKey, currentHash)) continue;
//}
return true;
}
// Got to prototype enumeration if needed
if (!inside && prototype != null) {
inside = true;
props = prototype.getProperties();
while (props.hasMoreElements()) {
currentKey = (String) props.nextElement();
currentHash = currentKey.hashCode();
//if (properties.containsKey(currentKey, currentHash)) continue;
return true;
}
}
return false;
}
public Object nextElement() {
if (hasMoreElements()) {
String key = currentKey;
int hash = key.hashCode();
currentKey = null;
ESValue value = null;
try {
value = ESObject.this.getProperty(key, hash);
} catch (EcmaScriptException e) {
throw new ProgrammingError("Unexpected exception " + e);
}
String propertyKind;
if (inSpecial) {
propertyKind = "HIDDEN";
} else if (inside && properties.containsKey(key, hash)) {
propertyKind = "INVISIBLE";
} else {
propertyKind = isHiddenProperty(key, hash) ? "HIDDEN" : "VISIBLE";
}
propertyKind += (inside ? " PROTOTYPE" : " OBJECT");
propertyKind += " PROPERTY";
return new ValueDescription(key,
propertyKind,
value.toString());
} else {
throw new java.util.NoSuchElementException();
}
}
};
}
/**
* Returns a full description of the value, with the specified name.
*
* @param name The name of the value to describe
*
* @return the description of this value
*/
public ValueDescription getDescription(String name) {
return new ValueDescription(name,
"OBJECT",
this.toString());
}
}

View file

@ -0,0 +1,142 @@
// ESPackages.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
import java.util.Date;
import java.util.Enumeration;
import java.lang.reflect.*;
import java.io.*;
import java.awt.event.*;
import java.util.EventListener;
import java.util.zip.*;
/**
* Implements the object loader
*/
public class ESPackages extends ESLoader {
/**
* Create the top level package loader (object Package)
* @param evaluator the evaluator
*/
public ESPackages(Evaluator evaluator) {
super(evaluator);
}
/**
* Create a new package loader or package prefix
* @param packageName The extension of the package name
* @param previousPackage Represents the higher level package names
* @param classLoader the class loader to use for this loader
* @param evaluator the evaluator
*/
public ESPackages(String packageName,
ESPackages previousPackage,
LocalClassLoader classLoader,
Evaluator evaluator) {
super(packageName,previousPackage,classLoader,evaluator);
}
// overrides
public ESObject getPrototype() {
throw new ProgrammingError("Cannot get prototype of Package");
}
// overrides
public String getESClassName() {
return "Packages";
}
// Utility routine to load a class
private Class loadClass(String className) throws ClassNotFoundException {
if (classLoader == null) {
return Class.forName(className);
} else {
return classLoader.loadClass(className); // use our own class loader
}
}
// overrides
// Getting a property dynamically creates a new Package prefix object
// If the resulting name represents a class then the class object is created
// and returned (and will be used for example by the "new" operator).
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
ESValue value = (ESValue) properties.get(propertyName, hash);
if (value == null) {
String packageName = buildPrefix();
String fullName = (packageName == null) ? propertyName : (packageName + "." + propertyName);
try {
Class cls = loadClass(fullName);
if (debugJavaAccess) {
System.out.println("** Class '" + fullName + "' loaded");
}
value = new ESWrapper(cls, evaluator);
} catch (ClassNotFoundException e) {
if (debugJavaAccess) {
System.out.println("** Could not load '" + fullName +
"' by " + this);
System.out.println("** Exception: " + e);
}
value = new ESPackages(propertyName, this, classLoader, evaluator);
}
properties.put(propertyName, hash, false, false, value); // Cache it for faster retrievial
}
return value;
}
// overrides
// Establish a bean classloader
// The parameter is the directory or jar to load from
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (previousPackage == null && classLoader == null) {
// This is the Package object
if (arguments.length<1) {
throw new EcmaScriptException("Missing class directory or file name");
}
String directoryOrJar = arguments[0].toString();
LocalClassLoader classLoader =
LocalClassLoader.makeLocalClassLoader(directoryOrJar);
return new ESPackages(null, null, classLoader, evaluator);
} else {
throw new EcmaScriptException("Java class not found: '" + buildPrefix() +"'");
}
}
// overrides
public String getTypeofString() {
return "JavaPackage";
}
// overrides
public String toDetailString() {
return "ES:<" + getESClassName() + ":'" + buildPrefix() + "'" +
((classLoader==null) ? "" : (",@" + classLoader)) + ">";
}
}

View file

@ -0,0 +1,95 @@
// ESPrimitive.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
/**
* This is the superclass of all primitive values (non object)
* of FESI. The conversion to a primitive value from a primitive
* value is always the same value, independently of the hint (9.1).
* <P>Use the isPrimitive function, so that further primitive could
* be added without subclassing this class.
*/
public abstract class ESPrimitive extends ESValue {
/**
* Create a new primitive value. Does not add any specific information.
*
*/
public ESPrimitive() {
super();
}
/**
* Indicate that this value is a primitive value, useful for various
* tests in conversions. This avoid testing the type, in case additional
* primitives must be created.
*
* @return true
*/
public final boolean isPrimitive() {
return true;
}
/**
* Return false to indicate that this value is not composite.
*
* @return false
*/
public boolean isComposite() {return false; }
/**
* Convert to a primitive - a NOOP for a primitive.
*
* @return this
* @exception EcmaScriptException not thrown
*/
public final ESValue toESPrimitive() throws EcmaScriptException {
return this;
}
/**
* Convert to a primitive - a NOOP for a primitive.
*
* @param hint ignored
* @return this
* @exception EcmaScriptException not thrown
*/
public final ESValue toESPrimitive(int hint) throws EcmaScriptException {
return this;
}
/**
* Returns a full description of the value, with the specified name.
*
* @param name The name of the value to describe
*
* @return the description of this value
*/
public ValueDescription getDescription(String name) {
return new ValueDescription(name,
"PRIMITIVE",
this.toString());
}
}

View file

@ -0,0 +1,137 @@
// ESreference.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
/**
* Currently a reference is not a FESI value, as it can never be returned
* as a valid value by an EcmaScript function (8.7). It would be easy
* to make ESReference a subclass of ESValue or to create a common
* superclass (ESData) for both ESReference and ESValue if so desired in
* the future (in fact this was the case in the first version of the system).
* <P>References are less used than in the standard, as they are built only
* if required for assignement.
*/
public class ESReference {
private ESObject base; // null means a property of the global object
private String propertyName; // Should never be null for a valid reference
private int hash; // hashCode of propertyName
/**
* Create a new reference given a base and a property name
*
* @param base - may be null
* @param propertyName - may not be null
* @param hash - hashCode of propertyName
*/
public ESReference(ESValue base, String propertyName, int hash) {
// Make sure the property name is not null
if (propertyName == null) {
throw new NullPointerException();
}
this.base = (ESObject) base;
this.propertyName = propertyName;
this.hash = hash;
// System.out.println("NEWREF: " + this);
}
/**
* Return the base object to which the property applies
* Only used for the DELETE operation. See 8.7.1
*
* @return The base object, possibly null
* @exception EcmaScriptException Not thrown
*/
public ESValue getBase() throws EcmaScriptException {
return base;
}
/**
* Get the name of the property to apply to the base object
* Only used for the DELETE operation. See 8.7.2
*
* @return The name of the property, never null
* @exception EcmaScriptException not thrown
*/
public String getPropertyName() throws EcmaScriptException {
return propertyName;
}
/**
* Return the referenced value unless it is global and not defined, in which case
* an exception is raised (see 8.7.3). By the definition of getProperty, and undefined
* value is returned if the base object is defined but the property does
* not exist (see 8.6.2.1).
*
* @return The referenced value
* @exception EcmaScriptException if the value is not defined
*/
public ESValue getValue() throws EcmaScriptException {
if (base == null) {
throw new EcmaScriptException("global variable '" + propertyName + "' does not have a value");
}
return base.getProperty(propertyName, hash);
}
/**
* Update the referenced value, creating it if needed. If the base is
* is null use the global object, otherwise use the base object.
* See 8.7.4.
*
* @param g The global object to use if thre base is null
* @param v The value to put
* @exception EcmaScriptException May be thrown by putProperty
*/
public void putValue(ESObject g, ESValue v) throws EcmaScriptException {
// System.out.println("PUT " + v + " to " + this);
if (base==null) {
g.putProperty(propertyName, v, hash);
} else {
base.putProperty(propertyName, v, hash);
}
}
/**
* Return a string identifying the reference type and its content
*
* @return a string
*/
public String toDetailString() {
return "ES:*<" + ((base==null) ? "null" : base.toString()) + ":" + propertyName +">";
}
/**
* Return the name of the reference, using a dot notation (could use
* the bracket notation, or check which one is most appropriate).
* Note that the base object is returned between braces, we do
* not know its name at this stage. This is used for debugging
* purpose, there is no way to get the string of a reference in
* EcmaScript.
*
* @return The string naming the reference.
*/
public String toString() {
return ((base==null) ? "" : ("{" + base.toString() + "}.")) + propertyName;
}
}

109
src/FESI/Data/ESString.java Normal file
View file

@ -0,0 +1,109 @@
// ESString.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Interpreter.Evaluator;
import FESI.Exceptions.*;
/**
* Implements the string primitive value
*/
public final class ESString extends ESPrimitive {
// The value
private String string;
/**
* Create a new value from the string parameters
*
* @param value The immutable value
*/
public ESString(String value) {
this.string = value;
}
// overrides
public String toDetailString() {
return "ES:\"" + string + "\"";
}
// overrides
public int getTypeOf() {
return EStypeString;
}
// overrides
public String getTypeofString() {
return "string";
}
// overrides
public String toString() {
return string;
}
/**
* Returns the length of the string
*
* @return the length of the string
*/
public int getStringLength() {
return string.length();
}
// overrides
public double doubleValue() {
double value = Double.NaN;
try {
// Will accept leading / trailing spaces, unlike new Integer !
value = (Double.valueOf(string)).doubleValue();
} catch (NumberFormatException e) {
}
return value;
}
// overrides
public boolean booleanValue() {
return string.length()>0;
}
// overrides
public ESValue toESString() {
return this;
}
// overrides
public ESValue toESObject(Evaluator evaluator) throws EcmaScriptException {
StringPrototype theObject = null;
ESObject sp = evaluator.getStringPrototype();
theObject= new StringPrototype(sp, evaluator);
theObject.value = this;
return theObject;
}
// overrides
public Object toJavaObject() {
return string;
}
// overrides
public boolean isStringValue() {
return true;
}
}

View file

@ -0,0 +1,101 @@
// ESUndefined.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
/**
* Implements the Undefined primitive value.
* <P>There is a single Undefined value reached by ESUndefined.theUndefined
* <P>The primitive Undefined, null and the java null are not
* equivallent and must be used in the appropriate context
*/
public final class ESUndefined extends ESPrimitive {
/**
* the READ-ONLY undefined value
*/
public static ESUndefined theUndefined = new ESUndefined();
private ESUndefined() {
}
/**
* Implements a specific error message if an undfined value is called
* @param thisObject The object on which the call is made
* @param arguments The arguments of the function
* @exception EcmaScriptException Thrown to indicate call on undefined value
* @return never
*/
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException("Function called on undefined value or property");
}
/**
* Implements a specific error message if an undfined value is called via new
* @param thisObject The object on which the call is made
* @param arguments The arguments of the function
* @exception EcmaScriptException Thrown to indicate call on undefined value
* @return never
*/
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException("'new' called on undefined value or property");
}
// overrides
public String toDetailString() {
return "ES:<undefined>";
}
// overrides
public int getTypeOf() {
return EStypeUndefined;
}
// overrides
public String getTypeofString() {
return "undefined";
}
// overrides
public String toString() {
return "undefined";
}
// overrides
public double doubleValue() {
return Double.NaN;
}
// overrides
public boolean booleanValue() {
return false;
}
// overrides
public Object toJavaObject() {
return null; // should throw an error
}
}

338
src/FESI/Data/ESValue.java Normal file
View file

@ -0,0 +1,338 @@
// ESValue.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import java.util.Enumeration;
import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator;
/**
* All EcmaScript values are subclasses of this class.
* The ESValue support many operations which may not be
* implemented by all type (and then generate an error),
* to simplify type checking.
* <P>ESReference are currently not value - see ESReference.
*/
public abstract class ESValue {
// Codes for the getTypeOf, used to implement "=="
public static final int EStypeUndefined = 1;
public static final int EStypeNull = 2;
public static final int EStypeBoolean = 3;
public static final int EStypeNumber = 4;
public static final int EStypeString = 5;
public static final int EStypeObject = 6;
// The following routines access the value as a primitive type. They are
// the prefered way to access the value of a primitive type or the default
// value of an object if its type is known.
// If the object is a reference, it will be dereferenced until a value is
// found, this may generate an error or return a dummy value.
//
// toString() is considered part of these data access routine, however
// it may never fail. It is implemented as described in 9.8.
/**
* Returns a detailed description of the value, intended for debugging.
* (toString returns the official string representation, as defined in 9.8).
*
* @return the detailled information
*/
abstract public String toDetailString();
/**
* Return a Java object which is the object to pass to Java routines
* called by FESI. This may be the corresponding Java object (for
* example the String), or a wrapper object. When received back from
* a Java routine, an equivallent (but probably not identical) object
* must be built.
*
* @return a Java object equivallent to the EcmaScript object.
*/
public abstract Object toJavaObject();
/**
* Return the double value of this ESValue as defined in 9.3, throw an
* exception if not defined.
*
* @return a double
* @exception EcmaScriptException Thrown because by default this is not supported
*/
public double doubleValue() throws EcmaScriptException {
throw new EcmaScriptException("Conversion to double unsupported by " + this);
}
/**
* Return the boolean value of this ESValue as defined in 9.2, throw an
* exception if not defined.
*
* @return a boolean
* @exception EcmaScriptException Thrown because by default this is not supported
*/
public boolean booleanValue() throws EcmaScriptException {
throw new EcmaScriptException("Conversion to boolean unsupported by " + this);
}
/**
* Return the EcmaScript object of this ESValue as definined in 9.9, throw
* an exception if not defined.
*
* @param evaluator The evaluator object
* @return an ESObject
* @exception EcmaScriptException Thrown because by default this is not supported
*/
public ESValue toESObject(Evaluator evaluator) throws EcmaScriptException {
throw new EcmaScriptException("Conversion to object unsupported by " + this);
}
// The following routines are derived from the doubleValue of the
// ESvalue. They may be overriden for efficiency by classes which
// contain an integer or other equivallent.
/**
* Return the Integer value, as defined in 9.4.
*
* @return An integer inside a double
* @exception EcmaScriptException Not thrown
*/
public double toInteger() throws EcmaScriptException {
double value = this.doubleValue();
if (Double.isNaN(value)) {
return 0.0;
} else if ((value == 0.0) ||
Double.isInfinite(value)) {
return value;
} else {
return (double)((long) value);
}
}
/**
* Return the 32 bit integer, as defined in 9.5
*
* @return The signed 32 bit integer
* @exception EcmaScriptException Not thrown
*/
public int toInt32() throws EcmaScriptException {
double value = this.toInteger();
return (int) value;
}
/**
* Returned the unsigned 32 bit integer (9.6). Currently
* implemented as toInt32 !
*
* @return The integer
* @exception EcmaScriptException Not thrown
*/
public int toUInt32() throws EcmaScriptException {
double value = this.toInteger();
return (int) value;
}
/**
* Return the unsigned 16 bit integer (9.7). Currently
* ignore the sign issue.
*
* @return The unsigned as a short
* @exception EcmaScriptException Not thrown
*/
public short toUInt16() throws EcmaScriptException {
double value = this.toInteger();
return (short) value;
}
// Convertion to EcmaScript primitive type - rebuild the primitive type based
// on the convertion to the Java primitive type. May be overriden by a subclass
// for efficiency purpose (especially if it does not require a conversion).
// In fact on toESNumber is used (to implement the operator +), and this
// is a very minor performance enhancement - so the routine could be
// easily supressed
/**
* Convert the value to an EcmaScript boolean (9.2) if possible
*
* @return The EcmaScript boolean value
* @exception EcmaScriptException Not thrown
*/
public ESValue toESBoolean() throws EcmaScriptException {
return ESBoolean.makeBoolean(this.booleanValue());
}
/**
* Convert the value to an EcmaScript string (9.8) if possible
*
* @return The EcmaScript string value (there is always one!)
*/
public ESValue toESString() {
return new ESString(this.toString());
}
/**
* Convert the value to an EcmaScript number (9.3) if possible
*
* @return The EcmaScript number value
* @exception EcmaScriptException From doubleValue
*/
public ESValue toESNumber() throws EcmaScriptException {
double d = this.doubleValue();
return new ESNumber(d);
}
// Provide support to easily distinguish primitive values from other, and
// to convert values to primitive value. If the desired type is known
// the direct conversion routines are prefered.
/**
* Return true if the value is a built-in primitive
*
* @return true if a primitive
*/
abstract public boolean isPrimitive();
/**
* Transform to a primitive as described in 9.1
*
* @return A primitive value
* @exception EcmaScriptException If conversion is impossible
*/
abstract public ESValue toESPrimitive() throws EcmaScriptException;
/**
* Transform to a primitive as described in 9.1, with a specified hint
*
* @param preferedType the prefered type to return
* @return a primitive value
* @exception EcmaScriptException If conversion is impossible
*/
abstract public ESValue toESPrimitive(int preferedType) throws EcmaScriptException;
// [[Call]] support (to ease check of type)
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException("Function called on non object: " + this);
}
// [[Construct]] support (to ease check of type)
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
throw new EcmaScriptException("'new' called on non object: " + this);
}
// abstract public ESValue doNewObject();
/**
* Information routine to check if a value is a number (for array indexing)
* if true, must implement conversions to double and int without evaluator.
* @return true if a number.
*/
public boolean isNumberValue() {
return false;
}
/**
* Information routine to check if a value is a string
* if true, must implement toString without a evaluator.
* @return true if a String (ESString or StringPrototype).
*/
public boolean isStringValue() {
return false;
}
/**
* Information routine to check if a value is a boolean
* if true, must implement booleanValue without a evaluator.
* @return true if a boolean (ESBoolean or BooleanPrototype).
*/
public boolean isBooleanValue() {
return false;
}
/**
* Return a code indicating the type of the object for the implementation
* of the "==" operator.
*
* @return A type code
*/
public abstract int getTypeOf();
/**
* Return the name of the type of the object for the typeof operator
*
* @return The name of the type as a String
*/
public abstract String getTypeofString();
// Support to list description of objects
/**
* Return true if the value is composite (even if not an
* object). A composite value can be examined by getAllDescriptions.
* A composite value may have no component!
*
* @return true if composite
*/
abstract public boolean isComposite();
/**
* Return an enumeration of all description of elements of this
* value (for example properties of an object).
*
* @return Enumerator of all components or NULL.
*/
public Enumeration getAllDescriptions() {return null;}
/**
* Returns a full description of the value, with the specified name.
*
* @param name The name of the value to describe
*
* @return the description of this value
*/
abstract public ValueDescription getDescription(String name);
/**
* Returns a full description of the unnamed value.
*
* @return the description of this value
*/
public ValueDescription getDescription() {
return getDescription(null);
}
}

1484
src/FESI/Data/ESWrapper.java Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,153 @@
// FunctionObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Parser.*;
import FESI.AST.*;
import java.util.Vector;
import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator;
import FESI.Interpreter.StringEvaluationSource;
import FESI.Interpreter.FunctionEvaluationSource;
import FESI.Interpreter.EcmaScriptVariableVisitor;
/**
* Implements the EcmaScript Function singleton
*/
public class FunctionObject extends BuiltinFunctionObject
implements EcmaScriptTreeConstants {
static boolean debugParse = false;
FunctionObject(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator, "Function", 1);
}
// overrides
public String getESClassName() {
return "Function";
}
// overrides - call and new have the same effect
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
return doConstruct(thisObject, arguments);
}
// overrides - build a new function
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESObject fp = evaluator.getFunctionPrototype();
ConstructedFunctionObject theFunction = null;
ASTFormalParameterList fpl = null;
ASTStatementList sl = null;
StringBuffer parameters = new StringBuffer();
int nArgs = arguments.length;
int i;
for (i=0; i<(nArgs-1); i++) {
if (i>0) {parameters.append(",");}
String arg = arguments[i].toString();
parameters.append(arg);
}
String body = arguments[i].toString();
//System.out.println("P:'"+parameters+"'");
//System.out.println("B:'"+body+"'");
String trimedParams = parameters.toString().trim();
String fullFunctionText = "function anonymous (" +
trimedParams +
") {" +
body.toString() +
"}";
java.io.StringReader is;
EcmaScript parser;
// Special case for empty parameters
if (trimedParams.length()==0) {
fpl = new ASTFormalParameterList(JJTFORMALPARAMETERLIST);
} else {
is =
new java.io.StringReader(trimedParams);
parser = new EcmaScript(is);
try {
fpl = (ASTFormalParameterList) parser.FormalParameterList();
is.close();
} catch (ParseException e) {
if (debugParse) {
System.out.println("[[PARSING ERROR DETECTED: (debugParse true)]]");
System.out.println(e.getMessage());
System.out.println("[[BY ROUTINE:]]");
e.printStackTrace();
System.out.println();
}
throw new EcmaScriptParseException(e,
new StringEvaluationSource(fullFunctionText,
null)
);
}
}
is = new java.io.StringReader(body.toString());
parser = new EcmaScript(is);
try {
sl = (ASTStatementList) parser.StatementList();
is.close();
} catch (ParseException e) {
if (debugParse) {
System.out.println("[[PARSING ERROR DETECTED: (debugParse true)]]");
System.out.println(e.getMessage());
System.out.println("[[BY ROUTINE:]]");
e.printStackTrace();
System.out.println();
}
throw new EcmaScriptParseException(e,
new StringEvaluationSource(fullFunctionText, null));
}
FunctionEvaluationSource fes =
new FunctionEvaluationSource(
new StringEvaluationSource(fullFunctionText,null),
"<anonymous function>");
EcmaScriptVariableVisitor varDeclarationVisitor = evaluator.getVarDeclarationVisitor();
Vector variableNames = varDeclarationVisitor.processVariableDeclarations(sl, fes);
theFunction = ConstructedFunctionObject.makeNewConstructedFunction(
evaluator,
"anonymous",
fes,
fullFunctionText,
fpl.getArguments(),
variableNames,
sl);
return theFunction;
}
// overrides
public String toString() {
return "<Function>";
}
}

View file

@ -0,0 +1,142 @@
// FunctionPrototype.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator;
import FESI.Interpreter.ScopeChain;
/**
* Implements the prototype and is the class of all Function objects
*/
public class FunctionPrototype extends ESObject {
private String functionName = null;
private int length = 0;
private static final String LENGTHstring = ("length").intern();
private static final int LENGTHhash = LENGTHstring.hashCode();
FunctionPrototype(ESObject prototype, Evaluator evaluator, String functionName, int length) {
super(prototype, evaluator);
this.functionName = functionName;
this.length = length;
}
FunctionPrototype(ESObject prototype, Evaluator evaluator, int length) {
super(prototype, evaluator);
this.length = length;
}
// overrides
public String getESClassName() {
return "Function";
}
public String getFunctionName() {
if (functionName == null) {
return "anonymous";
} else {
return functionName;
}
}
/**
* get the string defining the function
* @return a String indicating that this is the function prototype
*/
public String getFunctionImplementationString() {
return "{<FunctionPrototype (" + this.getClass().getName() + ")>}";
}
/**
* get the string defining the function
* @return a string indicating that the function prototype has no argument
*/
public String getFunctionParametersString() {
return "()";
}
/**
* Get the number of arguments property
*/
public int getLengthProperty() {
return length;
}
// overrides
public ESValue getPropertyInScope(String propertyName, ScopeChain previousScope, int hash)
throws EcmaScriptException {
if (hash==LENGTHhash && propertyName.equals(LENGTHstring)) {
return new ESNumber(length);
}
return super.getPropertyInScope(propertyName, previousScope, hash);
}
// overrides
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
if (hash==LENGTHhash && propertyName.equals(LENGTHstring)) {
return new ESNumber(length);
} else {
return super.getProperty(propertyName, hash);
}
}
// overrides
public boolean hasProperty(String propertyName, int hash)
throws EcmaScriptException {
if (hash==LENGTHhash && propertyName.equals(LENGTHstring)) {
return true;
} else {
return super.hasProperty(propertyName, hash);
}
}
// overrides
public void putProperty(String propertyName, ESValue propertyValue, int hash)
throws EcmaScriptException {
if (!(hash==LENGTHhash && propertyName.equals(LENGTHstring))) {
super.putProperty(propertyName,propertyValue, hash);
} // Allowed via putHiddenProperty, used internally !
}
// overrides
public String[] getSpecialPropertyNames() {
String [] ns = {LENGTHstring};
return ns;
}
// overrides
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
return ESUndefined.theUndefined;
}
// overrides
public String getTypeofString() {
return "function";
}
// overrides
public String toString() {
return "<" + getESClassName() + ":" + this.getFunctionName() +">";
}
}

View file

@ -0,0 +1,455 @@
// GlobalObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import java.util.Hashtable;
import FESI.Exceptions.*;
import FESI.Interpreter.Evaluator;
/**
* Implements the EmcaScript 'global' object
*/
public class GlobalObject extends ObjectPrototype {
static private final String VALUEstring = ("value").intern();
static private final int VALUEhash = VALUEstring.hashCode();
static private final String ERRORstring = ("error").intern();
static private final int ERRORhash = ERRORstring.hashCode();
private GlobalObject(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator);
}
/**
* Create the single global object
* @param evaluator theEvaluator
* @return the 'global' singleton
*/
static public GlobalObject makeGlobalObject(Evaluator evaluator) {
GlobalObject go = null;
try {
// For objectPrototype
class ObjectPrototypeToString extends BuiltinFunctionObject {
ObjectPrototypeToString(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String result = "[object " + thisObject.getESClassName() +"]";
return new ESString(result);
}
}
class ObjectPrototypeValueOf extends BuiltinFunctionObject {
ObjectPrototypeValueOf(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
return thisObject;
}
}
// For functionPrototype
class FunctionPrototypeToString extends BuiltinFunctionObject {
FunctionPrototypeToString(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String s = "function " +
((FunctionPrototype) thisObject).getFunctionName() +
((FunctionPrototype) thisObject).getFunctionParametersString() +
((FunctionPrototype) thisObject).getFunctionImplementationString() ;
return new ESString(s);
}
}
// For GlobalObject
class GlobalObjectThrowError extends BuiltinFunctionObject {
GlobalObjectThrowError(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESObject result = ObjectObject.createObject(this.evaluator);
if (arguments.length<1) {
throw new EcmaScriptException("Exception thrown by throwError");
}
if (arguments[0] instanceof ESWrapper) {
Object o = ((ESWrapper) arguments[0]).getJavaObject();
if (o instanceof Throwable) {
throw new EcmaScriptException(o.toString(), (Throwable) o);
} else {
throw new EcmaScriptException(o.toString());
}
}
String text = arguments[0].toString();
throw new EcmaScriptException(text);
}
}
class GlobalObjectTryEval extends BuiltinFunctionObject {
GlobalObjectTryEval(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESObject result = ObjectObject.createObject(this.evaluator);
if (arguments.length<1) {
result.putProperty(ERRORstring,ESNull.theNull,ERRORhash);
return result;
}
if (!(arguments[0] instanceof ESString)) {
result.putProperty(VALUEstring,arguments[0],VALUEhash);
result.putProperty(ERRORstring,ESNull.theNull,ERRORhash);
return result;
}
String program = arguments[0].toString();
ESValue value = ESUndefined.theUndefined;
try {
value = this.evaluator.evaluateEvalString(program);
} catch (EcmaScriptParseException e) {
e.setNeverIncomplete();
if (arguments.length>1) {
result.putProperty(VALUEstring,arguments[1],VALUEhash);
}
result.putProperty(ERRORstring,
ESLoader.normalizeValue(e,this.evaluator),
ERRORhash);
return result;
} catch (EcmaScriptException e) {
if (arguments.length>1) {
result.putProperty(VALUEstring,arguments[1],VALUEhash);
}
result.putProperty(ERRORstring,
ESLoader.normalizeValue(e,this.evaluator),
ERRORhash);
return result;
}
result.putProperty(VALUEstring,value,VALUEhash);
result.putProperty(ERRORstring,ESNull.theNull,ERRORhash);
return result;
}
}
class GlobalObjectEval extends BuiltinFunctionObject {
GlobalObjectEval(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length<1) return ESUndefined.theUndefined;
if (!(arguments[0] instanceof ESString)) return arguments[0];
String program = arguments[0].toString();
ESValue value = ESUndefined.theUndefined;
try {
value = this.evaluator.evaluateEvalString(program);
} catch (EcmaScriptParseException e) {
e.setNeverIncomplete();
throw e;
}
return value;
}
}
class GlobalObjectParseInt extends BuiltinFunctionObject {
GlobalObjectParseInt(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 2);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length<1) return ESUndefined.theUndefined;
int radix = 10;
String s = arguments[0].toString().trim();
if (arguments.length>1) {
radix = arguments[1].toInt32();
if (radix<2 || radix>36) return new ESNumber(Double.NaN);
if (radix == 16) {
if (s.startsWith("0x") || s.startsWith("0X")) {
s=s.substring(2);
}
}
} else {
if (s.startsWith("0x") || s.startsWith("0X")) {
s=s.substring(2);
radix = 16;
} else if (s.startsWith("0")) {
radix = 8;
}
}
double d = Double.NaN;
int k = -1;
for (int i=0; i<s.length() && k == -1; i++) {
char c= s.charAt(i);
switch (radix) {
case 2:
if (c<'0' || '1'<c) k=i;
break;
case 8:
if (c<'0' || '7'<c) k=i;
break;
case 10:
if (c<'0' || '9'<c) k=i;
break;
case 16:
if ((c<'0' || '9'<c) && (c<'a' || 'f'<c) && (c<'A' || 'F'<c)) k=i;
break;
default:
throw new EcmaScriptException("Only radix 2,8,10 and 16 supported");
}
}
if (k>0) s = s.substring(0,k);
if (s.length()>0) {
try {d = (double) Long.parseLong(s,radix);} catch (NumberFormatException e) {};
}
return new ESNumber(d);
}
}
class GlobalObjectParseFloat extends BuiltinFunctionObject {
GlobalObjectParseFloat(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length<1) return ESUndefined.theUndefined;
String s = arguments[0].toString().trim();
Double d = new Double(Double.NaN);
int i; // approximate look for a prefix
boolean efound = false;
boolean dotfound = false;
for (i=0; i<s.length(); i++) {
char c = s.charAt(i);
if ('0'<=c && c<='9') continue;
if (c=='+' || c=='-') continue; // accept sequences of signs...
if (c=='e' || c=='E') {
if (efound) break;
efound = true;
continue;
}
if (c=='.') {
if (dotfound || efound) break;
dotfound = true;
continue;
}
break;
}
// System.out.println("i="+i+", s="+s);
s = s.substring(0,i);
try {d = Double.valueOf(s); } catch (NumberFormatException e) {};
return new ESNumber(d.doubleValue());
}
}
class GlobalObjectEscape extends BuiltinFunctionObject {
GlobalObjectEscape(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length<=0) {
return ESUndefined.theUndefined;
} else {
StringBuffer dst = new StringBuffer();
String src = arguments[0].toString();
for (int i =0; i<src.length(); i++) {
char c = src.charAt(i);
if (('a'<=c && c<='z') ||
('A'<=c && c<='Z') ||
('0'<=c && c<='9') ||
c=='@' || c =='*' ||
c=='_' || c =='+' ||
c=='-' || c =='.' ||
c=='/') {
dst.append(c);
} else if (c<= (char) 0xF) {
dst.append("%0" + Integer.toHexString(c));
} else if (c<= (char) 0xFF) {
dst.append("%" + Integer.toHexString(c));
} else if (c<= (char) 0xFFF) {
dst.append("%u0" + Integer.toHexString(c));
} else {
dst.append("%u" + Integer.toHexString(c));
}
}
return new ESString(dst.toString());
}
}
}
class GlobalObjectUnescape extends BuiltinFunctionObject {
GlobalObjectUnescape(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length<=0) {
return ESUndefined.theUndefined;
} else {
StringBuffer dst = new StringBuffer();
String src = arguments[0].toString();
for (int i =0; i<src.length(); i++) {
char c = src.charAt(i);
if (c == '%') {
StringBuffer d = new StringBuffer();
c = src.charAt(++i); // May raise exception
if (c == 'u' || c == 'U') {
d.append(src.charAt(++i)); // May raise exception
d.append(src.charAt(++i)); // May raise exception
d.append(src.charAt(++i)); // May raise exception
d.append(src.charAt(++i)); // May raise exception
} else {
d.append(src.charAt(i)); // May raise exception
d.append(src.charAt(++i)); // May raise exception
}
c = (char) Integer.parseInt(d.toString(), 16);
}
dst.append(c);
}
return new ESString(dst.toString());
}
}
}
class GlobalObjectIsNaN extends BuiltinFunctionObject {
GlobalObjectIsNaN(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length<1) return ESUndefined.theUndefined;
double d = arguments[0].doubleValue();
return ESBoolean.makeBoolean(Double.isNaN(d));
}
}
class GlobalObjectIsFinite extends BuiltinFunctionObject {
GlobalObjectIsFinite(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length<1) return ESUndefined.theUndefined;
double d = arguments[0].doubleValue();
return ESBoolean.makeBoolean(!Double.isInfinite(d));
}
}
// Create object (not yet usable!) in right order for
// property chain
ObjectPrototype objectPrototype = new ObjectPrototype(null, evaluator);
FunctionPrototype functionPrototype = new FunctionPrototype(objectPrototype, evaluator, "[Function Prototype]", 0);
ObjectObject objectObject = new ObjectObject(functionPrototype, evaluator);
FunctionObject functionObject = new FunctionObject(functionPrototype, evaluator);
StringObject stringObject =
StringObject.makeStringObject(evaluator, objectPrototype, functionPrototype);
NumberObject numberObject =
NumberObject.makeNumberObject(evaluator, objectPrototype, functionPrototype);
BooleanObject booleanObject =
BooleanObject.makeBooleanObject(evaluator, objectPrototype, functionPrototype);
ArrayObject arrayObject =
ArrayObject.makeArrayObject(evaluator, objectPrototype, functionPrototype);
DateObject dateObject =
DateObject.makeDateObject(evaluator, objectPrototype, functionPrototype);
go = new GlobalObject(objectPrototype, evaluator);
// Set built-in properties
objectObject.putHiddenProperty("prototype",objectPrototype);
objectPrototype.putHiddenProperty("constructor",objectObject);
objectPrototype.putHiddenProperty("toString",
new ObjectPrototypeToString("toString", evaluator, functionPrototype));
objectPrototype.putHiddenProperty("valueOf",
new ObjectPrototypeValueOf("valueOf", evaluator, functionPrototype));
functionPrototype.putHiddenProperty("constructor",functionObject);
functionPrototype.putHiddenProperty("toString",
new FunctionPrototypeToString("toString", evaluator, functionPrototype));
functionObject.putHiddenProperty("prototype",functionPrototype);
functionObject.putHiddenProperty("length",new ESNumber(1));
// Save system object so that they can be quickly found
evaluator.setObjectPrototype(objectPrototype);
evaluator.setFunctionPrototype(functionPrototype);
evaluator.setFunctionObject(functionObject);
// Populate the global object
go.putHiddenProperty("throwError",
new GlobalObjectThrowError("throwError", evaluator, functionPrototype));
go.putHiddenProperty("tryEval",
new GlobalObjectTryEval("tryEval", evaluator, functionPrototype));
go.putHiddenProperty("eval",
new GlobalObjectEval("eval", evaluator, functionPrototype));
go.putHiddenProperty("parseInt",
new GlobalObjectParseInt("parseInt", evaluator, functionPrototype));
go.putHiddenProperty("parseFloat",
new GlobalObjectParseFloat("parseFloat", evaluator, functionPrototype));
go.putHiddenProperty("escape",
new GlobalObjectEscape("escape", evaluator, functionPrototype));
go.putHiddenProperty("unescape",
new GlobalObjectUnescape("unescape", evaluator, functionPrototype));
go.putHiddenProperty("isNaN",
new GlobalObjectIsNaN("isNaN", evaluator, functionPrototype));
go.putHiddenProperty("isFinite",
new GlobalObjectIsFinite("isFinite", evaluator, functionPrototype));
go.putHiddenProperty("Object", objectObject);
go.putHiddenProperty("Function", functionObject);
go.putHiddenProperty("String", stringObject);
go.putHiddenProperty("Number", numberObject);
go.putHiddenProperty("Boolean", booleanObject);
go.putHiddenProperty("Array", arrayObject);
go.putHiddenProperty("Date", dateObject);
go.putHiddenProperty("NaN", new ESNumber(Double.NaN));
go.putHiddenProperty("Infinity", new ESNumber(Double.POSITIVE_INFINITY));
go.putHiddenProperty("Array", ArrayObject.makeArrayObject(evaluator, objectPrototype, functionPrototype));
go.putHiddenProperty("Math", MathObject.makeMathObject(evaluator, objectPrototype, functionPrototype));
} catch (EcmaScriptException e) {
e.printStackTrace();
throw new ProgrammingError(e.getMessage());
}
return go;
}
}

View file

@ -0,0 +1,143 @@
// JSGlobalWrapper.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.jslib.*;
import FESI.Exceptions.*;
import FESI.Extensions.Extension;
import FESI.Interpreter.Evaluator;
/**
* Package an EcmaScript object as a JSObject for use by the
* Netscape like interface. Specialled for the global object.
*/
public class JSGlobalWrapper extends JSWrapper implements JSGlobalObject {
/**
* Create a JSGlobalWrapper object over the global object
* @param go the EcmaScript global object
* @param evaluator the Evaluator
*/
public JSGlobalWrapper(GlobalObject go, Evaluator evaluator) {
super(go, evaluator);
}
/**
* Package any object as an EcmaScript object, allowing to use
* it for example with an "eval" function, where it becomes the
* 'this' object.
*
* @param object The object to wrap.
*/
public JSObject makeObjectWrapper(Object object) {
synchronized (evaluator) {
if (object instanceof JSWrapper) {
return (JSWrapper) object; // Already a JSObject
}
if (object instanceof ESWrapper) {
// A java object wrapped as an ecmascript object
ESWrapper eswrapper = (ESWrapper) object;
// Just wrap it for the JS interface
return new JSWrapper(eswrapper,evaluator);
}
// Any native java object - make it an internal ES object, then wrap it
// for the public interface
ESWrapper eswrapper = new ESWrapper(object, evaluator);
return new JSWrapper(eswrapper,evaluator);
}
}
/**
* Mark an object as a bean, restricting its access by FESI scripts
* to the public bean methods and properties.
*
* @param object The object to wrap as a bean.
*/
public Object makeBeanWrapper(Object object) {
synchronized (evaluator) {
if (object instanceof ESWrapper) {
ESWrapper eswrapper = (ESWrapper) object;
if (eswrapper.isBean()) {
return eswrapper;
} else {
return new ESWrapper(eswrapper.getJavaObject(), eswrapper.getEvaluator(), true);
}
} else {
return new ESWrapper(object, evaluator, true);
}
}
}
/**
* Make a new object based on a given prototype (which may be null).
* The object is of class Object and has initially no property.
*
* @return A new object
*/
public JSObject makeJSObject() {
return makeJSObject(null);
}
/**
* Make a new object based the object prototype object.
* The object is of class Object and has initially no property.
*
* @param prototype An object to use as prototype for this object
* @return A new object
*/
public JSObject makeJSObject(JSObject prototype) {
synchronized (evaluator) {
ESObject op = evaluator.getObjectPrototype();
if (prototype != null) {
Evaluator otherEvaluator = ((JSWrapper) prototype).evaluator;
if (otherEvaluator != evaluator) throw new ProgrammingError("Evaluator mismatch");
op = (ESObject) ((JSWrapper) prototype).getESObject();
}
ESObject object = new ObjectPrototype((ESObject) op, evaluator);
return new JSWrapper(object, evaluator);
}
}
/**
* Make a new array object.
* The object is of class Array and is empty (length 0).
*
* @return A new object
*/
public JSObject makeJSArrayObject() {
synchronized (evaluator) {
ESObject ap = evaluator.getArrayPrototype();
ArrayPrototype theArray = new ArrayPrototype(ap, evaluator);
return new JSWrapper(theArray, evaluator);
}
}
/**
* Display the string value of the contained object
* @return The string value
*/
public String toString() {
return object.toString();
}
}

View file

@ -0,0 +1,505 @@
// JSRWrapper.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.jslib.*;
import FESI.Exceptions.*;
import FESI.Extensions.Extension;
import FESI.Interpreter.Evaluator;
import FESI.Interpreter.UserEvaluationSource;
import java.io.Reader;
/**
* Package an EcmaScript object as a JSObject for use by the
* Netscape like interface.
*/
public class JSWrapper implements JSObject {
protected Evaluator evaluator;
protected ESObject object;
/**
* Create a JSWraper for an EcmaScript object
* @param object the EcmaScript object
* @param evaluator theEvaluator
*/
public JSWrapper(ESObject object, Evaluator evaluator) {
super();
this.object = object;
this.evaluator = evaluator;
}
// overrides
public ESObject getESObject() {
return object;
}
/**
* Return the global object attached to this object
* @return the global object
*/
public JSGlobalObject getGlobalObject() {
return new JSGlobalWrapper(evaluator.getGlobalObject(), evaluator);
}
/**
* Implements the call the specified EcmaScript method of this object
*
* @param methodName The name of the method to call
* @param args An array of parameters.
* @return The result of the evaluation
* @exception JSException For any error during interpretation
*/
public Object call(String methodName,Object args[]) throws JSException {
Object obj = null;
synchronized (evaluator) {
try {
ESValue function = object.getProperty(methodName, methodName.hashCode());
ESValue[] esargs = null;
if (args == null) {
esargs = new ESValue[0];
} else {
esargs = new ESValue[args.length];
for (int i=0; i<args.length; i++) {
esargs[i] = ESLoader.normalizeValue(args[i], evaluator);
}
}
ESValue value = function.callFunction(object, esargs); // should never return null
obj = value.toJavaObject();
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return obj;
}
/**
* Implements the evaluation of a string with this object as the 'this' object.
* The string is considered a main program (top level return is not allowed)
*
* @param s The string to evaluate
* @return The result of the evaluation (null if no value returned)
* @exception JSException For any error during interpretation
*/
public Object eval(String s) throws JSException {
Object obj = null;
synchronized (evaluator) {
try {
ESValue value = evaluator.evaluate(s, object, false); // Can return null !
if (value != null) obj = value.toJavaObject();
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return obj;
}
/**
* Evaluate a Reader stream with this object as the 'this' object.
* Consider the stream being a main program, not allowing the
* return statement.
*
* @param r The Reader stream to evaluate
* @param d A description of the Reader for error messages
* @return The result of the evaluation (null if no value returned)
* @exception JSException For any error during interpretation
*/
public Object eval(Reader r, String d) throws JSException {
Object obj = null;
synchronized (evaluator) {
try {
UserEvaluationSource ses;
if (d==null) {
ses = new UserEvaluationSource("<Anonymous stream>", null);
} else {
ses = new UserEvaluationSource(d, null);
}
ESValue value =
evaluator.evaluate(r,
object,
ses,
false);
if (value != null) obj = value.toJavaObject();
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return obj;
}
/**
* Evaluate a Reader stream with this object as the 'this' object.
* Consider the stream being a function program, allowing the
* return statement.
*
* @param r The Reader stream to evaluate
* @param d A description of the Reader for error messages
* @return The result of the evaluation (null if no value returned)
* @exception JSException For any error during interpretation
*/
public Object evalAsFunction(Reader r, String d) throws JSException {
Object obj = null;
synchronized (evaluator) {
try {
UserEvaluationSource ses;
if (d==null) {
ses = new UserEvaluationSource("<Anonymous stream>", null);
} else {
ses = new UserEvaluationSource(d, null);
}
ESValue value =
evaluator.evaluate(r,
object,
ses,
true);
if (value != null) obj = value.toJavaObject();
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return obj;
}
/**
* Implements the evaluation of a string with this object as the 'this' object.
* The string is considered a function (top level return are allowed)
* Passing the specified parameters (names and values must have the same length)
*
* @param s The string to evaluate
* @return The result of the evaluation (null if no value returned)
* @exception JSException For any error during interpretation
*/
public Object evalAsFunction(String s) throws JSException {
Object obj = null;
synchronized (evaluator) {
try {
ESValue value = evaluator.evaluate(s, object, true); // Can return null !
if (value != null) obj = value.toJavaObject();
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return obj;
/*
// This work but is less efficient
evalAsFunction(s, null, null);
*/
}
/**
* Evaluate a Reader stream with this object as the 'this' object.
* Consider the stream being a function program, allowing the
* return statement.
* Passing the specified parameters (names and values must have the same length)
*
* @param r The Reader stream to evaluate
* @param d A description of the Reader for error messages
* @param names the names of the parameters
* @param values the values of the parameters
* @return The result of the evaluation (null if no value returned)
* @exception JSException For any error during interpretation
*/
public Object evalAsFunction(Reader r, String d, String [] names, Object values[]) throws JSException {
Object obj = null;
throw new ProgrammingError("NOT IMPLEMENTED");
/*
synchronized (evaluator) {
try {
UserEvaluationSource ses;
if (d==null) {
ses = new UserEvaluationSource("<Anonymous stream>", null);
} else {
ses = new UserEvaluationSource(d, null);
}
ESValue value =
evaluator.evaluate(r,
object,
ses,
true);
if (value != null) obj = value.toJavaObject();
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return obj;
*/
}
/**
* Implements the evaluation of a string with this object as the 'this' object.
* The string is considered a function (top level return are allowed)
*
* @param body The string to evaluate
* @param names the names of the parameters
* @param values the values of the parameters
* @return The result of the evaluation (null if no value returned)
* @exception JSException For any error during interpretation
*/
public Object evalAsFunction(String body, String [] names, Object values[]) throws JSException {
Object obj = null;
synchronized (evaluator) {
try {
// Create function
int argLength = (names==null ? 0 : names.length);
int checkLength = (values==null ? 0 : names.length);
if (argLength!=checkLength) {
throw new JSException("argument names and values arrays must have the same length, now: " +
argLength + ", " + checkLength);
}
ESValue esArgs[] = new ESValue[argLength+1]; // space for body
for (int i=0; i<argLength; i++) {
esArgs[i] = new ESString(names[i]);
}
esArgs[argLength] = new ESString(body); // body is the last value
ESObject fo = evaluator.getFunctionObject();
ESObject theFunction = fo.doConstruct(null, esArgs);
// Now call function
esArgs = new ESValue[argLength]; // just what is needed
for (int i=0; i<argLength; i++) {
esArgs[i] = ESLoader.normalizeValue(values[i], this.evaluator);
}
ESValue value = theFunction.callFunction(object, esArgs);
if (value != null) obj = value.toJavaObject();
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return obj;
}
/**
* Implements the get named property of this object.
*
* @param name The name of the property to get
* @return The value of the property
* @exception JSException For any error during interpretation
*/
public Object getMember(String name) throws JSException {
Object obj = null;
synchronized (evaluator) {
try {
ESValue value = object.getProperty(name, name.hashCode());
obj = value.toJavaObject();
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return obj;
}
/**
* Implement the get indexed property of this object (useful for arrays).
*
* @param index The index value of the property (converted
* to string if not an array)
* @return The value of the property
* @exception JSException For any error during interpretation
*/
public Object getSlot(int index) throws JSException {
Object obj = null;
synchronized (evaluator) {
try {
ESValue value = object.getProperty(index);
obj = value.toJavaObject();
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return obj;
}
// This Netscape function is not implemented
// public static JSObject getWindow(Applet applet) throws JSException;
/**
* Implement the deletion of a named property of this object
*
* @param name The name of the property to delete
* @exception JSException For any error during interpretation
*/
public void removeMember(String name) throws JSException {
synchronized (evaluator) {
try {
object.deleteProperty(name, name.hashCode());
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
// return;
}
/**
* Implements the set value of a named property of this object
*
* @param name The name of the property to set
* @param value The value to set the property to.
* @exception JSException For any error during interpretation
*/
public void setMember(String name, Object value) throws JSException {
synchronized (evaluator) {
try {
ESValue esvalue = ESLoader.normalizeValue(value, evaluator);
object.putProperty(name, esvalue, name.hashCode());
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return;
}
/**
* Implement the set property by index value. Useful for arrays.
*
* @param index The index of the property in the array.
* @param value The value to set the property to.
* @exception JSException For any error during interpretation
*/
public void setSlot(int index, Object value) throws JSException {
synchronized (evaluator) {
try {
ESValue esvalue = ESLoader.normalizeValue(value, evaluator);
object.putProperty(index, esvalue);
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
return;
}
/**
* Implement the creation of a new evaluator, with no extension loaded.
*
* @return The global object of the created evaluator.
* @exception JSException For any error during initialization
*/
static public JSGlobalObject makeEvaluator() throws JSException {
Evaluator evaluator = new Evaluator();
GlobalObject go = evaluator.getGlobalObject();
return new JSGlobalWrapper(go,evaluator);
}
/**
* Implement the creation of a new evaluator, with specfied extensions loaded.
*
* @param extensions The class name of the extensions to load.
* @return The global object of the created evaluator.
* @exception JSException For any error during initialization
*/
static public JSGlobalObject makeEvaluator(String [] extensions) throws JSException {
Evaluator evaluator = new Evaluator();
GlobalObject go = evaluator.getGlobalObject();
try {
if (extensions != null) {
for (int i =0; i<extensions.length; i++) {
Object e = evaluator.addMandatoryExtension(extensions[i]);
if (e==null) { // Should never happens
throw new JSException ("Could not load extension '" + extensions[i] + "'");
}
}
}
return new JSGlobalWrapper(go,evaluator);
} catch (EcmaScriptException e) {
throw new JSException (e.getMessage(), e);
}
}
/**
* Create a built-in function object from a JSFunction object, so that
* it can be called as a standard function by native objects.
* Parameters are transformed in JSobjects if possible Java primitives are
* are left unhacnged and FESI primitives are transformed to Java primitives.
* @param evaluator the Evaluator
* @param jsf The function to wrap
*/
static public ESObject wrapJSFunction(Evaluator evaluator, JSFunction jsf) {
synchronized (evaluator) {
final JSFunction theFunction = jsf;
class WrapedJSFunction extends BuiltinFunctionObject {
WrapedJSFunction(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESValue value = ESUndefined.theUndefined;
Object jsArguments[] = new Object[arguments.length];
for (int i =0; i<arguments.length; i++) {
if (arguments[i] instanceof ESWrapper) {
jsArguments[i] = ((ESWrapper)arguments[i]).getJavaObject();
} else if (arguments[i] instanceof ESObject) {
jsArguments[i] = new JSWrapper((ESObject) arguments[i], this.evaluator);
} else {
jsArguments[i] = arguments[i].toJavaObject();
}
}
try {
Object result = theFunction.doCall(
new JSWrapper(thisObject, this.evaluator), jsArguments);
value = ESLoader.normalizeValue(result, this.evaluator);
} catch (JSException e) {
throw new EcmaScriptException(e.getMessage());
}
return value;
}
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESObject value = null;
Object jsArguments[] = new Object[arguments.length];
for (int i =0; i<arguments.length; i++) {
if (arguments[i] instanceof ESWrapper) {
jsArguments[i] = ((ESWrapper)arguments[i]).getJavaObject();
} else if (arguments[i] instanceof ESObject) {
jsArguments[i] = new JSWrapper((ESObject) arguments[i], this.evaluator);
} else {
jsArguments[i] = arguments[i].toJavaObject();
}
}
try {
Object result = theFunction.doNew(
new JSWrapper(thisObject, this.evaluator), jsArguments);
value = ESLoader.normalizeObject(result, this.evaluator);
} catch (JSException e) {
throw new EcmaScriptException(e.getMessage());
}
return value;
}
}
return new WrapedJSFunction(jsf.toString(),
evaluator,
(FunctionPrototype) evaluator.getFunctionPrototype());
}
}
/**
* Display the string value of the contained object
* @return The string value
*/
public String toString() {
return object.toString();
}
}

View file

@ -0,0 +1,262 @@
// MathObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
/**
* Implemements the EcmaScript Math singleton.
*/
public class MathObject extends ObjectPrototype {
private FunctionPrototype fp;
private MathObject(ESObject prototype, Evaluator evaluator, FunctionPrototype functionPrototype)
throws EcmaScriptException {
super(prototype, evaluator);
// Initialization used to be in makeMathObject, but this caused
// some problemsto the users of JBuilder. So it is moved in
// the constructor
putHiddenProperty("E", new ESNumber(Math.E));
putHiddenProperty("LN10", new ESNumber(Math.log(10.0d)));
putHiddenProperty("LN2", new ESNumber(Math.log(2.0d)));
putHiddenProperty("LOG2E", new ESNumber(1.0d/Math.log(2.0d)));
putHiddenProperty("LOG10E", new ESNumber(1.0d/Math.log(10.0d)));
putHiddenProperty("PI", new ESNumber(Math.PI));
putHiddenProperty("SQRT1_2", new ESNumber(1.0d/Math.sqrt(2.0d)));
putHiddenProperty("SQRT2", new ESNumber(Math.sqrt(2.0d)));
putHiddenProperty("abs",
new BuiltinMathFunctionOne("abs", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.abs(arg);
}
}
);
putHiddenProperty("acos",
new BuiltinMathFunctionOne("acos", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.acos(arg);
}
}
);
putHiddenProperty("asin",
new BuiltinMathFunctionOne("asin", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.asin(arg);
}
}
);
putHiddenProperty("atan",
new BuiltinMathFunctionOne("atan", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.atan(arg);
}
}
);
putHiddenProperty("atan2",
new BuiltinMathFunctionTwo("atan2", evaluator, functionPrototype) {
public double applyMathFunction(double arg1, double arg2) {
return Math.atan2(arg1,arg2);
}
}
);
putHiddenProperty("ceil",
new BuiltinMathFunctionOne("ceil", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.ceil(arg);
}
}
);
putHiddenProperty("cos",
new BuiltinMathFunctionOne("cos", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.cos(arg);
}
}
);
putHiddenProperty("exp",
new BuiltinMathFunctionOne("exp", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.exp(arg);
}
}
);
putHiddenProperty("floor",
new BuiltinMathFunctionOne("floor", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.floor(arg);
}
}
);
putHiddenProperty("log",
new BuiltinMathFunctionOne("log", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.log(arg);
}
}
);
putHiddenProperty("max",
new BuiltinMathFunctionTwo("max", evaluator, functionPrototype) {
public double applyMathFunction(double arg1, double arg2) {
return Math.max(arg1,arg2);
}
}
);
putHiddenProperty("min",
new BuiltinMathFunctionTwo("min", evaluator, functionPrototype) {
public double applyMathFunction(double arg1, double arg2) {
return Math.min(arg1,arg2);
}
}
);
putHiddenProperty("pow",
new BuiltinMathFunctionTwo("pow", evaluator, functionPrototype) {
public double applyMathFunction(double arg1, double arg2) {
double d = Double.NaN;
try {
d = Math.pow(arg1,arg2);
} catch (ArithmeticException e) {
// return NaN
}
return d;
}
}
);
putHiddenProperty("random",
new BuiltinMathFunctionZero("random", evaluator, functionPrototype) {
public double applyMathFunction() {
return Math.random();
}
}
);
putHiddenProperty("round",
new BuiltinMathFunctionOne("round", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.round(arg);
}
}
);
putHiddenProperty("sin",
new BuiltinMathFunctionOne("sin", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.sin(arg);
}
}
);
putHiddenProperty("sqrt",
new BuiltinMathFunctionOne("sqrt", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.sqrt(arg);
}
}
);
putHiddenProperty("tan",
new BuiltinMathFunctionOne("tan", evaluator, functionPrototype) {
public double applyMathFunction(double arg) {
return Math.tan(arg);
}
}
);
}
// overrides
public String getESClassName() {
return "Math";
}
// class of nilary functions
abstract class BuiltinMathFunctionZero extends BuiltinFunctionObject {
BuiltinMathFunctionZero(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 0);
}
abstract double applyMathFunction();
public ESValue callFunction(ESObject thisObject, ESValue[] arguments)
throws EcmaScriptException {
return new ESNumber(applyMathFunction());
}
}
// class of unary functions
abstract class BuiltinMathFunctionOne extends BuiltinFunctionObject {
BuiltinMathFunctionOne(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
abstract double applyMathFunction(double arg);
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
double arg = (arguments.length>0) ?
arguments[0].doubleValue() :
Double.NaN;
if (Double.isNaN(arg)) {
return new ESNumber(Double.NaN);
}
return new ESNumber(applyMathFunction(arg));
}
}
// class of dyadic functions
abstract class BuiltinMathFunctionTwo extends BuiltinFunctionObject {
BuiltinMathFunctionTwo(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 2);
}
abstract double applyMathFunction(double arg1, double arg2);
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length<2) {
throw new EcmaScriptException("Missing parameter in function " + this);
}
double arg1 = (arguments.length>0) ?
arguments[0].doubleValue() :
Double.NaN;
double arg2 = (arguments.length>01) ?
arguments[1].doubleValue() :
Double.NaN;
if (Double.isNaN(arg1) || Double.isNaN(arg2)) {
return new ESNumber(Double.NaN);
}
return new ESNumber(applyMathFunction(arg1, arg2));
}
}
/**
* Utility function to create the Math single object
*
* @param evaluator the Evaluator
* @param objectPrototype The Object prototype attached to the evaluator
* @param functionPrototype The Function prototype attached to the evaluator
*
* @return the Math singleton
*/
static public ESObject makeMathObject (Evaluator evaluator,
ObjectPrototype prototype,
FunctionPrototype functionPrototype) {
try {
MathObject mo = new MathObject(prototype, evaluator, functionPrototype);
return mo;
} catch (EcmaScriptException e) {
e.printStackTrace();
throw new ProgrammingError(e.getMessage());
}
}
}

View file

@ -0,0 +1,136 @@
// NumberObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
/**
* Implemements the EcmaScript Number singleton.
*/
public class NumberObject extends BuiltinFunctionObject {
private NumberObject(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator, "Number", 1);
}
// overrides
public String toString() {
return "<Number>";
}
// overrides
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length==0) {
return new ESNumber(0.0);
} else {
return new ESNumber(arguments[0].doubleValue());
}
}
// overrides
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
NumberPrototype theObject = null;
ESObject np = evaluator.getNumberPrototype();
theObject= new NumberPrototype(np, evaluator);
if (arguments.length>0) {
theObject.value = new ESNumber(arguments[0].doubleValue());
} else {
theObject.value = new ESNumber(0.0);
}
return theObject;
}
/**
* Utility function to create the single Number object
*
* @param evaluator the Evaluator
* @param objectPrototype The Object prototype attached to the evaluator
* @param functionPrototype The Function prototype attached to the evaluator
*
* @return the Number singleton
*/
public static NumberObject makeNumberObject(Evaluator evaluator,
ObjectPrototype objectPrototype,
FunctionPrototype functionPrototype) {
NumberPrototype numberPrototype = new NumberPrototype(objectPrototype, evaluator);
NumberObject numberObject = new NumberObject(functionPrototype, evaluator);
try {
// For numberPrototype
class NumberPrototypeToString extends BuiltinFunctionObject {
NumberPrototypeToString(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESValue v = ((NumberPrototype) thisObject).value;
String s = v.toString();
if (arguments.length>0) {
double d = arguments[0].doubleValue();
if (!Double.isNaN(d)) {
s = Long.toString(((long)v.doubleValue()),(int)d);
}
}
return new ESString(s);
}
}
class NumberPrototypeValueOf extends BuiltinFunctionObject {
NumberPrototypeValueOf(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
return ((NumberPrototype) thisObject).value;
}
}
numberObject.putHiddenProperty("prototype",numberPrototype);
numberObject.putHiddenProperty("length",new ESNumber(1));
numberObject.putHiddenProperty("MAX_VALUE",new ESNumber(Double.MAX_VALUE));
numberObject.putHiddenProperty("MIN_VALUE",new ESNumber(Double.MIN_VALUE));
numberObject.putHiddenProperty("NaN",new ESNumber(Double.NaN));
numberObject.putHiddenProperty("NEGATIVE_INFINITY",new ESNumber(Double.NEGATIVE_INFINITY));
numberObject.putHiddenProperty("POSITIVE_INFINITY",new ESNumber(Double.POSITIVE_INFINITY));
numberPrototype.putHiddenProperty("constructor",numberObject);
numberPrototype.putHiddenProperty("toString",
new NumberPrototypeToString("toString", evaluator, functionPrototype));
numberPrototype.putHiddenProperty("valueOf",
new NumberPrototypeValueOf("valueOf", evaluator, functionPrototype));
} catch (EcmaScriptException e) {
e.printStackTrace();
throw new ProgrammingError(e.getMessage());
}
evaluator.setNumberPrototype(numberPrototype);
return numberObject;
}
}

View file

@ -0,0 +1,80 @@
// NumberPrototype.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
/**
* Implements the prototype and is the class of all Number objects
*/
class NumberPrototype extends ESObject {
// The value
protected ESNumber value = new ESNumber(0.0);
/**
* Create a new un-initialzed Number
*/
NumberPrototype(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator);
}
// overrides
public String getESClassName() {
return "Number";
}
// overrides
public boolean isNumberValue() {
return true;
}
// overrides
public double doubleValue() {
return value.doubleValue();
}
// overrides
public boolean booleanValue() {
return value.booleanValue();
}
// overrides
public String toString() {
return value.toString();
}
// overrides
public ESValue toESNumber() throws EcmaScriptException {
return value;
}
// overrides
public Object toJavaObject() {
return new Double(value.doubleValue());
}
// overrides
public String toDetailString() {
return "ES:[Object: builtin " + this.getClass().getName() + ":" +
((value == null) ? "null" : value.toString()) + "]";
}
}

View file

@ -0,0 +1,85 @@
// ObjectObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import java.util.Hashtable;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
/**
* Implemements the EcmaScript Object singleton.
*/
public class ObjectObject extends BuiltinFunctionObject {
public ObjectObject(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator, "Object", 1);
}
// overrides
public String toString() {
return "<Object>";
}
/**
* Create an EcmaScript Object for a specified evaluator
* @param evaluator the Evaluator
* @return the new object
*/
static public ObjectPrototype createObject(Evaluator evaluator) {
ESObject op = evaluator.getObjectPrototype();
return new ObjectPrototype(op, evaluator);
}
// overrides
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESValue theValue;
if (arguments.length==0) {
theValue = createObject(evaluator);
} else {
if (arguments[0] == ESNull.theNull ||
arguments[0] == ESUndefined.theUndefined) {
theValue = createObject(evaluator);
} else {
theValue = arguments[0].toESObject(evaluator);
}
}
return (ESObject) theValue;
}
// overrides
public ESValue callFunction( ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESValue theValue;
if (arguments.length==0) {
theValue = createObject(evaluator);
} else {
if (arguments[0] == ESNull.theNull ||
arguments[0] == ESUndefined.theUndefined) {
theValue = createObject(evaluator);
} else {
theValue = arguments[0].toESObject(evaluator);
}
}
return theValue;
}
}

View file

@ -0,0 +1,41 @@
// ObjectPrototype.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Interpreter.Evaluator;
import FESI.Exceptions.*;
/**
* Implements the prototype and is the class of all Object objects.
* <P>All functionality of objects is implemented in the superclass
* ESObject.
*/
public class ObjectPrototype extends ESObject {
/**
* Create a new Object with a specific prototype. This should be used
* by routine implementing object with another prototype than Object.
* To create an EcmaScript Object use ObjectObject.createObject()
*
* @param prototype the prototype of the new object
* @param evaluator The evaluator
*/
public ObjectPrototype(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator);
}
}

View file

@ -0,0 +1,340 @@
// StringObject.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
/**
* Implemements the EcmaScript String singleton.
*/
public class StringObject extends BuiltinFunctionObject {
private StringObject(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator, "String", 1);
}
// overrides
public String toString() {
return "<String>";
}
// overrides
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
if (arguments.length==0) {
return new ESString("");
} else {
return new ESString(arguments[0].toString());
}
}
// overrides
public ESObject doConstruct(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
StringPrototype theObject = null;
ESObject sp = evaluator.getStringPrototype();
theObject= new StringPrototype(sp, evaluator);
if (arguments.length>0) {
theObject.value = new ESString(arguments[0].toString());
} else {
theObject.value = new ESString("");
}
return theObject;
}
/**
* Utility function to create the single String object
*
* @param evaluator the Evaluator
* @param objectPrototype The Object prototype attached to the evaluator
* @param functionPrototype The Function prototype attached to the evaluator
*
* @return the String singleton
*/
public static StringObject makeStringObject(Evaluator evaluator,
ObjectPrototype objectPrototype,
FunctionPrototype functionPrototype) {
StringPrototype stringPrototype = new StringPrototype(objectPrototype, evaluator);
StringObject stringObject = new StringObject(functionPrototype, evaluator);
try {
// For stringPrototype
class StringPrototypeToString extends BuiltinFunctionObject {
StringPrototypeToString(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
return ((StringPrototype) thisObject).value;
}
}
class StringPrototypeValueOf extends BuiltinFunctionObject {
StringPrototypeValueOf(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
return ((StringPrototype) thisObject).value;
}
}
class StringPrototypeCharAt extends BuiltinFunctionObject {
StringPrototypeCharAt(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String str = thisObject.toString();
int pos = 0;
if (arguments.length>0) {
pos = arguments[0].toInt32();
}
if (pos>=0 && pos <str.length()) {
char c[] = {str.charAt(pos)};
return new ESString(new String(c));
} else {
return new ESString("");
}
}
}
class StringPrototypeCharCodeAt extends BuiltinFunctionObject {
StringPrototypeCharCodeAt(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String str = thisObject.toString();
int pos = 0;
if (arguments.length>0) {
pos = arguments[0].toInt32();
}
if (pos>=0 && pos <str.length()) {
char c = str.charAt(pos);
return new ESNumber((double) c);
} else {
return new ESNumber(Double.NaN);
}
}
}
class StringPrototypeIndexOf extends BuiltinFunctionObject {
StringPrototypeIndexOf(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String str = thisObject.toString();
int pos = 0;
if (arguments.length<=0) {
return new ESNumber(-1);
}
String searched = arguments[0].toString();
if (arguments.length>1) {
pos = arguments[1].toInt32();
}
int res = str.indexOf(searched, pos);
return new ESNumber(res);
}
}
class StringPrototypeLastIndexOf extends BuiltinFunctionObject {
StringPrototypeLastIndexOf(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String str = thisObject.toString();
int pos = str.length();
if (arguments.length<=0) {
return new ESNumber(-1);
}
String searched = arguments[0].toString();
if (arguments.length>1) {
double p = arguments[1].doubleValue();
if (!Double.isNaN(p)) pos = arguments[1].toInt32();
}
int res = str.lastIndexOf(searched, pos);
return new ESNumber(res);
}
}
// This code is replaced by the ReegExp variant when RegExp is loaded
class StringPrototypeSplit extends BuiltinFunctionObject {
StringPrototypeSplit(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String str = thisObject.toString();
ESObject ap = this.evaluator.getArrayPrototype();
ArrayPrototype theArray = new ArrayPrototype(ap, this.evaluator);
if (arguments.length<=0) {
theArray.setSize(1);
theArray.setElementAt(thisObject, 0);
} else {
String sep = arguments[0].toString();
if (sep.length()==0) {
int l = str.length();
theArray.setSize(l);
for (int i=0; i<l; i++) {
theArray.setElementAt(
new ESString(str.substring(i,i+1)), i);
}
} else {
int i = 0;
int start = 0;
while (start<str.length()) {
int pos = str.indexOf(sep, start);
if (pos<0) pos = str.length();
// System.out.println("start: " + start + ", pos: " + pos);
theArray.setSize(i+1);
theArray.setElementAt(
new ESString(str.substring(start, pos)),i);
start = pos + sep.length();
i++;
}
}
}
return theArray;
}
}
class StringPrototypeSubstring extends BuiltinFunctionObject {
StringPrototypeSubstring(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String str = thisObject.toString();
int start = 0;
int end = str.length();
if (arguments.length>0) {
start = arguments[0].toInt32();
}
if (start<0) start = 0;
else if (start>str.length()) start = str.length();
if (arguments.length>1) {
end = arguments[1].toInt32();
if (end<0) end = 0;
else if (end>str.length()) end = str.length();
}
if (start>end) {
int x = start; start = end; end = x;
}
return new ESString(str.substring(start, end));
}
}
class StringPrototypeToLowerCase extends BuiltinFunctionObject {
StringPrototypeToLowerCase(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String str = thisObject.toString();
return new ESString(str.toLowerCase());
}
}
class StringPrototypeToUpperCase extends BuiltinFunctionObject {
StringPrototypeToUpperCase(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
String str = thisObject.toString();
return new ESString(str.toUpperCase());
}
}
// For stringObject
class StringObjectFromCharCode extends BuiltinFunctionObject {
StringObjectFromCharCode(String name, Evaluator evaluator, FunctionPrototype fp) {
super(fp, evaluator, name, 1);
}
public ESValue callFunction(ESObject thisObject,
ESValue[] arguments)
throws EcmaScriptException {
ESObject sp = this.evaluator.getStringPrototype();
StringPrototype theObject= new StringPrototype(sp, this.evaluator);
StringBuffer sb = new StringBuffer();
for (int i =0; i<arguments.length; i++) {
char c = (char)(arguments[i].toUInt16());
sb.append(c);
}
theObject.value = new ESString(sb.toString());
return theObject;
}
}
stringObject.putHiddenProperty("prototype",stringPrototype);
stringObject.putHiddenProperty("length",new ESNumber(1));
stringObject.putHiddenProperty("fromCharCode",
new StringObjectFromCharCode("fromCharCode", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("constructor",stringObject);
stringPrototype.putHiddenProperty("toString",
new StringPrototypeToString("toString", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("valueOf",
new StringPrototypeValueOf("valueOf", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("charAt",
new StringPrototypeCharAt("charAt", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("charCodeAt",
new StringPrototypeCharCodeAt("charCodeAt", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("indexOf",
new StringPrototypeIndexOf("indexOf", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("lastIndexOf",
new StringPrototypeLastIndexOf("lastIndexOf", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("split",
new StringPrototypeSplit("split", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("substring",
new StringPrototypeSubstring("substring", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("toLowerCase",
new StringPrototypeToLowerCase("toLowerCase", evaluator, functionPrototype));
stringPrototype.putHiddenProperty("toUpperCase",
new StringPrototypeToUpperCase("toUpperCase", evaluator, functionPrototype));
} catch (EcmaScriptException e) {
e.printStackTrace();
throw new ProgrammingError(e.getMessage());
}
evaluator.setStringPrototype(stringPrototype);
return stringObject;
}
}

View file

@ -0,0 +1,92 @@
// StringPrototype.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
import FESI.Exceptions.*;
import FESI.Interpreter.*;
class StringPrototype extends ESObject {
private static final String LENGTHstring = ("length").intern();
private static final int LENGTHhash = LENGTHstring.hashCode();
ESString value = new ESString("");
StringPrototype(ESObject prototype, Evaluator evaluator) {
super(prototype, evaluator);
}
public String getESClassName() {
return "String";
}
public String toString() {
return value.toString();
}
public ESValue toESString() {
return value;
}
public boolean booleanValue() throws EcmaScriptException {
return value.booleanValue();
}
public double doubleValue() throws EcmaScriptException {
return value.doubleValue();
}
public ESValue getPropertyInScope(String propertyName, ScopeChain previousScope, int hash)
throws EcmaScriptException {
if (hash==LENGTHhash && propertyName.equals(LENGTHstring)) {
return new ESNumber(value.getStringLength());
}
return super.getPropertyInScope(propertyName, previousScope, hash);
}
public ESValue getProperty(String propertyName, int hash)
throws EcmaScriptException {
if (hash==LENGTHhash && propertyName.equals(LENGTHstring)) {
return new ESNumber(value.getStringLength());
} else {
return super.getProperty(propertyName, hash);
}
}
public String[] getSpecialPropertyNames() {
String [] ns = {LENGTHstring};
return ns;
}
public Object toJavaObject() {
return value.toString();
}
public String toDetailString() {
return "ES:[Object: builtin " + this.getClass().getName() + ":" +
((value == null) ? "null" : value.toString()) + "]";
}
/**
* Information routine to check if a value is a string
* if true, must implement toString without a evaluator.
* @return true
*/
public boolean isStringValue() {
return true;
}
}

View file

@ -0,0 +1,89 @@
// ValueDescription.java
// FESI Copyright (c) Jean-Marc Lugrin, 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package FESI.Data;
/**
* A ValueDescription is used to describe the property or field of
* an object (for debugging tools).
*/
public class ValueDescription {
private static String eol = System.getProperty("line.separator", "\n");
/**
* The name of this value (for example the property name
* if it is a property), null if not known or irrelevant.
*/
public String name = null;
/**
* The string describing the type of this value.
*/
public String type;
/**
* The string describing the value.
*/
public String value;
/**
* Build a value descriptor for an unknown name
*/
public ValueDescription (String type, String value) {
this.type = type;
this.value = value;
}
/**
* Build a value descriptor for a specified name
*/
public ValueDescription (String name, String type, String value) {
this.name = name;
this.type = type;
this.value = value;
}
public String toString() {
String propertyValue = value;
// Remove leading eol
while (propertyValue.indexOf("\n")==0) {
propertyValue = propertyValue.substring(1);
}
while (propertyValue.indexOf(eol)==0) {
propertyValue = propertyValue.substring(eol.length());
}
// limit size
if (propertyValue.length()>250) {
propertyValue = propertyValue.substring(0,250) + "...";
}
// keep only first line
int ieol = propertyValue.indexOf(eol);
if (ieol==-1) ieol = propertyValue.indexOf("\n");
if (ieol!=-1) {
propertyValue = propertyValue.substring(0,ieol) + "...";
}
if (name == null) {
return type + ": " + propertyValue;
} else {
return name + ": [" + type + "]: " + propertyValue;
}
}
}