diff --git a/js/rhino/org/mozilla/javascript/IdFunction.java b/js/rhino/org/mozilla/javascript/IdFunction.java index 92f40d7d026..e69de29bb2d 100644 --- a/js/rhino/org/mozilla/javascript/IdFunction.java +++ b/js/rhino/org/mozilla/javascript/IdFunction.java @@ -1,286 +0,0 @@ -/* -*- 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 oqr - * 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 - * - * 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. - */ - -// API class - -package org.mozilla.javascript; - -public class IdFunction extends ScriptableObject implements Function -{ - /** Indicates that native implementation was overwritten by script */ - public static final - IdFunction WAS_OVERWRITTEN = new IdFunction(null, "", 0); - - public static final int FUNCTION_ONLY = 0; - - public static final int CONSTRUCTOR_ONLY = 1; - - public static final int FUNCTION_AND_CONSTRUCTOR = 2; - - public static interface Master { - /** 'thisObj' will be null if invoked as constructor, in which case - ** instance of Scriptable should be returned */ - public Object execMethod(int methodId, IdFunction function, - Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - throws JavaScriptException; - - public int methodArity(int methodId, IdFunction function); - - public Scriptable getParentScope(); - } - - public IdFunction(Master master, String name, int id) { - this.master = master; - this.methodName = name; - this.methodId = id; - } - - /** - ** Primary goal of idTag is to allow to use the same method id in class - ** and its descendants. - */ - public final Object idTag() { - return idTag; - } - - public void setIdTag(Object tag) { - idTag = tag; - } - - public final int functionType() { - return functionType; - } - - public void setFunctionType(int type) { - functionType = type; - } - - public String getClassName() { return "Function"; } - - public boolean has(String name, Scriptable start) { - return nameToId(name) != 0 || super.has(name, start); - } - - public Object get(String name, Scriptable start) { - int id = nameToId(name); - return (0 != id) ? getField(id) : super.get(name, start); - } - - public void put(String name, Scriptable start, Object value) { - if (nameToId(name) == 0) { - super.put(name, start, value); - } - } - - public void delete(String name) { - if (nameToId(name) == 0) { - super.delete(name); - } - } - - /** - * Implements the instanceof operator for JavaScript Function objects. - *
- *
- * foo = new Foo();
- *
- * @param instance The value that appeared on the LHS of the instanceof
- * operator
- * @return true if the "prototype" property of "this" appears in
- * value's prototype chain
- *
- */
- public boolean hasInstance(Scriptable instance) {
- Object protoProp = ScriptableObject.getProperty(this, "prototype");
- if (protoProp instanceof Scriptable && protoProp != Undefined.instance)
- {
- return ScriptRuntime.jsDelegatesTo(instance, (Scriptable)protoProp);
- }
- throw NativeGlobal.typeError1
- ("msg.instanceof.bad.prototype", this.methodName, instance);
- }
-
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,
- Object[] args)
- throws JavaScriptException
- {
- if (functionType != CONSTRUCTOR_ONLY) {
- return master.execMethod(methodId, this, cx, scope, thisObj, args);
- }
- else {
- return Undefined.instance;
- }
- }
-
- public Scriptable construct(Context cx, Scriptable scope, Object[] args)
- throws JavaScriptException
- {
- if (functionType != FUNCTION_ONLY) {
- // It is program error not to return Scriptable from constructor
- Scriptable result = (Scriptable)master.execMethod(methodId, this,
- cx, scope,
- null, args);
- postConstruction(result);
- return result;
- }
- else {
- return Undefined.instance;
- }
- }
-
- public Scriptable getPrototype() {
- // For native functions this is not called often so it is better
- // to run this expensive operation here and not in constructor
- return getFunctionPrototype(getParentScope());
- }
-
- public Scriptable getParentScope() {
- Scriptable result = super.getParentScope();
- if (result == null) {
- result = master.getParentScope();
- }
- return result;
- }
-
- // Copied from NativeFunction
- protected Scriptable getClassPrototype() {
- Object protoVal = immunePrototypeProperty;
- if (protoVal == NOT_FOUND) {
- protoVal = super.get("prototype", this);
- }
- if (!(protoVal instanceof Scriptable)
- || protoVal == Undefined.instance)
- {
- protoVal = getClassPrototype(this, "Object");
- }
- return (Scriptable) protoVal;
- }
-
- protected Object toStringForScript(Context cx) {
- StringBuffer sb = new StringBuffer();
- sb.append("function ");
- sb.append(methodName);
- sb.append("() { [native code for ");
- if (master instanceof Scriptable) {
- Scriptable smaster = (Scriptable)master;
- sb.append(smaster.getClassName());
- sb.append('.');
- }
- sb.append(methodName);
- sb.append(", arity=");
- sb.append(getArity());
- sb.append("] }");
- return sb.toString();
- }
-
- /** Make value as DontEnum, DontDelete, ReadOnly
- ** prototype property of this native Function object
- ** if not already set
- */
- protected void setImmunePrototypeProperty(Object value) {
- if (immunePrototypeProperty == NOT_FOUND) {
- immunePrototypeProperty = value;
- }
- }
-
- private int getArity() {
- return master.methodArity(methodId, this);
- }
-
- // Copied from NativeFunction.construct
- private void postConstruction(Scriptable newObj) {
- if (newObj.getPrototype() == null) {
- newObj.setPrototype(getClassPrototype());
- }
- if (newObj.getParentScope() == null) {
- Scriptable parent = getParentScope();
- if (newObj != parent) {
- newObj.setParentScope(parent);
- }
- }
- }
-
- private Object getField(int fieldId) {
- switch (fieldId) {
- case ID_ARITY: case ID_LENGTH:
- return new Integer(getArity());
- case ID_NAME:
- return methodName;
- case ID_PROTOTYPE:
- return immunePrototypeProperty;
- }
- return null;
- }
-
- private int nameToId(String s) {
- int id = 0;
- String guess = null;
- switch (s.length()) {
- case 4: guess = "name"; id = ID_NAME; break;
- case 5: guess = "arity"; id = ID_ARITY; break;
- case 6: guess = "length"; id = ID_LENGTH; break;
- case 9:
- if (immunePrototypeProperty != NOT_FOUND) {
- // Try to guess only if immunePrototypeProperty is defined,
- // delegate to ScriptableObject otherwise
- guess = "prototype"; id = ID_PROTOTYPE;
- }
- break;
-
- }
- return (guess != null && guess.equals(s)) ? id : 0;
- }
-
- private static final int
- ID_ARITY = 1,
- ID_LENGTH = 2,
- ID_NAME = 3,
- ID_PROTOTYPE = 4;
-
- protected final Master master;
- protected final int methodId;
-
- protected String methodName;
-
- protected Object idTag;
-
- protected int functionType = FUNCTION_ONLY;
-
- // If != NOT_FOUND, represent script-immune prototype property
- private Object immunePrototypeProperty = NOT_FOUND;
-}
diff --git a/js/rhino/org/mozilla/javascript/NativeMath.java b/js/rhino/org/mozilla/javascript/NativeMath.java
index 3c732cb5dc6..a56a6d031d9 100644
--- a/js/rhino/org/mozilla/javascript/NativeMath.java
+++ b/js/rhino/org/mozilla/javascript/NativeMath.java
@@ -46,6 +46,7 @@ public class NativeMath extends ScriptableObject
implements IdFunction.Master, ScopeInitializer
{
public void scopeInit(Context cx, Scriptable scope, boolean sealed) {
+ sealFunctions = sealed;
setPrototype(getObjectPrototype(scope));
setParentScope(scope);
if (sealed) {
@@ -97,36 +98,29 @@ public class NativeMath extends ScriptableObject
}
public void put(String name, Scriptable start, Object value) {
- if (doOverwrite(name)) {
+ if (doOverwrite(name, start)) {
super.put(name, start, value);
}
}
public void delete(String name) {
- if (doOverwrite(name)) {
+ // Let the super class to throw exceptions for sealed objects
+ if (isSealed() || doOverwrite(name, this)) {
super.delete(name);
}
}
// Return true to invoke put/delete in super class
- private boolean doOverwrite(String name) {
- if (isSealed()) {
- // Let the super class to throw exceptions for sealed objects
- return true;
- }
+ private boolean doOverwrite(String name, Scriptable start) {
int id = nameToId(name);
- if (id > LAST_METHOD_ID) {
- // Ignore modifications of read-only Math constants
- return false;
- }
-
- if (0 != id) {
- if (functionPool[id] != IdFunction.WAS_OVERWRITTEN) {
- synchronized (this) {
- // Forget default implementation
- // Must be synchronized to avoid clearance of overwritten
- // mark by another thread running in wrapMethod
- functionPool[id] = IdFunction.WAS_OVERWRITTEN;
+ if (id != 0) {
+ if (id > LAST_METHOD_ID) {
+ // Ignore modifications of read-only Math constants
+ return false;
+ }
+ else {
+ if (this == start) {
+ overwriteMethod(id);
}
}
}
@@ -137,11 +131,23 @@ public class NativeMath extends ScriptableObject
synchronized (this) {
IdFunction f = functionPool[id];
if (f == null) {
- f = functionPool[id] = new IdFunction(this, name, id);
+ f = new IdFunction(this, name, id);
+ if (sealFunctions) { f.sealObject(); }
+ functionPool[id] = f;
}
return f;
}
}
+
+ private void overwriteMethod(int id) {
+ if (functionPool[id] != IdFunction.WAS_OVERWRITTEN) {
+ // Must be synchronized to avoid clearance of overwritten mark
+ // by another thread running in wrapMethod
+ synchronized (this) {
+ functionPool[id] = IdFunction.WAS_OVERWRITTEN;
+ }
+ }
+ }
private Double getField(int fieldId) {
switch (fieldId) {
@@ -176,39 +182,66 @@ public class NativeMath extends ScriptableObject
throws JavaScriptException
{
switch (methodId) {
- case Id_abs: return wrap_dbl(js_abs(to_dbl(args, 0)));
- case Id_acos: return wrap_dbl(js_acos(to_dbl(args, 0)));
- case Id_asin: return wrap_dbl(js_asin(to_dbl(args, 0)));
- case Id_atan: return wrap_dbl(js_atan(to_dbl(args, 0)));
- case Id_atan2: return wrap_dbl
- (js_atan2(to_dbl(args, 0), to_dbl(args, 1)));
- case Id_ceil: return wrap_dbl(js_ceil(to_dbl(args, 0)));
- case Id_cos: return wrap_dbl(js_cos(to_dbl(args, 0)));
- case Id_exp: return wrap_dbl(js_exp(to_dbl(args, 0)));
- case Id_floor: return wrap_dbl(js_floor(to_dbl(args, 0)));
- case Id_log: return wrap_dbl(js_log(to_dbl(args, 0)));
- case Id_max: return wrap_dbl(js_max(args));
- case Id_min: return wrap_dbl(js_min(args));
- case Id_pow: return wrap_dbl
- (js_pow(to_dbl(args, 0), to_dbl(args, 1)));
- case Id_random: return wrap_dbl(js_random());
- case Id_round: return wrap_dbl(js_round(to_dbl(args, 0)));
- case Id_sin: return wrap_dbl(js_sin(to_dbl(args, 0)));
- case Id_sqrt: return wrap_dbl(js_sqrt(to_dbl(args, 0)));
- case Id_tan: return wrap_dbl(js_tan(to_dbl(args, 0)));
+ case Id_abs: return wrap_double
+ (js_abs(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_acos: return wrap_double
+ (js_acos(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_asin: return wrap_double
+ (js_asin(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_atan: return wrap_double
+ (js_atan(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_atan2: return wrap_double
+ (js_atan2(ScriptRuntime.toNumber(args, 0),
+ ScriptRuntime.toNumber(args, 1)));
+
+ case Id_ceil: return wrap_double
+ (js_ceil(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_cos: return wrap_double
+ (js_cos(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_exp: return wrap_double
+ (js_exp(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_floor: return wrap_double
+ (js_floor(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_log: return wrap_double
+ (js_log(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_max: return wrap_double
+ (js_max(args));
+
+ case Id_min: return wrap_double
+ (js_min(args));
+
+ case Id_pow: return wrap_double
+ (js_pow(ScriptRuntime.toNumber(args, 0),
+ ScriptRuntime.toNumber(args, 1)));
+
+ case Id_random: return wrap_double
+ (js_random());
+
+ case Id_round: return wrap_double
+ (js_round(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_sin: return wrap_double
+ (js_sin(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_sqrt: return wrap_double
+ (js_sqrt(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_tan: return wrap_double
+ (js_tan(ScriptRuntime.toNumber(args, 0)));
}
return null;
}
- private double to_dbl(Object[] args, int index) {
- return ScriptRuntime.toNumber(args, index);
- }
-
- private double to_dbl(Object arg) {
- return ScriptRuntime.toNumber(arg);
- }
-
- private Double wrap_dbl(double x) {
+ private Double wrap_double(double x) {
return (x == x) ? new Double(x) : ScriptRuntime.NaNobj;
}
@@ -410,5 +443,7 @@ public class NativeMath extends ScriptableObject
// Last accessed function cache
private IdFunction lastFunction = IdFunction.WAS_OVERWRITTEN;
+
+ private boolean sealFunctions;
}
diff --git a/js/rhino/src/org/mozilla/javascript/IdFunction.java b/js/rhino/src/org/mozilla/javascript/IdFunction.java
index 92f40d7d026..bcb4736aa89 100644
--- a/js/rhino/src/org/mozilla/javascript/IdFunction.java
+++ b/js/rhino/src/org/mozilla/javascript/IdFunction.java
@@ -106,7 +106,8 @@ public class IdFunction extends ScriptableObject implements Function
}
public void delete(String name) {
- if (nameToId(name) == 0) {
+ // Let the super class throw exceptions for sealed objects
+ if (isSealed() || nameToId(name) == 0) {
super.delete(name);
}
}
diff --git a/js/rhino/src/org/mozilla/javascript/NativeMath.java b/js/rhino/src/org/mozilla/javascript/NativeMath.java
index 3c732cb5dc6..a56a6d031d9 100644
--- a/js/rhino/src/org/mozilla/javascript/NativeMath.java
+++ b/js/rhino/src/org/mozilla/javascript/NativeMath.java
@@ -46,6 +46,7 @@ public class NativeMath extends ScriptableObject
implements IdFunction.Master, ScopeInitializer
{
public void scopeInit(Context cx, Scriptable scope, boolean sealed) {
+ sealFunctions = sealed;
setPrototype(getObjectPrototype(scope));
setParentScope(scope);
if (sealed) {
@@ -97,36 +98,29 @@ public class NativeMath extends ScriptableObject
}
public void put(String name, Scriptable start, Object value) {
- if (doOverwrite(name)) {
+ if (doOverwrite(name, start)) {
super.put(name, start, value);
}
}
public void delete(String name) {
- if (doOverwrite(name)) {
+ // Let the super class to throw exceptions for sealed objects
+ if (isSealed() || doOverwrite(name, this)) {
super.delete(name);
}
}
// Return true to invoke put/delete in super class
- private boolean doOverwrite(String name) {
- if (isSealed()) {
- // Let the super class to throw exceptions for sealed objects
- return true;
- }
+ private boolean doOverwrite(String name, Scriptable start) {
int id = nameToId(name);
- if (id > LAST_METHOD_ID) {
- // Ignore modifications of read-only Math constants
- return false;
- }
-
- if (0 != id) {
- if (functionPool[id] != IdFunction.WAS_OVERWRITTEN) {
- synchronized (this) {
- // Forget default implementation
- // Must be synchronized to avoid clearance of overwritten
- // mark by another thread running in wrapMethod
- functionPool[id] = IdFunction.WAS_OVERWRITTEN;
+ if (id != 0) {
+ if (id > LAST_METHOD_ID) {
+ // Ignore modifications of read-only Math constants
+ return false;
+ }
+ else {
+ if (this == start) {
+ overwriteMethod(id);
}
}
}
@@ -137,11 +131,23 @@ public class NativeMath extends ScriptableObject
synchronized (this) {
IdFunction f = functionPool[id];
if (f == null) {
- f = functionPool[id] = new IdFunction(this, name, id);
+ f = new IdFunction(this, name, id);
+ if (sealFunctions) { f.sealObject(); }
+ functionPool[id] = f;
}
return f;
}
}
+
+ private void overwriteMethod(int id) {
+ if (functionPool[id] != IdFunction.WAS_OVERWRITTEN) {
+ // Must be synchronized to avoid clearance of overwritten mark
+ // by another thread running in wrapMethod
+ synchronized (this) {
+ functionPool[id] = IdFunction.WAS_OVERWRITTEN;
+ }
+ }
+ }
private Double getField(int fieldId) {
switch (fieldId) {
@@ -176,39 +182,66 @@ public class NativeMath extends ScriptableObject
throws JavaScriptException
{
switch (methodId) {
- case Id_abs: return wrap_dbl(js_abs(to_dbl(args, 0)));
- case Id_acos: return wrap_dbl(js_acos(to_dbl(args, 0)));
- case Id_asin: return wrap_dbl(js_asin(to_dbl(args, 0)));
- case Id_atan: return wrap_dbl(js_atan(to_dbl(args, 0)));
- case Id_atan2: return wrap_dbl
- (js_atan2(to_dbl(args, 0), to_dbl(args, 1)));
- case Id_ceil: return wrap_dbl(js_ceil(to_dbl(args, 0)));
- case Id_cos: return wrap_dbl(js_cos(to_dbl(args, 0)));
- case Id_exp: return wrap_dbl(js_exp(to_dbl(args, 0)));
- case Id_floor: return wrap_dbl(js_floor(to_dbl(args, 0)));
- case Id_log: return wrap_dbl(js_log(to_dbl(args, 0)));
- case Id_max: return wrap_dbl(js_max(args));
- case Id_min: return wrap_dbl(js_min(args));
- case Id_pow: return wrap_dbl
- (js_pow(to_dbl(args, 0), to_dbl(args, 1)));
- case Id_random: return wrap_dbl(js_random());
- case Id_round: return wrap_dbl(js_round(to_dbl(args, 0)));
- case Id_sin: return wrap_dbl(js_sin(to_dbl(args, 0)));
- case Id_sqrt: return wrap_dbl(js_sqrt(to_dbl(args, 0)));
- case Id_tan: return wrap_dbl(js_tan(to_dbl(args, 0)));
+ case Id_abs: return wrap_double
+ (js_abs(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_acos: return wrap_double
+ (js_acos(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_asin: return wrap_double
+ (js_asin(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_atan: return wrap_double
+ (js_atan(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_atan2: return wrap_double
+ (js_atan2(ScriptRuntime.toNumber(args, 0),
+ ScriptRuntime.toNumber(args, 1)));
+
+ case Id_ceil: return wrap_double
+ (js_ceil(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_cos: return wrap_double
+ (js_cos(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_exp: return wrap_double
+ (js_exp(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_floor: return wrap_double
+ (js_floor(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_log: return wrap_double
+ (js_log(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_max: return wrap_double
+ (js_max(args));
+
+ case Id_min: return wrap_double
+ (js_min(args));
+
+ case Id_pow: return wrap_double
+ (js_pow(ScriptRuntime.toNumber(args, 0),
+ ScriptRuntime.toNumber(args, 1)));
+
+ case Id_random: return wrap_double
+ (js_random());
+
+ case Id_round: return wrap_double
+ (js_round(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_sin: return wrap_double
+ (js_sin(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_sqrt: return wrap_double
+ (js_sqrt(ScriptRuntime.toNumber(args, 0)));
+
+ case Id_tan: return wrap_double
+ (js_tan(ScriptRuntime.toNumber(args, 0)));
}
return null;
}
- private double to_dbl(Object[] args, int index) {
- return ScriptRuntime.toNumber(args, index);
- }
-
- private double to_dbl(Object arg) {
- return ScriptRuntime.toNumber(arg);
- }
-
- private Double wrap_dbl(double x) {
+ private Double wrap_double(double x) {
return (x == x) ? new Double(x) : ScriptRuntime.NaNobj;
}
@@ -410,5 +443,7 @@ public class NativeMath extends ScriptableObject
// Last accessed function cache
private IdFunction lastFunction = IdFunction.WAS_OVERWRITTEN;
+
+ private boolean sealFunctions;
}
- * foo instanceof Foo; // true
- *