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.applet.Applet;
023 
024 import org.jscripter.sim.Simul;
025 
026 
027 import netscape.javascript.JSException;
028 import netscape.javascript.JSObject;
029 import js.*;
030 import js.core.*;
031 import js.user.*;
032 
033 /**
034  * <p>An abstract <b>internal</b> class for JS Embeded Simulation.</p>
035  * <p>This <b>internal</b> class is only extended internally in JS Simulation Library.</p>
036  *
037  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
038  * 
039  * @javascript Re-compilers must report error on resolving an <tt>internal</tt> class. 
040  */
041 public abstract class Embeded extends Simul
042 {
043     final static Object[] noargs = new Object[]{};
044 
045     /**
046      * <p>Internally creates a JS Embeded Simulation from an applet.</p>
047      * @param applet A Java applet.
048      * @return A Js Embeded Simulation.
049      * @since 1.0
050      * 
051      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> constructor. 
052      */
053     public static final Embeded create(Applet applet) {
054         JSObject win = (JSObject)JSObject.getWindow(applet);
055 //      if ((Boolean)win.eval("!XMLHttpRequest&&ActiveXObject")) {
056         if ((Boolean)win.eval("/MSIE/i.test(navigator.userAgent)")) {
057             return new EmbededIE(applet);
058         } else {
059             return new EmbededFF(applet);
060         }
061     }
062 
063     /**
064      * <p>Internally checks if the simulation is limited to JavaScript core features only.</p>
065      * <p>This method always returns <tt>false</tt>.</p>
066      * @return <tt>true</tt> if this is a core simulation; <tt>false</tt>, otherwise;
067      * @since 1.0
068      * 
069      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
070      */
071     @Override
072     protected final boolean isCore() {
073         return false;
074     }
075 
076     private final JSObject win;
077 
078     /**
079      * <p>Internally constructs a JS Embeded Simulation from an applet.</p>
080      * @param applet A Java applet.
081      * @since 1.0
082      * 
083      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> constructor. 
084      */
085     protected Embeded(Applet applet) {
086         win = (JSObject)JSObject.getWindow(applet);
087         win.eval(
088                 "window.$f=function(o){var f=function(){return o.apply(this,arguments);};f.$f=o;return f;};" +
089                 "window.$destroy=function(o){delete o;};" +
090                 "window.$nhc=0;" +
091                 "window.$hc=function(o){return o.$$hc?o.$$hc:(o.$$hc=window.$nhc++);};" +
092                 "window.$eq=function(v,o){return v==o;};" +
093                 "window.$eqs=function(v,o){return v===o;};" +
094                 "window.$in=function(s,o){return s in o;};" +
095                 "window.$ins=function(o,f){return o instanceof f;};" +
096                 "window.$keys=function(o){" +
097                     "var r=[];" +
098                     "for(var p in o){" +
099                         "r.push(p);" +
100                     "}" +
101                     "return r;" +
102                 "};" +
103                 "window.$ap=function(o,a){" +
104                     "for(var p in a){" +
105                         "o[p]=a[p];" +
106                     "}" +
107                 "};" +
108                 "window.$cp=function(o){" +
109                     "var c={};" +
110                     "$apply(c,o);" +
111                     "return c;" +
112                 "};"
113         );
114     }
115 
116     /**
117      * <p>Internally returns the global {@link JSObject} object for the current browser.</p>
118      * @return The global {@link JSObject} object for the current browser.
119      * @since 1.0
120      * 
121      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
122      */
123     protected final JSObject getWindow() {
124         return win;
125     }
126 
127     /**
128      * <p>Returns the opaque global object with the client-side support.</p>
129      * @return The opaque global object with the client-side support.
130      * @see Js#win()
131      * @see jsx.client.Client
132      * @since 1.0
133      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
134      */
135     @Override
136     protected abstract JsWin win();
137 
138     /**
139      * <p>Returns the opaque global object with the core support only.</p>
140      * <p>This method returns exactly the same as {@link #win()}.</p>
141      * @return The opaque global object with the core support only.
142      * @see Js#core()
143      * @see jsx.client.Global
144      * @since 1.0
145      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
146      */
147     @Override
148     protected final JsGlobal core() {
149         return win();
150     }
151 
152     /**
153      * <p>Internally down cast an object to array type.</p>
154      * <p>This method is internal and only called inside of opaque or internal classes 
155      * or class members.</p>
156      * @param o The object
157      * @since 1.0
158      * @return The array representation of an object
159      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
160      */
161     @SuppressWarnings("unchecked")
162     @Override
163     protected final JsArray toJsArray(JsObject o) {
164         Unwrappable<JseObject> u = o == null ? null : (Unwrappable<JseObject>)o.var();
165         return u == null ? null : new JseArray(u.unwrap());
166     }
167 
168     /**
169      * <p>Internally down cast an object to boolean type.</p>
170      * <p>This method is internal and only called inside of opaque or internal classes 
171      * or class members.</p>
172      * @param o The object
173      * @since 1.0
174      * @return The boolean representation of an object
175      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
176      */
177     @SuppressWarnings("unchecked")
178     @Override
179     protected final JsBoolean toJsBoolean(JsObject o) {
180         Unwrappable<JseObject> u = o == null ? null : (Unwrappable<JseObject>)o.var();
181         return u == null ? null : new JseBoolean(u.unwrap());
182     }
183 
184     /**
185      * <p>Internally down cast an object to date type.</p>
186      * <p>This method is internal and only called inside of opaque or internal classes 
187      * or class members.</p>
188      * @param o The object
189      * @since 1.0
190      * @return The date representation of an object
191      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
192      */
193     @SuppressWarnings("unchecked")
194     @Override
195     protected final JsDate toJsDate(JsObject o) {
196         Unwrappable<JseObject> u = o == null ? null : (Unwrappable<JseObject>)o.var();
197         return u == null ? null : new JseDate(u.unwrap());
198     }
199 
200     /**
201      * <p>Internally down cast an object to function type.</p>
202      * <p>This method is internal and only called inside of opaque or internal classes 
203      * or class members.</p>
204      * @param o The object
205      * @since 1.0
206      * @return The function representation of an object
207      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
208      */
209     @SuppressWarnings("unchecked")
210     @Override
211     protected final <T> JsFunction<T> toJsFunction(JsObject o) {
212         Unwrappable<JseObject> u = o == null ? null : (Unwrappable<JseObject>)o.var();
213         return u == null ? null : new JseFunction<T>(u.unwrap());
214     }
215 
216     /**
217      * <p>Internally down cast an object to function type.</p>
218      * <p>This method is internal and only called inside of opaque or internal classes 
219      * or class members.</p>
220      * @param o The object
221      * @param w A wrapper to perform the cast
222      * @since 1.0
223      * @return The function representation of an object
224      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
225      */
226     @SuppressWarnings("unchecked")
227     @Override
228     protected final <T> JsFunction<T> toJsFunction(JsObject o, Generic<T> w) {
229         if (o == null) {
230             return null;
231         }
232         Unwrappable<JseObject> u = (Unwrappable<JseObject>)o.var();
233         if (u == null) {
234             return null;
235         }
236         return u == null ? null :
237             u instanceof JseFunctionW<?> ? new JseFunctionW<T>(u.unwrap(), (JseFunctionW<T>)u) :
238                 new JseFunctionW<T>(u.unwrap(), w);
239     }
240 
241     /**
242      * <p>Internally down cast an object to number type.</p>
243      * <p>This method is internal and only called inside of opaque or internal classes 
244      * or class members.</p>
245      * @param o The object
246      * @since 1.0
247      * @return The number representation of an object
248      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
249      */
250     @SuppressWarnings("unchecked")
251     @Override
252     protected final JsNumber toJsNumber(JsObject o) {
253         Unwrappable<JseObject> u = o == null ? null : (Unwrappable<JseObject>)o.var();
254         return u == null ? null : new JseNumber(u.unwrap());
255     }
256 
257     /**
258      * <p>Internally down cast an object to regular expression type.</p>
259      * <p>This method is internal and only called inside of opaque or internal classes 
260      * or class members.</p>
261      * @param o The object
262      * @since 1.0
263      * @return The regular expression representation of an object
264      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
265      */
266     @SuppressWarnings("unchecked")
267     @Override
268     protected final JsRegExp toJsRegExp(JsObject o) {
269         Unwrappable<JseObject> u = o == null ? null : (Unwrappable<JseObject>)o.var();
270         return u == null ? null : new JseRegExp(u.unwrap());
271     }
272 
273     /**
274      * <p>Internally down cast an object to string type.</p>
275      * <p>This method is internal and only called inside of opaque or internal classes 
276      * or class members.</p>
277      * @param o The object
278      * @since 1.0
279      * @return The string representation of an object
280      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
281      */
282     @SuppressWarnings("unchecked")
283     @Override
284     protected final JsString toJsString(JsObject o) {
285         Unwrappable<JseObject> u = o == null ? null : (Unwrappable<JseObject>)o.var();
286         return u == null ? null : new JseString(u.unwrap());
287     }
288 
289     /**
290      * <p>Gets the hash code of a value.</p>
291      * @param o Any value.
292      * @return The hash code of a value.
293      * @since 1.0
294      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
295      */
296     @Override
297     protected final int hashCode(Object o) {
298         o = o instanceof Var<?> ? ((Var<?>)o).var() : o;
299         return o instanceof Live ? (Integer)getWindow().call(
300                 "$hc",
301                 new Object[]{((Live)o).getJSObject()}
302         ) : o.hashCode();
303     }
304 
305     /**
306      * <p>Copies all the properties of <tt>a</tt> to <tt>o</tt>.</p>
307      * @param o The object that the properties being copied to.
308      * @param a The object that the properties being copied from.
309      * @since 1.0
310      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
311      */
312     @Override
313     protected void apply(JsObject o, ObjectLike a) {
314         JSObject jso = ((Live)o.var()).getJSObject();
315         JSObject obj = (JSObject)getWindow().call("Object", noargs);
316         ArrayLike<String> keys = Js.keys(a);
317         for (int i = 0, len = keys.length(); i < len; i++) {
318             String k = keys.get(i);
319             try {
320                 obj.setMember(k, a.var(k));
321             } catch (JSException jse) {
322                 throw new RuntimeException(k + ':' + a.var(k), jse);
323             }
324         }
325         getWindow().call(
326                 "$ap",
327                 new Object[] {jso, obj}
328         );
329     }
330 
331     /**
332      * <p>Checks if a value equals another object.</p>
333      * @param v Any value
334      * @param o Any value
335      * @return <tt>true</tt> if <tt>v</tt> equals <tt>o</tt>; false, otherwise.
336      * @since 1.0
337      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
338      */
339     @Override
340     protected final boolean equals(Object v, Object o) {
341         return eqs(v, o);
342     }
343 
344     /**
345      * <p>Checks whether the two operands are "equal" using a more relaxed definition of 
346      * sameness that allows type conversions, resembling the equality operator in 
347      * JavaScript.</p>
348      * <p>The equality and identity operations check whether two values are the same, using 
349      * two different definitions of sameness. Both operations accept operands of any type, 
350      * and both return <tt>true</tt> if their operands are the same and <tt>false</tt> 
351      * if they are different. The identity operation checks whether its two operands are 
352      * "identical" using a strict definition of sameness. The equality operation checks 
353      * whether its two operands are "equal" using a more relaxed definition of sameness 
354      * that allows type conversions.</p>
355      * <p>The identity operation is standardized by ECMAScript v3 and implemented in 
356      * JavaScript 1.3 and later. Be sure you understand the differences between the 
357      * assignment, equality, and identity operations, and be careful to use the correct one 
358      * when coding! Although it is tempting to call all three operations "equals," it may 
359      * help to reduce confusion if you read "gets or is assigned" for assignment operation, 
360      * "is equal to" for equality operation, and "is identical to" for identity operation.</p>
361      * <p>In JavaScript, numbers, strings, and boolean values are compared by value. In this 
362      * case, two separate values are involved, and the equality and identity operations 
363      * check that these two values are identical. This means that two variables are equal 
364      * or identical only if they contain the same value. For example, two strings are equal 
365      * only if they each contain exactly the same characters.</p>
366      * <p>On the other hand, objects, arrays, and functions are compared by reference. This 
367      * means that two variables are equal only if they refer to the same object. Two 
368      * separate arrays are never equal or identical, even if they contain equal or identical 
369      * elements. Two variables that contain references to objects, arrays, or functions are 
370      * equal only if they refer to the same object, array, or function. If you want to test 
371      * that two distinct objects contain the same properties or that two distinct arrays 
372      * contain the same elements, you'll have to check the properties or elements individually 
373      * for equality or identity. And, if any of the properties or elements are themselves 
374      * objects or arrays, you'll have to decide how deep you want the comparison to go.</p>
375      * <p>The following rules determine whether two values are equal according to the 
376      * equality operation:
377      * <ul>
378      * <li>If the two values have the same type, test them for identity. If the values are 
379      * identical, they are equal; if they are not identical, they are not equal.</li>
380      * <li>If the two values do not have the same type, they may still be equal. Use the 
381      * following rules and type conversions to check for equality:</li>
382      * <ul>
383      * <li>If one value is null and the other is undefined, they are equal.</li>
384      * <li>If one value is a number and the other is a string, convert the string to a 
385      * number and try the comparison again, using the converted value.</li>
386      * <li>If either value is <tt>true</tt>, convert it to 1 and try the comparison 
387      * again. If either value is <tt>false</tt>, convert it to 0 and try the comparison 
388      * again.</li>
389      * <li>If one value is an object and the other is a number or string, convert the 
390      * object to a primitive and try the comparison again. An object is converted to a 
391      * primitive value by either its <tt>toString()</tt> method or its <tt>valueOf()</tt> 
392      * method. The built-in classes of core JavaScript attempt <tt>valueOf()</tt> 
393      * conversion before <tt>toString()</tt> conversion, except for the Date class, 
394      * which performs <tt>toString()</tt> conversion. Objects that are not part of core 
395      * JavaScript may convert themselves to primitive values in an implementation-defined 
396      * way.</li>
397      * <li>Any other combinations of values are not equal.</li>
398      * </ul>
399      * </ul>
400      * @param v Any value or object.
401      * @param o Any value or object.
402      * @return <tt>true</tt> if the first operand equals the second; <tt>false</tt>, 
403      * otherwise;
404      * @since 1.0
405      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
406      */
407     @Override
408     protected final boolean eq(Object v, Object o) {
409         v = v instanceof Var<?> ? ((Var<?>)v).var() : v;
410         o = o instanceof Var<?> ? ((Var<?>)o).var() : o;
411         boolean nv = Js.undefined(v);
412         boolean no = Js.undefined(o);
413         if (nv && no) {
414             return true;
415         } else if (nv || no) {
416             return false;
417         }
418         if (v instanceof Var<?> && o instanceof Var<?>) {
419             return (Boolean)getWindow().call(
420                     "$eq",
421                     new Object[]{
422                             ((Live)v).getJSObject(),
423                             ((Live)o).getJSObject()
424                     }
425             );
426         }
427         return eqv(Js.valueOf(v), Js.valueOf(o));
428     }
429 
430     /**
431      * <p>Checks whether the two operands are "identical" using a strict definition of 
432      * sameness, resembling the identity operator in JavaScript.</p>
433      * <p>The equality and identity operations check whether two values are the same, using 
434      * two different definitions of sameness. Both operations accept operands of any type, 
435      * and both return <tt>true</tt> if their operands are the same and <tt>false</tt> 
436      * if they are different. The identity operation checks whether its two operands are 
437      * "identical" using a strict definition of sameness. The equality operation checks 
438      * whether its two operands are "equal" using a more relaxed definition of sameness 
439      * that allows type conversions.</p>
440      * <p>The identity operation is standardized by ECMAScript v3 and implemented in 
441      * JavaScript 1.3 and later. Be sure you understand the differences between the 
442      * assignment, equality, and identity operations, and be careful to use the correct one 
443      * when coding! Although it is tempting to call all three operations "equals," it may 
444      * help to reduce confusion if you read "gets or is assigned" for assignment operation, 
445      * "is equal to" for equality operation, and "is identical to" for identity operation.</p>
446      * <p>In JavaScript, numbers, strings, and boolean values are compared by value. In this 
447      * case, two separate values are involved, and the equality and identity operations 
448      * check that these two values are identical. This means that two variables are equal 
449      * or identical only if they contain the same value. For example, two strings are equal 
450      * only if they each contain exactly the same characters.</p>
451      * <p>On the other hand, objects, arrays, and functions are compared by reference. This 
452      * means that two variables are equal only if they refer to the same object. Two 
453      * separate arrays are never equal or identical, even if they contain equal or identical 
454      * elements. Two variables that contain references to objects, arrays, or functions are 
455      * equal only if they refer to the same object, array, or function. If you want to test 
456      * that two distinct objects contain the same properties or that two distinct arrays 
457      * contain the same elements, you'll have to check the properties or elements individually 
458      * for equality or identity. And, if any of the properties or elements are themselves 
459      * objects or arrays, you'll have to decide how deep you want the comparison to go.</p>
460      * <p>The following rules determine whether two values are identical according to the identity operation:
461      * <ul>
462      * <li>If the two values have different types, they are not identical.</li>
463      * <li>If both values are numbers and have the same value, they are identical, unless 
464      * either or both values are <tt>NaN</tt>, in which case they are not identical. 
465      * The <tt>NaN</tt> value is never identical to any other value, including itself! 
466      * To check whether a value is <tt>NaN</tt>, use the global {@link Js#isNaN(Object)} 
467      * function.</li>
468      * <li>If both values are strings and contain exactly the same characters in the same 
469      * positions, they are identical. If the strings differ in length or content, they are 
470      * not identical. Note that in some cases, the Unicode standard allows more than one 
471      * way to encode the same string. For efficiency, however, JavaScript's string 
472      * comparison compares strictly on a character-by-character basis, and it assumes that 
473      * all strings have been converted to a "normalized form" before they are compared. 
474      * See the {@link StringLike#localeCompare(Object)} for another way to compare strings.</li>
475      * <li>If both values are the boolean value <tt>true</tt> or both are the boolean 
476      * value <tt>false</tt>, they are identical.</li>
477      * <li>If both values refer to the same object, array, or function, they are identical. 
478      * If they refer to different objects (or arrays or functions) they are not identical, 
479      * even if both objects have identical properties or both arrays have identical elements.</li>
480      * <li>If both values are null or both values are undefined, they are identical.</li>
481      * </ul>
482      * @param v Any value or object.
483      * @param o Any value or object.
484      * @return <tt>true</tt> if the first operand is identical to the second; 
485      * <tt>false</tt>, otherwise;
486      * @since 1.0
487      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
488      */
489     @Override
490     protected final boolean eqs(Object v, Object o) {
491         v = v instanceof Var<?> ? ((Var<?>)v).var() : v;
492         o = o instanceof Var<?> ? ((Var<?>)o).var() : o;
493         boolean nv = Js.undefined(v);
494         boolean no = Js.undefined(o);
495         if (nv && no) {
496             return true;
497         } else if (nv || no) {
498             return false;
499         }
500         boolean lv = v instanceof Var<?>;
501         boolean lo = o instanceof Var<?>;
502         if (lv && lo) {
503             return (Boolean)getWindow().call(
504                     "$eqs",
505                     new Object[]{
506                             ((Live)v).getJSObject(),
507                             ((Live)o).getJSObject()
508                     }
509             );
510         }
511         return !lv && !lo && v.equals(o);
512     }
513 
514     /**
515      * <p>Checks if the first operand is the name of a property of the second, resembling 
516      * the <tt>in</tt> operator in JavaScript.</p>
517      * <p>This operation converts the first operand to a string and expects the second 
518      * operand be an object (or array).</p>
519      * @param v Any value that is or can be converted to a string.
520      * @param o Any object or array.
521      * @return <tt>true</tt> if the first operand is the name of a property of the 
522      * second operand; <tt>false</tt>, otherwise;
523      * @since 1.0
524      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
525      */
526     @Override
527     protected final boolean in(Object v, Object o) {
528         v = v instanceof Var<?> ? ((Var<?>)v).var() : v;
529         o = o instanceof Var<?> ? ((Var<?>)o).var() : o;
530         return o instanceof Live && (Boolean)getWindow().call(
531                 "$in",
532                 new Object[]{
533                         v instanceof Live ? ((Live)v).getJSObject() : Js.toString(v),
534                         ((Live)o).getJSObject()
535                 }
536         );
537     }
538 
539     /**
540      * <p>Checks if the first operand is an instance of the second, resembling the 
541      * <tt>instanceof</tt> operator in JavaScript.</p>
542      * <p>This operation expects the first operand be an object and the second be a class 
543      * of objects. In JavaScript, classes of objects are defined by the constructor function 
544      * that initializes them.</p>
545      * @param v Any value or object.
546      * @param o A constructor function.
547      * @return <tt>true</tt> if the first operand is an instance of the second; 
548      * <tt>false</tt>, otherwise;
549      * @since 1.0
550      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
551      */
552     @Override
553     protected final boolean instanceOf(Object v, Object o) {
554         v = v instanceof Var<?> ? ((Var<?>)v).var() : v;
555         o = o instanceof Var<?> ? ((Var<?>)o).var() : o;
556         return v instanceof Live && o instanceof Live && (Boolean)getWindow().call(
557                 "$ins",
558                 new Object[]{
559                         ((Live)v).getJSObject(),
560                         ((Live)o).getJSObject()
561                 }
562         );
563     }
564 
565     /**
566      * <p>Gets the value or object contained in a <tt>RuntimeException</tt> object 
567      * thrown by JS Simulation.</p>
568      * @param e The <tt>RuntimeException</tt> object thrown by JS Simulation.
569      * @return The value or object contained in the <tt>RuntimeException</tt> object.
570      * @since 1.0
571      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
572      */
573     @SuppressWarnings("deprecation")
574     @Override
575     protected final Object err(RuntimeException e) {
576         return e instanceof JSException ? ((JSException)e).getWrappedException() : e;
577     }
578 
579     /**
580      * <p>Checks if a variable represents a Java object.</p>
581      * @param v Any value or object.
582      * @return <tt>true</tt> if <tt>v</tt> is Java; <tt>false</tt>, otherwise.
583      * @since 1.0
584      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
585      */
586     @Override
587     protected boolean isJavaObject(Object v) {
588         return !(v instanceof JseObject) && !v.getClass().isPrimitive();
589     }
590 }