Bug 728423 - Fix warnings in js/src related to JSObject::asString et al (r=luke)

--HG--
extra : rebase_source : 8b64d2593d684a4e5d0d1ee87072db03afb78efe
This commit is contained in:
Jeff Walden 2012-02-20 13:56:10 -08:00
parent c9d1a52e78
commit 294b5f03eb
21 changed files with 356 additions and 182 deletions

View File

@ -153,6 +153,7 @@ CPPSRCS = \
ScopeObject.cpp \
Debugger.cpp \
GlobalObject.cpp \
MethodGuard.cpp \
Stack.cpp \
String.cpp \
BytecodeCompiler.cpp \

View File

@ -45,6 +45,7 @@
#include "jsobj.h"
#include "vm/GlobalObject.h"
#include "vm/MethodGuard.h"
#include "vm/Stack.h"
#include "jsobjinlines.h"

View File

@ -42,6 +42,7 @@
#include "builtin/RegExp.h"
#include "vm/MethodGuard-inl.h"
#include "vm/RegExpObject-inl.h"
#include "vm/RegExpStatics-inl.h"

View File

@ -92,6 +92,7 @@
#include "js/MemoryMetrics.h"
#include "mozilla/Util.h"
#include "yarr/BumpPointerAllocator.h"
#include "vm/MethodGuard.h"
#include "jsatominlines.h"
#include "jsinferinlines.h"

View File

@ -127,6 +127,7 @@
#include "methodjit/StubCalls-inl.h"
#include "vm/ArgumentsObject.h"
#include "vm/MethodGuard.h"
#include "ds/Sort.h"

View File

@ -53,13 +53,15 @@
#include "jsobj.h"
#include "jsstr.h"
#include "vm/BooleanObject-inl.h"
#include "vm/GlobalObject.h"
#include "jsinferinlines.h"
#include "jsobjinlines.h"
#include "jsstrinlines.h"
#include "vm/BooleanObject-inl.h"
#include "vm/MethodGuard-inl.h"
using namespace js;
using namespace js::types;

View File

@ -79,6 +79,7 @@
#include "jsobjinlines.h"
#include "jsstrinlines.h"
#include "vm/MethodGuard-inl.h"
#include "vm/Stack-inl.h"
using namespace mozilla;

View File

@ -71,8 +71,9 @@
#include "frontend/BytecodeCompiler.h"
#include "frontend/BytecodeEmitter.h"
#include "frontend/TokenStream.h"
#include "vm/ScopeObject.h"
#include "vm/Debugger.h"
#include "vm/MethodGuard.h"
#include "vm/ScopeObject.h"
#if JS_HAS_GENERATORS
# include "jsiter.h"
@ -91,8 +92,8 @@
#include "jsinferinlines.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"
#include "vm/ScopeObject-inl.h"
#include "vm/ArgumentsObject-inl.h"
#include "vm/ScopeObject-inl.h"
#include "vm/Stack-inl.h"
using namespace mozilla;

View File

@ -76,6 +76,7 @@
#include "jsinferinlines.h"
#include "jsobjinlines.h"
#include "vm/MethodGuard-inl.h"
#include "vm/Stack-inl.h"
#include "vm/String-inl.h"

View File

@ -72,6 +72,7 @@
#include "jslibmath.h"
#include "vm/GlobalObject.h"
#include "vm/MethodGuard.h"
#include "jsatominlines.h"
#include "jsinferinlines.h"
@ -79,6 +80,7 @@
#include "jsobjinlines.h"
#include "jsstrinlines.h"
#include "vm/MethodGuard-inl.h"
#include "vm/NumberObject-inl.h"
#include "vm/String-inl.h"

View File

