зеркало из 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,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче