예제 #1
0
        public JSArray splice(long first, long len)
        {
            JSArray result = new JSArray(GLOBAL);

            if (first < 0)
            {
                first += length;
            }
            if (len < 0)
            {
                return(result);
            }
            if (first < 0)
            {
                first = 0;
            }
            long i = first, end = Math.Min(first + len, length);

            while (i < end)
            {
                result.push(this[i++].GetValue(GLOBAL));
            }
            while (i < length)
            {
                this[first++] = this[i++];
            }
            length = first;
            return(result);
        }
예제 #2
0
        public JSArray slice(long start, long end)
        {
            long    i, target = 0;
            JSArray result;

            if (start < 0)
            {
                start = length - start - 1;
            }
            if (end < 0)
            {
                end = length - end - 1;
            }

            result = new JSArray(GLOBAL, end - start);

            for (i = start; i < end; i++, target++)
            {
                object o = this[i].GetValue(GLOBAL);
                if (!(o == null && o == JSUndefined.Undefined))
                {
                    result[target].SetValue(GLOBAL, o);
                }
            }

            return(result);
        }
예제 #3
0
            int IComparer <object> .Compare(object a, object b)
            {
                if (a.Equals(b))
                {
                    return(0);
                }
                JSArray array  = new JSArray(GLOBAL, new object[] { a, b });
                double  number = JSObject.ToNumber(GLOBAL, mSorter.Call(GLOBAL, GLOBAL.currentContext.thisOb, array, GLOBAL.currentContext));

                return((int)number);
            }
예제 #4
0
 public JSNativeEvent(ExecutionContext GLOBAL, object thisRef, EventInfo eventInfo)
 {
     this.GLOBAL   = GLOBAL;
     mHookedUp     = new JSArray(GLOBAL);
     mThisRef      = thisRef;
     mEventInfo    = eventInfo;
     mCallDelegate = Delegate.CreateDelegate(typeof(TriggerEventDelegate), GetType().GetMethod("TriggerEvent"), false);
     if (mCallDelegate != null)
     {
         eventInfo.AddEventHandler(mThisRef, mCallDelegate);
     }
 }
예제 #5
0
        public static JSArray concat(ExecutionContext GLOBAL, params JSArray[] arrays)
        {
            JSArray newArray = new JSArray(GLOBAL);

            foreach (JSArray ja in arrays)
            {
                int i;
                for (i = 0; i < ja.length; i++)
                {
                    newArray.push(ja[i].GetValue(GLOBAL));
                }
            }
            return(newArray);
        }
예제 #6
0
        public void TriggerEvent(object sender, EventArgs args)
        {
            object  senderOb = JSObject.ToJS(GLOBAL, sender), argsOb = JSObject.ToJS(GLOBAL, args);
            JSArray argArray = new JSArray(GLOBAL, new object[] { senderOb, argsOb });

            foreach (object ob in mHookedUp)
            {
                JSObjectBase obBase = ob as JSObjectBase;
                if (obBase != null)
                {
                    obBase.Call(GLOBAL, ob, argArray, GLOBAL.currentContext);
                }
            }
        }
예제 #7
0
        public override object Construct(ExecutionContext GLOBAL, JSObjectBase a, ExecutionContext x)
        {
            JSArray ar   = new JSArray(GLOBAL);
            long    alen = (long)JSObject.ToNumber(GLOBAL, a.GetItem(GLOBAL, "length").GetValue(GLOBAL));

            if (alen == 1 && a.GetItem(GLOBAL, "0").GetValue(GLOBAL) is double)
            {
                ar = new JSArray(GLOBAL, (long)JSObject.ToNumber(GLOBAL, a.GetItem(GLOBAL, "0").GetValue(GLOBAL)));
            }
            else
            {
                long i;
                for (i = 0; i < alen; i++)
                {
                    ar.push(a.GetItem(GLOBAL, i.ToString()).GetValue(GLOBAL));
                }
            }
            ar.DefProp(GLOBAL, "prototype", mPrototype, false);
            ar.DefProp(GLOBAL, "constructor", this);
            return(ar);
        }
