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,7 +3226,7 @@ switch (op) {
//stringReg: name of special property
Object obj = stack[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);
continue Loop;
}

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

@ -53,8 +53,9 @@ public abstract class Reference
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
* bits of the result.
@ -1518,6 +1492,46 @@ public class ScriptRuntime {
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)
{
return ref.get(cx);
@ -1530,8 +1544,7 @@ public class ScriptRuntime {
public static Object deleteReference(Reference ref, Context cx)
{
ref.delete(cx);
return wrapBoolean(!ref.has(cx));
return wrapBoolean(ref.delete(cx));
}
static boolean isSpecialProperty(String s)
@ -1539,66 +1552,10 @@ public class ScriptRuntime {
return s.equals("__proto__") || s.equals("__parent__");
}
public static Reference specialReference(final Object obj,
final String specialProperty,
Context cx,
final Scriptable scope)
public static Reference specialRef(Object obj, String specialProperty,
Context cx, Scriptable scope)
{
final int PROTO = 0;
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;
}
};
return SpecialRef.createSpecial(cx, scope, obj, specialProperty);
}
/**
@ -1617,19 +1574,7 @@ public class ScriptRuntime {
{
Scriptable sobj = (obj instanceof Scriptable)
? (Scriptable)obj : toObject(cx, scope, obj);
boolean result;
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);
}
}
boolean result = deleteObjectElem(sobj, id, cx);
return wrapBoolean(result);
}
@ -2727,22 +2672,7 @@ public class ScriptRuntime {
throw typeError0("msg.instanceof.not.object");
}
boolean result;
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;
return hasObjectElem((Scriptable)b, a, cx);
}
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.addALoad(contextLocal);
cfw.addALoad(variableObjectLocal);
addScriptRuntimeInvoke("specialReference",
addScriptRuntimeInvoke(
"specialRef",
"(Ljava/lang/Object;"
+"Ljava/lang/String;"
+"Lorg/mozilla/javascript/Context;"

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

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