예제 #1
0
        public override void evalNative(int index, JsArray stack, int sp, int parCount)
        {
            switch (index)
            {
            // object methods

            case ID_EVAL:
                try {
                    stack.setObject(
                        sp,
                        eval(stack.getString(sp + 2),
                             stack.isNull(sp + 3) ? stack.getJsObject(sp) : stack.getJsObject(sp + 3))
                        );
                } catch (Exception e) {
                    throw new Exception("" + e);
                }

                break;

            default:
                base.evalNative(index, stack, sp, parCount);
                break;
            }
        }
예제 #2
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);
            }
        }
예제 #3
0
        /**
         * Java implementations of JS array members and methods.
         */
        public override void evalNative(int index, JsArray stack,
                                        int sp, int parCount)
        {
            switch (index)
            {
            case ID_CONCAT:
                JsArray array = new JsArray();
                copy(0, array, 0, size_);
                stack.copy(sp + 2, array, size_, parCount);
                stack.setObject(sp, array);
                break;

            case ID_JOIN:
                StringBuilder buf = new StringBuilder();
                String        sep = stack.isNull(sp + 2) ? "," : stack.getString(sp + 2);
                for (int i = 0; i < size_; i++)
                {
                    if (i > 0)
                    {
                        buf.Append(sep);
                    }
                    if (!isNull(i))
                    {
                        buf.Append(getString(i));
                    }
                }
                stack.setObject(sp, buf.ToString());
                break;

            case ID_LENGTH_SET:
                setSize(stack.getInt(sp));
                break;

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

            case ID_POP:
                if (size_ == 0)
                {
                    stack.setObject(sp, null);
                }
                else
                {
                    copy(size_ - 1, stack, sp);
                    setSize(size_ - 1);
                }
                break;

            case ID_PUSH:
                stack.copy(sp + 2, this, size_, parCount);
                stack.setNumber(sp, size_);
                break;

            case ID_REVERSE:
                for (int i = 0; i < size_ / 2; i++)
                {
                    swap(i, size_ - 1 - i);
                }
                break;

            case ID_SHIFT:
                if (size_ == 0)
                {
                    stack.setObject(sp, null);
                }
                else
                {
                    copy(0, stack, sp);
                    copy(1, this, 0, size_ - 1);
                    setSize(size_ - 1);
                }
                break;

            case ID_SLICE:
                int start = stack.getInt(sp + 2);
                int end   = stack.isNull(sp + 3) ? size_ : stack.getInt(sp + 3);
                if (start < 0)
                {
                    start = Math.Max(size_ + start, 0);
                }
                if (end < 0)
                {
                    end = Math.Max(size_ + start, 0);
                }
                if (start > size_)
                {
                    start = size_;
                }
                if (end > size_)
                {
                    end = size_;
                }
                if (end < start)
                {
                    end = start;
                }
                array = new JsArray();
                copy(start, array, 0, end - start);
                stack.setObject(sp, array);
                break;

            case ID_SORT:
                Object compare = stack.getObject(sp + 2);
                if (compare is JsFunction)
                {
                    sort(0, size_, (JsFunction)compare, stack.getJsObject(sp), stack, sp);
                }
                else
                {
                    sort(0, size_);
                }
                stack.setObject(sp, this);
                break;

            case ID_SPLICE:
                array = new JsArray();
                start = stack.getInt(sp + 2);
                int delCount = stack.getInt(sp + 3);
                if (start < 0)
                {
                    start = size_ - start;
                }
                int itemCount = Math.Max(0, parCount - 2);
                copy(0, array, 0, start);
                stack.copy(sp + 4, array, start, itemCount);
                copy(start + delCount, array, start + itemCount, size_ - (start + delCount));
                stack.setObject(sp, array);
                break;

            case ID_UNSHIFT:
                copy(0, this, parCount, size_);
                stack.copy(sp + 2, this, 0, parCount);
                stack.setInt(sp, parCount);
                break;

            default:
                base.evalNative(index, stack, sp, parCount);
                break;
            }
        }