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: * Igor Bukanov, igor@fastmail.fm
026: *
027: * Alternatively, the contents of this file may be used under the terms of
028: * the GNU General Public License Version 2 or later (the "GPL"), in which
029: * case the provisions of the GPL are applicable instead of those above. If
030: * you wish to allow use of your version of this file only under the terms of
031: * the GPL and not to allow others to use your version of this file under the
032: * MPL, indicate your decision by deleting the provisions above and replacing
033: * them with the notice and other provisions required by the GPL. If you do
034: * not delete the provisions above, a recipient may use your version of this
035: * file under either the MPL or the GPL.
036: *
037: * ***** END LICENSE BLOCK ***** */
038:
039: package org.mozilla.javascript;
040:
041: class SpecialRef extends Ref {
042: static final long serialVersionUID = -7521596632456797847L;
043:
044: private static final int SPECIAL_NONE = 0;
045: private static final int SPECIAL_PROTO = 1;
046: private static final int SPECIAL_PARENT = 2;
047:
048: private Scriptable target;
049: private int type;
050: private String name;
051:
052: private SpecialRef(Scriptable target, int type, String name) {
053: this .target = target;
054: this .type = type;
055: this .name = name;
056: }
057:
058: static Ref createSpecial(Context cx, Object object, String name) {
059: Scriptable target = ScriptRuntime.toObjectOrNull(cx, object);
060: if (target == null) {
061: throw ScriptRuntime.undefReadError(object, name);
062: }
063:
064: int type;
065: if (name.equals("__proto__")) {
066: type = SPECIAL_PROTO;
067: } else if (name.equals("__parent__")) {
068: type = SPECIAL_PARENT;
069: } else {
070: throw new IllegalArgumentException(name);
071: }
072:
073: if (!cx.hasFeature(Context.FEATURE_PARENT_PROTO_PROPERTIES)) {
074: // Clear special after checking for valid name!
075: type = SPECIAL_NONE;
076: }
077:
078: return new SpecialRef(target, type, name);
079: }
080:
081: public Object get(Context cx) {
082: switch (type) {
083: case SPECIAL_NONE:
084: return ScriptRuntime.getObjectProp(target, name, cx);
085: case SPECIAL_PROTO:
086: return target.getPrototype();
087: case SPECIAL_PARENT:
088: return target.getParentScope();
089: default:
090: throw Kit.codeBug();
091: }
092: }
093:
094: public Object set(Context cx, Object value) {
095: switch (type) {
096: case SPECIAL_NONE:
097: return ScriptRuntime.setObjectProp(target, name, value, cx);
098: case SPECIAL_PROTO:
099: case SPECIAL_PARENT: {
100: Scriptable obj = ScriptRuntime.toObjectOrNull(cx, value);
101: if (obj != null) {
102: // Check that obj does not contain on its prototype/scope
103: // chain to prevent cycles
104: Scriptable search = obj;
105: do {
106: if (search == target) {
107: throw Context.reportRuntimeError1(
108: "msg.cyclic.value", name);
109: }
110: if (type == SPECIAL_PROTO) {
111: search = search.getPrototype();
112: } else {
113: search = search.getParentScope();
114: }
115: } while (search != null);
116: }
117: if (type == SPECIAL_PROTO) {
118: target.setPrototype(obj);
119: } else {
120: target.setParentScope(obj);
121: }
122: return obj;
123: }
124: default:
125: throw Kit.codeBug();
126: }
127: }
128:
129: public boolean has(Context cx) {
130: if (type == SPECIAL_NONE) {
131: return ScriptRuntime.hasObjectElem(target, name, cx);
132: }
133: return true;
134: }
135:
136: public boolean delete(Context cx) {
137: if (type == SPECIAL_NONE) {
138: return ScriptRuntime.deleteObjectElem(target, name, cx);
139: }
140: return false;
141: }
142: }
|