예제 #8
0
        internal object execute(Node n, ExecutionContext x)
        {
            int              i, j;
            List <Node>      aNode;
            ExecutionContext sEcon;
            JSObjectBase     jaa;
            JSObjectBase     f, tVal;
            object           r, s, u = null, v = null;
            Node             tNode = null, rNode = null, uNode = null;
            bool             matchDefault = false;
            bool             switchLoop;

            if (TraceExec)
            {
                UnityEngine.Debug.Log("Execute[" + n.ToString() + " => ");
            }

            try
            {
                switch (n.type)
                {
                case TokenType.Function:
                    if (n.functionForm != StatementForm.DECLARED_FORM)
                    {
                        if (n.name == null || n.name == "" || n.functionForm == StatementForm.STATEMENT_FORM)
                        {
                            v = new FunctionObject(GLOBAL, n, x.scope);
                            if (n.functionForm == StatementForm.STATEMENT_FORM)
                            {
                                x.scope.jobject.SetItem(GLOBAL, n.name, new JSSimpleProperty(n.name, v));
                            }
                        }
                        else
                        {
                            tVal = new JSObject();
                            ExecutionContext tmp = x.scope;
                            x.scope         = new ExecutionContext();
                            x.scope.jobject = tVal;
                            x.scope.parent  = tmp;
                            try
                            {
                                v = new FunctionObject(GLOBAL, n, x.scope);
                                tVal.SetItem(GLOBAL, n.name, new JSSimpleProperty(n.name, v, true, true));
                            }
                            finally
                            {
                                x.scope = x.scope.parent;
                            }
                        }
                    }
                    break;

                case TokenType.SCRIPT:
                    tVal  = x.scope.jobject;
                    aNode = n.funDecls;
                    for (i = 0, j = aNode.Count; i < j; i++)
                    {
                        s = aNode[i].name;
                        f = new FunctionObject(GLOBAL, aNode[i], x.scope);
                        tVal.SetItem(GLOBAL, s.ToString(), new JSSimpleProperty(s.ToString(), f, x.type != CodeType.EVAL_CODE));
                    }
                    aNode = n.varDecls;
                    for (i = 0, j = aNode.Count; i < j; i++)
                    {
                        uNode = aNode[i];
                        s     = uNode.name;
                        if (uNode.readOnly && tVal.HasOwnProperty(s.ToString()))
                        {
                            throw new TypeError
                                      ("Redeclaration of const " + s, uNode.filename, uNode.lineno);
                        }
                        if (uNode.readOnly || !tVal.HasOwnProperty(s.ToString()))
                        {
                            tVal.SetItem(GLOBAL, s.ToString(), new JSSimpleProperty(s.ToString(), JSUndefined.Undefined, x.type != CodeType.EVAL_CODE, uNode.readOnly));
                        }
                    }
                    // FALL THROUGH
                    for (i = 0, j = n.Count; i < j; i++)
                    {
                        execute(n[i], x);
                    }
                    break;

                case TokenType.BLOCK:
                    for (i = 0, j = n.Count; i < j; i++)
                    {
                        execute(n[i], x);
                    }
                    break;

                case TokenType.If:
                    if (JSObject.ToBool(GLOBAL, execute(n.condition, x)))
                    {
                        execute(n.thenPart, x);
                    }
                    else if (n.elsePart != null)
                    {
                        execute(n.elsePart, x);
                    }
                    break;

                case TokenType.Switch:
                    s     = Reference.GetValue(GLOBAL, execute(n.discriminant, x));
                    aNode = n.cases;
                    Node tt;
                    switchLoop = false;
                    for (i = 0, j = aNode.Count; ; i++)
                    {
                        if (i == j)
                        {
                            if (n.defaultIndex >= 0)
                            {
                                i            = n.defaultIndex - 1; // no case matched, do default
                                matchDefault = true;
                                continue;
                            }
                            break;                          // no default, exit switch_loop
                        }
                        tt = aNode[i];                      // next case (might be default!)
                        if (tt.type == TokenType.Case)
                        {
                            u = Reference.GetValue(GLOBAL, execute(tt.caseLabel, x));
                        }
                        else
                        {
                            if (!matchDefault)              // not defaulting, skip for now
                            {
                                continue;
                            }
                            u = s;                          // force match to do default
                        }
                        if (object.Equals(u, s))
                        {
                            for (; ;)
                            {                      // this loop exits switch_loop
                                if (tt.statements != null)
                                {
                                    try
                                    {
                                        execute(tt.statements, x);
                                    }
                                    catch (BreakException)
                                    {
                                        if (x.target == n)
                                        {
                                            switchLoop = true;
                                            break;
                                        }
                                        else
                                        {
                                            throw;
                                        }
                                    }
                                }
                                if (++i == j)
                                {
                                    switchLoop = true;
                                    break;
                                }
                                tNode = aNode[i];
                            }
                            // NOT REACHED
                        }
                        if (switchLoop)
                        {
                            break;
                        }
                    }
                    break;

                case TokenType.For:
                    if (n.setup != null)
                    {
                        Reference.GetValue(GLOBAL, execute(n.setup, x));
                    }
                    // FALL THROUGH
                    while (n.condition == null ||
                           JSObject.ToBool(GLOBAL, Reference.GetValue(GLOBAL, execute(n.condition, x))))
                    {
                        try
                        {
                            execute(n.body, x);
                        }
                        catch (BreakException)
                        {
                            if (x.target == n)
                            {
                                break;
                            }
                            throw;
                        }
                        catch (ContinueException)
                        {
                            if (x.target == n)
                            {
                                if (n.update != null)
                                {
                                    Reference.GetValue(GLOBAL, execute(n.update, x));
                                }
                                if (n.condition != null && !JSObject.ToBool(GLOBAL, Reference.GetValue(GLOBAL, execute(n.condition, x))))
                                {
                                    break;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            throw;
                        }
                        if (n.update != null)
                        {
                            Reference.GetValue(GLOBAL, execute(n.update, x));
                        }
                    }
                    break;

                case TokenType.While:
                    while (n.condition == null ||
                           JSObject.ToBool(GLOBAL, Reference.GetValue(GLOBAL, execute(n.condition, x))))
                    {
                        try
                        {
                            execute(n.body, x);
                        }
                        catch (BreakException)
                        {
                            if (x.target == n)
                            {
                                break;
                            }
                            throw;
                        }
                        catch (ContinueException)
                        {
                            if (x.target == n)
                            {
                                continue;
                            }
                            throw;
                        }
                        if (n.update != null)
                        {
                            Reference.GetValue(GLOBAL, execute(n.update, x));
                        }
                    }
                    break;

                case TokenType.FOR_IN:
                    uNode = n.varDecl;
                    if (uNode != null)
                    {
                        execute(uNode, x);
                    }
                    rNode = n.iterator;
                    v     = Reference.GetValue(GLOBAL, execute(n.jobject, x));

                    // ECMA deviation to track extant browser JS implementation behavior.
                    tVal = JSObject.ToObject(GLOBAL, v);
                    i    = 0;
                    jaa  = new JSArray(GLOBAL);
                    foreach (string ii in tVal.Properties)
                    {
                        string istr = (i++).ToString();
                        jaa.SetItem(GLOBAL, istr, new JSSimpleProperty(istr, ii));
                    }
                    for (j = i, i = 0; i < j; i++)
                    {
                        Reference.PutValue(GLOBAL, execute(rNode, x), jaa.GetItem(GLOBAL, i.ToString()).GetValue(GLOBAL));
                        try
                        {
                            execute(n.body, x);
                        }
                        catch (BreakException)
                        {
                            if (x.target == n)
                            {
                                break;
                            }
                            throw;
                        }
                        catch (ContinueException)
                        {
                            if (x.target == n)
                            {
                                continue;
                            }
                            throw;
                        }
                    }
                    break;

                case TokenType.Do:
                    do
                    {
                        try
                        {
                            execute(n.body, x);
                        }
                        catch (BreakException)
                        {
                            if (x.target != n)
                            {
                                break;
                            }
                            throw;
                        }
                        catch (ContinueException)
                        {
                            if (x.target != n)
                            {
                                continue;
                            }
                            throw;
                        }
                    } while (JSObject.ToBool(GLOBAL, Reference.GetValue(GLOBAL, execute(n.condition, x))));
                    break;

                case TokenType.Break:
                    x.target = n.target;
                    throw new BreakException();

                case TokenType.Continue:
                    x.target = ((Node)n).target;
                    throw new ContinueException();

                case TokenType.Try:
                    try
                    {
                        execute(n.tryBlock, x);
                    }
                    catch (Exception exn)
                    {
                        ThrownException ex = exn as ThrownException;
                        object          e;
                        if (ex != null)
                        {
                            e = ex.Value;
                        }
                        else
                        {
                            e = new JSInstanceWrapper(GLOBAL, exn);
                        }
                        j        = n.catchClauses.Count;
                        x.result = JSUndefined.Undefined;
                        for (i = 0; ; i++)
                        {
                            if (i == j)
                            {
                                throw;
                            }
                            tNode = n.catchClauses[i];
                            ExecutionContext xscope = new ExecutionContext();
                            xscope.jobject = new JSObject();
                            xscope.jobject.SetItem(GLOBAL, tNode.varName, new JSSimpleProperty(tNode.varName, e, false, false, true));
                            xscope.parent = x.scope;
                            x.scope       = xscope;
                            try
                            {
                                if (tNode.guard != null && !JSObject.ToBool(GLOBAL, Reference.GetValue(GLOBAL, execute(tNode.guard, x))))
                                {
                                    continue;
                                }
                                execute(tNode.block, x);
                                break;
                            }
                            finally
                            {
                                x.scope = x.scope.parent;
                            }
                        }
                    }
                    finally
                    {
                        if (n.finallyBlock != null)
                        {
                            execute(n.finallyBlock, x);
                        }
                    }
                    break;

                case TokenType.Throw:
                    x.result = Reference.GetValue(GLOBAL, execute(n.exception, x));
                    throw new ThrownException((double)(int)TokenType.Throw);

                case TokenType.Return:
                    x.result = n.valueNode == null ? JSUndefined.Undefined : Reference.GetValue(GLOBAL, execute(n.valueNode, x));
                    throw new ReturnException();

                case TokenType.With:
                {
                    r    = execute(n.jobject, x);
                    tVal = JSObject.ToObject(GLOBAL, Reference.GetValue(GLOBAL, r));
                    ExecutionContext tmp = x.scope;
                    x.scope         = new ExecutionContext();
                    x.scope.jobject = tVal;
                    x.scope.parent  = tmp;
                    try
                    {
                        execute(n.body, x);
                    }
                    finally
                    {
                        x.scope = x.scope.parent;
                    }
                }
                break;

                case TokenType.Var:
                case TokenType.Const:
                    for (i = 0, j = n.Count; i < j; i++)
                    {
                        uNode = n[i].initializer;
                        if (uNode == null)
                        {
                            continue;
                        }
                        string identName = n[i].name;
                        for (sEcon = x.scope; sEcon != null; sEcon = sEcon.parent)
                        {
                            if (sEcon.jobject.HasOwnProperty(identName))
                            {
                                break;
                            }
                        }
                        u = Reference.GetValue(GLOBAL, execute(uNode, x));
                        if (n.type == TokenType.Const)
                        {
                            sEcon.jobject.SetItem(GLOBAL, identName, new JSSimpleProperty(identName, u, true, true, false));
                        }
                        else
                        {
                            sEcon.jobject.SetItem(GLOBAL, identName, new JSSimpleProperty(identName, u));
                        }
                    }
                    break;

                case TokenType.Debugger:
                    throw new Exception("NYI: debugger");

                case TokenType.SEMICOLON:
                    if (n.expression != null)
                    {
                        x.result = Reference.GetValue(GLOBAL, execute(n.expression, x));
                    }
                    break;

                case TokenType.LABEL:
                    try
                    {
                        execute(n.statement, x);
                    }
                    catch (BreakException)
                    {
                        if (x.target != n)
                        {
                            throw;
                        }
                    }
                    break;

                case TokenType.COMMA:
                    for (i = 0, j = n.Count; i < j; i++)
                    {
                        v = Reference.GetValue(GLOBAL, execute(n[i], x));
                    }
                    break;

                case TokenType.ASSIGN:
                    r = execute(n[0], x);
                    TokenType tok = jsdefs.tokenWords[n.value.ToString()];
                    v = Reference.GetValue(GLOBAL, execute(n[1], x));
                    if (tok != TokenType.ASSIGN)
                    {
                        u = Reference.GetValue(GLOBAL, r);
                        if (tok != TokenType.PLUS)
                        {
                            double ld = JSObject.ToNumber(GLOBAL, u), bd = JSObject.ToNumber(GLOBAL, v);
                            long   laa = (long)ld, bb = (long)bd;
                            int    bint = (int)bb;
                            switch (tok)
                            {
                            case TokenType.BITWISE_OR: ld = laa | bb; break;

                            case TokenType.BITWISE_XOR: ld = laa ^ bb; break;

                            case TokenType.BITWISE_AND: ld = laa & bb; break;

                            case TokenType.LSH: ld = laa << bint; break;

                            case TokenType.RSH: ld = laa >> bint; break;

                            case TokenType.URSH: ld = ((uint)laa) >> bint; break;

                            case TokenType.MINUS: ld = ld - bd; break;

                            case TokenType.MUL: ld = ld * bd; break;

                            case TokenType.DIV: ld = ld / bd; break;

                            case TokenType.MOD: ld = laa % bb; break;
                            }
                            v = ld;
                        }
                        else
                        {
                            v = Add(u, v);
                        }
                    }
                    Reference.PutValue(GLOBAL, r, v);
                    break;

                case TokenType.HOOK:
                {
                    object res1 = Reference.GetValue(GLOBAL, execute(n[0], x));
                    v = JSObject.ToBool(GLOBAL, res1) ? Reference.GetValue(GLOBAL, execute(n[1], x))
                                                       : Reference.GetValue(GLOBAL, execute(n[2], x));
                }
                break;

                case TokenType.OR:
                {
                    object res1 = Reference.GetValue(GLOBAL, execute(n[0], x));
                    v = JSObject.ToBool(GLOBAL, res1) ? res1 : Reference.GetValue(GLOBAL, execute(n[1], x));
                }
                break;

                case TokenType.AND:
                {
                    object res1 = Reference.GetValue(GLOBAL, execute(n[0], x));
                    v = JSObject.ToBool(GLOBAL, res1) ? Reference.GetValue(GLOBAL, execute(n[1], x)) : res1;
                }
                break;

                case TokenType.BITWISE_OR:
                    v = (double)((int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) | (int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x))));
                    break;

                case TokenType.BITWISE_XOR:
                    v = (double)((int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) ^ (int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x))));
                    break;

                case TokenType.BITWISE_AND:
                    v = (double)((int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) & (int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x))));
                    break;

                case TokenType.EQ:
                    v = Reference.GetValue(GLOBAL, execute(n[0], x));
                    u = Reference.GetValue(GLOBAL, execute(n[1], x));
                    if ((v == null || v == JSUndefined.Undefined) && (u == null || u == JSUndefined.Undefined))
                    {
                        v = true;
                    }
                    else
                    {
                        v = JSObject.CompareTo(GLOBAL, v, u) == 0;
                    }
                    break;

                case TokenType.NE:
                    if (((u == null || u is JSUndefined) && (v != null && !(v is JSUndefined))) ||
                        ((v == null || v is JSUndefined) && (u != null && !(u is JSUndefined))))
                    {
                        return(true);
                    }

                    v = JSObject.CompareTo(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x)), Reference.GetValue(GLOBAL, execute(n[1], x))) != 0;
                    break;

                case TokenType.STRICT_EQ:
                    v = Object.Equals(Reference.GetValue(GLOBAL, execute(n[0], x)), Reference.GetValue(GLOBAL, execute(n[1], x)));
                    break;

                case TokenType.STRICT_NE:
                    v = !Object.Equals(Reference.GetValue(GLOBAL, execute(n[0], x)), Reference.GetValue(GLOBAL, execute(n[1], x)));
                    break;

                case TokenType.LT:
                    v = JSObject.CompareTo(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x)), Reference.GetValue(GLOBAL, execute(n[1], x))) == -1;
                    break;

                case TokenType.LE:
                    v = JSObject.CompareTo(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x)), Reference.GetValue(GLOBAL, execute(n[1], x))) != 1;
                    break;

                case TokenType.GE:
                    v = JSObject.CompareTo(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x)), Reference.GetValue(GLOBAL, execute(n[1], x))) != -1;
                    break;

                case TokenType.GT:
                    v = JSObject.CompareTo(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x)), Reference.GetValue(GLOBAL, execute(n[1], x))) == 1;
                    break;

                case TokenType.In:
                    v    = execute(n[1], x);
                    tVal = Reference.GetValue(GLOBAL, v) as JSObjectBase;
                    if (tVal == null)
                    {
                        throw new TypeError("invalid 'in' operand " + v.ToString());
                    }
                    v = tVal.HasProperty(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x)).ToString());
                    break;

                case TokenType.Instanceof:
                    u    = Reference.GetValue(GLOBAL, execute(n[0], x));
                    tVal = Reference.GetValue(GLOBAL, execute(n[1], x)) as JSObjectBase;
                    if (tVal == null)
                    {
                        throw new TypeError("Not an object in instanceof");
                    }
                    v = tVal.HasInstance(GLOBAL, u);
                    break;

                case TokenType.LSH:
                    v = (double)((int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) << (int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x))));
                    break;

                case TokenType.RSH:
                    v = (double)((int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) >> (int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x))));
                    break;

                case TokenType.URSH:
                    v = (double)((int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) >> (int)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x))));
                    break;

                case TokenType.PLUS:
                    v = Add(Reference.GetValue(GLOBAL, execute(n[0], x)), Reference.GetValue(GLOBAL, execute(n[1], x)));
                    break;

                case TokenType.MINUS:
                    v = JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) - JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x)));
                    break;

                case TokenType.MUL:
                    v = JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) * JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x)));
                    break;

                case TokenType.DIV:
                    v = JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) / JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x)));
                    break;

                case TokenType.MOD:
                    v = JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[0], x))) % (long)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute(n[1], x)));
                    break;

                case TokenType.Delete:
                {
                    u = execute((Node)n[0], x);
                    Reference refer = u as Reference;
                    if (refer != null)
                    {
                        v = refer.GetBase().Delete(refer.GetPropertyName());
                    }
                }
                break;

                case TokenType.Void:
                    Reference.GetValue(GLOBAL, execute((Node)n[0], x));
                    v = JSUndefined.Undefined;
                    break;

                case TokenType.Typeof:
                    u = execute((Node)n[0], x);
                    if (u is Reference)
                    {
                        Reference refer = (Reference)u;
                        if (refer.GetBase() == null)
                        {
                            v = JSUndefined.Undefined;
                            break;
                        }
                        u = Reference.GetValue(GLOBAL, refer);
                    }
                    v = JSObject.Typeof(u).ToLower();
                    break;

                case TokenType.NOT:
                    v = !JSObject.ToBool(GLOBAL, Reference.GetValue(GLOBAL, execute((Node)n[0], x)));
                    break;

                case TokenType.BITWISE_NOT:
                    v = (double)~(long)JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute((Node)n[0], x)));
                    break;

                case TokenType.UNARY_PLUS:
                    v = JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute((Node)n[0], x)));
                    break;

                case TokenType.UNARY_MINUS:
                    v = -JSObject.ToNumber(GLOBAL, Reference.GetValue(GLOBAL, execute((Node)n[0], x)));
                    break;

                case TokenType.INCREMENT:
                case TokenType.DECREMENT:
                {
                    object t = execute(n[0], x);
                    u = Reference.GetValue(GLOBAL, t);
                    if (n.postfix)
                    {
                        v = u;
                    }
                    Reference.PutValue(GLOBAL, t, n.type == TokenType.INCREMENT ? JSObject.ToNumber(GLOBAL, u) + 1 : JSObject.ToNumber(GLOBAL, u) - 1);
                    if (!n.postfix)
                    {
                        v = u;
                    }
                }
                break;

                case TokenType.DOT:
                {
                    r = execute((Node)n[0], x);
                    object t = Reference.GetValue(GLOBAL, r);
                    u = n[1].value;
                    v = new Reference(JSObject.ToObject(GLOBAL, t), u.ToString());
                }
                break;

                case TokenType.INDEX:
                {
                    r = execute(n[0], x);
                    object t = Reference.GetValue(GLOBAL, r);
                    u = Reference.GetValue(GLOBAL, execute(n[1], x));
                    v = new Reference(JSObject.ToObject(GLOBAL, t), u.ToString());
                }
                break;

                case TokenType.LIST:
                    // Curse ECMA for specifying that arguments is not an Array object!
                    tVal = new JSObject();
                    int k = 0;
                    CollectArguments(tVal, n, ref k, x);
                    tVal.SetItem(GLOBAL, "length", new JSSimpleProperty("length", (double)k));
                    v = tVal;
                    break;

                case TokenType.CALL:
                {
                    r = execute(n[0], x);
                    JSObjectBase args = (JSObjectBase)execute(n[1], x);
                    object       o    = Reference.GetValue(GLOBAL, r);
                    if (Object.ReferenceEquals(o, JSUndefined.Undefined))
                    {
                        throw new TypeError("Can't call undefined " + n[0].ToString() + " " + r);
                    }
                    JSObjectBase fun = (JSObjectBase)o;
                    tVal = (r is Reference) ? ((Reference)r).GetBase() : null;
                    if (tVal is Activation)
                    {
                        tVal = null;
                    }
                    try
                    {
                        v = apply(true, fun, tVal, args, x);
                    }
                    catch (TypeError te)
                    {
                        if (r is Reference)
                        {
                            throw new TypeError(((Reference)r).GetPropertyName() + ": " + te.Message);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
                break;

                case TokenType.New:
                case TokenType.NEW_WITH_ARGS:
                {
                    r = execute(n[0], x);
                    JSObjectBase fun = (JSObjectBase)Reference.GetValue(GLOBAL, r);
                    if (n.type == TokenType.New)
                    {
                        jaa = new JSArray(GLOBAL);
                    }
                    else
                    {
                        jaa = (JSObjectBase)execute(n[1], x);
                    }
                    v = fun.Construct(GLOBAL, jaa, x);
                }
                break;

                case TokenType.ARRAY_INIT:
                    JSArray jaa1 = new JSArray(GLOBAL);
                    for (i = 0, j = n.Count; i < j; i++)
                    {
                        if (n[i] != null)
                        {
                            jaa1[i] = new JSSimpleProperty(i.ToString(), Reference.GetValue(GLOBAL, execute(n[i], x)));
                        }
                    }
                    jaa1.length = j;
                    v           = jaa1;
                    break;

                case TokenType.OBJECT_INIT:
                    tVal = new JSObject();
                    for (i = 0, j = n.Count; i < j; i++)
                    {
                        Node tx = n[i];
                        if (tx.type == TokenType.PROPERTY_INIT)
                        {
                            tVal.SetItem(GLOBAL, tx[0].value.ToString(),
                                         new JSSimpleProperty
                                             (tx[0].value.ToString(),
                                             Reference.GetValue(GLOBAL, execute(tx[1], x))));
                        }
                        else
                        {
                            f = new FunctionObject(GLOBAL, tx, x.scope);
                            string           tname = tx.name;
                            JSSimpleProperty prop;
                            if (!tx.fields.TryGetValue(tname, out prop))
                            {
                                tx.fields[tname] = new JSSimpleProperty(tname, v);
                            }
                            if (tx.type == TokenType.GETTER)
                            {
                                prop.DefineGetter(new Thunk(tVal, f, x));
                            }
                            else
                            {
                                prop.DefineSetter(new Thunk(tVal, f, x));
                            }
                            tVal.SetItem(GLOBAL, tname, prop);
                        }
                    }
                    v = tVal;
                    break;

                case TokenType.Null:
                    v = null;
                    break;

                case TokenType.This:
                    v = x.thisOb;
                    break;

                case TokenType.True:
                    v = true;
                    break;

                case TokenType.False:
                    v = false;
                    break;

                case TokenType.IDENTIFIER:
                {
                    for (sEcon = x.scope; sEcon != null; sEcon = sEcon.parent)
                    {
                        if (sEcon.jobject != null && sEcon.jobject.HasProperty(GLOBAL, n.value.ToString()))
                        {
                            break;
                        }
                    }
                    v = new Reference(sEcon != null ? sEcon.jobject : GLOBAL.jobject, n.value.ToString());
                }
                break;

                case TokenType.NUMBER:
                case TokenType.STRING:
                case TokenType.REGEXP:
                    v = n.value;
                    break;

                case TokenType.GROUP:
                    v = execute(n[0], x);
                    break;

                default:
                    throw new TypeError("PANIC: unknown operation " + n.type.ToString() + ": " + n.ToString());
                }
            }
            catch (FalseReturn) { v = false; }
            catch (ContinueException) { throw; }
            catch (BreakException) { throw; }
            catch (ThrownException) { throw; }
            catch (ReturnException) { throw; }
            catch (Exception e)
            {
                throw new ScriptException(e.Message, n, e);
            }
            if (TraceExec)
            {
                UnityEngine.Debug.Log(v == null ? "(null)" : v.ToString() + " ]");
            }

            return(v);
        }
