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.client;
021 
022 import java.util.HashSet;
023 import java.util.Set;
024 
025 import netscape.javascript.JSException;
026 import netscape.javascript.JSObject;
027 import js.*;
028 import js.core.*;
029 
030 class JseObjectIE extends JseObject
031 {
032     static class JseoFunction<T> extends JseObjectIE implements HasFun<T>
033     {
034         private JSObject jsof;
035 
036         public JseoFunction(Function<T> var) {
037             super(var);
038         }
039 
040         @SuppressWarnings("unchecked")
041         public final Function<T> getFunction() {
042             return (Function<T>)var;
043         }
044 
045         @Override
046         public final synchronized JSObject getJSObject() {
047             if (jsof == null) {
048                 JSObject win = ((Live)((JsObject)Js.win()).var()).getJSObject();
049                 try {
050                     jsof = (JSObject)win.call("$f", new Object[]{getFunction()});
051                 } catch (JSException e) {
052                     throw e;
053                 }
054             }
055             return jsof;
056         }
057     }
058 
059     final static class IEMembers extends JsObject.Members
060     {
061         final static Mid attachEvent = id("attachEvent");
062         final static Mid detachEvent = id("detachEvent");
063         final static Mid selectNodes = id("selectNodes");
064 
065         private final static Set<Mid> ienats = new HashSet<Mid>();
066 
067         static {
068             ienats.add(attachEvent);
069             ienats.add(detachEvent);
070             ienats.add(selectNodes);
071         }
072 
073         private final static boolean isWin(JSObject o) {
074             JSObject win = ((Live)((JsObject)Js.win()).var()).getJSObject();
075             return (Boolean)win.call(
076                     "$eqs",
077                     new Object[]{o, win}
078             );
079         }
080 
081         private final static String delegate(Mid mid) {
082             JSObject win = ((Live)((JsObject)Js.win()).var()).getJSObject();
083             String delegator = "$$" + mid.toString();
084             synchronized(IEMembers.class) {
085                 try {
086                     win.getMember(delegator);
087                 } catch(JSException e) {
088                     win.eval("this." + delegator + "=function(o,a){return o." + mid.toString() + ".apply(o,a);}");
089                 }
090             }
091             return delegator;
092         }
093         final static Object callMember(JSObject jso, Mid mid) {
094             if (!ienats.contains(mid) || isWin(jso)) {
095                 return jso.call(mid.toString(), Embeded.noargs);
096             }
097             JSObject win = ((Live)((JsObject)Js.win()).var()).getJSObject();
098             return win.call(delegate(mid), new Object[]{jso});
099         }
100         final static Object callMember(JSObject jso, Mid mid, Object arg) {
101             if (Js.undefined(arg)) {
102                 return callMember(jso, mid);
103             }
104             if (!ienats.contains(mid) || isWin(jso)) {
105                 return jso.call(mid.toString(), new Object[]{unwrap(arg)});
106             }
107             JSObject win = ((Live)((JsObject)Js.win()).var()).getJSObject();
108             return win.call(delegate(mid), new Object[]{jso, new Object[]{unwrap(arg)}});
109         }
110         final static Object callMember(JSObject jso, Mid mid, Vars<?> args) {
111             if (!ienats.contains(mid) || isWin(jso)) {
112                 return jso.call(mid.toString(), unwrap(args));
113             }
114             JSObject win = ((Live)((JsObject)Js.win()).var()).getJSObject();
115             try {
116                 return win.call(delegate(mid), new Object[]{jso, unwrap(args.var().var())});
117             } catch (JSException e) {
118                 throw e;
119             }
120         }
121 
122         private final static <T> T set(JSObject jso, Object p, T v) {
123             JSObject win = ((Live)((JsObject)Js.win()).var()).getJSObject();
124             win.call("$$set", new Object[]{jso, p, unwrap(v)});
125             return v;
126         }
127         final static <T> T setMember(JSObject jso, Mid mid, T v) {
128             return set(jso, mid.toString(), v);
129         }
130         final static <T> T setSlot(JSObject jso, int i, T v) {
131             return set(jso, i, v);
132         }
133     }
134 
135     public JseObjectIE(Object var) {
136         super(var);
137     }
138 
139     public static final Object wrap(Object v) {
140         return v instanceof JSObject ? new JseObjectIE((JSObject)v) : v;
141     }
142 
143     @Override
144     public final Object callMember(Mid mid) {
145         return wrap(IEMembers.callMember(getJSObject(), mid));
146     }
147     @Override
148     public final Object callMember(Mid mid, Object arg) {
149         return wrap(IEMembers.callMember(getJSObject(), mid, arg));
150     }
151     @Override
152     public final Object callMember(Mid mid, Vars<?> args) {
153         return wrap(IEMembers.callMember(getJSObject(), mid, args));
154     }
155 
156     @Override
157     public final Object eval(String s) {
158         return wrap(getJSObject().eval(s));
159     }
160     @Override
161     public final Object var(Mid mid) {
162         try {
163             JSObject o = getJSObject();
164             if (o == null) return null;
165             return wrap(getJSObject().getMember(mid.toString()));
166         } catch (JSException jse) {
167             return null;
168         }
169     }
170     @Override
171     public final Object getSlot(int index) {
172         try {
173             JSObject o = getJSObject();
174             if (o == null) return null;
175             return wrap(getJSObject().getSlot(index));
176         } catch (JSException jse) {
177             return null;
178         }
179     }
180     @Override
181     public final void removeMember(Mid mid) {
182         getJSObject().removeMember(mid.toString());
183     }
184     @Override
185     public final <T> T var(Mid mid, T v) {
186         return IEMembers.setMember(getJSObject(), mid, v);
187     }
188     @Override
189     public final void setSlot(int index, Object v) {
190         IEMembers.setSlot(getJSObject(), index, v);
191     }
192 }