static boolean isWithFunction(Object functionObj) { if (functionObj instanceof IdFunctionObject) { IdFunctionObject f = (IdFunctionObject) functionObj; return f.hasTag(FTAG) && f.methodId() == Id_constructor; } return false; }
@Override public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(ITERATOR_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); if (id == Id_constructor) { return jsConstructor(cx, scope, thisObj, args); } if (!(thisObj instanceof NativeIterator)) throw incompatibleCallError(f); NativeIterator iterator = (NativeIterator) thisObj; switch (id) { case Id_next: return iterator.next(cx, scope); case Id___iterator__: // / XXX: what about argument? SpiderMonkey apparently ignores it return thisObj; default: throw new IllegalArgumentException(String.valueOf(id)); } }
private IdFunctionObject newIdFunction( Object tag, int id, String name, int arity, Scriptable scope) { IdFunctionObject f = new IdFunctionObject(this, tag, id, name, arity, scope); if (isSealed()) { f.sealObject(); } return f; }
public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (f.hasTag(FTAG)) { if (f.methodId() == Id_getClass) { return js_getClass(cx, scope, args); } } throw f.unknown(); }
static boolean isEvalFunction(Object functionObj) { if (functionObj instanceof IdFunctionObject) { IdFunctionObject function = (IdFunctionObject) functionObj; if (function.hasTag(FTAG) && function.methodId() == Id_eval) { return true; } } return false; }
public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (f.hasTag(FTAG)) { if (f.methodId() == Id_JavaAdapter) { return js_createAdpter(cx, scope, args); } } throw f.unknown(); }
public final void initPrototypeConstructor(IdFunctionObject f) { int id = prototypeValues.constructorId; if (id == 0) throw new IllegalStateException(); if (f.methodId() != id) throw new IllegalArgumentException(); if (isSealed()) { f.sealObject(); } prototypeValues.initValue(id, "constructor", f, DONTENUM); }
public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (f.hasTag(FTAG)) { if (f.methodId() == Id_constructor) { throw Context.reportRuntimeError1("msg.cant.call.indirect", "With"); } } throw f.unknown(); }
public static void init(Context cx, Scriptable scope, boolean sealed) { JavaAdapter obj = new JavaAdapter(); IdFunctionObject ctor = new IdFunctionObject(obj, FTAG, Id_JavaAdapter, "JavaAdapter", 1, scope); ctor.markAsConstructor(null); if (sealed) { ctor.sealObject(); } ctor.exportAsScopeProperty(); }
static void init(Scriptable scope, boolean sealed) { NativeWith obj = new NativeWith(); obj.setParentScope(scope); obj.setPrototype(ScriptableObject.getObjectPrototype(scope)); IdFunctionObject ctor = new IdFunctionObject(obj, FTAG, Id_constructor, "With", 0, scope); ctor.markAsConstructor(obj); if (sealed) { ctor.sealObject(); } ctor.exportAsScopeProperty(); }
final IdFunctionObject createPrecachedConstructor() { if (constructorId != 0) throw new IllegalStateException(); constructorId = obj.findPrototypeId("constructor"); if (constructorId == 0) { throw new IllegalStateException("No id for constructor property"); } obj.initPrototypeId(constructorId); if (constructor == null) { throw new IllegalStateException( obj.getClass().getName() + ".initPrototypeId() did not " + "initialize id=" + constructorId); } constructor.initFunction(obj.getClassName(), ScriptableObject.getTopLevelScope(obj)); constructor.markAsConstructor(obj); return constructor; }
@Override public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(GENERATOR_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); if (!(thisObj instanceof NativeGenerator)) throw incompatibleCallError(f); NativeGenerator generator = (NativeGenerator) thisObj; switch (id) { case Id_close: // need to run any pending finally clauses return generator.resume(cx, scope, GENERATOR_CLOSE, new GeneratorClosedException()); case Id_next: // arguments to next() are ignored generator.firstTime = false; return generator.resume(cx, scope, GENERATOR_SEND, Undefined.instance); case Id_send: { Object arg = args.length > 0 ? args[0] : Undefined.instance; if (generator.firstTime && !arg.equals(Undefined.instance)) { throw ScriptRuntime.typeError0("msg.send.newborn"); } return generator.resume(cx, scope, GENERATOR_SEND, arg); } case Id_throw: return generator.resume( cx, scope, GENERATOR_THROW, args.length > 0 ? args[0] : Undefined.instance); case Id___iterator__: return thisObj; default: throw new IllegalArgumentException(String.valueOf(id)); } }
public final IdFunctionObject exportAsJSClass( int maxPrototypeId, Scriptable scope, boolean sealed) { // Set scope and prototype unless this is top level scope itself if (scope != this && scope != null) { setParentScope(scope); setPrototype(getObjectPrototype(scope)); } activatePrototypeMap(maxPrototypeId); IdFunctionObject ctor = prototypeValues.createPrecachedConstructor(); if (sealed) { sealObject(); } fillConstructorProperties(ctor); if (sealed) { ctor.sealObject(); } ctor.exportAsScopeProperty(); return ctor; }
public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(SCRIPT_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); switch (id) { case Id_constructor: { String source = (args.length == 0) ? "" : ScriptRuntime.toString(args[0]); Script script = compile(cx, source); NativeScript nscript = new NativeScript(script); ScriptRuntime.setObjectProtoAndParent(nscript, scope); return nscript; } case Id_toString: { NativeScript real = realThis(thisObj, f); Script realScript = real.script; if (realScript == null) { return ""; } return cx.decompileScript(realScript, 0); } case Id_exec: { throw Context.reportRuntimeError1("msg.cant.call.indirect", "exec"); } case Id_compile: { NativeScript real = realThis(thisObj, f); String source = ScriptRuntime.toString(args, 0); real.script = compile(cx, source); return real; } } throw new IllegalArgumentException(String.valueOf(id)); }
public static void init(Context cx, Scriptable scope, boolean sealed) { ClassLoader loader = cx.getApplicationClassLoader(); final NativeJavaTopPackage top = new NativeJavaTopPackage(loader); top.setPrototype(getObjectPrototype(scope)); top.setParentScope(scope); for (int i = 0; i != commonPackages.length; i++) { NativeJavaPackage parent = top; for (int j = 0; j != commonPackages[i].length; j++) { parent = parent.forcePackage(commonPackages[i][j], scope); } } // getClass implementation IdFunctionObject getClass = new IdFunctionObject(top, FTAG, Id_getClass, "getClass", 1, scope); // We want to get a real alias, and not a distinct JavaPackage // with the same packageName, so that we share classes and top // that are underneath. String[] topNames = ScriptRuntime.getTopPackageNames(); NativeJavaPackage[] topPackages = new NativeJavaPackage[topNames.length]; for (int i = 0; i < topNames.length; i++) { topPackages[i] = (NativeJavaPackage) top.get(topNames[i], top); } // It's safe to downcast here since initStandardObjects takes // a ScriptableObject. ScriptableObject global = (ScriptableObject) scope; if (sealed) { getClass.sealObject(); } getClass.exportAsScopeProperty(); global.defineProperty("Packages", top, ScriptableObject.DONTENUM); for (int i = 0; i < topNames.length; i++) { global.defineProperty(topNames[i], topPackages[i], ScriptableObject.DONTENUM); } }
/* 35: */ /* 36: */ protected void fillConstructorProperties(IdFunctionObject ctor) /* 37: */ { /* 38: 78 */ int attr = 7; /* 39: */ /* 40: */ /* 41: */ /* 42: 82 */ ctor.defineProperty("NaN", ScriptRuntime.NaNobj, 7); /* 43: 83 */ ctor.defineProperty( "POSITIVE_INFINITY", ScriptRuntime.wrapNumber((1.0D / 0.0D)), 7); /* 44: */ /* 45: */ /* 46: 86 */ ctor.defineProperty( "NEGATIVE_INFINITY", ScriptRuntime.wrapNumber((-1.0D / 0.0D)), 7); /* 47: */ /* 48: */ /* 49: 89 */ ctor.defineProperty( "MAX_VALUE", ScriptRuntime.wrapNumber(1.7976931348623157E+308D), 7); /* 50: */ /* 51: */ /* 52: 92 */ ctor.defineProperty("MIN_VALUE", ScriptRuntime.wrapNumber(4.9E-324D), 7); /* 53: */ /* 54: */ /* 55: */ /* 56: 96 */ super.fillConstructorProperties(ctor); /* 57: */ }
public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(BOOLEAN_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); if (id == Id_constructor) { boolean b = ScriptRuntime.toBoolean(args, 0); if (thisObj == null) { // new Boolean(val) creates a new boolean object. return new NativeBoolean(b); } // Boolean(val) converts val to a boolean. return ScriptRuntime.wrapBoolean(b); } // The rest of Boolean.prototype methods require thisObj to be Boolean if (!(thisObj instanceof NativeBoolean)) { throw incompatibleCallError(f); } boolean value = ((NativeBoolean) thisObj).booleanValue; switch (id) { case Id_toString: return value ? "true" : "false"; case Id_toSource: return value ? "(new Boolean(true))" : "(new Boolean(false))"; case Id_valueOf: return ScriptRuntime.wrapBoolean(value); } throw new IllegalArgumentException(String.valueOf(id)); }
protected void addIdFunctionProperty(Scriptable obj, Object tag, int id, String name, int arity) { Scriptable scope = ScriptableObject.getTopLevelScope(obj); IdFunctionObject f = newIdFunction(tag, id, name, arity, scope); f.addAsProperty(obj); }
/* 86: */ /* 87: */ public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) /* 88: */ { /* 89:122 */ if (!f.hasTag(NUMBER_TAG)) { /* 90:123 */ return super.execIdCall(f, cx, scope, thisObj, args); /* 91: */ } /* 92:125 */ int id = f.methodId(); /* 93:126 */ if (id == 1) /* 94: */ { /* 95:127 */ double val = args.length >= 1 ? ScriptRuntime.toNumber(args[0]) : 0.0D; /* 96:129 */ if (thisObj == null) { /* 97:131 */ return new NativeNumber(val); /* 98: */ } /* 99:134 */ return ScriptRuntime.wrapNumber(val); /* 100: */ } /* 101:139 */ if (!(thisObj instanceof NativeNumber)) { /* 102:140 */ throw incompatibleCallError(f); /* 103: */ } /* 104:141 */ double value = ((NativeNumber) thisObj).doubleValue; /* 105:143 */ switch (id) /* 106: */ { /* 107: */ case 2: /* 108: */ case 3: /* 109:149 */ int base = args.length == 0 ? 10 : ScriptRuntime.toInt32(args[0]); /* 110: */ /* 111:151 */ return ScriptRuntime.numberToString(value, base); /* 112: */ case 4: /* 113:155 */ return "(new Number(" + ScriptRuntime.toString(value) + "))"; /* 114: */ case 5: /* 115:158 */ return ScriptRuntime.wrapNumber(value); /* 116: */ case 6: /* 117:161 */ return num_to(value, args, 2, 2, -20, 0); /* 118: */ case 7: /* 119:166 */ if (Double.isNaN(value)) { /* 120:167 */ return "NaN"; /* 121: */ } /* 122:169 */ if (Double.isInfinite(value)) /* 123: */ { /* 124:170 */ if (value >= 0.0D) { /* 125:171 */ return "Infinity"; /* 126: */ } /* 127:174 */ return "-Infinity"; /* 128: */ } /* 129:178 */ return num_to(value, args, 1, 3, 0, 1); /* 130: */ case 8: /* 131:184 */ if ((args.length == 0) || (args[0] == Undefined.instance)) { /* 132:185 */ return ScriptRuntime.numberToString(value, 10); /* 133: */ } /* 134:188 */ if (Double.isNaN(value)) { /* 135:189 */ return "NaN"; /* 136: */ } /* 137:191 */ if (Double.isInfinite(value)) /* 138: */ { /* 139:192 */ if (value >= 0.0D) { /* 140:193 */ return "Infinity"; /* 141: */ } /* 142:196 */ return "-Infinity"; /* 143: */ } /* 144:199 */ return num_to(value, args, 0, 4, 1, 0); /* 145: */ } /* 146:203 */ throw new IllegalArgumentException(String.valueOf(id)); /* 147: */ }
/** * 'thisObj' will be null if invoked as constructor, in which case * instance of Scriptable should * be returned. */ public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { throw f.unknown(); }
public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(MATH_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } double x; int methodId = f.methodId(); switch (methodId) { case Id_toSource: return "Math"; case Id_abs: x = ScriptRuntime.toNumber(args, 0); // abs(-0.0) should be 0.0, but -0.0 < 0.0 == false x = (x == 0.0) ? 0.0 : (x < 0.0) ? -x : x; break; case Id_acos: case Id_asin: x = ScriptRuntime.toNumber(args, 0); if (x == x && -1.0 <= x && x <= 1.0) { x = (methodId == Id_acos) ? Math.acos(x) : Math.asin(x); } else { x = Double.NaN; } break; case Id_atan: x = ScriptRuntime.toNumber(args, 0); x = Math.atan(x); break; case Id_atan2: x = ScriptRuntime.toNumber(args, 0); x = Math.atan2(x, ScriptRuntime.toNumber(args, 1)); break; case Id_ceil: x = ScriptRuntime.toNumber(args, 0); x = Math.ceil(x); break; case Id_cos: x = ScriptRuntime.toNumber(args, 0); x = (x == Double.POSITIVE_INFINITY || x == Double.NEGATIVE_INFINITY) ? Double.NaN : Math.cos(x); break; case Id_exp: x = ScriptRuntime.toNumber(args, 0); x = (x == Double.POSITIVE_INFINITY) ? x : (x == Double.NEGATIVE_INFINITY) ? 0.0 : Math.exp(x); break; case Id_floor: x = ScriptRuntime.toNumber(args, 0); x = Math.floor(x); break; case Id_log: x = ScriptRuntime.toNumber(args, 0); // Java's log(<0) = -Infinity; we need NaN x = (x < 0) ? Double.NaN : Math.log(x); break; case Id_max: case Id_min: x = (methodId == Id_max) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; for (int i = 0; i != args.length; ++i) { double d = ScriptRuntime.toNumber(args[i]); if (d != d) { x = d; // NaN break; } if (methodId == Id_max) { // if (x < d) x = d; does not work due to -0.0 >= +0.0 x = Math.max(x, d); } else { x = Math.min(x, d); } } break; case Id_pow: x = ScriptRuntime.toNumber(args, 0); x = js_pow(x, ScriptRuntime.toNumber(args, 1)); break; case Id_random: x = Math.random(); break; case Id_round: x = ScriptRuntime.toNumber(args, 0); if (x == x && x != Double.POSITIVE_INFINITY && x != Double.NEGATIVE_INFINITY) { // Round only finite x long l = Math.round(x); if (l != 0) { x = l; } else { // We must propagate the sign of d into the result if (x < 0.0) { x = ScriptRuntime.negativeZero; } else if (x != 0.0) { x = 0.0; } } } break; case Id_sin: x = ScriptRuntime.toNumber(args, 0); x = (x == Double.POSITIVE_INFINITY || x == Double.NEGATIVE_INFINITY) ? Double.NaN : Math.sin(x); break; case Id_sqrt: x = ScriptRuntime.toNumber(args, 0); x = Math.sqrt(x); break; case Id_tan: x = ScriptRuntime.toNumber(args, 0); x = Math.tan(x); break; default: throw new IllegalStateException(String.valueOf(methodId)); } return ScriptRuntime.wrapNumber(x); }
public static void init(Context cx, Scriptable scope, boolean sealed) { NativeGlobal obj = new NativeGlobal(); for (int id = 1; id <= LAST_SCOPE_FUNCTION_ID; ++id) { String name; int arity = 1; switch (id) { case Id_decodeURI: name = "decodeURI"; break; case Id_decodeURIComponent: name = "decodeURIComponent"; break; case Id_encodeURI: name = "encodeURI"; break; case Id_encodeURIComponent: name = "encodeURIComponent"; break; case Id_escape: name = "escape"; break; case Id_eval: name = "eval"; break; case Id_isFinite: name = "isFinite"; break; case Id_isNaN: name = "isNaN"; break; case Id_isXMLName: name = "isXMLName"; break; case Id_parseFloat: name = "parseFloat"; break; case Id_parseInt: name = "parseInt"; arity = 2; break; case Id_unescape: name = "unescape"; break; case Id_uneval: name = "uneval"; break; default: throw Kit.codeBug(); } IdFunctionObject f = new IdFunctionObject(obj, FTAG, id, name, arity, scope); if (sealed) { f.sealObject(); } f.exportAsScopeProperty(); } ScriptableObject.defineProperty(scope, "NaN", ScriptRuntime.NaNobj, ScriptableObject.DONTENUM); ScriptableObject.defineProperty( scope, "Infinity", ScriptRuntime.wrapNumber(Double.POSITIVE_INFINITY), ScriptableObject.DONTENUM); ScriptableObject.defineProperty( scope, "undefined", Undefined.instance, ScriptableObject.DONTENUM); String[] errorMethods = Kit.semicolonSplit( "" + "ConversionError;" + "EvalError;" + "RangeError;" + "ReferenceError;" + "SyntaxError;" + "TypeError;" + "URIError;" + "InternalError;" + "JavaException;"); /* Each error constructor gets its own Error object as a prototype, with the 'name' property set to the name of the error. */ for (int i = 0; i < errorMethods.length; i++) { String name = errorMethods[i]; Scriptable errorProto = ScriptRuntime.newObject(cx, scope, "Error", ScriptRuntime.emptyArgs); errorProto.put("name", errorProto, name); if (sealed) { if (errorProto instanceof ScriptableObject) { ((ScriptableObject) errorProto).sealObject(); } } IdFunctionObject ctor = new IdFunctionObject(obj, FTAG, Id_new_CommonError, name, 1, scope); ctor.markAsConstructor(errorProto); if (sealed) { ctor.sealObject(); } ctor.exportAsScopeProperty(); } }
public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(MATH_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } double x; int methodId = f.getMethodId(); switch (methodId) { case Id_toSource: return "Math"; case Id_abs: x = ScriptRuntime.toNumber(args, 0); // abs(-0.0) should be 0.0, but -0.0 < 0.0 == false x = (x == 0.0) ? 0.0 : (x < 0.0) ? -x : x; break; case Id_ceil: x = ScriptRuntime.toNumber(args, 0); x = Math.ceil(x); break; case Id_floor: x = ScriptRuntime.toNumber(args, 0); x = Math.floor(x); break; case Id_max: case Id_min: x = (methodId == Id_max) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; for (int i = 0; i != args.length; ++i) { double d = ScriptRuntime.toNumber(args[i]); if (d != d) { x = d; // NaN break; } if (methodId == Id_max) { // if (x < d) x = d; does not work due to -0.0 >= +0.0 x = Math.max(x, d); } else { x = Math.min(x, d); } } break; case Id_random: Random generator = new Random(System.currentTimeMillis()); x = generator.nextDouble(); break; case Id_round: x = ScriptRuntime.toNumber(args, 0); if (x == x && x != Double.POSITIVE_INFINITY && x != Double.NEGATIVE_INFINITY) { // Round only finite x long l = (long) (int) ((x + 0.5) * 100.0) / 100; if (l != 0) { x = l; } else { // We must propagate the sign of d into the result if (x < 0.0) { x = ScriptRuntime.negativeZero; } else if (x != 0.0) { x = 0.0; } } } break; default: throw new IllegalStateException(String.valueOf(methodId)); } return ScriptRuntime.wrapNumber(x); }
/** * Utility method to construct type error to indicate incompatible call when converting script * thisObj to a particular type is not possible. Possible usage would be to have a private * function like realThis: * * <pre> * private static NativeSomething realThis(Scriptable thisObj, * IdFunctionObject f) * { * if (!(thisObj instanceof NativeSomething)) * throw incompatibleCallError(f); * return (NativeSomething)thisObj; * } * </pre> * * Note that although such function can be implemented universally via * java.lang.Class.isInstance(), it would be much more slower. * * @param f function that is attempting to convert 'this' object. * @return Scriptable object suitable for a check by the instanceof operator. * @throws RuntimeException if no more instanceof target can be found */ protected static EcmaError incompatibleCallError(IdFunctionObject f) { throw ScriptRuntime.typeError1("msg.incompat.call", f.getFunctionName()); }
public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (f.hasTag(FTAG)) { int methodId = f.methodId(); switch (methodId) { case Id_decodeURI: case Id_decodeURIComponent: { String str = ScriptRuntime.toString(args, 0); return decode(str, methodId == Id_decodeURI); } case Id_encodeURI: case Id_encodeURIComponent: { String str = ScriptRuntime.toString(args, 0); return encode(str, methodId == Id_encodeURI); } case Id_escape: return js_escape(args); case Id_eval: return js_eval(cx, scope, args); case Id_isFinite: { boolean result; if (args.length < 1) { result = false; } else { double d = ScriptRuntime.toNumber(args[0]); result = (d == d && d != Double.POSITIVE_INFINITY && d != Double.NEGATIVE_INFINITY); } return ScriptRuntime.wrapBoolean(result); } case Id_isNaN: { // The global method isNaN, as per ECMA-262 15.1.2.6. boolean result; if (args.length < 1) { result = true; } else { double d = ScriptRuntime.toNumber(args[0]); result = (d != d); } return ScriptRuntime.wrapBoolean(result); } case Id_isXMLName: { Object name = (args.length == 0) ? Undefined.instance : args[0]; XMLLib xmlLib = XMLLib.extractFromScope(scope); return ScriptRuntime.wrapBoolean(xmlLib.isXMLName(cx, name)); } case Id_parseFloat: return js_parseFloat(args); case Id_parseInt: return js_parseInt(args); case Id_unescape: return js_unescape(args); case Id_uneval: { Object value = (args.length != 0) ? args[0] : Undefined.instance; return ScriptRuntime.uneval(cx, scope, value); } case Id_new_CommonError: // The implementation of all the ECMA error constructors // (SyntaxError, TypeError, etc.) return NativeError.make(cx, scope, f, args); } } throw f.unknown(); }
@Override public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(OBJECT_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); switch (id) { case Id_constructor: { if (thisObj != null) { // BaseFunction.construct will set up parent, proto return f.construct(cx, scope, args); } if (args.length == 0 || args[0] == null || args[0] == Undefined.instance) { return new NativeObject(); } return ScriptRuntime.toObject(cx, scope, args[0]); } case Id_toLocaleString: { Object toString = ScriptableObject.getProperty(thisObj, "toString"); if (!(toString instanceof Callable)) { throw ScriptRuntime.notFunctionError(toString); } Callable fun = (Callable) toString; return fun.call(cx, scope, thisObj, ScriptRuntime.emptyArgs); } case Id_toString: { if (cx.hasFeature(Context.FEATURE_TO_STRING_AS_SOURCE)) { String s = ScriptRuntime.defaultObjectToSource( cx, scope, thisObj, args); int L = s.length(); if (L != 0 && s.charAt(0) == '(' && s.charAt(L - 1) == ')') { // Strip () that surrounds toSource s = s.substring(1, L - 1); } return s; } return ScriptRuntime.defaultObjectToString(thisObj); } case Id_valueOf: return thisObj; case Id_hasOwnProperty: { boolean result; Object arg = args.length < 1 ? Undefined.instance : args[0]; String s = ScriptRuntime.toStringIdOrIndex(cx, arg); if (s == null) { int index = ScriptRuntime.lastIndexResult(cx); result = thisObj.has(index, thisObj); } else { result = thisObj.has(s, thisObj); } return ScriptRuntime.wrapBoolean(result); } case Id_propertyIsEnumerable: { boolean result; Object arg = args.length < 1 ? Undefined.instance : args[0]; String s = ScriptRuntime.toStringIdOrIndex(cx, arg); if (s == null) { int index = ScriptRuntime.lastIndexResult(cx); result = thisObj.has(index, thisObj); if (result && thisObj instanceof ScriptableObject) { ScriptableObject so = (ScriptableObject) thisObj; int attrs = so.getAttributes(index); result = ((attrs & ScriptableObject.DONTENUM) == 0); } } else { result = thisObj.has(s, thisObj); if (result && thisObj instanceof ScriptableObject) { ScriptableObject so = (ScriptableObject) thisObj; int attrs = so.getAttributes(s); result = ((attrs & ScriptableObject.DONTENUM) == 0); } } return ScriptRuntime.wrapBoolean(result); } case Id_isPrototypeOf: { boolean result = false; if (args.length != 0 && args[0] instanceof Scriptable) { Scriptable v = (Scriptable) args[0]; do { v = v.getPrototype(); if (v == thisObj) { result = true; break; } } while (v != null); } return ScriptRuntime.wrapBoolean(result); } case Id_toSource: return ScriptRuntime.defaultObjectToSource(cx, scope, thisObj, args); case Id___defineGetter__: case Id___defineSetter__: { if (args.length < 2 || !(args[1] instanceof Callable)) { Object badArg = (args.length >= 2 ? args[1] : Undefined.instance); throw ScriptRuntime.notFunctionError(badArg); } if (!(thisObj instanceof ScriptableObject)) { throw Context.reportRuntimeError2( "msg.extend.scriptable", thisObj.getClass().getName(), String.valueOf(args[0])); } ScriptableObject so = (ScriptableObject) thisObj; String name = ScriptRuntime.toStringIdOrIndex(cx, args[0]); int index = (name != null ? 0 : ScriptRuntime.lastIndexResult(cx)); Callable getterOrSetter = (Callable) args[1]; boolean isSetter = (id == Id___defineSetter__); so.setGetterOrSetter(name, index, getterOrSetter, isSetter); if (so instanceof NativeArray) ((NativeArray) so).setDenseOnly(false); } return Undefined.instance; case Id___lookupGetter__: case Id___lookupSetter__: { if (args.length < 1 || !(thisObj instanceof ScriptableObject)) return Undefined.instance; ScriptableObject so = (ScriptableObject) thisObj; String name = ScriptRuntime.toStringIdOrIndex(cx, args[0]); int index = (name != null ? 0 : ScriptRuntime.lastIndexResult(cx)); boolean isSetter = (id == Id___lookupSetter__); Object gs; for (; ; ) { gs = so.getGetterOrSetter(name, index, isSetter); if (gs != null) break; // If there is no getter or setter for the object itself, // how about the prototype? Scriptable v = so.getPrototype(); if (v == null) break; if (v instanceof ScriptableObject) so = (ScriptableObject) v; else break; } if (gs != null) return gs; } return Undefined.instance; case ConstructorId_getPrototypeOf: { Object arg = args.length < 1 ? Undefined.instance : args[0]; Scriptable obj = ensureScriptable(arg); return obj.getPrototype(); } case ConstructorId_keys: { Object arg = args.length < 1 ? Undefined.instance : args[0]; Scriptable obj = ensureScriptable(arg); Object[] ids = obj.getIds(); for (int i = 0; i < ids.length; i++) { ids[i] = ScriptRuntime.toString(ids[i]); } return cx.newArray(scope, ids); } case ConstructorId_getOwnPropertyNames: { Object arg = args.length < 1 ? Undefined.instance : args[0]; ScriptableObject obj = ensureScriptableObject(arg); Object[] ids = obj.getAllIds(); for (int i = 0; i < ids.length; i++) { ids[i] = ScriptRuntime.toString(ids[i]); } return cx.newArray(scope, ids); } case ConstructorId_getOwnPropertyDescriptor: { Object arg = args.length < 1 ? Undefined.instance : args[0]; // TODO(norris): There's a deeper issue here if // arg instanceof Scriptable. Should we create a new // interface to admit the new ECMAScript 5 operations? ScriptableObject obj = ensureScriptableObject(arg); Object nameArg = args.length < 2 ? Undefined.instance : args[1]; String name = ScriptRuntime.toString(nameArg); Scriptable desc = obj.getOwnPropertyDescriptor(cx, name); return desc == null ? Undefined.instance : desc; } case ConstructorId_defineProperty: { Object arg = args.length < 1 ? Undefined.instance : args[0]; ScriptableObject obj = ensureScriptableObject(arg); Object name = args.length < 2 ? Undefined.instance : args[1]; Object descArg = args.length < 3 ? Undefined.instance : args[2]; ScriptableObject desc = ensureScriptableObject(descArg); obj.defineOwnProperty(cx, name, desc); return obj; } case ConstructorId_isExtensible: { Object arg = args.length < 1 ? Undefined.instance : args[0]; ScriptableObject obj = ensureScriptableObject(arg); return Boolean.valueOf(obj.isExtensible()); } case ConstructorId_preventExtensions: { Object arg = args.length < 1 ? Undefined.instance : args[0]; ScriptableObject obj = ensureScriptableObject(arg); obj.preventExtensions(); return obj; } case ConstructorId_defineProperties: { Object arg = args.length < 1 ? Undefined.instance : args[0]; ScriptableObject obj = ensureScriptableObject(arg); Object propsObj = args.length < 2 ? Undefined.instance : args[1]; Scriptable props = Context.toObject(propsObj, getParentScope()); obj.defineOwnProperties(cx, ensureScriptableObject(props)); return obj; } case ConstructorId_create: { Object arg = args.length < 1 ? Undefined.instance : args[0]; Scriptable obj = (arg == null) ? null : ensureScriptable(arg); ScriptableObject newObject = new NativeObject(); newObject.setParentScope(getParentScope()); newObject.setPrototype(obj); if (args.length > 1 && args[1] != Undefined.instance) { Scriptable props = Context.toObject(args[1], getParentScope()); newObject.defineOwnProperties(cx, ensureScriptableObject(props)); } return newObject; } case ConstructorId_isSealed: { Object arg = args.length < 1 ? Undefined.instance : args[0]; ScriptableObject obj = ensureScriptableObject(arg); if (obj.isExtensible()) return Boolean.FALSE; for (Object name : obj.getAllIds()) { Object configurable = obj.getOwnPropertyDescriptor(cx, name).get("configurable"); if (Boolean.TRUE.equals(configurable)) return Boolean.FALSE; } return Boolean.TRUE; } case ConstructorId_isFrozen: { Object arg = args.length < 1 ? Undefined.instance : args[0]; ScriptableObject obj = ensureScriptableObject(arg); if (obj.isExtensible()) return Boolean.FALSE; for (Object name : obj.getAllIds()) { ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name); if (Boolean.TRUE.equals(desc.get("configurable"))) return Boolean.FALSE; if (isDataDescriptor(desc) && Boolean.TRUE.equals(desc.get("writable"))) return Boolean.FALSE; } return Boolean.TRUE; } case ConstructorId_seal: { Object arg = args.length < 1 ? Undefined.instance : args[0]; ScriptableObject obj = ensureScriptableObject(arg); for (Object name : obj.getAllIds()) { ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name); if (Boolean.TRUE.equals(desc.get("configurable"))) { desc.put("configurable", desc, Boolean.FALSE); obj.defineOwnProperty(cx, name, desc, false); } } obj.preventExtensions(); return obj; } case ConstructorId_freeze: { Object arg = args.length < 1 ? Undefined.instance : args[0]; ScriptableObject obj = ensureScriptableObject(arg); for (Object name : obj.getAllIds()) { ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name); if (isDataDescriptor(desc) && Boolean.TRUE.equals(desc.get("writable"))) desc.put("writable", desc, Boolean.FALSE); if (Boolean.TRUE.equals(desc.get("configurable"))) desc.put("configurable", desc, Boolean.FALSE); obj.defineOwnProperty(cx, name, desc, false); } obj.preventExtensions(); return obj; } default: throw new IllegalArgumentException(String.valueOf(id)); } }
@Override public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(STRING_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); again: for (; ; ) { switch (id) { case ConstructorId_charAt: case ConstructorId_charCodeAt: case ConstructorId_indexOf: case ConstructorId_lastIndexOf: case ConstructorId_split: case ConstructorId_substring: case ConstructorId_toLowerCase: case ConstructorId_toUpperCase: case ConstructorId_substr: case ConstructorId_concat: case ConstructorId_slice: case ConstructorId_equalsIgnoreCase: case ConstructorId_match: case ConstructorId_search: case ConstructorId_replace: case ConstructorId_localeCompare: case ConstructorId_toLocaleLowerCase: { if (args.length > 0) { thisObj = ScriptRuntime.toObject(scope, ScriptRuntime.toString(args[0])); Object[] newArgs = new Object[args.length - 1]; for (int i = 0; i < newArgs.length; i++) newArgs[i] = args[i + 1]; args = newArgs; } else { thisObj = ScriptRuntime.toObject(scope, ScriptRuntime.toString(thisObj)); } id = -id; continue again; } case ConstructorId_fromCharCode: { int N = args.length; if (N < 1) return ""; StringBuffer sb = new StringBuffer(N); for (int i = 0; i != N; ++i) { sb.append(ScriptRuntime.toUint16(args[i])); } return sb.toString(); } case Id_constructor: { String s = (args.length >= 1) ? ScriptRuntime.toString(args[0]) : ""; if (thisObj == null) { // new String(val) creates a new String object. return new NativeString(s); } // String(val) converts val to a string value. return s; } case Id_toString: case Id_valueOf: // ECMA 15.5.4.2: 'the toString function is not generic. return realThis(thisObj, f).string; case Id_toSource: { String s = realThis(thisObj, f).string; return "(new String(\"" + ScriptRuntime.escapeString(s) + "\"))"; } case Id_charAt: case Id_charCodeAt: { // See ECMA 15.5.4.[4,5] String target = ScriptRuntime.toString(thisObj); double pos = ScriptRuntime.toInteger(args, 0); if (pos < 0 || pos >= target.length()) { if (id == Id_charAt) return ""; else return ScriptRuntime.NaNobj; } char c = target.charAt((int) pos); if (id == Id_charAt) return String.valueOf(c); else return ScriptRuntime.wrapInt(c); } case Id_indexOf: return ScriptRuntime.wrapInt(js_indexOf(ScriptRuntime.toString(thisObj), args)); case Id_lastIndexOf: return ScriptRuntime.wrapInt(js_lastIndexOf(ScriptRuntime.toString(thisObj), args)); case Id_split: return ScriptRuntime.checkRegExpProxy(cx) .js_split(cx, scope, ScriptRuntime.toString(thisObj), args); case Id_substring: return js_substring(cx, ScriptRuntime.toString(thisObj), args); case Id_toLowerCase: // See ECMA 15.5.4.11 return ScriptRuntime.toString(thisObj).toLowerCase(ScriptRuntime.ROOT_LOCALE); case Id_toUpperCase: // See ECMA 15.5.4.12 return ScriptRuntime.toString(thisObj).toUpperCase(ScriptRuntime.ROOT_LOCALE); case Id_substr: return js_substr(ScriptRuntime.toString(thisObj), args); case Id_concat: return js_concat(ScriptRuntime.toString(thisObj), args); case Id_slice: return js_slice(ScriptRuntime.toString(thisObj), args); case Id_bold: return tagify(thisObj, "b", null, null); case Id_italics: return tagify(thisObj, "i", null, null); case Id_fixed: return tagify(thisObj, "tt", null, null); case Id_strike: return tagify(thisObj, "strike", null, null); case Id_small: return tagify(thisObj, "small", null, null); case Id_big: return tagify(thisObj, "big", null, null); case Id_blink: return tagify(thisObj, "blink", null, null); case Id_sup: return tagify(thisObj, "sup", null, null); case Id_sub: return tagify(thisObj, "sub", null, null); case Id_fontsize: return tagify(thisObj, "font", "size", args); case Id_fontcolor: return tagify(thisObj, "font", "color", args); case Id_link: return tagify(thisObj, "a", "href", args); case Id_anchor: return tagify(thisObj, "a", "name", args); case Id_equals: case Id_equalsIgnoreCase: { String s1 = ScriptRuntime.toString(thisObj); String s2 = ScriptRuntime.toString(args, 0); return ScriptRuntime.wrapBoolean( (id == Id_equals) ? s1.equals(s2) : s1.equalsIgnoreCase(s2)); } case Id_match: case Id_search: case Id_replace: { int actionType; if (id == Id_match) { actionType = RegExpProxy.RA_MATCH; } else if (id == Id_search) { actionType = RegExpProxy.RA_SEARCH; } else { actionType = RegExpProxy.RA_REPLACE; } return ScriptRuntime.checkRegExpProxy(cx).action(cx, scope, thisObj, args, actionType); } // ECMA-262 1 5.5.4.9 case Id_localeCompare: { // For now, create and configure a collator instance. I can't // actually imagine that this'd be slower than caching them // a la ClassCache, so we aren't trying to outsmart ourselves // with a caching mechanism for now. Collator collator = Collator.getInstance(cx.getLocale()); collator.setStrength(Collator.IDENTICAL); collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); return ScriptRuntime.wrapNumber( collator.compare(ScriptRuntime.toString(thisObj), ScriptRuntime.toString(args, 0))); } case Id_toLocaleLowerCase: { return ScriptRuntime.toString(thisObj).toLowerCase(cx.getLocale()); } case Id_toLocaleUpperCase: { return ScriptRuntime.toString(thisObj).toUpperCase(cx.getLocale()); } case Id_trim: { String str = ScriptRuntime.toString(thisObj); char[] chars = str.toCharArray(); int start = 0; while (start < chars.length && ScriptRuntime.isJSWhitespaceOrLineTerminator(chars[start])) { start++; } int end = chars.length; while (end > start && ScriptRuntime.isJSWhitespaceOrLineTerminator(chars[end - 1])) { end--; } return str.substring(start, end); } } throw new IllegalArgumentException(String.valueOf(id)); } }
public Object execIdCall( IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(STRING_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); switch (id) { case ConstructorId_fromCharCode: { int N = args.length; if (N < 1) return ""; StringBuffer sb = new StringBuffer(N); for (int i = 0; i != N; ++i) { sb.append(ScriptRuntime.toUint16(args[i])); } return sb.toString(); } case Id_constructor: { String s = (args.length >= 1) ? ScriptRuntime.toString(args[0]) : ""; if (thisObj == null) { // new String(val) creates a new String object. return new NativeString(s); } // String(val) converts val to a string value. return s; } case Id_toString: case Id_valueOf: // ECMA 15.5.4.2: 'the toString function is not generic. return realThis(thisObj, f).string; case Id_toSource: { String s = realThis(thisObj, f).string; return "(new String(\"" + ScriptRuntime.escapeString(s) + "\"))"; } case Id_charAt: case Id_charCodeAt: { // See ECMA 15.5.4.[4,5] String target = ScriptRuntime.toString(thisObj); double pos = ScriptRuntime.toInteger(args, 0); if (pos < 0 || pos >= target.length()) { if (id == Id_charAt) return ""; else return ScriptRuntime.NaNobj; } char c = target.charAt((int) pos); if (id == Id_charAt) return String.valueOf(c); else return ScriptRuntime.wrapInt(c); } case Id_indexOf: return ScriptRuntime.wrapInt(js_indexOf(ScriptRuntime.toString(thisObj), args)); case Id_lastIndexOf: return ScriptRuntime.wrapInt(js_lastIndexOf(ScriptRuntime.toString(thisObj), args)); case Id_split: return js_split(cx, scope, ScriptRuntime.toString(thisObj), args); case Id_substring: return js_substring(cx, ScriptRuntime.toString(thisObj), args); case Id_toLowerCase: // See ECMA 15.5.4.11 return ScriptRuntime.toString(thisObj).toLowerCase(); case Id_toUpperCase: // See ECMA 15.5.4.12 return ScriptRuntime.toString(thisObj).toUpperCase(); case Id_substr: return js_substr(ScriptRuntime.toString(thisObj), args); case Id_concat: return js_concat(ScriptRuntime.toString(thisObj), args); case Id_slice: return js_slice(ScriptRuntime.toString(thisObj), args); case Id_bold: return tagify(thisObj, "b", null, null); case Id_italics: return tagify(thisObj, "i", null, null); case Id_fixed: return tagify(thisObj, "tt", null, null); case Id_strike: return tagify(thisObj, "strike", null, null); case Id_small: return tagify(thisObj, "small", null, null); case Id_big: return tagify(thisObj, "big", null, null); case Id_blink: return tagify(thisObj, "blink", null, null); case Id_sup: return tagify(thisObj, "sup", null, null); case Id_sub: return tagify(thisObj, "sub", null, null); case Id_fontsize: return tagify(thisObj, "font", "size", args); case Id_fontcolor: return tagify(thisObj, "font", "color", args); case Id_link: return tagify(thisObj, "a", "href", args); case Id_anchor: return tagify(thisObj, "a", "name", args); case Id_equals: case Id_equalsIgnoreCase: { String s1 = ScriptRuntime.toString(thisObj); String s2 = ScriptRuntime.toString(args, 0); return ScriptRuntime.wrapBoolean( (id == Id_equals) ? s1.equals(s2) : s1.equalsIgnoreCase(s2)); } case Id_match: case Id_search: case Id_replace: { int actionType; if (id == Id_match) { actionType = RegExpProxy.RA_MATCH; } else if (id == Id_search) { actionType = RegExpProxy.RA_SEARCH; } else { actionType = RegExpProxy.RA_REPLACE; } return ScriptRuntime.checkRegExpProxy(cx).action(cx, scope, thisObj, args, actionType); } } throw new IllegalArgumentException(String.valueOf(id)); }