예제 #9
0
        //
        // Basic matches
        //
        // The following requires double, float and decimal to be sorted before
        // integral types.  We'll generally prefer using double, float or decimal
        // versions of a function to integral versions, due to javascript's
        // preference of double for numerics
        //
        // ParamsArrayAttribute <- stop loop, try to convert all remaining arguments
        // IsOptional <- undefined or null -> RawDefaultValue
        // IsOut or IsRef <- (Nullable?)
        // float ... double and decimal <- number
        // byte ... ulong <- number
        // char <- jsstring, length = 1
        // string <- jsstring
        // Array <- jsarray (try to convert elements)
        // any kind of object <- IsAssignableFrom
        // bool <- almost anything
        //
        public static bool ConvertToType(ExecutionContext GLOBAL, object arg, Type argtype, out object result)
        {
            result = null;

            // Can't match: nonnumber into integral slot
            if (IsParamFloating(argtype))
            {
                if (!(arg is double))
                {
                    return(false);
                }
                if (argtype == typeof(double))
                {
                    result = (double)arg;
                    return(true);
                }
                else if (argtype == typeof(float))
                {
                    result = (float)(double)arg;
                    return(true);
                }
                else if (argtype == typeof(decimal))
                {
                    result = (decimal)(double)arg;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            if (IsParamIntegral(argtype))
            {
                if (argtype == typeof(byte))
                {
                    result = (byte)(double)arg;
                    return(true);
                }
                else if (argtype == typeof(short))
                {
                    result = (short)(double)arg;
                    return(true);
                }
                else if (argtype == typeof(ushort))
                {
                    result = (ushort)(double)arg;
                    return(true);
                }
                else if (argtype == typeof(int))
                {
                    result = (int)(double)arg;
                    return(true);
                }
                else if (argtype == typeof(uint))
                {
                    result = (uint)(double)arg;
                    return(true);
                }
                else if (argtype == typeof(long))
                {
                    result = (long)(double)arg;
                    return(true);
                }
                else if (argtype == typeof(ulong))
                {
                    result = (ulong)(double)arg;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            if (argtype == typeof(char))
            {
                string str = arg as string;
                if (arg is double)
                {
                    result = (char)(double)arg;
                    return(true);
                }
                else if (str != null && str.Length == 1)
                {
                    result = str[0];
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            if (argtype == typeof(string))
            {
                result = arg.ToString();
                return(true);
            }

            if (argtype.IsArray)
            {
                JSArray ja = arg as JSArray;
                if (ja == null)
                {
                    return(false);
                }
                Type eltType = argtype.GetElementType();
                System.Collections.ArrayList lo = new System.Collections.ArrayList();
                foreach (object aob in ja)
                {
                    object obelt;
                    if (!ConvertToType(GLOBAL, aob, eltType, out obelt))
                    {
                        return(false);
                    }
                    lo.Add(obelt);
                }
                result = lo.ToArray(eltType);
                return(true);
            }

            if (argtype == typeof(DateTime))
            {
                if (arg is JSDate)
                {
                    result = ((JSDate)arg).Value;
                    return(true);
                }
                else if (arg is DateTime)
                {
                    result = arg;
                    return(true);
                }
                else if (arg is long)
                {
                    JSDate jd = new JSDate(GLOBAL);
                    JSDate.setTime(jd, (long)arg);
                    result = jd.Value;
                    return(true);
                }
                else if (arg is double)
                {
                    JSDate jd = new JSDate(GLOBAL);
                    JSDate.setTime(jd, (long)((double)arg));
                    result = jd.Value;
                    return(true);
                }
                else if (arg is decimal)
                {
                    JSDate jd = new JSDate(GLOBAL);
                    JSDate.setTime(jd, (long)((decimal)arg));
                    result = jd.Value;
                    return(true);
                }
                else if (arg is JSInstanceWrapper)
                {
                    JSInstanceWrapper iw = (JSInstanceWrapper)arg;
                    if (iw.This is DateTime)
                    {
                        result = iw.This;
                        return(true);
                    }
                }
            }

            if (argtype == typeof(JSDate))
            {
                if (arg is JSDate)
                {
                    result = arg;
                    return(true);
                }
                else if (arg is DateTime)
                {
                    result = new JSDate(GLOBAL, (DateTime)arg);
                    return(true);
                }
                else if (arg is long)
                {
                    JSDate jd = new JSDate(GLOBAL);
                    JSDate.setTime(jd, (long)arg);
                    result = jd;
                    return(true);
                }
                else if (arg is double)
                {
                    JSDate jd = new JSDate(GLOBAL);
                    JSDate.setTime(jd, (long)((double)arg));
                    result = jd;
                    return(true);
                }
                else if (arg is decimal)
                {
                    JSDate jd = new JSDate(GLOBAL);
                    JSDate.setTime(jd, (long)((decimal)arg));
                    result = jd;
                    return(true);
                }
                else if (arg is JSInstanceWrapper)
                {
                    JSInstanceWrapper iw = (JSInstanceWrapper)arg;
                    if (iw.This is DateTime)
                    {
                        result = new JSDate(GLOBAL, (DateTime)iw.This);
                        return(true);
                    }
                }
            }

            if (arg is JSInstanceWrapper)
            {
                JSInstanceWrapper wrapper = (JSInstanceWrapper)arg;
                if (!argtype.IsAssignableFrom(wrapper.This.GetType()))
                {
                    return(false);
                }
                result = wrapper.This;
                return(true);
            }

            if (argtype == typeof(bool))
            {
                string str = arg as string;
                if (arg is bool)
                {
                    result = (bool)arg;
                }
                if (arg is double)
                {
                    result = (double)arg != 0.0;
                }
                if (str != null)
                {
                    result = str.ToString().Length != 0;
                }
                result = !(arg == null || arg == JSUndefined.Undefined);
                return(true);
            }

            return(false);
        }