зеркало из https://github.com/mozilla/gecko-dev.git
- Added Support for 'foo instanceof Components.interaces.nsIFoo'.
- Added support for reflecting interface constants as Components.interfaces.nsIFoo.* (this may change). - Only interfaces marked 'scriptable' are visible in the Components.interfaces array. - Getting rid of some of the template style syntax. - Added GetWStringCopied and GetWStringShared for lame tests of speed in wstring copies. - Cleaned up more Unix warnings.
This commit is contained in:
Родитель
9cd191ad4f
Коммит
bdc94f184f
|
@ -131,6 +131,9 @@ interface nsIXPCTestString : nsISupports {
|
|||
string GetStringA();
|
||||
void GetStringB(out string s);
|
||||
void GetStringC([shared,retval] out string s);
|
||||
|
||||
void GetWStringCopied([retval] out wstring s);
|
||||
void GetWStringShared([shared,retval] out wstring s);
|
||||
};
|
||||
|
||||
[scriptable, uuid(0ff4faf0-439a-11d3-988c-006008962422)]
|
||||
|
|
|
@ -229,7 +229,7 @@ nsXPConnect::IsISupportsDescendent(nsIInterfaceInfo* info)
|
|||
nsID* iid;
|
||||
if(NS_SUCCEEDED(oldest->GetIID(&iid)))
|
||||
{
|
||||
retval = iid->Equals(nsCOMTypeInfo<nsISupports>::GetIID());
|
||||
retval = iid->Equals(NS_GET_IID(nsISupports));
|
||||
nsAllocator::Free(iid);
|
||||
}
|
||||
NS_RELEASE(oldest);
|
||||
|
|
|
@ -246,8 +246,8 @@ nsXPCInterfaces::CacheDynaProp(JSContext *cx, JSObject *obj, jsid id,
|
|||
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
|
||||
if(xpc)
|
||||
{
|
||||
if(NS_SUCCEEDED(xpc->WrapNative(cx, nsid,
|
||||
nsIJSIID::GetIID(),
|
||||
if(NS_SUCCEEDED(xpc->WrapNative(cx, NS_STATIC_CAST(nsIJSID*,nsid),
|
||||
NS_GET_IID(nsIJSIID),
|
||||
&nsid_wrapper)))
|
||||
{
|
||||
JSObject* idobj;
|
||||
|
@ -789,6 +789,9 @@ nsXPCClassesByID::CacheDynaProp(JSContext *cx, JSObject *obj, jsid id,
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
// Currently the possible results do not change at runtime, so they are only
|
||||
// cached once (unlike ProgIDs, CLSIDs, and IIDs)
|
||||
|
||||
class nsXPCResults : public nsIXPCResults, public nsIXPCScriptable
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -224,9 +224,31 @@ nsJSID::NewID(const char* str)
|
|||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsJSIID, nsIJSID, nsIJSIID)
|
||||
NS_IMPL_ISUPPORTS3(nsJSIID, nsIJSID, nsIJSIID, nsIXPCScriptable)
|
||||
|
||||
XPC_IMPLEMENT_FORWARD_CREATE(nsJSIID)
|
||||
// XPC_IMPLEMENT_IGNORE_GETFLAGS(nsJSIID)
|
||||
// XPC_IMPLEMENT_IGNORE_LOOKUPPROPERTY(nsJSIID)
|
||||
XPC_IMPLEMENT_IGNORE_DEFINEPROPERTY(nsJSIID)
|
||||
// XPC_IMPLEMENT_IGNORE_GETPROPERTY(nsJSIID)
|
||||
XPC_IMPLEMENT_IGNORE_SETPROPERTY(nsJSIID)
|
||||
XPC_IMPLEMENT_IGNORE_GETATTRIBUTES(nsJSIID)
|
||||
XPC_IMPLEMENT_IGNORE_SETATTRIBUTES(nsJSIID)
|
||||
XPC_IMPLEMENT_IGNORE_DELETEPROPERTY(nsJSIID)
|
||||
XPC_IMPLEMENT_IGNORE_DEFAULTVALUE(nsJSIID)
|
||||
// XPC_IMPLEMENT_IGNORE_ENUMERATE(nsJSIID)
|
||||
XPC_IMPLEMENT_IGNORE_CHECKACCESS(nsJSIID)
|
||||
XPC_IMPLEMENT_IGNORE_CALL(nsJSIID)
|
||||
XPC_IMPLEMENT_IGNORE_CONSTRUCT(nsJSIID)
|
||||
// XPC_IMPLEMENT_FORWARD_HASINSTANCE(nsJSIID)
|
||||
XPC_IMPLEMENT_FORWARD_FINALIZE(nsJSIID)
|
||||
|
||||
nsJSIID::nsJSIID()
|
||||
: mCacheFilled(JS_FALSE)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
nsJSIID::nsJSIID() {NS_INIT_ISUPPORTS();}
|
||||
nsJSIID::~nsJSIID() {}
|
||||
|
||||
NS_IMETHODIMP nsJSIID::GetName(char * *aName)
|
||||
|
@ -297,8 +319,12 @@ nsJSIID::NewID(const char* str)
|
|||
nsIInterfaceInfoManager* iim;
|
||||
if(nsnull != (iim = nsXPConnect::GetInterfaceInfoManager()))
|
||||
{
|
||||
nsIInterfaceInfo* iinfo;
|
||||
PRBool canScript;
|
||||
nsID* pid;
|
||||
if(NS_SUCCEEDED(iim->GetIIDForName(str, &pid)) && pid)
|
||||
if(NS_SUCCEEDED(iim->GetInfoForName(str, &iinfo)) &&
|
||||
NS_SUCCEEDED(iinfo->IsScriptable(&canScript)) && canScript &&
|
||||
NS_SUCCEEDED(iinfo->GetIID(&pid)) && pid)
|
||||
{
|
||||
success = idObj->mDetails.InitWithName(*pid, str);
|
||||
nsAllocator::Free(pid);
|
||||
|
@ -312,6 +338,173 @@ nsJSIID::NewID(const char* str)
|
|||
return idObj;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSIID::HasInstance(JSContext *cx, JSObject *obj,
|
||||
jsval v, JSBool *bp,
|
||||
nsIXPConnectWrappedNative* wrapper,
|
||||
nsIXPCScriptable* arbitrary,
|
||||
JSBool* retval)
|
||||
{
|
||||
*bp = JS_FALSE;
|
||||
*retval = JS_TRUE;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if(!JSVAL_IS_PRIMITIVE(v))
|
||||
{
|
||||
// we have a JSObject
|
||||
JSObject* obj = JSVAL_TO_OBJECT(v);
|
||||
|
||||
NS_ASSERTION(obj, "when is an object not an object?");
|
||||
|
||||
// is this really a native xpcom object with a wrapper?
|
||||
nsXPCWrappedNative* other_wrapper =
|
||||
nsXPCWrappedNativeClass::GetWrappedNativeOfJSObject(cx,obj);
|
||||
|
||||
if(!other_wrapper)
|
||||
return NS_OK;
|
||||
|
||||
if(mDetails.GetID()->Equals(other_wrapper->GetIID()))
|
||||
*bp = JS_TRUE;
|
||||
else
|
||||
{
|
||||
// This would be so easy except for the case...
|
||||
// other_wrapper might inherit from our type
|
||||
nsXPCWrappedNativeClass* clazz;
|
||||
nsIInterfaceInfo* prev;
|
||||
if(!(clazz = other_wrapper->GetClass()) ||
|
||||
!(prev = clazz->GetInterfaceInfo()))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsIInterfaceInfo* cur;
|
||||
NS_ADDREF(prev);
|
||||
while(NS_SUCCEEDED(prev->GetParent(&cur)))
|
||||
{
|
||||
NS_RELEASE(prev);
|
||||
prev = cur;
|
||||
|
||||
nsID* iid;
|
||||
if(NS_SUCCEEDED(cur->GetIID(&iid)))
|
||||
{
|
||||
JSBool found = mDetails.GetID()->Equals(*iid);
|
||||
nsAllocator::Free(iid);
|
||||
if(found)
|
||||
{
|
||||
*bp = JS_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_RELEASE(prev);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsJSIID::FillCache(JSContext *cx, JSObject *obj,
|
||||
nsIXPConnectWrappedNative *wrapper,
|
||||
nsIXPCScriptable *arbitrary)
|
||||
{
|
||||
nsIInterfaceInfoManager* iim = nsnull;
|
||||
nsIInterfaceInfo* iinfo;
|
||||
PRUint16 count;
|
||||
|
||||
if(!(iim = XPTI_GetInterfaceInfoManager()) ||
|
||||
NS_FAILED(iim->GetInfoForIID(mDetails.GetID(), &iinfo)) ||
|
||||
!iinfo ||
|
||||
NS_FAILED(iinfo->GetConstantCount(&count)))
|
||||
|
||||
{
|
||||
NS_ASSERTION(0,"access to interface info is truly horked");
|
||||
NS_IF_RELEASE(iim);
|
||||
ThrowException(NS_ERROR_XPC_UNEXPECTED, cx);
|
||||
return;
|
||||
}
|
||||
NS_RELEASE(iim);
|
||||
|
||||
|
||||
for(PRUint16 i = 0; i < count; i++)
|
||||
{
|
||||
const nsXPTConstant* constant;
|
||||
jsid id;
|
||||
JSString *jstrid;
|
||||
jsval val;
|
||||
JSBool retval;
|
||||
|
||||
if(NS_FAILED(iinfo->GetConstant(i, &constant)) ||
|
||||
!(jstrid = JS_InternString(cx, constant->GetName())) ||
|
||||
!JS_ValueToId(cx, STRING_TO_JSVAL(jstrid), &id) ||
|
||||
!nsXPCWrappedNativeClass::GetConstantAsJSVal(cx, iinfo, i, &val) ||
|
||||
NS_FAILED(arbitrary->SetProperty(cx, obj, id, &val, wrapper, nsnull, &retval)) ||
|
||||
!retval)
|
||||
{
|
||||
ThrowException(NS_ERROR_XPC_UNEXPECTED, cx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mCacheFilled = JS_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSIID::GetFlags(JSContext *cx, JSObject *obj,
|
||||
nsIXPConnectWrappedNative* wrapper,
|
||||
JSUint32* flagsp,
|
||||
nsIXPCScriptable* arbitrary)
|
||||
{
|
||||
NS_PRECONDITION(flagsp, "bad param");
|
||||
*flagsp = XPCSCRIPTABLE_DONT_ENUM_STATIC_PROPS;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSIID::LookupProperty(JSContext *cx, JSObject *obj,
|
||||
jsid id,
|
||||
JSObject **objp, JSProperty **propp,
|
||||
nsIXPConnectWrappedNative* wrapper,
|
||||
nsIXPCScriptable* arbitrary,
|
||||
JSBool* retval)
|
||||
{
|
||||
if(!mCacheFilled)
|
||||
FillCache(cx, obj, wrapper, arbitrary);
|
||||
return arbitrary->LookupProperty(cx, obj, id, objp, propp, wrapper,
|
||||
nsnull, retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSIID::GetProperty(JSContext *cx, JSObject *obj,
|
||||
jsid id, jsval *vp,
|
||||
nsIXPConnectWrappedNative* wrapper,
|
||||
nsIXPCScriptable* arbitrary,
|
||||
JSBool* retval)
|
||||
{
|
||||
if(!mCacheFilled)
|
||||
FillCache(cx, obj, wrapper, arbitrary);
|
||||
return arbitrary->GetProperty(cx, obj, id, vp, wrapper, nsnull, retval);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSIID::Enumerate(JSContext *cx, JSObject *obj,
|
||||
JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp,
|
||||
nsIXPConnectWrappedNative *wrapper,
|
||||
nsIXPCScriptable *arbitrary,
|
||||
JSBool *retval)
|
||||
{
|
||||
if(enum_op == JSENUMERATE_INIT && !mCacheFilled)
|
||||
FillCache(cx, obj, wrapper, arbitrary);
|
||||
|
||||
return arbitrary->Enumerate(cx, obj, enum_op, statep, idp, wrapper,
|
||||
arbitrary, retval);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -534,10 +534,16 @@ public:
|
|||
|
||||
const XPCNativeMemberDescriptor* LookupMemberByID(jsid id) const;
|
||||
|
||||
static JSBool GetConstantAsJSVal(JSContext *cx,
|
||||
nsIInterfaceInfo* iinfo,
|
||||
PRUint16 index,
|
||||
jsval* vp);
|
||||
|
||||
JSBool GetConstantAsJSVal(JSContext* cx,
|
||||
nsXPCWrappedNative* wrapper,
|
||||
const XPCNativeMemberDescriptor* desc,
|
||||
jsval* vp);
|
||||
jsval* vp)
|
||||
{return GetConstantAsJSVal(cx, mInfo, desc->index, vp);}
|
||||
|
||||
enum CallMode {CALL_METHOD, CALL_GETTER, CALL_SETTER};
|
||||
|
||||
|
@ -760,7 +766,7 @@ protected:
|
|||
|
||||
// nsJSIID
|
||||
|
||||
class nsJSIID : public nsIJSIID
|
||||
class nsJSIID : public nsIJSIID, public nsIXPCScriptable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -770,6 +776,7 @@ public:
|
|||
|
||||
// we implement the rest...
|
||||
NS_DECL_NSIJSIID
|
||||
XPC_DECLARE_IXPCSCRIPTABLE
|
||||
|
||||
static nsJSIID* NewID(const char* str);
|
||||
|
||||
|
@ -779,8 +786,13 @@ public:
|
|||
private:
|
||||
void ResolveName();
|
||||
|
||||
void FillCache(JSContext *cx, JSObject *obj,
|
||||
nsIXPConnectWrappedNative *wrapper,
|
||||
nsIXPCScriptable *arbitrary);
|
||||
|
||||
private:
|
||||
nsJSID mDetails;
|
||||
JSBool mCacheFilled;
|
||||
};
|
||||
|
||||
// nsJSCID
|
||||
|
|
|
@ -80,7 +80,6 @@ XPCJSThrower::ThrowBadResultException(nsresult rv,
|
|||
char* sz;
|
||||
const char* format;
|
||||
const char* name;
|
||||
JSString* str = nsnull;
|
||||
|
||||
/*
|
||||
* If there is a pending exception when the native call returns and
|
||||
|
@ -136,7 +135,6 @@ XPCJSThrower::ThrowBadParamException(nsresult rv,
|
|||
{
|
||||
char* sz;
|
||||
const char* format;
|
||||
JSString* str = nsnull;
|
||||
|
||||
if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format))
|
||||
format = "";
|
||||
|
@ -160,7 +158,6 @@ XPCJSThrower::ThrowException(nsresult rv,
|
|||
{
|
||||
char* sz;
|
||||
const char* format;
|
||||
JSString* str = nsnull;
|
||||
|
||||
if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format))
|
||||
format = "";
|
||||
|
|
|
@ -265,21 +265,18 @@ nsXPCWrappedNativeClass::GetInterfaceName()
|
|||
return mName;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
nsXPCWrappedNativeClass::GetConstantAsJSVal(JSContext *cx,
|
||||
nsXPCWrappedNative* wrapper,
|
||||
const XPCNativeMemberDescriptor* desc,
|
||||
nsIInterfaceInfo* iinfo,
|
||||
PRUint16 index,
|
||||
jsval* vp)
|
||||
{
|
||||
const nsXPTConstant* constant;
|
||||
|
||||
NS_ASSERTION(desc->IsConstant(),"bad type");
|
||||
if(NS_FAILED(mInfo->GetConstant(desc->index, &constant)))
|
||||
{
|
||||
// XXX fail silently?
|
||||
*vp = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
if(NS_FAILED(iinfo->GetConstant(index, &constant)))
|
||||
return JS_FALSE;
|
||||
|
||||
const nsXPTCMiniVariant& mv = *constant->GetValue();
|
||||
|
||||
// XXX Big Hack!
|
||||
|
@ -288,7 +285,6 @@ nsXPCWrappedNativeClass::GetConstantAsJSVal(JSContext *cx,
|
|||
v.type = constant->GetType();
|
||||
memcpy(&v.val, &mv.val, sizeof(mv.val));
|
||||
|
||||
// XXX if iid consts are supported, then conditionally fill it in here
|
||||
return XPCConvert::NativeData2JS(cx, vp, &v.val, v.type, nsnull, nsnull);
|
||||
}
|
||||
|
||||
|
|
|
@ -196,7 +196,11 @@ WrappedNative_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||
if(desc)
|
||||
{
|
||||
if(desc->IsConstant())
|
||||
return clazz->GetConstantAsJSVal(cx, wrapper, desc, vp);
|
||||
{
|
||||
if(!clazz->GetConstantAsJSVal(cx, wrapper, desc, vp))
|
||||
*vp = JSVAL_NULL; //XXX silent failure?
|
||||
return JS_TRUE;
|
||||
}
|
||||
else if(desc->IsMethod())
|
||||
{
|
||||
// allow for lazy creation of 'prototypical' function invoke object
|
||||
|
|
|
@ -824,13 +824,13 @@ int main()
|
|||
|
||||
if(JS_GetProperty(jscontext, glob, "bar", &v) && JSVAL_IS_OBJECT(v))
|
||||
{
|
||||
JSObject* bar = JSVAL_TO_OBJECT(v);
|
||||
nsISupports* wrapper3;
|
||||
// JSObject* bar = JSVAL_TO_OBJECT(v);
|
||||
nsISupports* wrapper4;
|
||||
if(NS_SUCCEEDED(xpc->WrapJS(jscontext,
|
||||
JSVAL_TO_OBJECT(v),
|
||||
nsITestXPCFoo::GetIID(), &wrapper3)))
|
||||
nsITestXPCFoo::GetIID(), &wrapper4)))
|
||||
{
|
||||
nsITestXPCFoo* ptr = (nsITestXPCFoo*)wrapper3;
|
||||
nsITestXPCFoo* ptr = (nsITestXPCFoo*)wrapper4;
|
||||
int result;
|
||||
JSObject* test_js_obj;
|
||||
ptr->Test(11, 13, &result);
|
||||
|
@ -839,7 +839,7 @@ int main()
|
|||
|
||||
nsIXPConnectWrappedJSMethods* methods;
|
||||
|
||||
wrapper3->QueryInterface(nsIXPConnectWrappedJSMethods::GetIID(),
|
||||
wrapper4->QueryInterface(nsIXPConnectWrappedJSMethods::GetIID(),
|
||||
(void**) &methods);
|
||||
methods->GetJSObject(&test_js_obj);
|
||||
|
||||
|
@ -864,7 +864,7 @@ int main()
|
|||
// XPC_DUMP(xpc, 50);
|
||||
|
||||
NS_RELEASE(methods);
|
||||
NS_RELEASE(wrapper3);
|
||||
NS_RELEASE(wrapper4);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,58 @@ xpcstringtest::GetStringC(const char **s)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// quick and dirty!!!
|
||||
static PRUnichar* GetTestWString(int* size)
|
||||
{
|
||||
static PRUnichar* sWStr;
|
||||
static char str[] = "This is part of a long string... ";
|
||||
static const int slen = (sizeof(str)-1)/sizeof(char);
|
||||
static const int rep = 1;
|
||||
static const int space = (slen*rep*sizeof(PRUnichar))+sizeof(PRUnichar);
|
||||
|
||||
if(!sWStr)
|
||||
{
|
||||
sWStr = (PRUnichar*) nsAllocator::Alloc(space);
|
||||
if(sWStr)
|
||||
{
|
||||
PRUnichar* p = sWStr;
|
||||
for(int k = 0; k < rep; k++)
|
||||
for (int i = 0; i < slen; i++)
|
||||
*(p++) = (PRUnichar) str[i];
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
if(size)
|
||||
*size = space;
|
||||
return sWStr;
|
||||
}
|
||||
|
||||
/* void GetWStringCopied ([retval] out wstring s); */
|
||||
NS_IMETHODIMP xpcstringtest::GetWStringCopied(PRUnichar **s)
|
||||
{
|
||||
const char myResult[] = "result of xpcstringtest::GetStringB";
|
||||
|
||||
if(!s)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
int size;
|
||||
PRUnichar* str = GetTestWString(&size);
|
||||
if(!str)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*s = (PRUnichar*) nsAllocator::Clone(str, size);
|
||||
return *s ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* void GetWStringShared ([shared, retval] out wstring s); */
|
||||
NS_IMETHODIMP xpcstringtest::GetWStringShared(const PRUnichar **s)
|
||||
{
|
||||
if(!s)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*s = GetTestWString(nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// static
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
function enum_and_sort(o) {
|
||||
var all = [];
|
||||
for(n in o) all.push(n);
|
||||
all.sort();
|
||||
for(n in all) print(all[n]);
|
||||
print("total count: "+all.length);
|
||||
}
|
||||
|
||||
|
||||
print("enum_and_sort...\n");
|
||||
print(enum_and_sort);
|
||||
print("");
|
||||
|
||||
print("enum_and_sort(Components.results)...\n");
|
||||
enum_and_sort(Components.results);
|
||||
print("");
|
||||
|
||||
print("enum_and_sort(Components.interfaces)...\n");
|
||||
enum_and_sort(Components.interfaces);
|
||||
print("");
|
||||
|
||||
print("enum_and_sort(Components.classes)...\n");
|
||||
enum_and_sort(Components.classes);
|
||||
print("");
|
||||
|
||||
print("enum_and_sort(Components.classesByID)...\n");
|
||||
enum_and_sort(Components.classesByID);
|
||||
print("");
|
|
@ -0,0 +1,15 @@
|
|||
var iface_count = 0;
|
||||
var constant_count = 0;
|
||||
for(var iface_name in Components.interfaces) {
|
||||
var iface = Components.interfaces[iface_name];
|
||||
print(iface_name);
|
||||
var iface_name;
|
||||
for(var const_name in iface) {
|
||||
print(" "+const_name+" = "+iface[const_name])
|
||||
constant_count++;
|
||||
}
|
||||
iface_count++;
|
||||
}
|
||||
print("\n"+iface_count+" interfaces with "+constant_count+" constants");
|
||||
|
||||
|
Загрузка…
Ссылка в новой задаче