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:
parent
af35ca5581
commit
ee13186158
148 changed files with 34934 additions and 0 deletions
185
src/FESI/Data/ArrayObject.java
Normal file
185
src/FESI/Data/ArrayObject.java
Normal 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;
|
||||
}
|
||||
}
|
585
src/FESI/Data/ArrayPrototype.java
Normal file
585
src/FESI/Data/ArrayPrototype.java
Normal 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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
123
src/FESI/Data/BooleanObject.java
Normal file
123
src/FESI/Data/BooleanObject.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
80
src/FESI/Data/BooleanPrototype.java
Normal file
80
src/FESI/Data/BooleanPrototype.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
70
src/FESI/Data/BuiltinFunctionObject.java
Normal file
70
src/FESI/Data/BuiltinFunctionObject.java
Normal 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() +">";
|
||||
}
|
||||
|
||||
}
|
83
src/FESI/Data/CompatibilityDescriptor.java
Normal file
83
src/FESI/Data/CompatibilityDescriptor.java
Normal 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
|
256
src/FESI/Data/ConstructedFunctionObject.java
Normal file
256
src/FESI/Data/ConstructedFunctionObject.java
Normal 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;
|
||||
// }
|
||||
|
||||
}
|
803
src/FESI/Data/DateObject.java
Normal file
803
src/FESI/Data/DateObject.java
Normal 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;
|
||||
}
|
||||
}
|
225
src/FESI/Data/DatePrototype.java
Normal file
225
src/FESI/Data/DatePrototype.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
253
src/FESI/Data/ESArguments.java
Normal file
253
src/FESI/Data/ESArguments.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
319
src/FESI/Data/ESArrayWrapper.java
Normal file
319
src/FESI/Data/ESArrayWrapper.java
Normal 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
149
src/FESI/Data/ESBeans.java
Normal 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)) + ">";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
106
src/FESI/Data/ESBoolean.java
Normal file
106
src/FESI/Data/ESBoolean.java
Normal 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
494
src/FESI/Data/ESLoader.java
Normal 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
72
src/FESI/Data/ESNull.java
Normal 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
115
src/FESI/Data/ESNumber.java
Normal 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
775
src/FESI/Data/ESObject.java
Normal 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());
|
||||
}
|
||||
|
||||
}
|
142
src/FESI/Data/ESPackages.java
Normal file
142
src/FESI/Data/ESPackages.java
Normal 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)) + ">";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
95
src/FESI/Data/ESPrimitive.java
Normal file
95
src/FESI/Data/ESPrimitive.java
Normal 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());
|
||||
}
|
||||
|
||||
|
||||
}
|
137
src/FESI/Data/ESReference.java
Normal file
137
src/FESI/Data/ESReference.java
Normal 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
109
src/FESI/Data/ESString.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
101
src/FESI/Data/ESUndefined.java
Normal file
101
src/FESI/Data/ESUndefined.java
Normal 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
338
src/FESI/Data/ESValue.java
Normal 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
1484
src/FESI/Data/ESWrapper.java
Normal file
File diff suppressed because it is too large
Load diff
153
src/FESI/Data/FunctionObject.java
Normal file
153
src/FESI/Data/FunctionObject.java
Normal 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>";
|
||||
}
|
||||
}
|
142
src/FESI/Data/FunctionPrototype.java
Normal file
142
src/FESI/Data/FunctionPrototype.java
Normal 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() +">";
|
||||
}
|
||||
}
|
455
src/FESI/Data/GlobalObject.java
Normal file
455
src/FESI/Data/GlobalObject.java
Normal 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;
|
||||
}
|
||||
}
|
143
src/FESI/Data/JSGlobalWrapper.java
Normal file
143
src/FESI/Data/JSGlobalWrapper.java
Normal 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();
|
||||
}
|
||||
}
|
505
src/FESI/Data/JSWrapper.java
Normal file
505
src/FESI/Data/JSWrapper.java
Normal 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();
|
||||
}
|
||||
}
|
262
src/FESI/Data/MathObject.java
Normal file
262
src/FESI/Data/MathObject.java
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
136
src/FESI/Data/NumberObject.java
Normal file
136
src/FESI/Data/NumberObject.java
Normal 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;
|
||||
}
|
||||
}
|
80
src/FESI/Data/NumberPrototype.java
Normal file
80
src/FESI/Data/NumberPrototype.java
Normal 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()) + "]";
|
||||
}
|
||||
|
||||
}
|
85
src/FESI/Data/ObjectObject.java
Normal file
85
src/FESI/Data/ObjectObject.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
41
src/FESI/Data/ObjectPrototype.java
Normal file
41
src/FESI/Data/ObjectPrototype.java
Normal 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);
|
||||
}
|
||||
}
|
340
src/FESI/Data/StringObject.java
Normal file
340
src/FESI/Data/StringObject.java
Normal 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;
|
||||
}
|
||||
}
|
92
src/FESI/Data/StringPrototype.java
Normal file
92
src/FESI/Data/StringPrototype.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
89
src/FESI/Data/ValueDescription.java
Normal file
89
src/FESI/Data/ValueDescription.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue