Beispiel #1
0
        public virtual string getString(int i)
        {
            Object o = getObject(i);

            return((o is string)
        ? ((String)o)
            : JsSystem.toString(o));
        }
Beispiel #2
0
        /**
         * Returns the numerical value at array index i. If the actual value is not
         * numeric, it is converted automatically.
         */
        public double getNumber(int i)
        {
            if (i >= size_)
            {
                return(0);
            }
            Object o = objects[i];

            return(o == NUMBER_MARKER ? numbers[i] : JsSystem.toNumber(o));
        }
Beispiel #3
0
        /**
         * Returns a string representation of this array. This method does not check for
         * circular references, so if the array contains itself it will result in an
         * Exception.
         */
        public override string ToString()
        {
            StringBuilder buf = new StringBuilder();

            if (size_ > 0)
            {
                buf.Append(JsSystem.toString(getObject(0)));
                for (int i = 1; i < size_; i++)
                {
                    buf.Append(",");
                    buf.Append(JsSystem.toString(getObject(i)));
                }
            }

            return(buf.ToString());
        }
Beispiel #4
0
 /**
  * Creates a new function from the given function literal and context.
  */
 public JsFunction(JsFunction literal, JsObject context) :
     base(literal.__proto__)
 {
     this.byteCode               = literal.byteCode;
     this.context                = context;
     this.functionLiterals       = literal.functionLiterals;
     this.localNames             = literal.localNames;
     this.numberLiterals         = literal.numberLiterals;
     this.expectedParameterCount = literal.expectedParameterCount;
     this.prototype              = literal.prototype;
     this.stringLiterals         = literal.stringLiterals;
     this.varCount               = literal.varCount;
     this.factory                = JsSystem.getInstance();
     this.factoryTypeId          = JsSystem.FACTORY_ID_OBJECT;
     this.lineNumbers            = literal.lineNumbers;
 }
Beispiel #5
0
        /**
         * Performs multiplications for integer exponents. In all other cases,
         * exp(y * ln(x)) is calculated.
         */
        public static double pow(double x, double y)
        {
            long n = (long)y;

            if (y > 0 && y == n)
            {
                double result = 1;
                while (n > 0)
                {
                    if ((n & 1) != 0)
                    {
                        result *= x;
                        n--;
                    }
                    x  *= x;
                    n >>= 1;
                }
                return(result);
            }
            return(exp(y * JsSystem.ln(x)));
        }
Beispiel #6
0
        /**
         * Returns the boolean value at array index i. If the actual value is not
         * boolean, it is converted automatically according to the ECMA conversion
         * rules. This method handles Boolean.TRUE, Boolean.FALSE and numbers. All
         * other values are delegated to JsSystem.toBoolean()
         */
        public bool getBoolean(int i)
        {
            if (i >= size_)
            {
                return(false);
            }
            Object o = objects[i];

            if (o == NUMBER_MARKER)
            {
                double d = numbers[i];
                return(d != 0 && !Double.IsNaN(d));
            }
            if ((bool)o == true)
            {
                return(true);
            }
            if ((bool)o == false)
            {
                return(false);
            }

            return(JsSystem.toBoolean(o));
        }
