1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 package org.mozilla.javascript; 8 9 import java.io.Serializable; 10 11 /** 12 * This class implements the object lookup required for the 13 * <code>with</code> statement. 14 * It simply delegates every action to its prototype except 15 * for operations on its parent. 16 */ 17 public class NativeWith implements Scriptable, IdFunctionCall, Serializable { 18 19 private static final long serialVersionUID = 1L; 20 init(Scriptable scope, boolean sealed)21 static void init(Scriptable scope, boolean sealed) 22 { 23 NativeWith obj = new NativeWith(); 24 25 obj.setParentScope(scope); 26 obj.setPrototype(ScriptableObject.getObjectPrototype(scope)); 27 28 IdFunctionObject ctor = new IdFunctionObject(obj, FTAG, Id_constructor, 29 "With", 0, scope); 30 ctor.markAsConstructor(obj); 31 if (sealed) { 32 ctor.sealObject(); 33 } 34 ctor.exportAsScopeProperty(); 35 } 36 NativeWith()37 private NativeWith() { 38 } 39 NativeWith(Scriptable parent, Scriptable prototype)40 protected NativeWith(Scriptable parent, Scriptable prototype) { 41 this.parent = parent; 42 this.prototype = prototype; 43 } 44 getClassName()45 public String getClassName() { 46 return "With"; 47 } 48 has(String id, Scriptable start)49 public boolean has(String id, Scriptable start) 50 { 51 return prototype.has(id, prototype); 52 } 53 has(int index, Scriptable start)54 public boolean has(int index, Scriptable start) 55 { 56 return prototype.has(index, prototype); 57 } 58 get(String id, Scriptable start)59 public Object get(String id, Scriptable start) 60 { 61 if (start == this) 62 start = prototype; 63 return prototype.get(id, start); 64 } 65 get(int index, Scriptable start)66 public Object get(int index, Scriptable start) 67 { 68 if (start == this) 69 start = prototype; 70 return prototype.get(index, start); 71 } 72 put(String id, Scriptable start, Object value)73 public void put(String id, Scriptable start, Object value) 74 { 75 if (start == this) 76 start = prototype; 77 prototype.put(id, start, value); 78 } 79 put(int index, Scriptable start, Object value)80 public void put(int index, Scriptable start, Object value) 81 { 82 if (start == this) 83 start = prototype; 84 prototype.put(index, start, value); 85 } 86 delete(String id)87 public void delete(String id) 88 { 89 prototype.delete(id); 90 } 91 delete(int index)92 public void delete(int index) 93 { 94 prototype.delete(index); 95 } 96 getPrototype()97 public Scriptable getPrototype() { 98 return prototype; 99 } 100 setPrototype(Scriptable prototype)101 public void setPrototype(Scriptable prototype) { 102 this.prototype = prototype; 103 } 104 getParentScope()105 public Scriptable getParentScope() { 106 return parent; 107 } 108 setParentScope(Scriptable parent)109 public void setParentScope(Scriptable parent) { 110 this.parent = parent; 111 } 112 getIds()113 public Object[] getIds() { 114 return prototype.getIds(); 115 } 116 getDefaultValue(Class<?> typeHint)117 public Object getDefaultValue(Class<?> typeHint) { 118 return prototype.getDefaultValue(typeHint); 119 } 120 hasInstance(Scriptable value)121 public boolean hasInstance(Scriptable value) { 122 return prototype.hasInstance(value); 123 } 124 125 /** 126 * Must return null to continue looping or the final collection result. 127 */ updateDotQuery(boolean value)128 protected Object updateDotQuery(boolean value) 129 { 130 // NativeWith itself does not support it 131 throw new IllegalStateException(); 132 } 133 execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args)134 public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, 135 Scriptable thisObj, Object[] args) 136 { 137 if (f.hasTag(FTAG)) { 138 if (f.methodId() == Id_constructor) { 139 throw Context.reportRuntimeError1("msg.cant.call.indirect", "With"); 140 } 141 } 142 throw f.unknown(); 143 } 144 isWithFunction(Object functionObj)145 static boolean isWithFunction(Object functionObj) 146 { 147 if (functionObj instanceof IdFunctionObject) { 148 IdFunctionObject f = (IdFunctionObject)functionObj; 149 return f.hasTag(FTAG) && f.methodId() == Id_constructor; 150 } 151 return false; 152 } 153 newWithSpecial(Context cx, Scriptable scope, Object[] args)154 static Object newWithSpecial(Context cx, Scriptable scope, Object[] args) 155 { 156 ScriptRuntime.checkDeprecated(cx, "With"); 157 scope = ScriptableObject.getTopLevelScope(scope); 158 NativeWith thisObj = new NativeWith(); 159 thisObj.setPrototype(args.length == 0 160 ? ScriptableObject.getObjectPrototype(scope) 161 : ScriptRuntime.toObject(cx, scope, args[0])); 162 thisObj.setParentScope(scope); 163 return thisObj; 164 } 165 166 private static final Object FTAG = "With"; 167 168 private static final int 169 Id_constructor = 1; 170 171 protected Scriptable prototype; 172 protected Scriptable parent; 173 } 174