@ -90,9 +90,7 @@
#include "jsscriptinlines.h"
#include "jsstrinlines.h"
#include "vm/BooleanObject-inl.h"
#include "vm/NumberObject-inl.h"
#include "vm/StringObject-inl.h"
#include "vm/MethodGuard-inl.h"
#if JS_HAS_GENERATORS
#include "jsiter.h"
@ -6361,49 +6359,6 @@ js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
return JS_FALSE;
}
void
js::ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp)
{
Value &thisv = call.thisv();
#ifdef DEBUG
if (thisv.isObject()) {
JS_ASSERT(thisv.toObject().getClass() != clasp ||
!thisv.toObject().getProto() ||
thisv.toObject().getProto()->getClass() != clasp);
} else if (thisv.isString()) {
JS_ASSERT(clasp != &StringClass);
} else if (thisv.isNumber()) {
JS_ASSERT(clasp != &NumberClass);
} else if (thisv.isBoolean()) {
JS_ASSERT(clasp != &BooleanClass);
} else {
JS_ASSERT(thisv.isUndefined() || thisv.isNull());
}
#endif
if (JSFunction *fun = js_ValueToFunction(cx, &call.calleev(), 0)) {
JSAutoByteString funNameBytes;
if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
clasp->name, funName, InformalValueTypeName(thisv));
}
}
}
bool
js::HandleNonGenericMethodClassMismatch(JSContext *cx, CallArgs args, Native native, Class *clasp)
{
if (args.thisv().isObject()) {
JSObject &thisObj = args.thisv().toObject();
if (thisObj.isProxy())
return Proxy::nativeCall(cx, &thisObj, clasp, native, args);
}
ReportIncompatibleMethod(cx, args, clasp);
return false;
}
#ifdef DEBUG
/*

View File

@ -2030,71 +2030,6 @@ NonNullObject(JSContext *cx, const Value &v);
extern const char *
InformalValueTypeName(const Value &v);
/*
* Report an error if call.thisv is not compatible with the specified class.
*
* NB: most callers should be calling or NonGenericMethodGuard,
* HandleNonGenericMethodClassMismatch, or BoxedPrimitiveMethodGuard (so that
* transparent proxies are handled correctly). Thus, any caller of this
* function better have a good explanation for why proxies are being handled
* correctly (e.g., by IsCallable) or are not an issue (E4X).
*/
extern void
ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp);
/*
* A non-generic method is specified to report an error if args.thisv is not an
* object with a specific [[Class]] internal property (ES5 8.6.2).
* NonGenericMethodGuard performs this checking. Canonical usage is:
*
* CallArgs args = ...
* bool ok;
* JSObject *thisObj = NonGenericMethodGuard(cx, args, clasp, &ok);
* if (!thisObj)
* return ok;
*
* Specifically: if obj is a proxy, NonGenericMethodGuard will call the
* object's ProxyHandler's nativeCall hook (which may recursively call
* args.callee in args.thisv's compartment). Thus, there are three possible
* post-conditions:
*
* 1. thisv is an object of the given clasp: the caller may proceed;
*
* 2. there was an error: the caller must return 'false';
*
* 3. thisv wrapped an object of the given clasp and the native was reentered
* and completed succesfully: the caller must return 'true'.
*
* Case 1 is indicated by a non-NULL return value; case 2 by a NULL return
* value with *ok == false; and case 3 by a NULL return value with *ok == true.
*
* NB: since this guard may reenter the native, the guard must be placed before
* any effectful operations are performed.
*/
inline JSObject *
NonGenericMethodGuard(JSContext *cx, CallArgs args, Native native, Class *clasp, bool *ok);
/*
* NonGenericMethodGuard tests args.thisv's class using 'clasp'. If more than
* one class is acceptable (viz., isDenseArray() || isSlowArray()), the caller
* may test the class and delegate to HandleNonGenericMethodClassMismatch to
* handle the proxy case and error reporting. The 'clasp' argument is only used
* for error reporting (clasp->name).
*/
extern bool
HandleNonGenericMethodClassMismatch(JSContext *cx, CallArgs args, Native native, Class *clasp);
/*
* Implement the extraction of a primitive from a value as needed for the
* toString, valueOf, and a few other methods of the boxed primitives classes
* Boolean, Number, and String (e.g., ES5 15.6.4.2). If 'true' is returned, the
* extracted primitive is stored in |*v|. If 'false' is returned, the caller
* must immediately 'return *ok'. For details, see NonGenericMethodGuard.
*/
template <typename T>
inline bool
BoxedPrimitiveMethodGuard(JSContext *cx, CallArgs args, Native native, T *v, bool *ok);
} /* namespace js */
#endif /* jsobj_h___ */

View File

