001: /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002: *
003: * ***** BEGIN LICENSE BLOCK *****
004: * Version: MPL 1.1/GPL 2.0
005: *
006: * The contents of this file are subject to the Mozilla Public License Version
007: * 1.1 (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: * http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the
014: * License.
015: *
016: * The Original Code is Rhino code, released
017: * May 6, 1999.
018: *
019: * The Initial Developer of the Original Code is
020: * Netscape Communications Corporation.
021: * Portions created by the Initial Developer are Copyright (C) 1997-1999
022: * the Initial Developer. All Rights Reserved.
023: *
024: * Contributor(s):
025: * Norris Boyd
026: * Igor Bukanov
027: * Bob Jervis
028: * Mike McCabe
029: *
030: * Alternatively, the contents of this file may be used under the terms of
031: * the GNU General Public License Version 2 or later (the "GPL"), in which
032: * case the provisions of the GPL are applicable instead of those above. If
033: * you wish to allow use of your version of this file only under the terms of
034: * the GPL and not to allow others to use your version of this file under the
035: * MPL, indicate your decision by deleting the provisions above and replacing
036: * them with the notice and other provisions required by the GPL. If you do
037: * not delete the provisions above, a recipient may use your version of this
038: * file under either the MPL or the GPL.
039: *
040: * ***** END LICENSE BLOCK ***** */
041:
042: package org.mozilla.javascript;
043:
044: /**
045: * This class implements the Object native object.
046: * See ECMA 15.2.
047: * @author Norris Boyd
048: */
049: public class NativeObject extends IdScriptableObject {
050: static final long serialVersionUID = -6345305608474346996L;
051:
052: private static final Object OBJECT_TAG = new Object();
053:
054: static void init(Scriptable scope, boolean sealed) {
055: NativeObject obj = new NativeObject();
056: obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed);
057: }
058:
059: public String getClassName() {
060: return "Object";
061: }
062:
063: public String toString() {
064: return ScriptRuntime.defaultObjectToString(this );
065: }
066:
067: protected void initPrototypeId(int id) {
068: String s;
069: int arity;
070: switch (id) {
071: case Id_constructor:
072: arity = 1;
073: s = "constructor";
074: break;
075: case Id_toString:
076: arity = 0;
077: s = "toString";
078: break;
079: case Id_toLocaleString:
080: arity = 0;
081: s = "toLocaleString";
082: break;
083: case Id_valueOf:
084: arity = 0;
085: s = "valueOf";
086: break;
087: case Id_hasOwnProperty:
088: arity = 1;
089: s = "hasOwnProperty";
090: break;
091: case Id_propertyIsEnumerable:
092: arity = 1;
093: s = "propertyIsEnumerable";
094: break;
095: case Id_isPrototypeOf:
096: arity = 1;
097: s = "isPrototypeOf";
098: break;
099: case Id_toSource:
100: arity = 0;
101: s = "toSource";
102: break;
103: case Id___defineGetter__:
104: arity = 2;
105: s = "__defineGetter__";
106: break;
107: case Id___defineSetter__:
108: arity = 2;
109: s = "__defineSetter__";
110: break;
111: case Id___lookupGetter__:
112: arity = 1;
113: s = "__lookupGetter__";
114: break;
115: case Id___lookupSetter__:
116: arity = 1;
117: s = "__lookupSetter__";
118: break;
119: default:
120: throw new IllegalArgumentException(String.valueOf(id));
121: }
122: initPrototypeMethod(OBJECT_TAG, id, s, arity);
123: }
124:
125: public Object execIdCall(IdFunctionObject f, Context cx,
126: Scriptable scope, Scriptable this Obj, Object[] args) {
127: if (!f.hasTag(OBJECT_TAG)) {
128: return super .execIdCall(f, cx, scope, this Obj, args);
129: }
130: int id = f.methodId();
131: switch (id) {
132: case Id_constructor: {
133: if (this Obj != null) {
134: // BaseFunction.construct will set up parent, proto
135: return f.construct(cx, scope, args);
136: }
137: if (args.length == 0 || args[0] == null
138: || args[0] == Undefined.instance) {
139: return new NativeObject();
140: }
141: return ScriptRuntime.toObject(cx, scope, args[0]);
142: }
143:
144: case Id_toLocaleString: // For now just alias toString
145: case Id_toString: {
146: if (cx.hasFeature(Context.FEATURE_TO_STRING_AS_SOURCE)) {
147: String s = ScriptRuntime.defaultObjectToSource(cx,
148: scope, this Obj, args);
149: int L = s.length();
150: if (L != 0 && s.charAt(0) == '('
151: && s.charAt(L - 1) == ')') {
152: // Strip () that surrounds toSource
153: s = s.substring(1, L - 1);
154: }
155: return s;
156: }
157: return ScriptRuntime.defaultObjectToString(this Obj);
158: }
159:
160: case Id_valueOf:
161: return this Obj;
162:
163: case Id_hasOwnProperty: {
164: boolean result;
165: if (args.length == 0) {
166: result = false;
167: } else {
168: String s = ScriptRuntime.toStringIdOrIndex(cx, args[0]);
169: if (s == null) {
170: int index = ScriptRuntime.lastIndexResult(cx);
171: result = this Obj.has(index, this Obj);
172: } else {
173: result = this Obj.has(s, this Obj);
174: }
175: }
176: return ScriptRuntime.wrapBoolean(result);
177: }
178:
179: case Id_propertyIsEnumerable: {
180: boolean result;
181: if (args.length == 0) {
182: result = false;
183: } else {
184: String s = ScriptRuntime.toStringIdOrIndex(cx, args[0]);
185: if (s == null) {
186: int index = ScriptRuntime.lastIndexResult(cx);
187: result = this Obj.has(index, this Obj);
188: if (result && this Obj instanceof ScriptableObject) {
189: ScriptableObject so = (ScriptableObject) this Obj;
190: int attrs = so.getAttributes(index);
191: result = ((attrs & ScriptableObject.DONTENUM) == 0);
192: }
193: } else {
194: result = this Obj.has(s, this Obj);
195: if (result && this Obj instanceof ScriptableObject) {
196: ScriptableObject so = (ScriptableObject) this Obj;
197: int attrs = so.getAttributes(s);
198: result = ((attrs & ScriptableObject.DONTENUM) == 0);
199: }
200: }
201: }
202: return ScriptRuntime.wrapBoolean(result);
203: }
204:
205: case Id_isPrototypeOf: {
206: boolean result = false;
207: if (args.length != 0 && args[0] instanceof Scriptable) {
208: Scriptable v = (Scriptable) args[0];
209: do {
210: v = v.getPrototype();
211: if (v == this Obj) {
212: result = true;
213: break;
214: }
215: } while (v != null);
216: }
217: return ScriptRuntime.wrapBoolean(result);
218: }
219:
220: case Id_toSource:
221: return ScriptRuntime.defaultObjectToSource(cx, scope,
222: this Obj, args);
223: case Id___defineGetter__:
224: case Id___defineSetter__: {
225: if (args.length < 2 || !(args[1] instanceof Callable)) {
226: Object badArg = (args.length >= 2 ? args[1]
227: : Undefined.instance);
228: throw ScriptRuntime.notFunctionError(badArg);
229: }
230: if (!(this Obj instanceof ScriptableObject)) {
231: throw Context.reportRuntimeError2(
232: "msg.extend.scriptable", this Obj.getClass()
233: .getName(), String.valueOf(args[0]));
234: }
235: ScriptableObject so = (ScriptableObject) this Obj;
236: String name = ScriptRuntime.toStringIdOrIndex(cx, args[0]);
237: int index = (name != null ? 0 : ScriptRuntime
238: .lastIndexResult(cx));
239: Callable getterOrSetter = (Callable) args[1];
240: boolean isSetter = (id == Id___defineSetter__);
241: so.setGetterOrSetter(name, index, getterOrSetter, isSetter);
242: if (so instanceof NativeArray)
243: ((NativeArray) so).setDenseOnly(false);
244: }
245: return Undefined.instance;
246:
247: case Id___lookupGetter__:
248: case Id___lookupSetter__: {
249: if (args.length < 1
250: || !(this Obj instanceof ScriptableObject))
251: return Undefined.instance;
252:
253: ScriptableObject so = (ScriptableObject) this Obj;
254: String name = ScriptRuntime.toStringIdOrIndex(cx, args[0]);
255: int index = (name != null ? 0 : ScriptRuntime
256: .lastIndexResult(cx));
257: boolean isSetter = (id == Id___lookupSetter__);
258: Object gs;
259: for (;;) {
260: gs = so.getGetterOrSetter(name, index, isSetter);
261: if (gs != null)
262: break;
263: // If there is no getter or setter for the object itself,
264: // how about the prototype?
265: Scriptable v = so.getPrototype();
266: if (v == null)
267: break;
268: if (v instanceof ScriptableObject)
269: so = (ScriptableObject) v;
270: else
271: break;
272: }
273: if (gs != null)
274: return gs;
275: }
276: return Undefined.instance;
277:
278: default:
279: throw new IllegalArgumentException(String.valueOf(id));
280: }
281: }
282:
283: // #string_id_map#
284:
285: protected int findPrototypeId(String s) {
286: int id;
287: // #generated# Last update: 2007-05-09 08:15:55 EDT
288: L0: {
289: id = 0;
290: String X = null;
291: int c;
292: L: switch (s.length()) {
293: case 7:
294: X = "valueOf";
295: id = Id_valueOf;
296: break L;
297: case 8:
298: c = s.charAt(3);
299: if (c == 'o') {
300: X = "toSource";
301: id = Id_toSource;
302: } else if (c == 't') {
303: X = "toString";
304: id = Id_toString;
305: }
306: break L;
307: case 11:
308: X = "constructor";
309: id = Id_constructor;
310: break L;
311: case 13:
312: X = "isPrototypeOf";
313: id = Id_isPrototypeOf;
314: break L;
315: case 14:
316: c = s.charAt(0);
317: if (c == 'h') {
318: X = "hasOwnProperty";
319: id = Id_hasOwnProperty;
320: } else if (c == 't') {
321: X = "toLocaleString";
322: id = Id_toLocaleString;
323: }
324: break L;
325: case 16:
326: c = s.charAt(2);
327: if (c == 'd') {
328: c = s.charAt(8);
329: if (c == 'G') {
330: X = "__defineGetter__";
331: id = Id___defineGetter__;
332: } else if (c == 'S') {
333: X = "__defineSetter__";
334: id = Id___defineSetter__;
335: }
336: } else if (c == 'l') {
337: c = s.charAt(8);
338: if (c == 'G') {
339: X = "__lookupGetter__";
340: id = Id___lookupGetter__;
341: } else if (c == 'S') {
342: X = "__lookupSetter__";
343: id = Id___lookupSetter__;
344: }
345: }
346: break L;
347: case 20:
348: X = "propertyIsEnumerable";
349: id = Id_propertyIsEnumerable;
350: break L;
351: }
352: if (X != null && X != s && !X.equals(s))
353: id = 0;
354: break L0;
355: }
356: // #/generated#
357: return id;
358: }
359:
360: private static final int Id_constructor = 1, Id_toString = 2,
361: Id_toLocaleString = 3, Id_valueOf = 4,
362: Id_hasOwnProperty = 5, Id_propertyIsEnumerable = 6,
363: Id_isPrototypeOf = 7, Id_toSource = 8,
364: Id___defineGetter__ = 9, Id___defineSetter__ = 10,
365: Id___lookupGetter__ = 11, Id___lookupSetter__ = 12,
366: MAX_PROTOTYPE_ID = 12;
367:
368: // #/string_id_map#
369: }
|