Bug 1097267 - Change the enumerate hook usage in XPC and browser. r=bholley

This commit is contained in:
Tom Schuster 2014-12-11 19:31:10 +01:00
Родитель d7ef4e6227
Коммит 9dfe5c2fd4
8 изменённых файлов: 236 добавлений и 385 удалений

Просмотреть файл

@ -1003,9 +1003,9 @@ nsDOMClassInfo::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
}
NS_IMETHODIMP
nsDOMClassInfo::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj, uint32_t enum_op,
jsval *statep, jsid *idp, bool *_retval)
nsDOMClassInfo::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, JS::AutoIdVector &properties,
bool *_retval)
{
NS_WARNING("nsDOMClassInfo::NewEnumerate Don't call me!");

Просмотреть файл

@ -24,6 +24,7 @@ interface nsIXPConnectWrappedNative;
[ptr] native JSValPtr(JS::Value);
[ptr] native JSFreeOpPtr(JSFreeOp);
[ref] native JSCallArgsRef(const JS::CallArgs);
[ref] native JSAutoIdVector(JS::AutoIdVector);
/**
* Note: This is not really an XPCOM interface. For example, callers must
@ -113,7 +114,7 @@ interface nsIXPCScriptable : nsISupports
boolean newEnumerate(in nsIXPConnectWrappedNative wrapper,
in JSContextPtr cx, in JSObjectPtr obj,
in uint32_t enum_op, in JSValPtr statep, out jsid idp);
in JSAutoIdVector properties);
boolean resolve(in nsIXPConnectWrappedNative wrapper,
in JSContextPtr cx, in JSObjectPtr obj, in jsid id,

Просмотреть файл

@ -124,7 +124,7 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::SetProperty(nsIXPConnectWrappedNative *wrapper,
#endif
#ifndef XPC_MAP_WANT_NEWENUMERATE
NS_IMETHODIMP XPC_MAP_CLASSNAME::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, uint32_t enum_op, JS::Value * statep, jsid * idp, bool *_retval)
NS_IMETHODIMP XPC_MAP_CLASSNAME::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, JS::AutoIdVector &properties, bool *_retval)
{NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
#endif

Просмотреть файл

@ -239,55 +239,49 @@ NS_IMPL_RELEASE(nsXPCComponents_Interfaces)
#include "xpc_map_end.h" /* This will #undef the above */
/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
NS_IMETHODIMP
nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
uint32_t enum_op, jsval * statep,
jsid * idp, bool *_retval)
JSContext *cx, JSObject *obj,
JS::AutoIdVector &properties,
bool *_retval)
{
switch (enum_op) {
case JSENUMERATE_INIT:
case JSENUMERATE_INIT_ALL:
{
// Lazily init the list of interfaces when someone tries to
// enumerate them.
if (mInterfaces.IsEmpty()) {
XPTInterfaceInfoManager::GetSingleton()->
GetScriptableInterfaces(mInterfaces);
}
*statep = JSVAL_ZERO;
if (idp)
*idp = INT_TO_JSID(mInterfaces.Length());
return NS_OK;
}
case JSENUMERATE_NEXT:
{
uint32_t idx = statep->toInt32();
nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
*statep = UINT_TO_JSVAL(idx + 1);
if (interface) {
const char* name;
RootedId id(cx);
if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name) {
RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
if (idstr && JS_StringToId(cx, idstr, &id)) {
*idp = id;
return NS_OK;
}
}
}
// fall through
}
case JSENUMERATE_DESTROY:
default:
*statep = JSVAL_NULL;
return NS_OK;
// Lazily init the list of interfaces when someone tries to
// enumerate them.
if (mInterfaces.IsEmpty()) {
XPTInterfaceInfoManager::GetSingleton()->
GetScriptableInterfaces(mInterfaces);
}
if (!properties.reserve(mInterfaces.Length())) {
*_retval = false;
return NS_OK;
}
for (uint32_t index = 0; index < mInterfaces.Length(); index++) {
nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(index);
if (!interface)
continue;
const char* name;
if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name) {
RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
if (!idstr) {
*_retval = false;
return NS_OK;
}
RootedId id(cx);
if (!JS_StringToId(cx, idstr, &id)) {
*_retval = false;
return NS_OK;
}
properties.infallibleAppend(id);
}
}
return NS_OK;
}
NS_IMETHODIMP
@ -487,56 +481,49 @@ NS_IMPL_RELEASE(nsXPCComponents_InterfacesByID)
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
#include "xpc_map_end.h" /* This will #undef the above */
/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
NS_IMETHODIMP
nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
uint32_t enum_op, jsval * statep,
jsid * idp, bool *_retval)
JSContext *cx, JSObject *obj,
JS::AutoIdVector &properties,
bool *_retval)
{
switch (enum_op) {
case JSENUMERATE_INIT:
case JSENUMERATE_INIT_ALL:
{
// Lazily init the list of interfaces when someone tries to
// enumerate them.
if (mInterfaces.IsEmpty()) {
XPTInterfaceInfoManager::GetSingleton()->
GetScriptableInterfaces(mInterfaces);
}
*statep = JSVAL_ZERO;
if (idp)
*idp = INT_TO_JSID(mInterfaces.Length());
return NS_OK;
}
case JSENUMERATE_NEXT:
{
uint32_t idx = statep->toInt32();
nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
*statep = UINT_TO_JSVAL(idx + 1);
if (interface) {
nsIID const *iid;
char idstr[NSID_LENGTH];
if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) {
iid->ToProvidedString(idstr);
RootedString jsstr(cx, JS_NewStringCopyZ(cx, idstr));
RootedId id(cx);
if (jsstr && JS_StringToId(cx, jsstr, &id)) {
*idp = id;
return NS_OK;
}
}
}
// FALL THROUGH
}
case JSENUMERATE_DESTROY:
default:
*statep = JSVAL_NULL;
return NS_OK;
if (mInterfaces.IsEmpty()) {
XPTInterfaceInfoManager::GetSingleton()->
GetScriptableInterfaces(mInterfaces);
}
if (!properties.reserve(mInterfaces.Length())) {
*_retval = false;
return NS_OK;
}
for (uint32_t index = 0; index < mInterfaces.Length(); index++) {
nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(index);
if (!interface)
continue;
nsIID const *iid;
if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) {
char idstr[NSID_LENGTH];
iid->ToProvidedString(idstr);
RootedString jsstr(cx, JS_NewStringCopyZ(cx, idstr));
if (!jsstr) {
*_retval = false;
return NS_OK;
}
RootedId id(cx);
if (!JS_StringToId(cx, jsstr, &id)) {
*_retval = false;
return NS_OK;
}
properties.infallibleAppend(id);
}
}
return NS_OK;
}
NS_IMETHODIMP
@ -738,63 +725,50 @@ NS_IMPL_RELEASE(nsXPCComponents_Classes)
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
#include "xpc_map_end.h" /* This will #undef the above */
/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
NS_IMETHODIMP
nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
uint32_t enum_op, jsval * statep,
jsid * idp, bool *_retval)
JSContext *cx, JSObject *obj,
JS::AutoIdVector &properties,
bool *_retval)
{
nsISimpleEnumerator* e;
nsCOMPtr<nsIComponentRegistrar> compMgr;
if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr)
return NS_ERROR_UNEXPECTED;
switch (enum_op) {
case JSENUMERATE_INIT:
case JSENUMERATE_INIT_ALL:
{
nsCOMPtr<nsIComponentRegistrar> compMgr;
if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
NS_FAILED(compMgr->EnumerateContractIDs(&e)) || !e ) {
*statep = JSVAL_NULL;
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsISimpleEnumerator> e;
if (NS_FAILED(compMgr->EnumerateContractIDs(getter_AddRefs(e))) || !e)
return NS_ERROR_UNEXPECTED;
bool hasMore;
nsCOMPtr<nsISupports> isup;
while(NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
if (!holder)
continue;
nsAutoCString name;
if (NS_SUCCEEDED(holder->GetData(name))) {
RootedString idstr(cx, JS_NewStringCopyN(cx, name.get(), name.Length()));
if (!idstr) {
*_retval = false;
return NS_OK;
}
*statep = PRIVATE_TO_JSVAL(e);
if (idp)
*idp = INT_TO_JSID(0); // indicate that we don't know the count
return NS_OK;
}
case JSENUMERATE_NEXT:
{
nsCOMPtr<nsISupports> isup;
bool hasMore;
e = (nsISimpleEnumerator*) statep->toPrivate();
if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
if (holder) {
nsAutoCString name;
if (NS_SUCCEEDED(holder->GetData(name))) {
RootedString idstr(cx, JS_NewStringCopyN(cx, name.get(), name.Length()));
RootedId id(cx);
if (idstr && JS_StringToId(cx, idstr, &id)) {
*idp = id;
return NS_OK;
}
}
}
RootedId id(cx);
if (!JS_StringToId(cx, idstr, &id)) {
*_retval = false;
return NS_OK;
}
// else... FALL THROUGH
}
case JSENUMERATE_DESTROY:
default:
e = (nsISimpleEnumerator*) statep->toPrivate();
NS_IF_RELEASE(e);
*statep = JSVAL_NULL;
return NS_OK;
if (!properties.append(id)) {
*_retval = false;
return NS_OK;
}
}
}
return NS_OK;
}
NS_IMETHODIMP
@ -977,63 +951,51 @@ NS_IMPL_RELEASE(nsXPCComponents_ClassesByID)
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
#include "xpc_map_end.h" /* This will #undef the above */
/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
NS_IMETHODIMP
nsXPCComponents_ClassesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
uint32_t enum_op, jsval * statep,
jsid * idp, bool *_retval)
JSContext *cx, JSObject *obj,
JS::AutoIdVector &properties,
bool *_retval)
{
nsCOMPtr<nsIComponentRegistrar> compMgr;
if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr)
return NS_ERROR_UNEXPECTED;
nsISimpleEnumerator* e;
if (NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e)
return NS_ERROR_UNEXPECTED;
switch (enum_op) {
case JSENUMERATE_INIT:
case JSENUMERATE_INIT_ALL:
{
nsCOMPtr<nsIComponentRegistrar> compMgr;
if (NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e ) {
*statep = JSVAL_NULL;
return NS_ERROR_UNEXPECTED;
bool hasMore;
nsCOMPtr<nsISupports> isup;
while(NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
if (!holder)
continue;
char* name;
if (NS_SUCCEEDED(holder->ToString(&name)) && name) {
RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
if (!idstr) {
*_retval = false;
return NS_OK;
}
*statep = PRIVATE_TO_JSVAL(e);
if (idp)
*idp = INT_TO_JSID(0); // indicate that we don't know the count
return NS_OK;
}
case JSENUMERATE_NEXT:
{
nsCOMPtr<nsISupports> isup;
bool hasMore;
e = (nsISimpleEnumerator*) statep->toPrivate();
if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
if (holder) {
char* name;
if (NS_SUCCEEDED(holder->ToString(&name)) && name) {
RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
nsMemory::Free(name);
RootedId id(cx);
if (idstr && JS_StringToId(cx, idstr, &id)) {
*idp = id;
return NS_OK;
}
}
}
RootedId id(cx);
if (!JS_StringToId(cx, idstr, &id)) {
*_retval = false;
return NS_OK;
}
// else... FALL THROUGH
}
case JSENUMERATE_DESTROY:
default:
e = (nsISimpleEnumerator*) statep->toPrivate();
NS_IF_RELEASE(e);
*statep = JSVAL_NULL;
return NS_OK;
if (!properties.append(id)) {
*_retval = false;
return NS_OK;
}
}
}
return NS_OK;
}
static bool
@ -1240,49 +1202,34 @@ NS_IMPL_RELEASE(nsXPCComponents_Results)
#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
#include "xpc_map_end.h" /* This will #undef the above */
/* bool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in uint32_t enum_op, in JSValPtr statep, out JSID idp); */
NS_IMETHODIMP
nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
uint32_t enum_op, jsval * statep,
jsid * idp, bool *_retval)
JSContext *cx, JSObject *obj,
JS::AutoIdVector &properties,
bool *_retval)
{
const void** iter;
switch (enum_op) {
case JSENUMERATE_INIT:
case JSENUMERATE_INIT_ALL:
{
if (idp)
*idp = INT_TO_JSID(nsXPCException::GetNSResultCount());
void** space = (void**) new char[sizeof(void*)];
*space = nullptr;
*statep = PRIVATE_TO_JSVAL(space);
const char* name;
const void* iter = nullptr;
while (nsXPCException::IterateNSResults(nullptr, &name, nullptr, &iter)) {
RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
if (!idstr) {
*_retval = false;
return NS_OK;
}
case JSENUMERATE_NEXT:
{
const char* name;
iter = (const void**) statep->toPrivate();
if (nsXPCException::IterateNSResults(nullptr, &name, nullptr, iter)) {
RootedString idstr(cx, JS_NewStringCopyZ(cx, name));
JS::RootedId id(cx);
if (idstr && JS_StringToId(cx, idstr, &id)) {
*idp = id;
return NS_OK;
}
}
// else... FALL THROUGH
RootedId id(cx);
if (!JS_StringToId(cx, idstr, &id)) {
*_retval = false;
return NS_OK;
}
case JSENUMERATE_DESTROY:
default:
iter = (const void**) statep->toPrivate();
delete [] (char*) iter;
*statep = JSVAL_NULL;
if (!properties.append(id)) {
*_retval = false;
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -698,7 +698,7 @@ const XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
nullptr, // deleteGeneric
nullptr, nullptr, // watch/unwatch
nullptr, // getElements
XPC_WN_JSOp_Enumerate,
nullptr, // enumerate
XPC_WN_JSOp_ThisObject,
}
}
@ -928,118 +928,48 @@ XPC_WN_Helper_Resolve(JSContext *cx, HandleObject obj, HandleId id, bool *resolv
return retval;
}
/***************************************************************************/
/*
Here are the enumerator cases:
set jsclass enumerate to stub (unless noted otherwise)
if ( helper wants new enumerate )
if ( DONT_ENUM_STATICS )
forward to scriptable enumerate
else
if ( set not mutated )
forward to scriptable enumerate
else
call shared enumerate
forward to scriptable enumerate
else if ( helper wants old enumerate )
use this JSOp
if ( DONT_ENUM_STATICS )
call scriptable enumerate
call stub
else
if ( set not mutated )
call scriptable enumerate
call stub
else
call shared enumerate
call scriptable enumerate
call stub
else //... if ( helper wants NO enumerate )
if ( DONT_ENUM_STATICS )
use enumerate stub - don't use this JSOp thing at all
else
do shared enumerate - don't use this JSOp thing at all
*/
bool
XPC_WN_JSOp_Enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
MutableHandleValue statep, MutableHandleId idp)
static bool
XPC_WN_Helper_Enumerate(JSContext *cx, HandleObject obj)
{
const js::Class *clazz = js::GetObjectClass(obj);
if (!IS_WN_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) {
// obj must be a prototype object or a wrapper w/o a
// helper. Short circuit this call to the default
// implementation.
return JS_EnumerateState(cx, obj, enum_op, statep, idp);
}
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
if (!si)
if (!si || !si->GetFlags().WantEnumerate())
return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
if (!XPC_WN_Shared_Enumerate(cx, obj))
return false;
bool retval = true;
nsresult rv;
nsresult rv = si->GetCallback()->Enumerate(wrapper, cx, obj, &retval);
if (NS_FAILED(rv))
return Throw(rv, cx);
return retval;
}
if (si->GetFlags().WantNewEnumerate()) {
// XXXevilpie I am like 80% sure that has no effect on what is actually
// enumerated.
// The loop in jsiter.cpp will only put stuff that is actually in idp
// into the property id array.
if (enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) {
if (wrapper->HasMutatedSet() &&
!XPC_WN_Shared_Enumerate(cx, obj)) {
statep.set(JSVAL_NULL);
return false;
}
}
/***************************************************************************/
rv = si->GetCallback()->
NewEnumerate(wrapper, cx, obj, enum_op, statep.address(), idp.address(), &retval);
static bool
XPC_WN_JSOp_Enumerate(JSContext *cx, HandleObject obj, AutoIdVector &properties)
{
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
if ((enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) &&
(NS_FAILED(rv) || !retval)) {
statep.set(JSVAL_NULL);
}
XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
if (!si || !si->GetFlags().WantNewEnumerate())
return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
if (NS_FAILED(rv))
return Throw(rv, cx);
return retval;
}
if (!XPC_WN_Shared_Enumerate(cx, obj))
return false;
if (si->GetFlags().WantEnumerate()) {
if (enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) {
if (wrapper->HasMutatedSet() &&
!XPC_WN_Shared_Enumerate(cx, obj)) {
statep.set(JSVAL_NULL);
return false;
}
rv = si->GetCallback()->
Enumerate(wrapper, cx, obj, &retval);
if (NS_FAILED(rv) || !retval)
statep.set(JSVAL_NULL);
if (NS_FAILED(rv))
return Throw(rv, cx);
if (!retval)
return false;
// Then fall through and call the default implementation...
}
}
// else call js_ObjectOps.enumerate...
return JS_EnumerateState(cx, obj, enum_op, statep, idp);
bool retval = true;
nsresult rv = si->GetCallback()->NewEnumerate(wrapper, cx, obj, properties, &retval);
if (NS_FAILED(rv))
return Throw(rv, cx);
return retval;
}
JSObject*
@ -1131,10 +1061,14 @@ XPCNativeScriptableShared::PopulateJSClass()
setProperty = XPC_WN_CannotModifyStrictPropertyStub;
mJSClass.base.setProperty = setProperty;
// We figure out most of the enumerate strategy at call time.
MOZ_ASSERT_IF(mFlags.WantEnumerate(), !mFlags.WantNewEnumerate());
MOZ_ASSERT_IF(mFlags.WantNewEnumerate(), !mFlags.WantEnumerate());
if (mFlags.WantNewEnumerate() || mFlags.WantEnumerate())
// We will use ops->enumerate set below for NewEnumerate
if (mFlags.WantNewEnumerate())
mJSClass.base.enumerate = nullptr;
else if (mFlags.WantEnumerate())
mJSClass.base.enumerate = XPC_WN_Helper_Enumerate;
else
mJSClass.base.enumerate = XPC_WN_Shared_Enumerate;
@ -1152,7 +1086,8 @@ XPCNativeScriptableShared::PopulateJSClass()
mJSClass.base.finalize = XPC_WN_NoHelper_Finalize;
js::ObjectOps *ops = &mJSClass.base.ops;
ops->enumerate = XPC_WN_JSOp_Enumerate;
if (mFlags.WantNewEnumerate())
ops->enumerate = XPC_WN_JSOp_Enumerate;
ops->thisObject = XPC_WN_JSOp_ThisObject;

Просмотреть файл

@ -948,10 +948,6 @@ XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp);
extern bool
XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp);
extern bool
XPC_WN_JSOp_Enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp enum_op,
JS::MutableHandleValue statep, JS::MutableHandleId idp);
extern JSObject*
XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
@ -975,7 +971,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
nullptr, /* deleteGeneric */ \
nullptr, nullptr, /* watch/unwatch */ \
nullptr, /* getElements */ \
XPC_WN_JSOp_Enumerate, \
nullptr, /* enumerate */ \
XPC_WN_JSOp_ThisObject, \
}
@ -998,7 +994,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
nullptr, /* deleteGeneric */ \
nullptr, nullptr, /* watch/unwatch */ \
nullptr, /* getElements */ \
XPC_WN_JSOp_Enumerate, \
nullptr, /* enumerate */ \
XPC_WN_JSOp_ThisObject, \
}

Просмотреть файл

@ -89,67 +89,36 @@ NS_IMETHODIMP
StatementParams::NewEnumerate(nsIXPConnectWrappedNative *aWrapper,
JSContext *aCtx,
JSObject *aScopeObj,
uint32_t aEnumOp,
jsval *_statep,
jsid *_idp,
JS::AutoIdVector &aProperties,
bool *_retval)
{
NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
JS::RootedObject scope(aCtx, aScopeObj);
switch (aEnumOp) {
case JSENUMERATE_INIT:
case JSENUMERATE_INIT_ALL:
{
// Start our internal index at zero.
*_statep = JSVAL_ZERO;
if (!aProperties.reserve(mParamCount)) {
*_retval = false;
return NS_OK;
}
// And set our length, if needed.
if (_idp)
*_idp = INT_TO_JSID(mParamCount);
for (uint32_t i = 0; i < mParamCount; i++) {
// Get the name of our parameter.
nsAutoCString name;
nsresult rv = mStatement->GetParameterName(i, name);
NS_ENSURE_SUCCESS(rv, rv);
break;
// But drop the first character, which is going to be a ':'.
JS::RootedString jsname(aCtx, ::JS_NewStringCopyN(aCtx, &(name.get()[1]),
name.Length() - 1));
NS_ENSURE_TRUE(jsname, NS_ERROR_OUT_OF_MEMORY);
// Set our name.
JS::Rooted<jsid> id(aCtx);
if (!::JS_StringToId(aCtx, jsname, &id)) {
*_retval = false;
return NS_OK;
}
case JSENUMERATE_NEXT:
{
NS_ASSERTION(*_statep != JSVAL_NULL, "Internal state is null!");
// Make sure we are in range first.
uint32_t index = static_cast<uint32_t>(_statep->toInt32());
if (index >= mParamCount) {
*_statep = JSVAL_NULL;
return NS_OK;
}
// Get the name of our parameter.
nsAutoCString name;
nsresult rv = mStatement->GetParameterName(index, name);
NS_ENSURE_SUCCESS(rv, rv);
// But drop the first character, which is going to be a ':'.
JS::RootedString jsname(aCtx, ::JS_NewStringCopyN(aCtx, &(name.get()[1]),
name.Length() - 1));
NS_ENSURE_TRUE(jsname, NS_ERROR_OUT_OF_MEMORY);
// Set our name.
JS::Rooted<jsid> id(aCtx);
if (!::JS_StringToId(aCtx, jsname, &id)) {
*_retval = false;
return NS_OK;
}
*_idp = id;
// And increment our index.
*_statep = INT_TO_JSVAL(++index);
break;
}
case JSENUMERATE_DESTROY:
{
// Clear our state.
*_statep = JSVAL_NULL;
break;
}
aProperties.infallibleAppend(id);
}
return NS_OK;

Просмотреть файл

@ -21,8 +21,11 @@ function test_params_enumerate()
// Make sure they are right.
let expected = ["a", "b", "c"];
let index = 0;
for (let name in stmt.params)
for (let name in stmt.params) {
if (name == "QueryInterface")
continue;
do_check_eq(name, expected[index++]);
}
}
function test_params_prototype()