@ -1915,74 +1915,6 @@ PropDesc::checkSetter(JSContext *cx)
return true;
}
namespace detail {
template<typename T> class PrimitiveBehavior { };
template<>
class PrimitiveBehavior<JSString *> {
public:
static inline bool isType(const Value &v) { return v.isString(); }
static inline JSString *extract(const Value &v) { return v.toString(); }
static inline JSString *extract(JSObject &obj) { return obj.asString().unbox(); }
static inline Class *getClass() { return &StringClass; }
};
template<>
class PrimitiveBehavior<bool> {
public:
static inline bool isType(const Value &v) { return v.isBoolean(); }
static inline bool extract(const Value &v) { return v.toBoolean(); }
static inline bool extract(JSObject &obj) { return obj.asBoolean().unbox(); }
static inline Class *getClass() { return &BooleanClass; }
};
template<>
class PrimitiveBehavior<double> {
public:
static inline bool isType(const Value &v) { return v.isNumber(); }
static inline double extract(const Value &v) { return v.toNumber(); }
static inline double extract(JSObject &obj) { return obj.asNumber().unbox(); }
static inline Class *getClass() { return &NumberClass; }
};
} /* namespace detail */
inline JSObject *
NonGenericMethodGuard(JSContext *cx, CallArgs args, Native native, Class *clasp, bool *ok)
{
const Value &thisv = args.thisv();
if (thisv.isObject()) {
JSObject &obj = thisv.toObject();
if (obj.getClass() == clasp) {
*ok = true; /* quell gcc overwarning */
return &obj;
}
}
*ok = HandleNonGenericMethodClassMismatch(cx, args, native, clasp);
return NULL;
}
template <typename T>
inline bool
BoxedPrimitiveMethodGuard(JSContext *cx, CallArgs args, Native native, T *v, bool *ok)
{
typedef detail::PrimitiveBehavior<T> Behavior;
const Value &thisv = args.thisv();
if (Behavior::isType(thisv)) {
*v = Behavior::extract(thisv);
return true;
}
if (!NonGenericMethodGuard(cx, args, native, Behavior::getClass(), ok))
return false;
*v = Behavior::extract(thisv.toObject());
return true;
}
inline bool
ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx)
{

View File

@ -50,6 +50,8 @@
#include "jsproxy.h"
#include "jsscope.h"
#include "vm/MethodGuard.h"
#include "jsatominlines.h"
#include "jsinferinlines.h"
#include "jsobjinlines.h"

View File

@ -81,6 +81,7 @@
#include "jsobjinlines.h"
#include "jsautooplen.h" // generated headers last
#include "vm/MethodGuard-inl.h"
#include "vm/RegExpObject-inl.h"
#include "vm/RegExpStatics-inl.h"
#include "vm/StringObject-inl.h"

View File

@ -67,6 +67,8 @@
#include "jsobjinlines.h"
#include "jstypedarrayinlines.h"
#include "vm/MethodGuard-inl.h"
using namespace mozilla;
using namespace js;
using namespace js::gc;

View File

@ -54,6 +54,8 @@
#include "jsgcinlines.h"
#include "jsobjinlines.h"
#include "vm/MethodGuard-inl.h"
using namespace js;
namespace js {

View File

@ -70,6 +70,7 @@
#include "frontend/Parser.h"
#include "frontend/TokenStream.h"
#include "vm/GlobalObject.h"
#include "vm/MethodGuard.h"
#include "jsatominlines.h"
#include "jsinferinlines.h"

125
js/src/vm/MethodGuard-inl.h Normal file
View File

@ -0,0 +1,125 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey method-guard code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef MethodGuard_inl_h___
#define MethodGuard_inl_h___
#include "jsobj.h"
#include "MethodGuard.h"
#include "jsobjinlines.h"
#include "BooleanObject-inl.h"
#include "NumberObject-inl.h"
#include "StringObject-inl.h"
namespace js {
namespace detail {
template<typename T> class PrimitiveBehavior { };
template<>
class PrimitiveBehavior<bool> {
public:
static inline bool isType(const Value &v) { return v.isBoolean(); }
static inline bool extract(const Value &v) { return v.toBoolean(); }
static inline bool extract(JSObject &obj) { return obj.asBoolean().unbox(); }
static inline Class *getClass() { return &BooleanClass; }
};
template<>
class PrimitiveBehavior<double> {
public:
static inline bool isType(const Value &v) { return v.isNumber(); }
static inline double extract(const Value &v) { return v.toNumber(); }
static inline double extract(JSObject &obj) { return obj.asNumber().unbox(); }
static inline Class *getClass() { return &NumberClass; }
};
template<>
class PrimitiveBehavior<JSString *> {
public:
static inline bool isType(const Value &v) { return v.isString(); }
static inline JSString *extract(const Value &v) { return v.toString(); }
static inline JSString *extract(JSObject &obj) { return obj.asString().unbox(); }
static inline Class *getClass() { return &StringClass; }
};
} /* namespace detail */
inline JSObject *
NonGenericMethodGuard(JSContext *cx, CallArgs args, Native native, Class *clasp, bool *ok)
{
const Value &thisv = args.thisv();
if (thisv.isObject()) {
JSObject &obj = thisv.toObject();
if (obj.getClass() == clasp) {
*ok = true; /* quell gcc overwarning */
return &obj;
}
}
*ok = HandleNonGenericMethodClassMismatch(cx, args, native, clasp);
return NULL;
}
template <typename T>
inline bool
BoxedPrimitiveMethodGuard(JSContext *cx, CallArgs args, Native native, T *v, bool *ok)
{
typedef detail::PrimitiveBehavior<T> Behavior;
const Value &thisv = args.thisv();
if (Behavior::isType(thisv)) {
*v = Behavior::extract(thisv);
return true;
}
if (!NonGenericMethodGuard(cx, args, native, Behavior::getClass(), ok))
return false;
*v = Behavior::extract(thisv.toObject());
return true;
}
} /* namespace js */
#endif /* MethodGuard_inl_h___ */

91
js/src/vm/MethodGuard.cpp Normal file
View File

@ -0,0 +1,91 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey method-guard code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "jsproxy.h"
#include "MethodGuard.h"
#include "Stack.h"
#include "jsfuninlines.h"
#include "jsobjinlines.h"
using namespace js;
void
js::ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp)
{
Value &thisv = call.thisv();
#ifdef DEBUG
if (thisv.isObject()) {
JS_ASSERT(thisv.toObject().getClass() != clasp ||
!thisv.toObject().getProto() ||
thisv.toObject().getProto()->getClass() != clasp);
} else if (thisv.isString()) {
JS_ASSERT(clasp != &StringClass);
} else if (thisv.isNumber()) {
JS_ASSERT(clasp != &NumberClass);
} else if (thisv.isBoolean()) {
JS_ASSERT(clasp != &BooleanClass);
} else {
JS_ASSERT(thisv.isUndefined() || thisv.isNull());
}
#endif
if (JSFunction *fun = js_ValueToFunction(cx, &call.calleev(), 0)) {
JSAutoByteString funNameBytes;
if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
clasp->name, funName, InformalValueTypeName(thisv));
}
}
}
bool
js::HandleNonGenericMethodClassMismatch(JSContext *cx, CallArgs args, Native native, Class *clasp)
{
if (args.thisv().isObject()) {
JSObject &thisObj = args.thisv().toObject();
if (thisObj.isProxy())
return Proxy::nativeCall(cx, &thisObj, clasp, native, args);
}
ReportIncompatibleMethod(cx, args, clasp);
return false;
}