Beispiel #7
0
        /**
         * Execute java member implementation. Parameters for functions start at
         * stack[sp+2]. Function and getter results are returned at stack[sp+0].
         * The assignement value for a setter is stored at stack[sp+0].
         */
        public virtual void evalNative(int index, JsArray stack, int sp, int parCount)
        {
            Object obj;

            switch (index)
            {
            // object methods

            case ID_NOOP:
                break;

            case ID_INIT_OBJECT:
                obj = stack.getObject(sp + 2);
                if (isConstruction(stack, sp))
                {
                    if (obj is Boolean || obj is Double ||
                        obj is String)
                    {
                        value = obj;
                    }
                    else if (obj is JsObject)
                    {
                        stack.setObject(sp - 1, obj);
                    }
                    // otherwise, don't do anything -- regular constructor call
                }
                else
                {
                    if (obj == null || obj == JsSystem.JS_NULL)
                    {
                        stack.setObject(sp, new JsObject(OBJECT_PROTOTYPE));
                    }
                    else
                    {
                        stack.setObject(sp, JsSystem.toJsObject(obj));
                    }
                }
                break;

            case ID_TO_STRING:
            case ID_TO_LOCALE_STRING:
                stack.setObject(sp, JsSystem.toString(stack.getObject(sp)));
                break;

            case ID_HAS_OWN_PROPERTY:
                stack.setBoolean(sp, data != null &&
                                 data[stack.getString(sp + 2)] != null);
                break;

            case ID_IS_PROTOTYPE_OF:
                obj = stack.getObject(sp + 2);
                stack.setBoolean(sp, false);
                while (obj is JsObject)
                {
                    if (obj == this)
                    {
                        stack.setBoolean(sp, true);
                        break;
                    }
                }
                break;

            case ID_PROPERTY_IS_ENUMERABLE:
                obj = getRawInPrototypeChain(stack.getString(sp + 2));
                stack.setBoolean(sp, obj != null && !(obj is JsFunction));
                break;

            case ID_VALUE_OF:
                stack.setObject(sp, value == null ? this : value);
                break;

            // Number methods

            case ID_INIT_NUMBER:
                if (isConstruction(stack, sp))
                {
                    value = (Double)(stack.getNumber(sp + 2));
                }
                else
                {
                    stack.setNumber(sp, stack.getNumber(sp + 2));
                }
                break;

            // Boolean methods

            case ID_INIT_BOOLEAN:
                if (isConstruction(stack, sp))
                {
                    value = stack.getBoolean(sp + 2) ? true : false;
                }
                else
                {
                    stack.setObject(sp, stack.getBoolean(sp + 2)
                          ? true : false);
                }
                break;

            case ID_INIT_STRING:
                if (isConstruction(stack, sp))
                {
                    value = stack.getString(sp + 2);
                }
                else
                {
                    stack.setObject(sp, parCount == 0 ? "" : stack.getString(sp + 2));
                }
                break;

            // initializers that can be used as functions need to be covered in Object

            case ID_INIT_ARRAY:
                JsArray array = (isConstruction(stack, sp)
          ? (JsArray)this : new JsArray());
                if (parCount == 1 && stack.isNumber(sp + 2))
                {
                    array.setSize(stack.getInt(sp + 2));
                }
                else
                {
                    for (int i2 = 0; i2 < parCount; i2++)
                    {
                        stack.copy(sp + i2 + 2, array, i2);
                    }
                }
                stack.setObject(sp, array);
                break;

            case ID_INIT_ERROR:
                if (isConstruction(stack, sp))
                {
                    setObject("message", stack.getString(sp + 2));
                }
                else
                {
                    stack.setObject(sp, new JsError(stack.getJsObject(sp),
                                                    stack.getString(sp + 2)));
                }
                break;


            case ID_INIT_FUNCTION:
                // Note: this will exchange the "this" object at sp-1 if it is used as constructor
                bool construction = isConstruction(stack, sp);

                StringBuilder buf = new StringBuilder("(function(");
                for (int i3 = 0; i3 < parCount - 1; i3++)
                {
                    if (i3 != 0)
                    {
                        buf.Append(',');
                    }
                    buf.Append(stack.getString(sp + 2 + i3));
                }
                buf.Append("){");
                if (parCount != 0)
                {
                    buf.Append(stack.getString(sp + 2 + parCount - 1));
                }
                buf.Append("});");

                Console.WriteLine("eval: " + buf);

                JsObject   global = (JsObject)stack.getObject(0);
                JsFunction eval   = (JsFunction)global.getObject("eval");
                stack.setObject(sp, global); // global
                stack.setObject(sp + 1, eval);
                stack.setObject(sp + 2, buf.ToString());
                eval.eval(stack, sp, 1);

                if (construction)
                {
                    stack.copy(sp, stack, sp - 1);
                }
                break;


            case ID_INIT_DATE:
                // reset to defaults
                if (isConstruction(stack, sp))
                {
                    JsDate d_2 = (JsDate)this;
                    if (parCount == 1)
                    {
                        d_2.time.setTime(new DateTime((long)stack.getNumber(sp + 2)));
                    }
                    else if (parCount > 1)
                    {
                        d_2.time.setTime(new DateTime());
                        int year = stack.getInt(sp + 2);
                        if (year >= 0 && year <= 99)
                        {
                            year += 1900;
                        }
                        d_2.setDate(false, year,
                                    stack.getNumber(sp + 3),
                                    stack.getNumber(sp + 4));

                        d_2.setTime(false, stack.getNumber(sp + 5),
                                    stack.getNumber(sp + 6),
                                    stack.getNumber(sp + 7),
                                    stack.getNumber(sp + 8));
                    }
                }
                else
                {
                    stack.setObject(sp,
                                    new JsDate(JsDate.DATE_PROTOTYPE).toString(true, true, true));
                }
                break;


            // global properties

            case ID_PRINT:
                Console.WriteLine(stack.getString(sp + 2));
                break;

            case ID_PARSE_INT:
                String s = stack.getString(sp + 2).Trim().ToLower();
                try {
                    if (stack.isNull(sp + 3))
                    {
                        stack.setInt(sp, s.StartsWith("0x")
                                ? Convert.ToInt32(s.Substring(2), 16)
                                    : Convert.ToInt32(s));
                    }
                    else
                    {
                        stack.setInt(sp, Convert.ToInt32(s, stack.getInt(sp + 3)));
                    }
                } catch (FormatException) {
                    stack.setInt(sp, 0);
                }
                break;

            case ID_PARSE_FLOAT:
                try {
                    stack.setNumber(sp, Convert.ToDouble(stack.getString(sp + 2)));
                } catch (FormatException) {
                    stack.setNumber(sp, double.NaN);
                }
                break;

            case ID_IS_NAN:
                stack.setBoolean(sp, double.IsNaN(stack.getNumber(sp + 2)));
                break;

            case ID_IS_FINITE:
                double d_ = stack.getNumber(sp + 2);
                stack.setBoolean(sp, !Double.IsInfinity(d_) && !Double.IsNaN(d_));
                break;

            case ID_DECODE_URI:
                obj = stack.getObject(sp + 2);
                if (obj is sbyte[])
                {
                    stack.setObject(sp, JsSystem.decodeURI((sbyte[])obj));
                }
                else
                {
                    stack.setObject(sp, JsSystem.decodeURI(obj.ToString()));
                }
                break;

            case ID_ENCODE_URI:
                obj = stack.getObject(sp + 2);
                if (obj is sbyte[])
                {
                    stack.setObject(sp, JsSystem.encodeURI((sbyte[])obj));
                }
                else
                {
                    stack.setObject(sp, JsSystem.encodeURI(obj.ToString()));
                }
                break;

            //TODO Implement
            case ID_DECODE_URI_COMPONENT:
            case ID_ENCODE_URI_COMPONENT:
                throw new Exception("NYI");

            // math properties

            case ID_ABS:
                stack.setNumber(sp, Math.Abs(stack.getNumber(sp + 2)));
                break;

            case ID_ACOS:
            case ID_ASIN:
            case ID_ATAN:
            case ID_ATAN2:
                throw new Exception("NYI");

            case ID_CEIL:
                stack.setNumber(sp, Math.Ceiling(stack.getNumber(sp + 2)));
                break;

            case ID_COS:
                stack.setNumber(sp, Math.Cos(stack.getNumber(sp + 2)));
                break;

            case ID_EXP:
                stack.setNumber(sp, JsSystem.exp(stack.getNumber(sp + 2)));
                break;

            case ID_FLOOR:
                stack.setNumber(sp, Math.Floor(stack.getNumber(sp + 2)));
                break;

            case ID_LOG:
                stack.setNumber(sp, JsSystem.ln(stack.getNumber(sp + 2)));
                break;

            case ID_MAX:
                double d2 = Double.NegativeInfinity;
                for (int i3 = 0; i3 < parCount; i3++)
                {
                    d2 = Math.Max(d2, stack.getNumber(sp + 2 + i3));
                }
                stack.setNumber(sp, d2);
                break;

            case ID_MIN:
                double d3 = Double.PositiveInfinity;
                for (int i4 = 0; i4 < parCount; i4++)
                {
                    d3 = Math.Min(d3, stack.getNumber(sp + 2 + i4));
                }
                stack.setNumber(sp, d3);
                break;

            case ID_POW:
                stack.setNumber(sp, JsSystem.pow(stack.getNumber(sp + 2),
                                                 stack.getNumber(sp + 3)));
                break;

            case ID_RANDOM:
                stack.setNumber(sp, JsSystem.random.NextDouble());
                break;

            case ID_ROUND:
                stack.setNumber(sp, Math.Floor(stack.getNumber(sp + 2) + 0.5));
                break;

            case ID_SIN:
                stack.setNumber(sp, Math.Sin(stack.getNumber(sp + 2)));
                break;

            case ID_SQRT:
                stack.setNumber(sp, Math.Sqrt(stack.getNumber(sp + 2)));
                break;

            case ID_TAN:
                stack.setNumber(sp, Math.Tan(stack.getNumber(sp + 2)));
                break;

            // string methods

            case ID_FROM_CHAR_CODE:
                char[] chars = new char[parCount];
                for (int i5 = 0; i5 < parCount; i5++)
                {
                    chars[i5] = (char)stack.getInt(sp + 2 + i5);
                }
                stack.setObject(sp, new String(chars));
                break;

            // string.prototype methods

            case ID_CHAR_AT:
                s = stack.getString(sp);
                int i6 = stack.getInt(sp + 2);
                stack.setObject(sp, i6 < 0 || i6 >= s.Length
                    ? "" : s.Substring(i6, 1));
                break;

            case ID_CHAR_CODE_AT:
                s = stack.getString(sp);
                int i7 = stack.getInt(sp + 2);
                stack.setNumber(sp, i7 < 0 || i7 >= s.Length
                        ? Double.NaN : s[i7]);
                break;

            case ID_CONCAT:
                buf = new StringBuilder(stack.getString(sp));
                for (int i8 = 0; i8 < parCount; i8++)
                {
                    buf.Append(stack.getString(sp + i8 + 2));
                }
                stack.setObject(sp, buf.ToString());
                break;

            case ID_INDEX_OF:
                stack.setNumber(sp, stack.getString(sp).IndexOf(stack.getString(sp + 2),
                                                                stack.getInt(sp + 3)));
                break;

            case ID_LAST_INDEX_OF:
                s = stack.getString(sp);
                String find = stack.getString(sp + 2);
                double d4   = stack.getNumber(sp + 3);
                int    max  = (Double.IsNaN(d4)) ? s.Length : (int)d4;

                int best = -1;
                while (true)
                {
                    int found = s.IndexOf(find, best + 1);
                    if (found == -1 || found > max)
                    {
                        break;
                    }
                    best = found;
                }

                stack.setNumber(sp, best);
                break;

            case ID_LOCALE_COMPARE:
                stack.setNumber(sp,
                                stack.getString(sp).CompareTo(stack.getString(sp + 2)));
                break;

            case ID_REPLACE:
                s    = stack.getString(sp);
                find = stack.getString(sp + 2);
                String replace = stack.getString(sp + 3);
                if (!find.Equals(""))
                {
                    StringBuilder sb     = new StringBuilder(s);
                    int           length = find.Length;

                    // Parse nodes into vector
                    while ((index = sb.ToString().IndexOf(find)) >= 0)
                    {
                        sb.Remove(index, index + length);
                        sb.Insert(index, replace);
                    }
                    stack.setObject(sp, sb.ToString());
                    sb = null;
                }
                break;

            case ID_MATCH:
            case ID_SEARCH:
                throw new Exception("Regexp NYI");

            case ID_SLICE:
                s = stack.getString(sp);
                int len   = s.Length;
                int start = stack.getInt(sp + 2);
                int end   = stack.isNull(sp + 3) ? len : stack.getInt(sp + 3);
                if (start < 0)
                {
                    start = Math.Max(len + start, 0);
                }
                if (end < 0)
                {
                    end = Math.Max(len + start, 0);
                }
                if (start > len)
                {
                    start = len;
                }
                if (end > len)
                {
                    end = len;
                }
                if (end < start)
                {
                    end = start;
                }
                stack.setObject(sp, s.Substring(start, end - start));
                break;

            case ID_SPLIT:
                s = stack.getString(sp);
                String sep   = stack.getString(sp + 2);
                double limit = stack.getNumber(sp + 3);
                if (Double.IsNaN(limit) || limit < 1)
                {
                    limit = Double.MaxValue;
                }

                JsArray a = new JsArray();
                if (sep.Length == 0)
                {
                    if (s.Length < limit)
                    {
                        limit = s.Length;
                    }
                    for (int i9 = 0; i9 < limit; i9++)
                    {
                        a.setObject(i9, s.Substring(i9, 1));
                    }
                }
                else
                {
                    int cut0 = 0;
                    while (cut0 < s.Length && a.size() < limit)
                    {
                        int cut = s.IndexOf(sep, cut0);
                        if (cut == -1)
                        {
                            cut = s.Length;
                        }
                        a.setObject(a.size(), s.Substring(cut0, cut - cut0));
                        cut0 = cut + sep.Length;
                    }
                }
                stack.setObject(sp, a);
                break;

            case ID_SUBSTRING:
                s     = stack.getString(sp);
                len   = s.Length;
                start = stack.getInt(sp + 2);
                end   = stack.isNull(sp + 3) ? len : stack.getInt(sp + 3);
                if (start > end)
                {
                    int tmp = end;
                    end   = start;
                    start = tmp;
                }
                start = Math.Min(Math.Max(0, start), len);
                end   = Math.Min(Math.Max(0, end), len);
                stack.setObject(sp, s.Substring(start, end - start));
                break;

            case ID_TO_LOWER_CASE: //TODO: which locale to use as defautlt? us?
            case ID_TO_LOCALE_LOWER_CASE:
                stack.setObject(sp, stack.getString(sp + 2).ToLower());
                break;

            case ID_TO_UPPER_CASE: //TODO: which locale to use as defautlt? us?
            case ID_TO_LOCALE_UPPER_CASE:
                stack.setObject(sp, stack.getString(sp + 2).ToUpper());
                break;

            case ID_LENGTH:
                stack.setInt(sp, ToString().Length);
                break;

            case ID_LENGTH_SET:
                // cannot be changed!
                break;

            case ID_TO_EXPONENTIAL:
            case ID_TO_FIXED:
            case ID_TO_PRECISION:
                stack.setObject(sp, JsSystem.formatNumber(index,
                                                          stack.getNumber(sp + 2), stack.getNumber(sp + 3)));
                break;

            case ID_UTC:
                JsDate date = new JsDate(JsDate.DATE_PROTOTYPE);
                date.time.setTime(new DateTime());
                int year2 = stack.getInt(sp + 2);
                if (year2 >= 0 && year2 <= 99)
                {
                    year2 += 1900;
                }
                date.setDate(true, year2,
                             stack.getNumber(sp + 3),
                             stack.getNumber(sp + 4));

                date.setTime(true, stack.getNumber(sp + 5),
                             stack.getNumber(sp + 6),
                             stack.getNumber(sp + 7),
                             stack.getNumber(sp + 8));

                stack.setNumber(sp, date.time.getTime().Ticks);
                break;

            case ID_PARSE:
                double[] vals = { Double.NaN, Double.NaN, Double.NaN,
                                  Double.NaN, Double.NaN, Double.NaN, Double.NaN };

                s = stack.getString(sp + 2);
                int curr = -1;
                int pos  = 0;
                for (int i10 = 0; i10 < s.Length; i10++)
                {
                    char c = s[i10];
                    if (c >= '0' && c <= '9')
                    {
                        if (curr == -1)
                        {
                            curr = c - 48;
                        }
                        else
                        {
                            curr = curr * 10 + (c - 48);
                        }
                    }
                    else if (curr != -1)
                    {
                        if (pos < vals.Length)
                        {
                            vals[pos++] = curr;
                        }
                        curr = -1;
                    }
                }
                if (curr != -1 && pos < vals.Length)
                {
                    vals[pos++] = curr;
                }

                bool utc = s.EndsWith("GMT") || s.EndsWith("UTC");
                date = new JsDate(JsDate.DATE_PROTOTYPE);
                date.time.setTime(new DateTime());
                date.setDate(utc, vals[0], vals[1], vals[2]);
                date.setTime(utc, vals[3], vals[4], vals[5], vals[6]);
                stack.setNumber(sp, date.time.getTime().Ticks);
                break;

            // Math constants

            case ID_E:
                stack.setNumber(sp, Math.E);
                break;

            case ID_LN10:
                stack.setNumber(sp, 2.302585092994046);
                break;

            case ID_LN2:
                stack.setNumber(sp, JsSystem.LN2);
                break;

            case ID_LOG2E:
                stack.setNumber(sp, 1.4426950408889634);
                break;

            case ID_LOG10E:
                stack.setNumber(sp, 0.4342944819032518);
                break;

            case ID_PI:
                stack.setNumber(sp, Math.PI);
                break;

            case ID_SQRT1_2:
                stack.setNumber(sp, Math.Sqrt(0.5));
                break;

            case ID_SQRT2:
                stack.setNumber(sp, Math.Sqrt(2.0));
                break;

            case ID_E_SET:
            case ID_LN10_SET:
            case ID_LN2_SET:
            case ID_LOG2E_SET:
            case ID_LOG10E_SET:
            case ID_PI_SET:
            case ID_SQRT1_2_SET:
            case ID_SQRT2_SET:
                // dont do anything: cannot overwrite those values!
                break;

            default:
                throw new ArgumentException("Unknown native id: " + index
                                            + " this: " + this);
            }
        }
Beispiel #8
0
 /**
  * Returns the string value for the given key. If the actual value is not a
  * string, it is converted automatically, using the ECMA 262 conversion
  * rules.
  */
 public String getString(String key)
 {
     return(JsSystem.toString(getObject(key)));
 }
Beispiel #9
0
 /**
  * Returns the numeric value for the given key. If the actual value is not
  * numeric, it is converted automatically, using the ECMA 262 conversion
  * rules.
  */
 public double getNumber(String key)
 {
     return(JsSystem.toNumber(getObject(key)));
 }
Beispiel #10
0
 public virtual JsObject getJsObject(int i)
 {
     return(JsSystem.toJsObject(getObject(i)));
 }
Beispiel #11
0
 public Eval() :
     base(COMPILER_PROTOTYPE)
 {
     scopeChain = JsSystem.createGlobal();
     addVar("eval", new JsFunction(ID_EVAL, 2));
 }