Implementing bug 245882: now ImporterTopLevel can be constructed from JavaScript using JavaImporter to allow to have class and package collections without namespace polluting.

This commit is contained in:
igor%mir2.org 2004-06-09 07:36:31 +00:00
parent 5a060bf553
commit 407b7697c2
2 changed files with 182 additions and 103 deletions

View File

@ -1207,33 +1207,24 @@ public class Context
NativeCall.init(this, scope, sealed);
NativeScript.init(this, scope, sealed);
new LazilyLoadedCtor(scope,
"RegExp",
"org.mozilla.javascript.regexp.NativeRegExp",
sealed);
// This creates the Packages and java package roots.
new LazilyLoadedCtor(scope,
"Packages",
"org.mozilla.javascript.NativeJavaTopPackage",
sealed);
new LazilyLoadedCtor(scope,
"java",
"org.mozilla.javascript.NativeJavaTopPackage",
sealed);
new LazilyLoadedCtor(scope,
"getClass",
"org.mozilla.javascript.NativeJavaTopPackage",
sealed);
new LazilyLoadedCtor(scope,
"JavaAdapter",
"org.mozilla.javascript.JavaAdapter",
sealed);
for (int i = 0; i != lazilyNames.length; i += 2) {
String topProperty = lazilyNames[i];
String className = lazilyNames[i + 1];
new LazilyLoadedCtor(scope, topProperty, className, sealed);
}
return scope;
}
private static final String[] lazilyNames = {
"RegExp", "org.mozilla.javascript.regexp.NativeRegExp",
"Packages", "org.mozilla.javascript.NativeJavaTopPackage",
"java", "org.mozilla.javascript.NativeJavaTopPackage",
"getClass", "org.mozilla.javascript.NativeJavaTopPackage",
"JavaAdapter", "org.mozilla.javascript.JavaAdapter",
"JavaImporter", "org.mozilla.javascript.ImporterTopLevel",
};
/**
* Get the singleton object that represents the JavaScript Undefined value.
*/

View File

@ -20,6 +20,7 @@
*
* Contributor(s):
* Norris Boyd
* Igor Bukanov
* Matthias Radestock
*
* Alternatively, the contents of this file may be used under the
@ -70,7 +71,7 @@ import java.io.Serializable;
*
* @author Norris Boyd
*/
public class ImporterTopLevel extends ScriptableObject
public class ImporterTopLevel extends IdScriptable
{
public ImporterTopLevel() { }
@ -85,13 +86,24 @@ public class ImporterTopLevel extends ScriptableObject
public String getClassName()
{
return "global";
return (topScopeFlag) ? "global" : "JavaImporter";
}
public static void init(Context cx, Scriptable scope, boolean sealed)
{
ImporterTopLevel obj = new ImporterTopLevel();
obj.prototypeFlag = true;
obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);
}
public void initStandardObjects(Context cx, boolean sealed)
{
cx.initStandardObjects(this, sealed);
ImporterFunctions.setup(this);
prototypeFlag = true;
addAsPrototype(MAX_PROTOTYPE_ID, cx, this, sealed);
// set the flag after IdScriptable.addAsPrototype() calls
// getClassName() to get constructor name right.
topScopeFlag = true;
}
public boolean has(String name, Scriptable start) {
@ -128,95 +140,171 @@ public class ImporterTopLevel extends ScriptableObject
return result;
}
void importClass(Context cx, Scriptable thisObj, Object[] args)
{
for (int i=0; i<args.length; i++) {
Object cl = args[i];
if (!(cl instanceof NativeJavaClass)) {
throw Context.reportRuntimeError1(
"msg.not.class", Context.toString(cl));
}
String s = ((NativeJavaClass) cl).getClassObject().getName();
String n = s.substring(s.lastIndexOf('.')+1);
Object val = thisObj.get(n, thisObj);
if (val != NOT_FOUND && val != cl) {
throw Context.reportRuntimeError1("msg.prop.defined", n);
}
//thisObj.defineProperty(n, cl, DONTENUM);
thisObj.put(n,thisObj,cl);
}
}
/**
* @deprecated Kept only for compatibility.
*/
public void importPackage(Context cx, Scriptable thisObj, Object[] args,
Function funObj)
{
importPackage(cx, thisObj, args);
js_importPackage(args);
}
void importPackage(Context cx, Scriptable thisObj, Object[] args)
private Object js_construct(Scriptable scope, Object[] args)
{
ImporterTopLevel result = new ImporterTopLevel();
for (int i = 0; i != args.length; ++i) {
Object arg = args[i];
if (arg instanceof NativeJavaClass) {
result.importClass((NativeJavaClass)arg);
} else if (arg instanceof NativeJavaPackage) {
result.importPackage((NativeJavaPackage)arg);
} else {
throw Context.reportRuntimeError1(
"msg.not.class.not.pkg", Context.toString(arg));
}
}
// set explicitly prototype and scope
// as otherwise in topScopeFlag mode BaseFunction.construct
// would keep them set to null. It also allow to use
// JavaImporter without new and still get properly
// initialized object.
result.setParentScope(scope);
result.setPrototype(this);
return result;
}
private Object js_importClass(Object[] args)
{
for (int i = 0; i != args.length; i++) {
Object pkg = args[i];
if (!(pkg instanceof NativeJavaPackage)) {
Object arg = args[i];
if (!(arg instanceof NativeJavaClass)) {
throw Context.reportRuntimeError1(
"msg.not.pkg", Context.toString(pkg));
"msg.not.class", Context.toString(arg));
}
synchronized (importedPackages) {
for (int j = 0; j != importedPackages.size(); j++) {
if (pkg == importedPackages.get(j)) {
pkg = null;
break;
}
}
if (pkg != null) {
importedPackages.add(pkg);
}
}
}
}
private ObjArray importedPackages = new ObjArray();
}
final class ImporterFunctions extends JIFunction
{
private ImporterFunctions(ImporterTopLevel importer, int id)
{
this.importer = importer;
this.id = id;
if (id == Id_importClass) {
initNameArity("importClass", 1);
} else {
if (id != Id_importPackage) Kit.codeBug();
initNameArity("importPackage", 1);
}
defineAsProperty(importer);
}
static void setup(ImporterTopLevel importer)
{
new ImporterFunctions(importer, Id_importClass);
new ImporterFunctions(importer, Id_importPackage);
}
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
Object[] args)
throws JavaScriptException
{
if (id == Id_importClass) {
importer.importClass(cx, thisObj, args);
} else {
if (id != Id_importPackage) Kit.codeBug();
importer.importPackage(cx, thisObj, args);
importClass((NativeJavaClass)arg);
}
return Undefined.instance;
}
private static final int
Id_importClass = 1,
Id_importPackage = 2;
private Object js_importPackage(Object[] args)
{
for (int i = 0; i != args.length; i++) {
Object arg = args[i];
if (!(arg instanceof NativeJavaPackage)) {
throw Context.reportRuntimeError1(
"msg.not.pkg", Context.toString(arg));
}
importPackage((NativeJavaPackage)arg);
}
return Undefined.instance;
}
private ImporterTopLevel importer;
private int id;
private void importPackage(NativeJavaPackage pkg)
{
synchronized (importedPackages) {
for (int j = 0; j != importedPackages.size(); j++) {
if (pkg == importedPackages.get(j)) {
pkg = null;
break;
}
}
if (pkg != null) {
importedPackages.add(pkg);
}
}
}
private void importClass(NativeJavaClass cl)
{
String s = cl.getClassObject().getName();
String n = s.substring(s.lastIndexOf('.')+1);
Object val = get(n, this);
if (val != NOT_FOUND && val != cl) {
throw Context.reportRuntimeError1("msg.prop.defined", n);
}
//defineProperty(n, cl, DONTENUM);
put(n, this, cl);
}
public int methodArity(int methodId) {
if (prototypeFlag) {
switch (methodId) {
case Id_constructor: return 0;
case Id_importClass: return 1;
case Id_importPackage: return 1;
}
}
return super.methodArity(methodId);
}
public Object execMethod
(int methodId, IdFunction f,
Context cx, Scriptable scope, Scriptable thisObj, Object[] args)
{
if (prototypeFlag) {
switch (methodId) {
case Id_constructor:
return js_construct(scope, args);
case Id_importClass:
return realThis(thisObj, f).js_importClass(args);
case Id_importPackage:
return realThis(thisObj, f).js_importPackage(args);
}
}
return super.execMethod(methodId, f, cx, scope, thisObj, args);
}
private static ImporterTopLevel realThis(Scriptable thisObj, IdFunction f)
{
if (!(thisObj instanceof ImporterTopLevel))
throw incompatibleCallError(f);
return (ImporterTopLevel)thisObj;
}
protected String getIdName(int id)
{
if (prototypeFlag) {
switch (id) {
case Id_constructor: return "constructor";
case Id_importClass: return "importClass";
case Id_importPackage: return "importPackage";
}
}
return super.getIdName(id);
}
// #string_id_map#
protected int mapNameToId(String s) {
if (!prototypeFlag) { return 0; }
int id;
// #generated# Last update: 2004-06-08 02:03:11 CEST
L0: { id = 0; String X = null; int c;
int s_length = s.length();
if (s_length==11) {
c=s.charAt(0);
if (c=='c') { X="constructor";id=Id_constructor; }
else if (c=='i') { X="importClass";id=Id_importClass; }
}
else if (s_length==13) { X="importPackage";id=Id_importPackage; }
if (X!=null && X!=s && !X.equals(s)) id = 0;
}
// #/generated#
return id;
}
private static final int
Id_constructor = 1,
Id_importClass = 2,
Id_importPackage = 3,
MAX_PROTOTYPE_ID = 3;
// #/string_id_map#
private ObjArray importedPackages = new ObjArray();
private boolean prototypeFlag;
private boolean topScopeFlag;
}