116
js/src/vm/MethodGuard.h Normal file
View File

@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey method-guard code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Method prologue type-checking and unwrapping of the this parameter. */
#ifndef MethodGuard_h___
#define MethodGuard_h___
#include "jsobj.h"
namespace js {
/*
* Report an error if call.thisv is not compatible with the specified class.
*
* NB: most callers should be calling or NonGenericMethodGuard,
* HandleNonGenericMethodClassMismatch, or BoxedPrimitiveMethodGuard (so that
* transparent proxies are handled correctly). Thus, any caller of this
* function better have a good explanation for why proxies are being handled
* correctly (e.g., by IsCallable) or are not an issue (E4X).
*/
extern void
ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp);
/*
* A non-generic method is specified to report an error if args.thisv is not an
* object with a specific [[Class]] internal property (ES5 8.6.2).
* NonGenericMethodGuard performs this checking. Canonical usage is:
*
* CallArgs args = ...
* bool ok;
* JSObject *thisObj = NonGenericMethodGuard(cx, args, clasp, &ok);
* if (!thisObj)
* return ok;
*
* Specifically: if obj is a proxy, NonGenericMethodGuard will call the
* object's ProxyHandler's nativeCall hook (which may recursively call
* args.callee in args.thisv's compartment). Thus, there are three possible
* post-conditions:
*
* 1. thisv is an object of the given clasp: the caller may proceed;
*
* 2. there was an error: the caller must return 'false';
*
* 3. thisv wrapped an object of the given clasp and the native was reentered
* and completed succesfully: the caller must return 'true'.
*
* Case 1 is indicated by a non-NULL return value; case 2 by a NULL return
* value with *ok == false; and case 3 by a NULL return value with *ok == true.
*
* NB: since this guard may reenter the native, the guard must be placed before
* any effectful operations are performed.
*/
inline JSObject *
NonGenericMethodGuard(JSContext *cx, CallArgs args, Native native, Class *clasp, bool *ok);
/*
* NonGenericMethodGuard tests args.thisv's class using 'clasp'. If more than
* one class is acceptable (viz., isDenseArray() || isSlowArray()), the caller
* may test the class and delegate to HandleNonGenericMethodClassMismatch to
* handle the proxy case and error reporting. The 'clasp' argument is only used
* for error reporting (clasp->name).
*/
extern bool
HandleNonGenericMethodClassMismatch(JSContext *cx, CallArgs args, Native native, Class *clasp);
/*
* Implement the extraction of a primitive from a value as needed for the
* toString, valueOf, and a few other methods of the boxed primitives classes
* Boolean, Number, and String (e.g., ES5 15.6.4.2). If 'true' is returned, the
* extracted primitive is stored in |*v|. If 'false' is returned, the caller
* must immediately 'return *ok'. For details, see NonGenericMethodGuard.
*/
template <typename T>
inline bool
BoxedPrimitiveMethodGuard(JSContext *cx, CallArgs args, Native native, T *v, bool *ok);
} /* namespace js */
#endif /* MethodGuard_h___ */