001 
002 /*
003  *  JScripter Simulation 1.0 - For Java To Script
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package org.jscripter.sim.core;
021 
022 import java.util.HashSet;
023 import java.util.Iterator;
024 import java.util.Set;
025 
026 import org.jscripter.sim.SimUtil;
027 
028 
029 import js.*;
030 import js.core.*;
031 
032 class JscObject extends JsObject implements
033     Iterable<JsObject.Mid>, Like<Object>, LikeObject, Unwrappable<JscObject>
034 {
035     private ObjectLike objectLike;
036 
037     public JscObject(Object var, ObjectLike objectLike) {
038         super(var);
039         this.objectLike = objectLike;
040     }
041     public JscObject(ObjectLike like) {
042         this("[object Object]", like);
043     }
044     public JscObject() {
045         this(Js.object());
046     }
047 
048     public final JscObject unwrap() {
049         return this;
050     }
051 
052     public final Object like() {
053         return var;
054     }
055 
056     public final ObjectLike likeObject() {
057         return objectLike;
058     }
059 
060     @Override
061     public final JscObject var() {
062         return this;
063     }
064 
065     public final Iterator<Mid> iterator() {
066         Set<Mid> mids = new HashSet<Mid>();
067         Iterator<Mid> it = Core.get().iterator(likeObject());
068         while (it.hasNext()) {
069             mids.add(it.next());
070         }
071         JsObject p = JsFunction.prototype.with(this);
072         if (Js.be(p)) {
073             it = ((JscObject)((Unwrappable<?>)p.var()).unwrap()).iterator();
074             while (it.hasNext()) {
075                 mids.add(it.next());
076             }
077         }
078         return mids.iterator();
079     }
080 
081     @Override
082     public final String typeof() {
083         return undefined() ? "undefined" : "object";
084     }
085 
086     @Override
087     public final boolean undefined() {
088         return var == null;
089     }
090 
091     @Override
092     public final String toString() {
093         return toString.with(this).call(this);
094     }
095 
096     @Override
097     public final Object valueOf() {
098         return valueOf.with(this).call(this);
099     }
100 
101     @Override
102     public final boolean delete() {
103         if (undefined()) return false;
104         var = null;
105         objectLike = null;
106         return true;
107     }
108 
109     @Override
110     public final boolean delete(Mid mid) {
111         if (undefined()) {
112             return false;
113         }
114         if (likeObject().delete(mid)) {
115             return true;
116         }
117         JsObject p = JsFunction.prototype.with(this);
118         if (Js.be(p) && Js.be(p.var(mid))) {
119             likeObject().var(mid, null);
120             return true;
121         }
122         return false;
123     }
124 
125     @Override
126     public final Object var(Mid mid) {
127         if (mid == JsArray.length.mid()) {
128             Object like = like();
129             return like instanceof StringLike ?
130                     ((StringLike)like).length() : ((ArrayLike<?>)like).length();
131         } else if (mid == JsArray.index.mid()) {
132             return ((ArrayLike<?>)like()).index();
133         } else if (mid == JsArray.input.mid()) {
134             return ((ArrayLike<?>)like()).input();
135         } else if (mid == JsRegExp.global.mid()) {
136             return ((RegExpLike)like()).global();
137         } else if (mid == JsRegExp.ignoreCase.mid()) {
138             return ((RegExpLike)like()).ignoreCase();
139         } else if (mid == JsRegExp.multiline.mid()) {
140             return ((RegExpLike)like()).multiline();
141         } else if (mid == JsRegExp.lastIndex.mid()) {
142             return ((RegExpLike)like()).lastIndex();
143         } else if (mid == JsRegExp.source.mid()) {
144             return ((RegExpLike)like()).source();
145         }
146         Object o = likeObject().var(mid);
147         if (o != null) {
148             return o;
149         }
150         JsObject p = (JsObject)likeObject().var(JsFunction.prototype.mid());
151         return Js.be(p) ? p.var(mid) : null;
152     }
153 
154     public final <T> T var(Mid mid, T v) {
155         if (mid == JsArray.length.mid()) {
156             ((ArrayLike<?>)like()).length(
157                     SimUtil.getNumber(v).intValue()
158             );
159             return v;
160         } else if (mid == JsRegExp.lastIndex.mid()) {
161             ((RegExpLike)like()).lastIndex(
162                     SimUtil.getNumber(v).intValue()
163             );
164             return v;
165         }
166         likeObject().var(mid, v instanceof JsObject       ? ((JsObject      )v).var() :
167                               v instanceof Function<?>    ? ((Function<?>   )v).var() :
168                               v instanceof Var<?>         ? ((Var<?>        )v).var() : v);
169         return v;
170     }
171 
172     @Override
173     protected final <T> T call(JsFunction.Member<T> member) {
174         return member.with(this).call(this);
175     }
176     @Override
177     protected final <T> T call(JsFunction.Member<T> member, Object arg) {
178         return member.with(this).call(this, arg);
179     }
180     @Override
181     protected final <T> T call(JsFunction.Member<T> member, Vars<?> args) {
182         return member.with(this).call(this, args);
183     }
184 }