зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
2116663b00
Коммит
59af2f367b
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче