mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
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:
parent
5a060bf553
commit
407b7697c2
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user