More Reference clenups: Reference.delete now returns boolean to follow JS semantic clother and Reference implementation for __proto__|__parent__ is moved to a separated file SpecialRef.

This commit is contained in:
igor%mir2.org 2004-10-01 13:32:14 +00:00
Родитель 2116663b00
Коммит 59af2f367b
6 изменённых файлов: 206 добавлений и 124 удалений

Просмотреть файл

@ -3226,8 +3226,8 @@ switch (op) {
//stringReg: name of special property //stringReg: name of special property
Object obj = stack[stackTop]; Object obj = stack[stackTop];
if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
stack[stackTop] = ScriptRuntime.specialReference(obj, stringReg, stack[stackTop] = ScriptRuntime.specialRef(obj, stringReg,
cx, frame.scope); cx, frame.scope);
continue Loop; continue Loop;
} }
case Token.REF_MEMBER: { case Token.REF_MEMBER: {

Просмотреть файл

@ -53,8 +53,9 @@ public abstract class Reference
public abstract Object set(Context cx, Object value); public abstract Object set(Context cx, Object value);
public void delete(Context cx) public boolean delete(Context cx)
{ {
return false;
} }
} }

Просмотреть файл

@ -1116,32 +1116,6 @@ public class ScriptRuntime {
} }
} }
public static Scriptable getProto(Object obj, Scriptable scope) {
Scriptable s;
if (obj instanceof Scriptable) {
s = (Scriptable) obj;
} else {
s = toObject(scope, obj);
}
if (s == null) {
throw typeError0("msg.null.to.object");
}
return s.getPrototype();
}
public static Scriptable getParent(Object obj, Scriptable scope) {
Scriptable s;
if (obj instanceof Scriptable) {
s = (Scriptable) obj;
} else {
s = toObject(scope, obj);
}
if (s == null) {
throw typeError0("msg.null.to.object");
}
return s.getParentScope();
}
/** /**
* Return -1L if str is not an index or the index value as lower 32 * Return -1L if str is not an index or the index value as lower 32
* bits of the result. * bits of the result.
@ -1518,6 +1492,46 @@ public class ScriptRuntime {
return value; return value;
} }
public static boolean deleteObjectElem(Scriptable target, Object elem,
Context cx)
{
boolean result;
if (target instanceof XMLObject) {
XMLObject xmlObject = (XMLObject)target;
result = xmlObject.ecmaDelete(cx, elem);
} else {
String s = toStringIdOrIndex(cx, elem);
if (s == null) {
int index = lastIndexResult(cx);
result = ScriptableObject.deleteProperty(target, index);
} else {
result = ScriptableObject.deleteProperty(target, s);
}
}
return result;
}
public static boolean hasObjectElem(Scriptable target, Object elem,
Context cx)
{
boolean result;
if (target instanceof XMLObject) {
XMLObject xmlObject = (XMLObject)target;
result = xmlObject.ecmaHas(cx, elem);
} else {
String s = toStringIdOrIndex(cx, elem);
if (s == null) {
int index = lastIndexResult(cx);
result = ScriptableObject.hasProperty(target, index);
} else {
result = ScriptableObject.hasProperty(target, s);
}
}
return result;
}
public static Object getReference(Reference ref, Context cx) public static Object getReference(Reference ref, Context cx)
{ {
return ref.get(cx); return ref.get(cx);
@ -1530,8 +1544,7 @@ public class ScriptRuntime {
public static Object deleteReference(Reference ref, Context cx) public static Object deleteReference(Reference ref, Context cx)
{ {
ref.delete(cx); return wrapBoolean(ref.delete(cx));
return wrapBoolean(!ref.has(cx));
} }
static boolean isSpecialProperty(String s) static boolean isSpecialProperty(String s)
@ -1539,66 +1552,10 @@ public class ScriptRuntime {
return s.equals("__proto__") || s.equals("__parent__"); return s.equals("__proto__") || s.equals("__parent__");
} }
public static Reference specialReference(final Object obj, public static Reference specialRef(Object obj, String specialProperty,
final String specialProperty, Context cx, Scriptable scope)
Context cx,
final Scriptable scope)
{ {
final int PROTO = 0; return SpecialRef.createSpecial(cx, scope, obj, specialProperty);
final int PARENT = 1;
final int id;
if (specialProperty.equals("__proto__")) {
id = PROTO;
} else if (specialProperty.equals("__parent__")) {
id = PARENT;
} else {
throw Kit.codeBug();
}
final boolean
specials = cx.hasFeature(Context.FEATURE_PARENT_PROTO_PROPRTIES);
final Scriptable sobj = toObject(scope, obj);
return new Reference() {
public Object get(Context cx2)
{
if (!specials) {
return getObjectProp(sobj, specialProperty, cx2);
}
if (id == PROTO) {
return getProto(sobj, scope);
} else {
return getParent(sobj, scope);
}
}
public Object set(Context cx2, Object value)
{
if (!specials) {
return setObjectProp(sobj, specialProperty, value, cx2);
}
Scriptable result;
if (value == null) {
result = null;
} else {
result = toObject(scope, value);
Scriptable s = result;
do {
if (s == sobj) {
throw Context.reportRuntimeError1(
"msg.cyclic.value", specialProperty);
}
s = (id == PROTO)
? s.getPrototype() : s.getParentScope();
} while (s != null);
}
if (id == PROTO) {
sobj.setPrototype(result);
} else {
sobj.setParentScope(result);
}
return result;
}
};
} }
/** /**
@ -1617,19 +1574,7 @@ public class ScriptRuntime {
{ {
Scriptable sobj = (obj instanceof Scriptable) Scriptable sobj = (obj instanceof Scriptable)
? (Scriptable)obj : toObject(cx, scope, obj); ? (Scriptable)obj : toObject(cx, scope, obj);
boolean result; boolean result = deleteObjectElem(sobj, id, cx);
if (sobj instanceof XMLObject) {
XMLObject xmlObject = (XMLObject)sobj;
result = xmlObject.ecmaDelete(cx, id);
} else {
String s = toStringIdOrIndex(cx, id);
if (s == null) {
int index = lastIndexResult(cx);
result = ScriptableObject.deleteProperty(sobj, index);
} else {
result = ScriptableObject.deleteProperty(sobj, s);
}
}
return wrapBoolean(result); return wrapBoolean(result);
} }
@ -2727,22 +2672,7 @@ public class ScriptRuntime {
throw typeError0("msg.instanceof.not.object"); throw typeError0("msg.instanceof.not.object");
} }
boolean result; return hasObjectElem((Scriptable)b, a, cx);
if (b instanceof XMLObject) {
XMLObject xmlObject = (XMLObject)b;
result = xmlObject.ecmaHas(cx, a);
} else {
String s = toStringIdOrIndex(cx, a);
if (s == null) {
int index = lastIndexResult(cx);
result = ScriptableObject.hasProperty((Scriptable)b, index);
} else {
result = ScriptableObject.hasProperty((Scriptable)b, s);
}
}
return result;
} }
public static boolean cmp_LT(Object val1, Object val2) public static boolean cmp_LT(Object val1, Object val2)

Просмотреть файл

@ -0,0 +1,150 @@
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Rhino code, released
* May 6, 1999.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Igor Bukanov, igor@fastmail.fm
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
package org.mozilla.javascript;
class SpecialRef extends Reference
{
private static final int SPECIAL_NONE = 0;
private static final int SPECIAL_PROTO = 1;
private static final int SPECIAL_PARENT = 2;
private int type;
private Scriptable scope;
private Scriptable target;
private String name;
private SpecialRef(int type, Scriptable scope, Scriptable target,
String name)
{
this.type = type;
this.scope = scope;
this.target = target;
this.name = name;
}
static Reference createSpecial(Context cx, Scriptable scope, Object object,
String name)
{
Scriptable target = ScriptRuntime.toObject(scope, object);
int type;
if (name.equals("__proto__")) {
type = SPECIAL_PROTO;
} else if (name.equals("__parent__")) {
type = SPECIAL_PARENT;
} else {
throw new IllegalArgumentException(name);
}
if (!cx.hasFeature(Context.FEATURE_PARENT_PROTO_PROPRTIES)) {
// Clear special after checking for valid name!
type = SPECIAL_NONE;
}
return new SpecialRef(type, scope, target, name);
}
public Object get(Context cx)
{
switch (type) {
case SPECIAL_NONE:
return ScriptRuntime.getObjectProp(target, name, cx);
case SPECIAL_PROTO:
return target.getPrototype();
case SPECIAL_PARENT:
return target.getParentScope();
default:
throw Kit.codeBug();
}
}
public Object set(Context cx, Object value)
{
switch (type) {
case SPECIAL_NONE:
return ScriptRuntime.setObjectProp(target, name, value, cx);
case SPECIAL_PROTO:
case SPECIAL_PARENT:
{
Scriptable obj;
if (value == null) {
obj = null;
} else {
obj = ScriptRuntime.toObject(scope, value);
// Check that obj does not contain on its prototype/scope
// chain to prevent cycles
Scriptable search = obj;
do {
if (search == target) {
throw Context.reportRuntimeError1(
"msg.cyclic.value", name);
}
if (type == SPECIAL_PROTO) {
search = search.getPrototype();
} else {
search = search.getParentScope();
}
} while (search != null);
}
if (type == SPECIAL_PROTO) {
target.setPrototype(obj);
} else {
target.setParentScope(obj);
}
return obj;
}
default:
throw Kit.codeBug();
}
}
public boolean has(Context cx)
{
if (type == SPECIAL_NONE) {
return ScriptRuntime.hasObjectElem(target, name, cx);
}
return true;
}
public boolean delete(Context cx)
{
if (type == SPECIAL_NONE) {
return ScriptRuntime.deleteObjectElem(target, name, cx);
}
return false;
}
}

Просмотреть файл

@ -2130,7 +2130,8 @@ class BodyCodegen
cfw.addPush(special); cfw.addPush(special);
cfw.addALoad(contextLocal); cfw.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal); cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("specialReference", addScriptRuntimeInvoke(
"specialRef",
"(Ljava/lang/Object;" "(Ljava/lang/Object;"
+"Ljava/lang/String;" +"Ljava/lang/String;"
+"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Context;"

Просмотреть файл

@ -96,12 +96,12 @@ class XMLReference extends Reference
return value; return value;
} }
public void delete(Context cx) public boolean delete(Context cx)
{ {
if (xmlObject == null) { if (xmlObject != null) {
return; xmlObject.deleteXMLProperty(xmlName, descendants);
} }
xmlObject.deleteXMLProperty(xmlName, descendants); return !has(cx);
} }
} }