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: *
028: * Alternatively, the contents of this file may be used under the terms of
029: * the GNU General Public License Version 2 or later (the "GPL"), in which
030: * case the provisions of the GPL are applicable instead of those above. If
031: * you wish to allow use of your version of this file only under the terms of
032: * the GPL and not to allow others to use your version of this file under the
033: * MPL, indicate your decision by deleting the provisions above and replacing
034: * them with the notice and other provisions required by the GPL. If you do
035: * not delete the provisions above, a recipient may use your version of this
036: * file under either the MPL or the GPL.
037: *
038: * ***** END LICENSE BLOCK ***** */
039:
040: package org.mozilla.javascript;
041:
042: import java.io.Serializable;
043:
044: /**
045: * This class implements the object lookup required for the
046: * <code>with</code> statement.
047: * It simply delegates every action to its prototype except
048: * for operations on its parent.
049: */
050: public class NativeWith implements Scriptable, IdFunctionCall,
051: Serializable {
052:
053: private static final long serialVersionUID = 1L;
054:
055: static void init(Scriptable scope, boolean sealed) {
056: NativeWith obj = new NativeWith();
057:
058: obj.setParentScope(scope);
059: obj.setPrototype(ScriptableObject.getObjectPrototype(scope));
060:
061: IdFunctionObject ctor = new IdFunctionObject(obj, FTAG,
062: Id_constructor, "With", 0, scope);
063: ctor.markAsConstructor(obj);
064: if (sealed) {
065: ctor.sealObject();
066: }
067: ctor.exportAsScopeProperty();
068: }
069:
070: private NativeWith() {
071: }
072:
073: protected NativeWith(Scriptable parent, Scriptable prototype) {
074: this .parent = parent;
075: this .prototype = prototype;
076: }
077:
078: public String getClassName() {
079: return "With";
080: }
081:
082: public boolean has(String id, Scriptable start) {
083: return prototype.has(id, prototype);
084: }
085:
086: public boolean has(int index, Scriptable start) {
087: return prototype.has(index, prototype);
088: }
089:
090: public Object get(String id, Scriptable start) {
091: if (start == this )
092: start = prototype;
093: return prototype.get(id, start);
094: }
095:
096: public Object get(int index, Scriptable start) {
097: if (start == this )
098: start = prototype;
099: return prototype.get(index, start);
100: }
101:
102: public void put(String id, Scriptable start, Object value) {
103: if (start == this )
104: start = prototype;
105: prototype.put(id, start, value);
106: }
107:
108: public void put(int index, Scriptable start, Object value) {
109: if (start == this )
110: start = prototype;
111: prototype.put(index, start, value);
112: }
113:
114: public void delete(String id) {
115: prototype.delete(id);
116: }
117:
118: public void delete(int index) {
119: prototype.delete(index);
120: }
121:
122: public Scriptable getPrototype() {
123: return prototype;
124: }
125:
126: public void setPrototype(Scriptable prototype) {
127: this .prototype = prototype;
128: }
129:
130: public Scriptable getParentScope() {
131: return parent;
132: }
133:
134: public void setParentScope(Scriptable parent) {
135: this .parent = parent;
136: }
137:
138: public Object[] getIds() {
139: return prototype.getIds();
140: }
141:
142: public Object getDefaultValue(Class typeHint) {
143: return prototype.getDefaultValue(typeHint);
144: }
145:
146: public boolean hasInstance(Scriptable value) {
147: return prototype.hasInstance(value);
148: }
149:
150: /**
151: * Must return null to continue looping or the final collection result.
152: */
153: protected Object updateDotQuery(boolean value) {
154: // NativeWith itself does not support it
155: throw new IllegalStateException();
156: }
157:
158: public Object execIdCall(IdFunctionObject f, Context cx,
159: Scriptable scope, Scriptable this Obj, Object[] args) {
160: if (f.hasTag(FTAG)) {
161: if (f.methodId() == Id_constructor) {
162: throw Context.reportRuntimeError1(
163: "msg.cant.call.indirect", "With");
164: }
165: }
166: throw f.unknown();
167: }
168:
169: static boolean isWithFunction(Object functionObj) {
170: if (functionObj instanceof IdFunctionObject) {
171: IdFunctionObject f = (IdFunctionObject) functionObj;
172: return f.hasTag(FTAG) && f.methodId() == Id_constructor;
173: }
174: return false;
175: }
176:
177: static Object newWithSpecial(Context cx, Scriptable scope,
178: Object[] args) {
179: ScriptRuntime.checkDeprecated(cx, "With");
180: scope = ScriptableObject.getTopLevelScope(scope);
181: NativeWith this Obj = new NativeWith();
182: this Obj.setPrototype(args.length == 0 ? ScriptableObject
183: .getClassPrototype(scope, "Object") : ScriptRuntime
184: .toObject(cx, scope, args[0]));
185: this Obj.setParentScope(scope);
186: return this Obj;
187: }
188:
189: private static final Object FTAG = new Object();
190:
191: private static final int Id_constructor = 1;
192:
193: protected Scriptable prototype;
194: protected Scriptable parent;
195: }
|