mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
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:
parent
c9d1a52e78
commit
294b5f03eb
@ -153,6 +153,7 @@ CPPSRCS = \
|
||||
ScopeObject.cpp \
|
||||
Debugger.cpp \
|
||||
GlobalObject.cpp \
|
||||
MethodGuard.cpp \
|
||||
Stack.cpp \
|
||||
String.cpp \
|
||||
BytecodeCompiler.cpp \
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/MethodGuard.h"
|
||||
#include "vm/Stack.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include "builtin/RegExp.h"
|
||||
|
||||
#include "vm/MethodGuard-inl.h"
|
||||
#include "vm/RegExpObject-inl.h"
|
||||
#include "vm/RegExpStatics-inl.h"
|
||||
|
||||
|
@ -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"
|
||||
|
@ -127,6 +127,7 @@
|
||||
#include "methodjit/StubCalls-inl.h"
|
||||
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/MethodGuard.h"
|
||||
|
||||
#include "ds/Sort.h"
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -79,6 +79,7 @@
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/MethodGuard-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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___ */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -50,6 +50,8 @@
|
||||
#include "jsproxy.h"
|
||||
#include "jsscope.h"
|
||||
|
||||
#include "vm/MethodGuard.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -54,6 +54,8 @@
|
||||
#include "jsgcinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/MethodGuard-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
namespace js {
|
||||
|
@ -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
125
js/src/vm/MethodGuard-inl.h
Normal 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
91
js/src/vm/MethodGuard.cpp
Normal 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
116
js/src/vm/MethodGuard.h
Normal 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___ */
|
Loading…
Reference in New Issue
Block a user