зеркало из https://github.com/mozilla/gecko-dev.git
(unrebased) fat value patch
This commit is contained in:
Родитель
2ea3056f2b
Коммит
55e7f5e2d3
|
@ -717,7 +717,7 @@ JSTrapStatus
|
|||
jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure)
|
||||
{
|
||||
JSDExecHook* jsdhook = (JSDExecHook*) JSVAL_TO_PRIVATE(((jsval)closure));
|
||||
JSDExecHook* jsdhook = (JSDExecHook*)closure;
|
||||
JSD_ExecutionHookProc hook;
|
||||
void* hookData;
|
||||
JSDContext* jsdc;
|
||||
|
@ -800,7 +800,7 @@ jsd_SetExecutionHook(JSDContext* jsdc,
|
|||
|
||||
if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script,
|
||||
(jsbytecode*)pc, jsd_TrapHandler,
|
||||
(void*) PRIVATE_TO_JSVAL(jsdhook)) )
|
||||
PRIVATE_TO_JSVAL(jsdhook)) )
|
||||
{
|
||||
free(jsdhook);
|
||||
JSD_UNLOCK();
|
||||
|
|
|
@ -206,10 +206,9 @@ jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
|
|||
jsdouble*
|
||||
jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
jsval val = jsdval->val;
|
||||
if(!JSVAL_IS_DOUBLE(val))
|
||||
if(!JSVAL_IS_DOUBLE(jsdval->val))
|
||||
return 0;
|
||||
return JSVAL_TO_DOUBLE(val);
|
||||
return JSVAL_PTR_TO_DOUBLE_PTR(&jsdval->val);
|
||||
}
|
||||
|
||||
JSString*
|
||||
|
@ -342,14 +341,14 @@ static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
|
|||
jsdprop->flags = pd->flags | additionalFlags;
|
||||
jsdprop->slot = pd->slot;
|
||||
|
||||
if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id)))
|
||||
if(!(jsdprop->name = jsd_NewValue(jsdc, JSID_TO_JSVAL(pd->id))))
|
||||
goto new_prop_fail;
|
||||
|
||||
if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
|
||||
goto new_prop_fail;
|
||||
|
||||
if((jsdprop->flags & JSDPD_ALIAS) &&
|
||||
!(jsdprop->alias = jsd_NewValue(jsdc, pd->alias)))
|
||||
!(jsdprop->alias = jsd_NewValue(jsdc, JSID_TO_JSVAL(pd->alias))))
|
||||
goto new_prop_fail;
|
||||
|
||||
return jsdprop;
|
||||
|
@ -492,7 +491,7 @@ jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
|
|||
JSPropertyDesc pd;
|
||||
const jschar * nameChars;
|
||||
size_t nameLen;
|
||||
jsval val;
|
||||
jsval val, nameval;
|
||||
|
||||
if(!jsd_IsValueObject(jsdc, jsdval))
|
||||
return NULL;
|
||||
|
@ -548,8 +547,11 @@ jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
|
|||
|
||||
JS_EndRequest(cx);
|
||||
|
||||
pd.id = STRING_TO_JSVAL(name);
|
||||
pd.alias = pd.slot = pd.spare = 0;
|
||||
nameval = STRING_TO_JSVAL(name);
|
||||
if (!JS_ValueToId(cx, &nameval, &pd.id))
|
||||
return NULL;
|
||||
pd.slot = pd.spare = 0;
|
||||
pd.alias = JSID_NULL;
|
||||
pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
|
||||
| (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0
|
||||
| (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "jsdbgapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsd_xpc.h"
|
||||
|
||||
#include "nsIXPConnect.h"
|
||||
|
@ -1014,7 +1012,8 @@ jsdScript::CreatePPLineMap()
|
|||
PRBool scriptOwner = PR_FALSE;
|
||||
|
||||
if (fun) {
|
||||
if (fun->nargs > 12)
|
||||
uintN nargs = JS_GetFunctionArgumentCount(cx, fun);
|
||||
if (nargs > 12)
|
||||
return nsnull;
|
||||
JSString *jsstr = JS_DecompileFunctionBody (cx, fun, 4);
|
||||
if (!jsstr)
|
||||
|
@ -1023,7 +1022,7 @@ jsdScript::CreatePPLineMap()
|
|||
const char *argnames[] = {"arg1", "arg2", "arg3", "arg4",
|
||||
"arg5", "arg6", "arg7", "arg8",
|
||||
"arg9", "arg10", "arg11", "arg12" };
|
||||
fun = JS_CompileUCFunction (cx, obj, "ppfun", fun->nargs, argnames,
|
||||
fun = JS_CompileUCFunction (cx, obj, "ppfun", nargs, argnames,
|
||||
JS_GetStringChars(jsstr),
|
||||
JS_GetStringLength(jsstr),
|
||||
"x-jsd:ppbuffer?type=function", 3);
|
||||
|
@ -1232,37 +1231,32 @@ jsdScript::GetParameterNames(PRUint32* count, PRUnichar*** paramNames)
|
|||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
if (!fun || !fun->hasLocalNames() || fun->nargs == 0) {
|
||||
uintN nargs = JS_GetFunctionArgumentCount(cx, fun);
|
||||
if (!fun || !JS_FunctionHasLocalNames(cx, fun) || nargs == 0) {
|
||||
*count = 0;
|
||||
*paramNames = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUnichar **ret =
|
||||
static_cast<PRUnichar**>(NS_Alloc(fun->nargs * sizeof(PRUnichar*)));
|
||||
static_cast<PRUnichar**>(NS_Alloc(nargs * sizeof(PRUnichar*)));
|
||||
if (!ret)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool);
|
||||
void *mark;
|
||||
jsuword *names = JS_GetFunctionLocalNameArray(cx, fun, &mark);
|
||||
if (!names) {
|
||||
NS_Free(ret);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
for (uintN i = 0; i < fun->nargs; ++i) {
|
||||
JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(names[i]);
|
||||
for (uintN i = 0; i < nargs; ++i) {
|
||||
JSAtom *atom = JS_LocalNameToAtom(names[i]);
|
||||
if (!atom) {
|
||||
ret[i] = 0;
|
||||
} else {
|
||||
jsval atomVal = ATOM_KEY(atom);
|
||||
if (!JSVAL_IS_STRING(atomVal)) {
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, ret);
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
JSString *str = JSVAL_TO_STRING(atomVal);
|
||||
JSString *str = JS_AtomKey(atom);
|
||||
ret[i] = NS_strndup(reinterpret_cast<PRUnichar*>(JS_GetStringChars(str)),
|
||||
JS_GetStringLength(str));
|
||||
if (!ret[i]) {
|
||||
|
@ -1272,10 +1266,10 @@ jsdScript::GetParameterNames(PRUint32* count, PRUnichar*** paramNames)
|
|||
}
|
||||
}
|
||||
}
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
JS_ReleaseFunctionLocalNameArray(cx, mark);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
*count = fun->nargs;
|
||||
*count = nargs;
|
||||
*paramNames = ret;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1484,8 +1478,7 @@ jsdScript::SetBreakpoint(PRUint32 aPC)
|
|||
{
|
||||
ASSERT_VALID_EPHEMERAL;
|
||||
jsuword pc = mFirstPC + aPC;
|
||||
JSD_SetExecutionHook (mCx, mScript, pc, jsds_ExecutionHookProc,
|
||||
reinterpret_cast<void *>(PRIVATE_TO_JSVAL(NULL)));
|
||||
JSD_SetExecutionHook (mCx, mScript, pc, jsds_ExecutionHookProc, NULL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1989,7 +1982,7 @@ jsdStackFrame::Eval (const nsAString &bytes, const nsACString &fileName,
|
|||
if (JS_IsExceptionPending(cx))
|
||||
JS_GetPendingException (cx, &jv);
|
||||
else
|
||||
jv = 0;
|
||||
jv = JSVAL_NULL;
|
||||
}
|
||||
|
||||
JS_RestoreExceptionState (cx, estate);
|
||||
|
@ -2436,8 +2429,8 @@ jsdService::SetInitAtStartup (PRBool state)
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (state && mInitAtStartup == triYes ||
|
||||
!state && mInitAtStartup == triNo) {
|
||||
if ((state && mInitAtStartup == triYes) ||
|
||||
(!state && mInitAtStartup == triNo)) {
|
||||
/* already in the requested state */
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
695
js/src/jsapi.cpp
695
js/src/jsapi.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
1256
js/src/jsapi.h
1256
js/src/jsapi.h
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -46,14 +46,12 @@
|
|||
#include "jspubtd.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#define ARRAY_CAPACITY_MIN 7
|
||||
|
||||
extern JSBool
|
||||
js_IdIsIndex(jsval id, jsuint *indexp);
|
||||
js_IdIsIndex(jsid id, jsuint *indexp);
|
||||
|
||||
extern JSClass js_ArrayClass, js_SlowArrayClass;
|
||||
extern js::Class js_ArrayClass, js_SlowArrayClass;
|
||||
|
||||
inline bool
|
||||
JSObject::isDenseArray() const
|
||||
|
@ -112,7 +110,7 @@ extern JSObject * JS_FASTCALL
|
|||
js_NewArrayWithSlots(JSContext* cx, JSObject* proto, uint32 len);
|
||||
|
||||
extern JSObject *
|
||||
js_NewArrayObject(JSContext *cx, jsuint length, const jsval *vector, bool holey = false);
|
||||
js_NewArrayObject(JSContext *cx, jsuint length, const js::Value *vector, bool holey = false);
|
||||
|
||||
/* Create an array object that starts out already made slow/sparse. */
|
||||
extern JSObject *
|
||||
|
@ -125,7 +123,7 @@ static JS_INLINE uint32
|
|||
js_DenseArrayCapacity(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isDenseArray());
|
||||
return obj->dslots ? (uint32) obj->dslots[-1] : 0;
|
||||
return obj->dslots ? obj->dslotLength() : 0;
|
||||
}
|
||||
|
||||
static JS_INLINE void
|
||||
|
@ -133,7 +131,7 @@ js_SetDenseArrayCapacity(JSObject *obj, uint32 capacity)
|
|||
{
|
||||
JS_ASSERT(obj->isDenseArray());
|
||||
JS_ASSERT(obj->dslots);
|
||||
obj->dslots[-1] = (jsval) capacity;
|
||||
obj->dslots[-1].setPrivateUint32(capacity);
|
||||
}
|
||||
|
||||
extern JSBool
|
||||
|
@ -167,21 +165,23 @@ typedef JSBool (*JSComparator)(void *arg, const void *a, const void *b,
|
|||
* NB: vec is the array to be sorted, tmp is temporary space at least as big
|
||||
* as vec. Both should be GC-rooted if appropriate.
|
||||
*
|
||||
* isValue should true iff vec points to an array of js::Value
|
||||
*
|
||||
* The sorted result is in vec. vec may be in an inconsistent state if the
|
||||
* comparator function cmp returns an error inside a comparison, so remember
|
||||
* to check the return value of this function.
|
||||
*/
|
||||
extern JSBool
|
||||
extern bool
|
||||
js_MergeSort(void *vec, size_t nel, size_t elsize, JSComparator cmp,
|
||||
void *arg, void *tmp);
|
||||
void *arg, void *tmp, bool isValue);
|
||||
|
||||
#ifdef DEBUG_ARRAYS
|
||||
extern JSBool
|
||||
js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
|
||||
#endif
|
||||
|
||||
extern JSBool JS_FASTCALL
|
||||
js_ArrayCompPush(JSContext *cx, JSObject *obj, jsval v);
|
||||
js_ArrayCompPush(JSContext *cx, JSObject *obj, const js::Value &v);
|
||||
|
||||
/*
|
||||
* Fast dense-array-to-buffer conversion for use by canvas.
|
||||
|
@ -211,11 +211,11 @@ js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj);
|
|||
*/
|
||||
JSBool
|
||||
js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, JSProperty *prop,
|
||||
jsval *vp);
|
||||
js::Value *vp);
|
||||
|
||||
/* Array constructor native. Exposed only so the JIT can know its address. */
|
||||
JSBool
|
||||
js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
|
||||
js_Array(JSContext* cx, JSObject* obj, uintN argc, js::Value* argv, js::Value* rval);
|
||||
|
||||
/*
|
||||
* Friend api function that allows direct creation of an array object with a
|
||||
|
@ -229,8 +229,6 @@ js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
|
|||
* resulting array has length and count both equal to |capacity|.
|
||||
*/
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js_NewArrayObjectWithCapacity(JSContext *cx, jsuint capacity, jsval **vector);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
js_NewArrayObjectWithCapacity(JSContext *cx, jsuint capacity, js::Value **vector);
|
||||
|
||||
#endif /* jsarray_h___ */
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* JS atom table.
|
||||
*/
|
||||
|
@ -58,7 +60,13 @@
|
|||
#include "jsscan.h"
|
||||
#include "jsstr.h"
|
||||
#include "jsversion.h"
|
||||
#include "jsxml.h"
|
||||
|
||||
#include "jsstrinlines.h"
|
||||
#include "jsatominlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
/*
|
||||
* ATOM_HASH assumes that JSHashNumber is 32-bit even on 64-bit systems.
|
||||
|
@ -85,7 +93,7 @@ JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
|
|||
const char *
|
||||
js_AtomToPrintableString(JSContext *cx, JSAtom *atom)
|
||||
{
|
||||
return js_ValueToPrintableString(cx, ATOM_KEY(atom));
|
||||
return js_ValueToPrintableString(cx, Value(ATOM_TO_STRING(atom)));
|
||||
}
|
||||
|
||||
#define JS_PROTO(name,code,init) const char js_##name##_str[] = #name;
|
||||
|
@ -269,12 +277,12 @@ const char js_current_str[] = "current";
|
|||
*/
|
||||
typedef struct JSAtomHashEntry {
|
||||
JSDHashEntryHdr hdr;
|
||||
jsuword keyAndFlags;
|
||||
jsboxedword keyAndFlags;
|
||||
} JSAtomHashEntry;
|
||||
|
||||
#define ATOM_ENTRY_FLAG_MASK (ATOM_PINNED | ATOM_INTERNED)
|
||||
|
||||
JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JSVAL_ALIGN);
|
||||
JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JSBOXEDWORD_ALIGN);
|
||||
|
||||
/*
|
||||
* Helper macros to access and modify JSAtomHashEntry.
|
||||
|
@ -536,8 +544,8 @@ js_locked_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
|||
return JS_DHASH_NEXT;
|
||||
}
|
||||
JS_SET_TRACING_INDEX(trc, "locked_atom", (size_t)number);
|
||||
js_CallGCMarker(trc, ATOM_ENTRY_KEY(entry),
|
||||
IS_STRING_TABLE(table) ? JSTRACE_STRING : JSTRACE_DOUBLE);
|
||||
CallGCMarker(trc, ATOM_ENTRY_KEY(entry),
|
||||
IS_STRING_TABLE(table) ? JSTRACE_STRING : JSTRACE_DOUBLE);
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
@ -556,7 +564,7 @@ js_pinned_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
|||
? "pinned_atom"
|
||||
: "interned_atom",
|
||||
(size_t)number);
|
||||
js_CallGCMarker(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
|
||||
CallGCMarker(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
|
||||
}
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
@ -619,7 +627,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
|
|||
JSAtomHashEntry *entry;
|
||||
uint32 gen;
|
||||
jsdouble *key;
|
||||
jsval v;
|
||||
jsboxedword w;
|
||||
|
||||
state = &cx->runtime->atomState;
|
||||
table = &state->doubleAtoms;
|
||||
|
@ -632,7 +640,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
|
|||
gen = ++table->generation;
|
||||
JS_UNLOCK(cx, &state->lock);
|
||||
|
||||
key = js_NewWeaklyRootedDouble(cx, d);
|
||||
key = js_NewWeaklyRootedDoubleAtom(cx, d);
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
|
@ -652,11 +660,11 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
|
|||
}
|
||||
|
||||
finish:
|
||||
v = DOUBLE_TO_JSVAL((jsdouble *)ATOM_ENTRY_KEY(entry));
|
||||
cx->weakRoots.lastAtom = v;
|
||||
w = DOUBLE_TO_JSBOXEDWORD((jsdouble *)ATOM_ENTRY_KEY(entry));
|
||||
cx->weakRoots.lastAtom = (JSAtom *)w;
|
||||
JS_UNLOCK(cx, &state->lock);
|
||||
|
||||
return (JSAtom *)v;
|
||||
return (JSAtom *)w;
|
||||
|
||||
failed_hash_add:
|
||||
JS_UNLOCK(cx, &state->lock);
|
||||
|
@ -667,7 +675,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
|
|||
JSAtom *
|
||||
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
||||
{
|
||||
jsval v;
|
||||
JSAtom *atom;
|
||||
JSAtomState *state;
|
||||
JSDHashTable *table;
|
||||
JSAtomHashEntry *entry;
|
||||
|
@ -678,13 +686,13 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
|||
JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR);
|
||||
|
||||
if (str->isAtomized())
|
||||
return (JSAtom *) STRING_TO_JSVAL(str);
|
||||
return STRING_TO_ATOM(str);
|
||||
|
||||
size_t length = str->length();
|
||||
if (length == 1) {
|
||||
jschar c = str->chars()[0];
|
||||
if (c < UNIT_STRING_LIMIT)
|
||||
return (JSAtom *) STRING_TO_JSVAL(JSString::unitString(c));
|
||||
return STRING_TO_ATOM(JSString::unitString(c));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -705,7 +713,7 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
|||
if (length == 3)
|
||||
i = i * 10 + chars[2] - '0';
|
||||
if (jsuint(i) < INT_STRING_LIMIT)
|
||||
return (JSAtom *) STRING_TO_JSVAL(JSString::intString(i));
|
||||
return STRING_TO_ATOM(JSString::intString(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -775,10 +783,10 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
|||
finish:
|
||||
ADD_ATOM_ENTRY_FLAGS(entry, flags & (ATOM_PINNED | ATOM_INTERNED));
|
||||
JS_ASSERT(key->isAtomized());
|
||||
v = STRING_TO_JSVAL(key);
|
||||
cx->weakRoots.lastAtom = v;
|
||||
atom = STRING_TO_ATOM(key);
|
||||
cx->weakRoots.lastAtom = atom;
|
||||
JS_UNLOCK(cx, &state->lock);
|
||||
return (JSAtom *)v;
|
||||
return atom;
|
||||
|
||||
failed_hash_add:
|
||||
JS_UNLOCK(cx, &state->lock);
|
||||
|
@ -842,7 +850,7 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
|
|||
if (length == 1) {
|
||||
jschar c = *chars;
|
||||
if (c < UNIT_STRING_LIMIT)
|
||||
return (JSAtom *) STRING_TO_JSVAL(JSString::unitString(c));
|
||||
return STRING_TO_ATOM(JSString::unitString(c));
|
||||
}
|
||||
|
||||
str.initFlat((jschar *)chars, length);
|
||||
|
@ -855,26 +863,26 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
|
|||
: NULL;
|
||||
JS_UNLOCK(cx, &state->lock);
|
||||
|
||||
return str2 ? (JSAtom *)STRING_TO_JSVAL(str2) : NULL;
|
||||
return str2 ? STRING_TO_ATOM(str2) : NULL;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp)
|
||||
js_AtomizePrimitiveValue(JSContext *cx, jsboxedword w, JSAtom **atomp)
|
||||
{
|
||||
JSAtom *atom;
|
||||
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
atom = js_AtomizeString(cx, JSVAL_TO_STRING(v), 0);
|
||||
if (JSBOXEDWORD_IS_STRING(w)) {
|
||||
atom = js_AtomizeString(cx, JSBOXEDWORD_TO_STRING(w), 0);
|
||||
if (!atom)
|
||||
return JS_FALSE;
|
||||
} else if (JSVAL_IS_DOUBLE(v)) {
|
||||
atom = js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(v));
|
||||
} else if (JSBOXEDWORD_IS_DOUBLE(w)) {
|
||||
atom = js_AtomizeDouble(cx, *JSBOXEDWORD_TO_DOUBLE(w));
|
||||
if (!atom)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_BOOLEAN(v) ||
|
||||
JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v));
|
||||
atom = (JSAtom *)v;
|
||||
JS_ASSERT(JSBOXEDWORD_IS_INT(w) || JSBOXEDWORD_IS_BOOLEAN(w) ||
|
||||
JSBOXEDWORD_IS_NULL(w) || JSBOXEDWORD_IS_VOID(w));
|
||||
atom = (JSAtom *)w;
|
||||
}
|
||||
*atomp = atom;
|
||||
return JS_TRUE;
|
||||
|
@ -1265,3 +1273,96 @@ js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
|
|||
}
|
||||
al->clear();
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
bool
|
||||
js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval,
|
||||
jsid *idp)
|
||||
{
|
||||
JS_ASSERT(idval.isObject());
|
||||
if (obj->isXML()) {
|
||||
*idp = OBJECT_TO_JSID(&idval.asObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!js_IsFunctionQName(cx, &idval.asObject(), idp))
|
||||
return JS_FALSE;
|
||||
if (*idp != 0)
|
||||
return true;
|
||||
|
||||
return js_ValueToStringId(cx, idval, idp);
|
||||
}
|
||||
|
||||
bool
|
||||
js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval,
|
||||
jsid *idp, Value *vp)
|
||||
{
|
||||
JS_ASSERT(idval.isObject());
|
||||
if (obj->isXML()) {
|
||||
JSObject &idobj = idval.asObject();
|
||||
*idp = OBJECT_TO_JSID(&idobj);
|
||||
SetObject(vp, idobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!js_IsFunctionQName(cx, &idval.asObject(), idp))
|
||||
return JS_FALSE;
|
||||
if (*idp != 0) {
|
||||
vp->copy(IdToValue(*idp));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (js_ValueToStringId(cx, idval, idp)) {
|
||||
vp->setString(ATOM_TO_STRING(JSID_TO_ATOM(*idp)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
ValueToId(JSContext *cx, const Value *vp, jsid *idp)
|
||||
{
|
||||
int32_t i;
|
||||
if (ValueFitsInInt32(*vp, &i) && INT32_FITS_IN_JSID(i)) {
|
||||
*idp = INT_TO_JSID(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (vp->isObject()) {
|
||||
Class *clasp = vp->asObject().getClass();
|
||||
if (JS_UNLIKELY(clasp == &js_QNameClass.base ||
|
||||
clasp == &js_AttributeNameClass ||
|
||||
clasp == &js_AnyNameClass)) {
|
||||
*idp = OBJECT_TO_JSID(&vp->asObject());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return js_ValueToStringId(cx, *vp, idp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Normally, js::Value should not be passed by value, but this function should
|
||||
* only be used on cold paths, so ease of use wins out.
|
||||
*/
|
||||
Value
|
||||
IdToValue(jsid id)
|
||||
{
|
||||
ExplicitlyConstructedValue v;
|
||||
if (JSID_IS_INT(id))
|
||||
v.setInt32(JSID_TO_INT(id));
|
||||
else if (JSID_IS_ATOM(id))
|
||||
v.setString(ATOM_TO_STRING(JSID_TO_ATOM(id)));
|
||||
else if (JSID_IS_NULL(id))
|
||||
v.setNull();
|
||||
else
|
||||
SetObject(&v, *JSID_TO_OBJECT(id));
|
||||
return v;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
|
|
@ -52,18 +52,18 @@
|
|||
#include "jspubtd.h"
|
||||
#include "jslock.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#define ATOM_PINNED 0x1 /* atom is pinned against GC */
|
||||
#define ATOM_INTERNED 0x2 /* pinned variant for JS_Intern* API */
|
||||
#define ATOM_NOCOPY 0x4 /* don't copy atom string bytes */
|
||||
#define ATOM_TMPSTR 0x8 /* internal, to avoid extra string */
|
||||
|
||||
#define ATOM_KEY(atom) ((jsval)(atom))
|
||||
#define ATOM_IS_DOUBLE(atom) JSVAL_IS_DOUBLE(ATOM_KEY(atom))
|
||||
#define ATOM_TO_DOUBLE(atom) JSVAL_TO_DOUBLE(ATOM_KEY(atom))
|
||||
#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom))
|
||||
#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom))
|
||||
#define ATOM_KEY(atom) ((jsboxedword)(atom))
|
||||
#define ATOM_IS_DOUBLE(atom) JSBOXEDWORD_IS_DOUBLE(ATOM_KEY(atom))
|
||||
#define ATOM_TO_DOUBLE(atom) JSBOXEDWORD_TO_DOUBLE(ATOM_KEY(atom))
|
||||
#define ATOM_IS_STRING(atom) JSBOXEDWORD_IS_STRING(ATOM_KEY(atom))
|
||||
#define ATOM_TO_STRING(atom) JSBOXEDWORD_TO_STRING(ATOM_KEY(atom))
|
||||
#define STRING_TO_ATOM(str) (JS_ASSERT(str->isAtomized()), \
|
||||
(JSAtom *)STRING_TO_JSBOXEDWORD(str))
|
||||
|
||||
#if JS_BYTES_PER_WORD == 4
|
||||
# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2)
|
||||
|
@ -88,7 +88,7 @@ struct JSAtomListElement {
|
|||
|
||||
#define ALE_ATOM(ale) ((JSAtom *) (ale)->entry.key)
|
||||
#define ALE_INDEX(ale) (jsatomid(uintptr_t((ale)->entry.value)))
|
||||
#define ALE_VALUE(ale) ((jsval) (ale)->entry.value)
|
||||
#define ALE_VALUE(ale) ((jsboxedword) (ale)->entry.value)
|
||||
#define ALE_NEXT(ale) ((JSAtomListElement *) (ale)->entry.next)
|
||||
|
||||
/*
|
||||
|
@ -119,8 +119,6 @@ struct JSAtomSet {
|
|||
jsuint count; /* count of indexed literals */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
struct JSAtomList : public JSAtomSet
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
@ -198,8 +196,6 @@ class JSAtomListIterator {
|
|||
JSAtomListElement* operator ()();
|
||||
};
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct JSAtomMap {
|
||||
JSAtom **vector; /* array of ptrs to indexed atoms */
|
||||
jsatomid length; /* count of (to-be-)indexed atoms */
|
||||
|
@ -485,7 +481,7 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length);
|
|||
* This variant handles all primitive values.
|
||||
*/
|
||||
JSBool
|
||||
js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp);
|
||||
js_AtomizePrimitiveValue(JSContext *cx, jsboxedword w, JSAtom **atomp);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
|
@ -494,6 +490,18 @@ js_DumpAtoms(JSContext *cx, FILE *fp);
|
|||
|
||||
#endif
|
||||
|
||||
inline bool
|
||||
js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp);
|
||||
|
||||
inline bool
|
||||
js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp);
|
||||
|
||||
inline bool
|
||||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
||||
jsid *idp);
|
||||
inline bool
|
||||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
||||
jsid *idp, js::Value *vp);
|
||||
/*
|
||||
* For all unmapped atoms recorded in al, add a mapping from the atom's index
|
||||
* to its address. map->length must already be set to the number of atoms in
|
||||
|
@ -502,6 +510,14 @@ js_DumpAtoms(JSContext *cx, FILE *fp);
|
|||
extern void
|
||||
js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
namespace js {
|
||||
|
||||
Value
|
||||
IdToValue(jsid id);
|
||||
|
||||
bool
|
||||
ValueToId(JSContext *cx, const Value &v, jsid *idp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsatom_h___ */
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
/*
|
||||
* Convert v to an atomized string and wrap it as an id.
|
||||
*/
|
||||
inline JSBool
|
||||
js_ValueToStringId(JSContext *cx, jsval v, jsid *idp)
|
||||
inline bool
|
||||
js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp)
|
||||
{
|
||||
JSString *str;
|
||||
JSAtom *atom;
|
||||
|
@ -59,37 +59,85 @@ js_ValueToStringId(JSContext *cx, jsval v, jsid *idp)
|
|||
* done in js_js_AtomizeString) ensures the caller that the resulting id at
|
||||
* is least weakly rooted.
|
||||
*/
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
str = JSVAL_TO_STRING(v);
|
||||
if (v.isString()) {
|
||||
str = v.asString();
|
||||
if (str->isAtomized()) {
|
||||
cx->weakRoots.lastAtom = v;
|
||||
*idp = ATOM_TO_JSID((JSAtom *) v);
|
||||
return JS_TRUE;
|
||||
cx->weakRoots.lastAtom = *atomp = STRING_TO_ATOM(str);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
str = js_ValueToString(cx, v);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
}
|
||||
atom = js_AtomizeString(cx, str, 0);
|
||||
if (!atom)
|
||||
return JS_FALSE;
|
||||
*idp = ATOM_TO_JSID(atom);
|
||||
return JS_TRUE;
|
||||
return false;
|
||||
*atomp = atom;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline JSBool
|
||||
inline bool
|
||||
js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp)
|
||||
{
|
||||
JSAtom *atom;
|
||||
if (js_ValueToAtom(cx, v, &atom)) {
|
||||
*idp = ATOM_TO_JSID(atom);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
js_Int32ToId(JSContext* cx, int32 index, jsid* id)
|
||||
{
|
||||
if (INT_FITS_IN_JSVAL(index)) {
|
||||
if (INT32_FITS_IN_JSID(index)) {
|
||||
*id = INT_TO_JSID(index);
|
||||
JS_ASSERT(INT_JSID_TO_JSVAL(*id) == INT_TO_JSVAL(index));
|
||||
return JS_TRUE;
|
||||
return true;
|
||||
}
|
||||
JSString* str = js_NumberToString(cx, index);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
return js_ValueToStringId(cx, STRING_TO_JSVAL(str), id);
|
||||
return false;
|
||||
return js_ValueToStringId(cx, js::Value(str), id);
|
||||
}
|
||||
|
||||
inline bool
|
||||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
||||
jsid *idp)
|
||||
{
|
||||
JS_ASSERT_IF(idval.isInt32(), !INT32_FITS_IN_JSID(idval.asInt32()));
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
extern bool js_InternNonIntElementIdSlow(JSContext *, JSObject *,
|
||||
const js::Value &, jsid *);
|
||||
if (idval.isObject())
|
||||
return js_InternNonIntElementIdSlow(cx, obj, idval, idp);
|
||||
#endif
|
||||
|
||||
return js_ValueToStringId(cx, idval, idp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
||||
jsid *idp, js::Value *vp)
|
||||
{
|
||||
JS_ASSERT_IF(idval.isInt32(), !INT32_FITS_IN_JSID(idval.asInt32()));
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
extern bool js_InternNonIntElementIdSlow(JSContext *, JSObject *,
|
||||
const js::Value &,
|
||||
jsid *, js::Value *);
|
||||
if (idval.isObject())
|
||||
return js_InternNonIntElementIdSlow(cx, obj, idval, idp, vp);
|
||||
#endif
|
||||
|
||||
JSAtom *atom;
|
||||
if (js_ValueToAtom(cx, idval, &atom)) {
|
||||
*idp = ATOM_TO_JSID(atom);
|
||||
vp->setString(ATOM_TO_STRING(atom));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* jsatominlines_h___ */
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* JS boolean implementation.
|
||||
*/
|
||||
|
@ -54,20 +56,15 @@
|
|||
#include "jsstr.h"
|
||||
#include "jsvector.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
/* Check pseudo-booleans values. */
|
||||
JS_STATIC_ASSERT(!(JSVAL_TRUE & JSVAL_HOLE_FLAG));
|
||||
JS_STATIC_ASSERT(!(JSVAL_FALSE & JSVAL_HOLE_FLAG));
|
||||
JS_STATIC_ASSERT(!(JSVAL_VOID & JSVAL_HOLE_FLAG));
|
||||
JS_STATIC_ASSERT((JSVAL_HOLE & JSVAL_HOLE_FLAG));
|
||||
JS_STATIC_ASSERT((JSVAL_HOLE & ~JSVAL_HOLE_FLAG) == JSVAL_VOID);
|
||||
JS_STATIC_ASSERT(!(JSVAL_ARETURN & JSVAL_HOLE_FLAG));
|
||||
using namespace js;
|
||||
|
||||
JSClass js_BooleanClass = {
|
||||
Class js_BooleanClass = {
|
||||
"Boolean",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
|
||||
PropertyStub, PropertyStub, PropertyStub, PropertyStub,
|
||||
EnumerateStub, ResolveStub, ConvertStub, NULL,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
|
@ -75,46 +72,46 @@ JSClass js_BooleanClass = {
|
|||
#include "jsprf.h"
|
||||
|
||||
static JSBool
|
||||
bool_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
bool_toSource(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsval v;
|
||||
Value v;
|
||||
char buf[32];
|
||||
JSString *str;
|
||||
|
||||
if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
|
||||
JS_ASSERT(v.isBoolean());
|
||||
JS_snprintf(buf, sizeof buf, "(new %s(%s))",
|
||||
js_BooleanClass.name,
|
||||
JS_BOOLEAN_STR(JSVAL_TO_BOOLEAN(v)));
|
||||
JS_BOOLEAN_STR(v.asBoolean()));
|
||||
str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
vp->setString(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
bool_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
bool_toString(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsval v;
|
||||
Value v;
|
||||
JSAtom *atom;
|
||||
JSString *str;
|
||||
|
||||
if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
|
||||
atom = cx->runtime->atomState.booleanAtoms[JSVAL_TO_BOOLEAN(v) ? 1 : 0];
|
||||
JS_ASSERT(v.isBoolean());
|
||||
atom = cx->runtime->atomState.booleanAtoms[v.asBoolean() ? 1 : 0];
|
||||
str = ATOM_TO_STRING(atom);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
vp->setString(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
bool_valueOf(JSContext *cx, uintN argc, jsval *vp)
|
||||
bool_valueOf(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return js_GetPrimitiveThis(cx, vp, &js_BooleanClass, vp);
|
||||
}
|
||||
|
@ -130,17 +127,18 @@ static JSFunctionSpec boolean_methods[] = {
|
|||
};
|
||||
|
||||
static JSBool
|
||||
Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
Boolean(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
{
|
||||
jsval bval;
|
||||
Value bval;
|
||||
|
||||
bval = (argc != 0)
|
||||
? BOOLEAN_TO_JSVAL(js_ValueToBoolean(argv[0]))
|
||||
: JSVAL_FALSE;
|
||||
if (!JS_IsConstructing(cx))
|
||||
*rval = bval;
|
||||
if (argc != 0)
|
||||
bval.setBoolean(js_ValueToBoolean(argv[0]));
|
||||
else
|
||||
obj->fslots[JSSLOT_PRIMITIVE_THIS] = bval;
|
||||
bval.setBoolean(false);
|
||||
if (!JS_IsConstructing(cx))
|
||||
rval->copy(bval);
|
||||
else
|
||||
obj->fslots[JSSLOT_PRIMITIVE_THIS].copy(bval);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -149,11 +147,11 @@ js_InitBooleanClass(JSContext *cx, JSObject *obj)
|
|||
{
|
||||
JSObject *proto;
|
||||
|
||||
proto = JS_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1,
|
||||
NULL, boolean_methods, NULL, NULL);
|
||||
proto = js_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1,
|
||||
NULL, boolean_methods, NULL, NULL);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
proto->fslots[JSSLOT_PRIMITIVE_THIS] = JSVAL_FALSE;
|
||||
proto->fslots[JSSLOT_PRIMITIVE_THIS].setBoolean(false);
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
@ -171,22 +169,22 @@ js_BooleanToCharBuffer(JSContext *cx, JSBool b, JSCharBuffer &cb)
|
|||
}
|
||||
|
||||
JSBool
|
||||
js_ValueToBoolean(jsval v)
|
||||
js_ValueToBoolean(const Value &v)
|
||||
{
|
||||
if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
|
||||
if (v.isNullOrUndefined())
|
||||
return JS_FALSE;
|
||||
if (JSVAL_IS_OBJECT(v))
|
||||
if (v.isObject())
|
||||
return JS_TRUE;
|
||||
if (JSVAL_IS_STRING(v))
|
||||
return JSVAL_TO_STRING(v)->length() != 0;
|
||||
if (JSVAL_IS_INT(v))
|
||||
return JSVAL_TO_INT(v) != 0;
|
||||
if (JSVAL_IS_DOUBLE(v)) {
|
||||
if (v.isString())
|
||||
return v.asString()->length() != 0;
|
||||
if (v.isInt32())
|
||||
return v.asInt32() != 0;
|
||||
if (v.isDouble()) {
|
||||
jsdouble d;
|
||||
|
||||
d = *JSVAL_TO_DOUBLE(v);
|
||||
d = v.asDouble();
|
||||
return !JSDOUBLE_IS_NaN(d) && d != 0;
|
||||
}
|
||||
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
|
||||
return JSVAL_TO_BOOLEAN(v);
|
||||
JS_ASSERT(v.isBoolean());
|
||||
return v.asBoolean();
|
||||
}
|
||||
|
|
|
@ -45,27 +45,7 @@
|
|||
|
||||
#include "jsapi.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* Special values, not visible to script but used internally by the engine.
|
||||
*
|
||||
* JSVAL_HOLE is a useful value for identifying a hole in an array. It's also
|
||||
* used in the interpreter to represent "no exception pending". In general it
|
||||
* can be used to represent "no value".
|
||||
*
|
||||
* A JSVAL_HOLE can be cheaply converted to undefined without affecting any
|
||||
* other boolean (or special value) by masking out JSVAL_HOLE_FLAG.
|
||||
*
|
||||
* JSVAL_ARETURN is used to throw asynchronous return for generator.close().
|
||||
*
|
||||
* NB: SPECIAL_TO_JSVAL(2) is JSVAL_VOID (see jsapi.h).
|
||||
*/
|
||||
#define JSVAL_HOLE_FLAG jsval(4 << JSVAL_TAGBITS)
|
||||
#define JSVAL_HOLE (JSVAL_VOID | JSVAL_HOLE_FLAG)
|
||||
#define JSVAL_ARETURN SPECIAL_TO_JSVAL(8)
|
||||
|
||||
extern JSClass js_BooleanClass;
|
||||
extern js::Class js_BooleanClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitBooleanClass(JSContext *cx, JSObject *obj);
|
||||
|
@ -77,8 +57,6 @@ extern JSBool
|
|||
js_BooleanToCharBuffer(JSContext *cx, JSBool b, JSCharBuffer &cb);
|
||||
|
||||
extern JSBool
|
||||
js_ValueToBoolean(jsval v);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
js_ValueToBoolean(const js::Value &v);
|
||||
|
||||
#endif /* jsbool_h___ */
|
||||
|
|
|
@ -222,7 +222,7 @@ struct ClosureVarInfo;
|
|||
#define _JS_CTYPE_SCOPEPROP _JS_CTYPE(JSScopeProperty *, _JS_PTR, --, --, INFALLIBLE)
|
||||
#define _JS_CTYPE_INTERPSTATE _JS_CTYPE(InterpState *, _JS_PTR, --, --, INFALLIBLE)
|
||||
#define _JS_CTYPE_FRAGMENT _JS_CTYPE(nanojit::Fragment *, _JS_PTR, --, --, INFALLIBLE)
|
||||
#define _JS_CTYPE_CLASS _JS_CTYPE(JSClass *, _JS_PTR, --, --, INFALLIBLE)
|
||||
#define _JS_CTYPE_CLASS _JS_CTYPE(js::Class *, _JS_PTR, --, --, INFALLIBLE)
|
||||
#define _JS_CTYPE_DOUBLEPTR _JS_CTYPE(double *, _JS_PTR, --, --, INFALLIBLE)
|
||||
#define _JS_CTYPE_CHARPTR _JS_CTYPE(char *, _JS_PTR, --, --, INFALLIBLE)
|
||||
#define _JS_CTYPE_APNPTR _JS_CTYPE(ArgsPrivateNative *, _JS_PTR, --, --, INFALLIBLE)
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* JS execution context.
|
||||
*/
|
||||
|
@ -104,7 +106,7 @@ CallStack::contains(const JSStackFrame *fp) const
|
|||
JSStackFrame *start;
|
||||
JSStackFrame *stop;
|
||||
if (isSuspended()) {
|
||||
start = suspendedFrame;
|
||||
start = suspendedFrame();
|
||||
stop = initialFrame->down;
|
||||
} else {
|
||||
start = cx->fp;
|
||||
|
@ -129,7 +131,7 @@ StackSpace::init()
|
|||
void *check = VirtualAlloc(p, sCommitBytes, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (p != check)
|
||||
return false;
|
||||
base = reinterpret_cast<jsval *>(p);
|
||||
base = reinterpret_cast<Value *>(p);
|
||||
commitEnd = base + sCommitVals;
|
||||
end = base + sCapacityVals;
|
||||
#else
|
||||
|
@ -137,7 +139,7 @@ StackSpace::init()
|
|||
p = mmap(NULL, sCapacityBytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (p == MAP_FAILED)
|
||||
return false;
|
||||
base = reinterpret_cast<jsval *>(p);
|
||||
base = reinterpret_cast<Value *>(p);
|
||||
end = base + sCapacityVals;
|
||||
#endif
|
||||
return true;
|
||||
|
@ -147,7 +149,7 @@ void
|
|||
StackSpace::finish()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
VirtualFree(base, (commitEnd - base) * sizeof(jsval), MEM_DECOMMIT);
|
||||
VirtualFree(base, (commitEnd - base) * sizeof(Value), MEM_DECOMMIT);
|
||||
VirtualFree(base, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap(base, sCapacityBytes);
|
||||
|
@ -156,11 +158,11 @@ StackSpace::finish()
|
|||
|
||||
#ifdef XP_WIN
|
||||
JS_FRIEND_API(bool)
|
||||
StackSpace::bumpCommit(jsval *from, ptrdiff_t nvals) const
|
||||
StackSpace::bumpCommit(Value *from, ptrdiff_t nvals) const
|
||||
{
|
||||
JS_ASSERT(end - from >= nvals);
|
||||
jsval *newCommit = commitEnd;
|
||||
jsval *request = from + nvals;
|
||||
Value *newCommit = commitEnd;
|
||||
Value *request = from + nvals;
|
||||
|
||||
/* Use a dumb loop; will probably execute once. */
|
||||
JS_ASSERT((end - newCommit) % sCommitVals == 0);
|
||||
|
@ -170,7 +172,7 @@ StackSpace::bumpCommit(jsval *from, ptrdiff_t nvals) const
|
|||
} while(newCommit < request);
|
||||
|
||||
/* Cast safe because sCapacityBytes is small. */
|
||||
int32 size = (int32)(newCommit - commitEnd) * sizeof(jsval);
|
||||
int32 size = (int32)(newCommit - commitEnd) * sizeof(Value);
|
||||
|
||||
if (!VirtualAlloc(commitEnd, size, MEM_COMMIT, PAGE_READWRITE))
|
||||
return false;
|
||||
|
@ -186,7 +188,7 @@ StackSpace::mark(JSTracer *trc)
|
|||
* The correctness/completeness of marking depends on the continuity
|
||||
* invariants described by the CallStack and StackSpace definitions.
|
||||
*/
|
||||
jsval *end = firstUnused();
|
||||
Value *end = firstUnused();
|
||||
for (CallStack *cs = currentCallStack; cs; cs = cs->getPreviousInThread()) {
|
||||
if (!cs->inContext()) {
|
||||
/* Mark slots/args trailing off callstack. */
|
||||
|
@ -219,14 +221,14 @@ StackSpace::mark(JSTracer *trc)
|
|||
JS_REQUIRES_STACK bool
|
||||
StackSpace::pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard &ag)
|
||||
{
|
||||
jsval *start = firstUnused();
|
||||
Value *start = firstUnused();
|
||||
uintN vplen = 2 + argc;
|
||||
ptrdiff_t nvals = ValuesPerCallStack + vplen;
|
||||
if (!ensureSpace(cx, start, nvals))
|
||||
return false;
|
||||
jsval *vp = start + ValuesPerCallStack;
|
||||
jsval *vpend = vp + vplen;
|
||||
memset(vp, 0, vplen * sizeof(jsval)); /* Init so GC-safe on exit. */
|
||||
Value *vp = start + ValuesPerCallStack;
|
||||
Value *vpend = vp + vplen;
|
||||
memset(vp, 0, vplen * sizeof(*vp)); /* Init so GC-safe on exit. */
|
||||
|
||||
CallStack *cs = new(start) CallStack;
|
||||
cs->setInitialArgEnd(vpend);
|
||||
|
@ -264,7 +266,7 @@ StackSpace::getInvokeFrame(JSContext *cx, const InvokeArgsGuard &ag,
|
|||
{
|
||||
if (ag.cs) {
|
||||
JS_ASSERT(ag.cs == currentCallStack && !ag.cs->inContext());
|
||||
jsval *start = ag.cs->getInitialArgEnd();
|
||||
Value *start = ag.cs->getInitialArgEnd();
|
||||
ptrdiff_t nvals = nmissing + ValuesPerStackFrame + nslots;
|
||||
if (!ensureSpace(cx, start, nvals))
|
||||
return false;
|
||||
|
@ -273,7 +275,7 @@ StackSpace::getInvokeFrame(JSContext *cx, const InvokeArgsGuard &ag,
|
|||
}
|
||||
|
||||
JS_ASSERT(isCurrent(cx) && currentCallStack->isActive());
|
||||
jsval *start = cx->regs->sp;
|
||||
Value *start = cx->regs->sp;
|
||||
ptrdiff_t nvals = nmissing + ValuesPerCallStack + ValuesPerStackFrame + nslots;
|
||||
if (!ensureSpace(cx, start, nvals))
|
||||
return false;
|
||||
|
@ -342,7 +344,7 @@ StackSpace::getExecuteFrame(JSContext *cx, JSStackFrame *down,
|
|||
uintN vplen, uintN nslots,
|
||||
ExecuteFrameGuard &fg) const
|
||||
{
|
||||
jsval *start = firstUnused();
|
||||
Value *start = firstUnused();
|
||||
ptrdiff_t nvals = ValuesPerCallStack + vplen + ValuesPerStackFrame + nslots;
|
||||
if (!ensureSpace(cx, start, nvals))
|
||||
return false;
|
||||
|
@ -378,7 +380,7 @@ StackSpace::popExecuteFrame(JSContext *cx)
|
|||
JS_REQUIRES_STACK void
|
||||
StackSpace::getSynthesizedSlowNativeFrame(JSContext *cx, CallStack *&cs, JSStackFrame *&fp)
|
||||
{
|
||||
jsval *start = firstUnused();
|
||||
Value *start = firstUnused();
|
||||
JS_ASSERT(size_t(end - start) >= ValuesPerCallStack + ValuesPerStackFrame);
|
||||
cs = new(start) CallStack;
|
||||
fp = reinterpret_cast<JSStackFrame *>(cs + 1);
|
||||
|
@ -412,16 +414,16 @@ StackSpace::popSynthesizedSlowNativeFrame(JSContext *cx)
|
|||
* up-frame's address is the top of the down-frame's stack, modulo missing
|
||||
* arguments.
|
||||
*/
|
||||
static inline jsval *
|
||||
static inline Value *
|
||||
InlineDownFrameSP(JSStackFrame *up)
|
||||
{
|
||||
JS_ASSERT(up->fun && up->script);
|
||||
jsval *sp = up->argv + up->argc;
|
||||
Value *sp = up->argv + up->argc;
|
||||
#ifdef DEBUG
|
||||
uint16 nargs = up->fun->nargs;
|
||||
uintN argc = up->argc;
|
||||
uintN missing = argc < nargs ? nargs - argc : 0;
|
||||
JS_ASSERT(sp == (jsval *)up - missing);
|
||||
JS_ASSERT(sp == (Value *)up - missing);
|
||||
#endif
|
||||
return sp;
|
||||
}
|
||||
|
@ -1351,7 +1353,7 @@ resolving_HashKey(JSDHashTable *table, const void *ptr)
|
|||
{
|
||||
const JSResolvingKey *key = (const JSResolvingKey *)ptr;
|
||||
|
||||
return (JSDHashNumber(uintptr_t(key->obj)) >> JSVAL_TAGBITS) ^ key->id;
|
||||
return (JSDHashNumber(uintptr_t(key->obj)) >> JSBOXEDWORD_TAGBITS) ^ key->id;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -1468,7 +1470,7 @@ js_EnterLocalRootScope(JSContext *cx)
|
|||
}
|
||||
|
||||
/* Push lrs->scopeMark to save it for restore when leaving. */
|
||||
int mark = js_PushLocalRoot(cx, lrs, INT_TO_JSVAL(lrs->scopeMark));
|
||||
int mark = js_PushLocalRoot(cx, lrs, (void *)lrs->scopeMark);
|
||||
if (mark < 0)
|
||||
return JS_FALSE;
|
||||
lrs->scopeMark = (uint32) mark;
|
||||
|
@ -1476,7 +1478,7 @@ js_EnterLocalRootScope(JSContext *cx)
|
|||
}
|
||||
|
||||
void
|
||||
js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
|
||||
js_LeaveLocalRootScopeWithResult(JSContext *cx, const Value &rval)
|
||||
{
|
||||
JSLocalRootStack *lrs;
|
||||
uint32 mark, m, n;
|
||||
|
@ -1512,10 +1514,10 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
|
|||
*/
|
||||
lrc = lrs->topChunk;
|
||||
m = mark & JSLRS_CHUNK_MASK;
|
||||
lrs->scopeMark = (uint32) JSVAL_TO_INT(lrc->roots[m]);
|
||||
if (JSVAL_IS_GCTHING(rval) && !JSVAL_IS_NULL(rval)) {
|
||||
lrs->scopeMark = (uint32) lrc->roots[m];
|
||||
if (rval.isGCThing()) {
|
||||
if (mark == 0) {
|
||||
cx->weakRoots.lastInternalResult = rval;
|
||||
cx->weakRoots.lastInternalResult = rval.asGCThing();
|
||||
} else {
|
||||
/*
|
||||
* Increment m to avoid the "else if (m == 0)" case below. If
|
||||
|
@ -1523,7 +1525,7 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
|
|||
* any chunk that contained only the old mark. Since rval *is*
|
||||
* a GC-thing here, we want to reuse that old mark's slot.
|
||||
*/
|
||||
lrc->roots[m++] = rval;
|
||||
lrc->roots[m++] = rval.asGCThing();
|
||||
++mark;
|
||||
}
|
||||
}
|
||||
|
@ -1551,41 +1553,36 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
|
|||
}
|
||||
|
||||
void
|
||||
js_ForgetLocalRoot(JSContext *cx, jsval v)
|
||||
js_ForgetLocalRoot(JSContext *cx, void *thing)
|
||||
{
|
||||
JSLocalRootStack *lrs;
|
||||
uint32 i, j, m, n, mark;
|
||||
JSLocalRootChunk *lrc, *lrc2;
|
||||
jsval top;
|
||||
|
||||
lrs = JS_THREAD_DATA(cx)->localRootStack;
|
||||
JSLocalRootStack *lrs = JS_THREAD_DATA(cx)->localRootStack;
|
||||
JS_ASSERT(lrs && lrs->rootCount);
|
||||
if (!lrs || lrs->rootCount == 0)
|
||||
return;
|
||||
|
||||
/* Prepare to pop the top-most value from the stack. */
|
||||
n = lrs->rootCount - 1;
|
||||
m = n & JSLRS_CHUNK_MASK;
|
||||
lrc = lrs->topChunk;
|
||||
top = lrc->roots[m];
|
||||
uint32 n = lrs->rootCount - 1;
|
||||
uint32 m = n & JSLRS_CHUNK_MASK;
|
||||
JSLocalRootChunk *lrc = lrs->topChunk;
|
||||
void *top = lrc->roots[m];
|
||||
|
||||
/* Be paranoid about calls on an empty scope. */
|
||||
mark = lrs->scopeMark;
|
||||
uint32 mark = lrs->scopeMark;
|
||||
JS_ASSERT(mark < n);
|
||||
if (mark >= n)
|
||||
return;
|
||||
|
||||
/* If v was not the last root pushed in the top scope, find it. */
|
||||
if (top != v) {
|
||||
/* Search downward in case v was recently pushed. */
|
||||
i = n;
|
||||
j = m;
|
||||
lrc2 = lrc;
|
||||
/* If thing was not the last root pushed in the top scope, find it. */
|
||||
if (top != thing) {
|
||||
/* Search downward in case thing was recently pushed. */
|
||||
uint32 i = n;
|
||||
uint32 j = m;
|
||||
JSLocalRootChunk *lrc2 = lrc;
|
||||
while (--i > mark) {
|
||||
if (j == 0)
|
||||
lrc2 = lrc2->down;
|
||||
j = i & JSLRS_CHUNK_MASK;
|
||||
if (lrc2->roots[j] == v)
|
||||
if (lrc2->roots[j] == thing)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1599,7 +1596,7 @@ js_ForgetLocalRoot(JSContext *cx, jsval v)
|
|||
}
|
||||
|
||||
/* Pop the last value from the stack. */
|
||||
lrc->roots[m] = JSVAL_NULL;
|
||||
lrc->roots[m] = NULL;
|
||||
lrs->rootCount = n;
|
||||
if (m == 0) {
|
||||
JS_ASSERT(n != 0);
|
||||
|
@ -1610,7 +1607,7 @@ js_ForgetLocalRoot(JSContext *cx, jsval v)
|
|||
}
|
||||
|
||||
int
|
||||
js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v)
|
||||
js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, void *thing)
|
||||
{
|
||||
uint32 n, m;
|
||||
JSLocalRootChunk *lrc;
|
||||
|
@ -1643,35 +1640,32 @@ js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v)
|
|||
lrs->topChunk = lrc;
|
||||
}
|
||||
lrs->rootCount = n + 1;
|
||||
lrc->roots[m] = v;
|
||||
lrc->roots[m] = thing;
|
||||
return (int) n;
|
||||
}
|
||||
|
||||
static void
|
||||
MarkLocalRoots(JSTracer *trc, JSLocalRootStack *lrs)
|
||||
{
|
||||
uint32 n, m, mark;
|
||||
JSLocalRootChunk *lrc;
|
||||
jsval v;
|
||||
|
||||
n = lrs->rootCount;
|
||||
uint32 n = lrs->rootCount;
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
mark = lrs->scopeMark;
|
||||
lrc = lrs->topChunk;
|
||||
uint32 mark = lrs->scopeMark;
|
||||
JSLocalRootChunk *lrc = lrs->topChunk;
|
||||
do {
|
||||
uint32 m;
|
||||
while (--n > mark) {
|
||||
m = n & JSLRS_CHUNK_MASK;
|
||||
v = lrc->roots[m];
|
||||
JS_ASSERT(JSVAL_IS_GCTHING(v) && v != JSVAL_NULL);
|
||||
void *thing = lrc->roots[m];
|
||||
JS_ASSERT(thing != NULL);
|
||||
JS_SET_TRACING_INDEX(trc, "local_root", n);
|
||||
js_CallValueTracerIfGCThing(trc, v);
|
||||
CallGCMarkerForGCThing(trc, thing);
|
||||
if (m == 0)
|
||||
lrc = lrc->down;
|
||||
}
|
||||
m = n & JSLRS_CHUNK_MASK;
|
||||
mark = JSVAL_TO_INT(lrc->roots[m]);
|
||||
mark = (uint32)lrc->roots[m];
|
||||
if (m == 0)
|
||||
lrc = lrc->down;
|
||||
} while (n != 0);
|
||||
|
@ -2114,13 +2108,13 @@ js_ReportIsNotDefined(JSContext *cx, const char *name)
|
|||
}
|
||||
|
||||
JSBool
|
||||
js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
|
||||
js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, const Value &v,
|
||||
JSString *fallback)
|
||||
{
|
||||
char *bytes;
|
||||
JSBool ok;
|
||||
|
||||
bytes = js_DecompileValueGenerator(cx, spindex, v, fallback);
|
||||
bytes = js_DecompileValueGenerator(cx, spindex, Jsvalify(&v), fallback);
|
||||
if (!bytes)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -2130,13 +2124,13 @@ js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
|
|||
js_GetErrorMessage, NULL,
|
||||
JSMSG_NO_PROPERTIES, bytes,
|
||||
NULL, NULL);
|
||||
} else if (JSVAL_IS_VOID(v)) {
|
||||
} else if (v.isUndefined()) {
|
||||
ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
|
||||
js_GetErrorMessage, NULL,
|
||||
JSMSG_UNEXPECTED_TYPE, bytes,
|
||||
js_undefined_str, NULL);
|
||||
} else {
|
||||
JS_ASSERT(JSVAL_IS_NULL(v));
|
||||
JS_ASSERT(v.isNull());
|
||||
ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
|
||||
js_GetErrorMessage, NULL,
|
||||
JSMSG_UNEXPECTED_TYPE, bytes,
|
||||
|
@ -2148,7 +2142,7 @@ js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
|
|||
}
|
||||
|
||||
void
|
||||
js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg)
|
||||
js_ReportMissingArg(JSContext *cx, const Value &v, uintN arg)
|
||||
{
|
||||
char argbuf[11];
|
||||
char *bytes;
|
||||
|
@ -2156,9 +2150,10 @@ js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg)
|
|||
|
||||
JS_snprintf(argbuf, sizeof argbuf, "%u", arg);
|
||||
bytes = NULL;
|
||||
if (VALUE_IS_FUNCTION(cx, *vp)) {
|
||||
atom = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(*vp))->atom;
|
||||
bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, *vp,
|
||||
if (v.isFunObj()) {
|
||||
atom = GET_FUNCTION_PRIVATE(cx, &v.asFunObj())->atom;
|
||||
bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK,
|
||||
Jsvalify(&v),
|
||||
ATOM_TO_STRING(atom));
|
||||
if (!bytes)
|
||||
return;
|
||||
|
@ -2171,7 +2166,7 @@ js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg)
|
|||
|
||||
JSBool
|
||||
js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
|
||||
intN spindex, jsval v, JSString *fallback,
|
||||
intN spindex, const Value &v, JSString *fallback,
|
||||
const char *arg1, const char *arg2)
|
||||
{
|
||||
char *bytes;
|
||||
|
@ -2179,7 +2174,7 @@ js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
|
|||
|
||||
JS_ASSERT(js_ErrorFormatString[errorNumber].argCount >= 1);
|
||||
JS_ASSERT(js_ErrorFormatString[errorNumber].argCount <= 3);
|
||||
bytes = js_DecompileValueGenerator(cx, spindex, v, fallback);
|
||||
bytes = js_DecompileValueGenerator(cx, spindex, Jsvalify(&v), fallback);
|
||||
if (!bytes)
|
||||
return JS_FALSE;
|
||||
|
||||
|
|
245
js/src/jscntxt.h
245
js/src/jscntxt.h
|
@ -285,62 +285,71 @@ class CallStack
|
|||
/* The first frame executed in this callstack. null iff cx is null */
|
||||
JSStackFrame *initialFrame;
|
||||
|
||||
/* If this callstack is suspended, the top of the callstack. */
|
||||
JSStackFrame *suspendedFrame;
|
||||
/*
|
||||
* Two values packed together to get sizeof(Value) alignment.
|
||||
* suspendedFrame: if this callstack is suspended, the top of the callstack.
|
||||
* saved: if this callstack is suspended, whether it is also saved.
|
||||
*/
|
||||
AlignedPtrAndFlag<JSStackFrame> suspendedFrameAndSaved;
|
||||
|
||||
/* If this callstack is suspended, |cx->regs| when it was suspended. */
|
||||
JSFrameRegs *suspendedRegs;
|
||||
|
||||
/* This callstack was suspended by JS_SaveFrameChain. */
|
||||
bool saved;
|
||||
|
||||
/* End of arguments before the first frame. See StackSpace comment. */
|
||||
jsval *initialArgEnd;
|
||||
js::Value *initialArgEnd;
|
||||
|
||||
/* The varobj on entry to initialFrame. */
|
||||
JSObject *initialVarObj;
|
||||
|
||||
JSStackFrame *suspendedFrame() const {
|
||||
return suspendedFrameAndSaved.ptr();
|
||||
}
|
||||
|
||||
bool saved() const {
|
||||
return suspendedFrameAndSaved.flag();
|
||||
}
|
||||
|
||||
public:
|
||||
CallStack()
|
||||
: cx(NULL), previousInContext(NULL), previousInThread(NULL),
|
||||
initialFrame(NULL), suspendedFrame(NULL), saved(false),
|
||||
initialFrame(NULL), suspendedFrameAndSaved(NULL, false),
|
||||
initialArgEnd(NULL), initialVarObj(NULL)
|
||||
{}
|
||||
|
||||
/* Safe casts guaranteed by the contiguous-stack layout. */
|
||||
|
||||
jsval *previousCallStackEnd() const {
|
||||
return (jsval *)this;
|
||||
Value *previousCallStackEnd() const {
|
||||
return (Value *)this;
|
||||
}
|
||||
|
||||
jsval *getInitialArgBegin() const {
|
||||
return (jsval *)(this + 1);
|
||||
Value *getInitialArgBegin() const {
|
||||
return (Value *)(this + 1);
|
||||
}
|
||||
|
||||
/* The three mutually exclusive states of a callstack */
|
||||
|
||||
bool inContext() const {
|
||||
JS_ASSERT(!!cx == !!initialFrame);
|
||||
JS_ASSERT_IF(!initialFrame, !suspendedFrame && !saved);
|
||||
JS_ASSERT_IF(!initialFrame, !suspendedFrame() && !saved());
|
||||
return cx;
|
||||
}
|
||||
|
||||
bool isActive() const {
|
||||
JS_ASSERT_IF(suspendedFrame, inContext());
|
||||
return initialFrame && !suspendedFrame;
|
||||
JS_ASSERT_IF(suspendedFrame(), inContext());
|
||||
return initialFrame && !suspendedFrame();
|
||||
}
|
||||
|
||||
bool isSuspended() const {
|
||||
JS_ASSERT_IF(!suspendedFrame, !saved);
|
||||
JS_ASSERT_IF(suspendedFrame, inContext());
|
||||
return suspendedFrame;
|
||||
JS_ASSERT_IF(!suspendedFrame(), !saved());
|
||||
JS_ASSERT_IF(suspendedFrame(), inContext());
|
||||
return !!suspendedFrame();
|
||||
}
|
||||
|
||||
/* Substate of suspended, queryable in any state. */
|
||||
|
||||
bool isSaved() const {
|
||||
JS_ASSERT_IF(saved, isSuspended());
|
||||
return saved;
|
||||
JS_ASSERT_IF(saved(), isSuspended());
|
||||
return saved();
|
||||
}
|
||||
|
||||
/* Transitioning between inContext <--> isActive */
|
||||
|
@ -365,37 +374,37 @@ class CallStack
|
|||
|
||||
void suspend(JSStackFrame *fp, JSFrameRegs *regs) {
|
||||
JS_ASSERT(fp && isActive() && contains(fp));
|
||||
suspendedFrame = fp;
|
||||
suspendedFrameAndSaved.set(fp, false);
|
||||
suspendedRegs = regs;
|
||||
}
|
||||
|
||||
void resume() {
|
||||
JS_ASSERT(suspendedFrame);
|
||||
suspendedFrame = NULL;
|
||||
JS_ASSERT(suspendedFrame());
|
||||
suspendedFrameAndSaved.set(NULL, false);
|
||||
}
|
||||
|
||||
/* When isSuspended, transitioning isSaved <--> !isSaved */
|
||||
|
||||
void save(JSStackFrame *fp, JSFrameRegs *regs) {
|
||||
JS_ASSERT(!saved);
|
||||
JS_ASSERT(!saved());
|
||||
suspend(fp, regs);
|
||||
saved = true;
|
||||
suspendedFrameAndSaved.setFlag();
|
||||
}
|
||||
|
||||
void restore() {
|
||||
JS_ASSERT(saved);
|
||||
saved = false;
|
||||
JS_ASSERT(saved());
|
||||
suspendedFrameAndSaved.unsetFlag();
|
||||
resume();
|
||||
}
|
||||
|
||||
/* Data available when !inContext */
|
||||
|
||||
void setInitialArgEnd(jsval *v) {
|
||||
void setInitialArgEnd(Value *v) {
|
||||
JS_ASSERT(!inContext() && !initialArgEnd);
|
||||
initialArgEnd = v;
|
||||
}
|
||||
|
||||
jsval *getInitialArgEnd() const {
|
||||
Value *getInitialArgEnd() const {
|
||||
JS_ASSERT(!inContext() && initialArgEnd);
|
||||
return initialArgEnd;
|
||||
}
|
||||
|
@ -413,7 +422,7 @@ class CallStack
|
|||
|
||||
JSStackFrame *getSuspendedFrame() const {
|
||||
JS_ASSERT(isSuspended());
|
||||
return suspendedFrame;
|
||||
return suspendedFrame();
|
||||
}
|
||||
|
||||
JSFrameRegs *getSuspendedRegs() const {
|
||||
|
@ -421,7 +430,7 @@ class CallStack
|
|||
return suspendedRegs;
|
||||
}
|
||||
|
||||
jsval *getSuspendedSP() const {
|
||||
js::Value *getSuspendedSP() const {
|
||||
JS_ASSERT(isSuspended());
|
||||
return suspendedRegs->sp;
|
||||
}
|
||||
|
@ -460,8 +469,8 @@ class CallStack
|
|||
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(CallStack) % sizeof(jsval) == 0);
|
||||
static const size_t ValuesPerCallStack = sizeof(CallStack) / sizeof(jsval);
|
||||
JS_STATIC_ASSERT(sizeof(CallStack) % sizeof(Value) == 0);
|
||||
static const size_t ValuesPerCallStack = sizeof(CallStack) / sizeof(Value);
|
||||
|
||||
/*
|
||||
* The ternary constructor is used when arguments are already pushed on the
|
||||
|
@ -473,13 +482,13 @@ class InvokeArgsGuard
|
|||
friend class StackSpace;
|
||||
JSContext *cx;
|
||||
CallStack *cs; /* null implies nothing pushed */
|
||||
jsval *vp;
|
||||
Value *vp;
|
||||
uintN argc;
|
||||
public:
|
||||
inline InvokeArgsGuard();
|
||||
inline InvokeArgsGuard(jsval *vp, uintN argc);
|
||||
inline InvokeArgsGuard(Value *vp, uintN argc);
|
||||
inline ~InvokeArgsGuard();
|
||||
jsval *getvp() const { return vp; }
|
||||
Value *getvp() const { return vp; }
|
||||
uintN getArgc() const { JS_ASSERT(vp != NULL); return argc; }
|
||||
};
|
||||
|
||||
|
@ -502,13 +511,13 @@ class ExecuteFrameGuard
|
|||
friend class StackSpace;
|
||||
JSContext *cx; /* null implies nothing pushed */
|
||||
CallStack *cs;
|
||||
jsval *vp;
|
||||
Value *vp;
|
||||
JSStackFrame *fp;
|
||||
JSStackFrame *down;
|
||||
public:
|
||||
ExecuteFrameGuard();
|
||||
JS_REQUIRES_STACK ~ExecuteFrameGuard();
|
||||
jsval *getvp() const { return vp; }
|
||||
Value *getvp() const { return vp; }
|
||||
JSStackFrame *getFrame() const { return fp; }
|
||||
};
|
||||
|
||||
|
@ -537,7 +546,7 @@ class ExecuteFrameGuard
|
|||
* ? <----' `----------' `----------'
|
||||
*
|
||||
* Moreover, the bytes between a callstack and its first frame and between two
|
||||
* adjacent frames in a callstack are GC-able jsvals. If the current frame's
|
||||
* adjacent frames in a callstack are GC-able Values. If the current frame's
|
||||
* regs pointer is null (e.g., native frame), there are no final slots.
|
||||
*
|
||||
* An empty callstack roots the initial slots before the initial frame is
|
||||
|
@ -570,16 +579,16 @@ class ExecuteFrameGuard
|
|||
*/
|
||||
class StackSpace
|
||||
{
|
||||
jsval *base;
|
||||
Value *base;
|
||||
#ifdef XP_WIN
|
||||
mutable jsval *commitEnd;
|
||||
mutable Value *commitEnd;
|
||||
#endif
|
||||
jsval *end;
|
||||
Value *end;
|
||||
CallStack *currentCallStack;
|
||||
|
||||
/* Although guards are friends, XGuard should only call popX(). */
|
||||
friend class InvokeArgsGuard;
|
||||
JS_REQUIRES_STACK inline void popInvokeArgs(JSContext *cx, jsval *vp);
|
||||
JS_REQUIRES_STACK inline void popInvokeArgs(JSContext *cx, Value *vp);
|
||||
friend class InvokeFrameGuard;
|
||||
JS_REQUIRES_STACK void popInvokeFrame(JSContext *cx, CallStack *maybecs);
|
||||
friend class ExecuteFrameGuard;
|
||||
|
@ -587,7 +596,7 @@ class StackSpace
|
|||
|
||||
/* Return a pointer to the first unused slot. */
|
||||
JS_REQUIRES_STACK
|
||||
inline jsval *firstUnused() const;
|
||||
inline Value *firstUnused() const;
|
||||
|
||||
#ifdef DEBUG
|
||||
inline bool isCurrent(JSContext *cx) const;
|
||||
|
@ -598,18 +607,18 @@ class StackSpace
|
|||
* Return whether nvals can be allocated from the top of the stack.
|
||||
* N.B. the caller must ensure |from == firstUnused()|.
|
||||
*/
|
||||
inline bool ensureSpace(JSContext *maybecx, jsval *from, ptrdiff_t nvals) const;
|
||||
inline bool ensureSpace(JSContext *maybecx, Value *from, ptrdiff_t nvals) const;
|
||||
|
||||
#ifdef XP_WIN
|
||||
/* Commit more memory from the reserved stack space. */
|
||||
JS_FRIEND_API(bool) bumpCommit(jsval *from, ptrdiff_t nvals) const;
|
||||
JS_FRIEND_API(bool) bumpCommit(Value *from, ptrdiff_t nvals) const;
|
||||
#endif
|
||||
|
||||
public:
|
||||
static const size_t sCapacityVals = 512 * 1024;
|
||||
static const size_t sCapacityBytes = sCapacityVals * sizeof(jsval);
|
||||
static const size_t sCapacityBytes = sCapacityVals * sizeof(Value);
|
||||
static const size_t sCommitVals = 16 * 1024;
|
||||
static const size_t sCommitBytes = sCommitVals * sizeof(jsval);
|
||||
static const size_t sCommitBytes = sCommitVals * sizeof(Value);
|
||||
|
||||
JS_STATIC_ASSERT(sCapacityVals % sCommitVals == 0);
|
||||
|
||||
|
@ -694,7 +703,7 @@ class StackSpace
|
|||
* call pushInlineFrame/popInlineFrame.
|
||||
*/
|
||||
JS_REQUIRES_STACK
|
||||
inline JSStackFrame *getInlineFrame(JSContext *cx, jsval *sp,
|
||||
inline JSStackFrame *getInlineFrame(JSContext *cx, Value *sp,
|
||||
uintN nmissing, uintN nslots) const;
|
||||
|
||||
JS_REQUIRES_STACK
|
||||
|
@ -737,7 +746,7 @@ class FrameRegsIter
|
|||
{
|
||||
CallStack *curcs;
|
||||
JSStackFrame *curfp;
|
||||
jsval *cursp;
|
||||
Value *cursp;
|
||||
jsbytecode *curpc;
|
||||
|
||||
public:
|
||||
|
@ -747,7 +756,7 @@ class FrameRegsIter
|
|||
FrameRegsIter &operator++();
|
||||
|
||||
JSStackFrame *fp() const { return curfp; }
|
||||
jsval *sp() const { return cursp; }
|
||||
Value *sp() const { return cursp; }
|
||||
jsbytecode *pc() const { return curpc; }
|
||||
};
|
||||
|
||||
|
@ -923,7 +932,7 @@ struct JSLocalRootChunk;
|
|||
#define JSLRS_CHUNK_MASK JS_BITMASK(JSLRS_CHUNK_SHIFT)
|
||||
|
||||
struct JSLocalRootChunk {
|
||||
jsval roots[JSLRS_CHUNK_SIZE];
|
||||
void *roots[JSLRS_CHUNK_SIZE];
|
||||
JSLocalRootChunk *down;
|
||||
};
|
||||
|
||||
|
@ -1141,12 +1150,24 @@ struct JSClassProtoCache {
|
|||
#endif
|
||||
friend JSBool js_GetClassPrototype(JSContext *cx, JSObject *scope,
|
||||
JSProtoKey protoKey, JSObject **protop,
|
||||
JSClass *clasp);
|
||||
js::Class *clasp);
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC visibility pop
|
||||
#endif
|
||||
};
|
||||
|
||||
struct JSRootInfo {
|
||||
JSRootInfo() {}
|
||||
JSRootInfo(const char *name, JSGCRootType type) : name(name), type(type) {}
|
||||
const char *name;
|
||||
JSGCRootType type;
|
||||
};
|
||||
|
||||
typedef js::HashMap<void *,
|
||||
JSRootInfo,
|
||||
js::DefaultHasher<void *>,
|
||||
js::SystemAllocPolicy> JSRootedValueMap;
|
||||
|
||||
struct JSRuntime {
|
||||
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
|
||||
JSRuntimeState state;
|
||||
|
@ -1172,7 +1193,7 @@ struct JSRuntime {
|
|||
JSGCChunkInfo *gcChunkList;
|
||||
JSGCArenaList gcArenaList[FINALIZE_LIMIT];
|
||||
JSGCDoubleArenaList gcDoubleArenaList;
|
||||
JSDHashTable gcRootsHash;
|
||||
JSRootedValueMap gcRootsHash;
|
||||
JSDHashTable gcLocksHash;
|
||||
jsrefcount gcKeepAtoms;
|
||||
size_t gcBytes;
|
||||
|
@ -1249,9 +1270,9 @@ struct JSRuntime {
|
|||
JSSetSlotRequest *setSlotRequests;
|
||||
|
||||
/* Well-known numbers held for use by this runtime's contexts. */
|
||||
jsval NaNValue;
|
||||
jsval negativeInfinityValue;
|
||||
jsval positiveInfinityValue;
|
||||
js::Value NaNValue;
|
||||
js::Value negativeInfinityValue;
|
||||
js::Value positiveInfinityValue;
|
||||
|
||||
js::DeflatedStringCache *deflatedStringCache;
|
||||
|
||||
|
@ -1640,7 +1661,7 @@ struct JSContext
|
|||
/*
|
||||
* cx->resolvingTable is non-null and non-empty if we are initializing
|
||||
* standard classes lazily, or if we are otherwise recursing indirectly
|
||||
* from js_LookupProperty through a JSClass.resolve hook. It is used to
|
||||
* from js_LookupProperty through a Class.resolve hook. It is used to
|
||||
* limit runaway recursion (see jsapi.c and jsobj.c).
|
||||
*/
|
||||
JSDHashTable *resolvingTable;
|
||||
|
@ -1656,7 +1677,7 @@ struct JSContext
|
|||
|
||||
/* Exception state -- the exception member is a GC root by definition. */
|
||||
JSPackedBool throwing; /* is there a pending exception? */
|
||||
jsval exception; /* most-recently-thrown exception */
|
||||
js::Value exception; /* most-recently-thrown exception */
|
||||
|
||||
/* Limit pointer for checking native stack consumption during recursion. */
|
||||
jsuword stackLimit;
|
||||
|
@ -1680,7 +1701,7 @@ struct JSContext
|
|||
|
||||
private:
|
||||
friend class js::StackSpace;
|
||||
friend JSBool js_Interpret(JSContext *);
|
||||
friend bool js::Interpret(JSContext *);
|
||||
|
||||
/* 'fp' and 'regs' must only be changed by calling these functions. */
|
||||
void setCurrentFrame(JSStackFrame *fp) {
|
||||
|
@ -2034,8 +2055,8 @@ struct JSContext
|
|||
|
||||
#ifdef DEBUG
|
||||
void assertValidStackDepth(uintN depth) {
|
||||
JS_ASSERT(0 <= regs->sp - StackBase(fp));
|
||||
JS_ASSERT(depth <= uintptr_t(regs->sp - StackBase(fp)));
|
||||
JS_ASSERT(0 <= regs->sp - fp->base());
|
||||
JS_ASSERT(depth <= uintptr_t(regs->sp - fp->base()));
|
||||
}
|
||||
#else
|
||||
void assertValidStackDepth(uintN /*depth*/) {}
|
||||
|
@ -2124,7 +2145,7 @@ class AutoGCRooter {
|
|||
|
||||
/*
|
||||
* Discriminates actual subclass of this being used. If non-negative, the
|
||||
* subclass roots an array of jsvals of the length stored in this field.
|
||||
* subclass roots an array of values of the length stored in this field.
|
||||
* If negative, meaning is indicated by the corresponding value in the enum
|
||||
* below. Any other negative value indicates some deeper problem such as
|
||||
* memory corruption.
|
||||
|
@ -2171,48 +2192,49 @@ class AutoSaveWeakRoots : private AutoGCRooter
|
|||
class AutoValueRooter : private AutoGCRooter
|
||||
{
|
||||
public:
|
||||
explicit AutoValueRooter(JSContext *cx, jsval v = JSVAL_NULL
|
||||
explicit AutoValueRooter(JSContext *cx
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, JSVAL), val(v)
|
||||
: AutoGCRooter(cx, JSVAL), val(js::NullValue())
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
AutoValueRooter(JSContext *cx, const Value &v
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, JSVAL)
|
||||
{
|
||||
val.copy(v);
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
AutoValueRooter(JSContext *cx, JSString *str
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, JSVAL), val(STRING_TO_JSVAL(str))
|
||||
: AutoGCRooter(cx, JSVAL), val(str)
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
AutoValueRooter(JSContext *cx, JSObject *obj
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, JSVAL), val(OBJECT_TO_JSVAL(obj))
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
void setObject(JSObject *obj) {
|
||||
JS_ASSERT(tag == JSVAL);
|
||||
val = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
/*
|
||||
* If you are looking for Object* overloads, use AutoObjectRooter instead;
|
||||
* rooting Object*s as a js::Value requires discerning whether or not it is
|
||||
* a function object. Also, AutoObjectRooter is smaller.
|
||||
*/
|
||||
|
||||
void setString(JSString *str) {
|
||||
JS_ASSERT(tag == JSVAL);
|
||||
JS_ASSERT(str);
|
||||
val = STRING_TO_JSVAL(str);
|
||||
val.setString(str);
|
||||
}
|
||||
|
||||
void setDouble(jsdouble *dp) {
|
||||
void setDouble(jsdouble d) {
|
||||
JS_ASSERT(tag == JSVAL);
|
||||
JS_ASSERT(dp);
|
||||
val = DOUBLE_TO_JSVAL(dp);
|
||||
JS_ASSERT(d);
|
||||
val.setDouble(d);
|
||||
}
|
||||
|
||||
jsval value() const {
|
||||
const Value &value() const {
|
||||
JS_ASSERT(tag == JSVAL);
|
||||
return val;
|
||||
}
|
||||
|
||||
jsval *addr() {
|
||||
Value *addr() {
|
||||
JS_ASSERT(tag == JSVAL);
|
||||
return &val;
|
||||
}
|
||||
|
@ -2220,7 +2242,7 @@ class AutoValueRooter : private AutoGCRooter
|
|||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
|
||||
private:
|
||||
jsval val;
|
||||
Value val;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
|
@ -2254,7 +2276,7 @@ class AutoObjectRooter : private AutoGCRooter {
|
|||
|
||||
class AutoArrayRooter : private AutoGCRooter {
|
||||
public:
|
||||
AutoArrayRooter(JSContext *cx, size_t len, jsval *vec
|
||||
AutoArrayRooter(JSContext *cx, size_t len, Value *vec
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, len), array(vec)
|
||||
{
|
||||
|
@ -2267,12 +2289,12 @@ class AutoArrayRooter : private AutoGCRooter {
|
|||
JS_ASSERT(tag >= 0);
|
||||
}
|
||||
|
||||
void changeArray(jsval *newArray, size_t newLength) {
|
||||
void changeArray(Value *newArray, size_t newLength) {
|
||||
changeLength(newLength);
|
||||
array = newArray;
|
||||
}
|
||||
|
||||
jsval *array;
|
||||
Value *array;
|
||||
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
|
||||
|
@ -2385,14 +2407,14 @@ class AutoEnumStateRooter : private AutoGCRooter
|
|||
public:
|
||||
AutoEnumStateRooter(JSContext *cx, JSObject *obj
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, ENUMERATOR), obj(obj), stateValue(JSVAL_NULL)
|
||||
: AutoGCRooter(cx, ENUMERATOR), obj(obj), stateValue()
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
JS_ASSERT(obj);
|
||||
}
|
||||
|
||||
~AutoEnumStateRooter() {
|
||||
if (!JSVAL_IS_NULL(stateValue)) {
|
||||
if (!stateValue.isNull()) {
|
||||
#ifdef DEBUG
|
||||
JSBool ok =
|
||||
#endif
|
||||
|
@ -2403,8 +2425,8 @@ class AutoEnumStateRooter : private AutoGCRooter
|
|||
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
|
||||
jsval state() const { return stateValue; }
|
||||
jsval * addr() { return &stateValue; }
|
||||
const Value &state() const { return stateValue; }
|
||||
Value *addr() { return &stateValue; }
|
||||
|
||||
protected:
|
||||
void trace(JSTracer *trc) {
|
||||
|
@ -2415,7 +2437,7 @@ class AutoEnumStateRooter : private AutoGCRooter
|
|||
JSObject * const obj;
|
||||
|
||||
private:
|
||||
jsval stateValue;
|
||||
Value stateValue;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
|
@ -2624,7 +2646,7 @@ js_WaitForGC(JSRuntime *rt);
|
|||
#endif
|
||||
|
||||
/*
|
||||
* JSClass.resolve and watchpoint recursion damping machinery.
|
||||
* Class.resolve and watchpoint recursion damping machinery.
|
||||
*/
|
||||
extern JSBool
|
||||
js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
|
||||
|
@ -2636,26 +2658,21 @@ js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
|
|||
|
||||
/*
|
||||
* Local root set management.
|
||||
*
|
||||
* NB: the jsval parameters below may be properly tagged jsvals, or GC-thing
|
||||
* pointers cast to (jsval). This relies on JSObject's tag being zero, but
|
||||
* on the up side it lets us push int-jsval-encoded scopeMark values on the
|
||||
* local root stack.
|
||||
*/
|
||||
extern JSBool
|
||||
js_EnterLocalRootScope(JSContext *cx);
|
||||
|
||||
#define js_LeaveLocalRootScope(cx) \
|
||||
js_LeaveLocalRootScopeWithResult(cx, JSVAL_NULL)
|
||||
js_LeaveLocalRootScopeWithResult(cx, sNullValue)
|
||||
|
||||
extern void
|
||||
js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval);
|
||||
js_LeaveLocalRootScopeWithResult(JSContext *cx, const js::Value &rval);
|
||||
|
||||
extern void
|
||||
js_ForgetLocalRoot(JSContext *cx, jsval v);
|
||||
js_ForgetLocalRoot(JSContext *cx, void *thing);
|
||||
|
||||
extern int
|
||||
js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v);
|
||||
js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, void *thing);
|
||||
|
||||
/*
|
||||
* Report an exception, which is currently realized as a printf-style format
|
||||
|
@ -2727,11 +2744,11 @@ js_ReportIsNotDefined(JSContext *cx, const char *name);
|
|||
* Report an attempt to access the property of a null or undefined value (v).
|
||||
*/
|
||||
extern JSBool
|
||||
js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
|
||||
js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, const js::Value &v,
|
||||
JSString *fallback);
|
||||
|
||||
extern void
|
||||
js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg);
|
||||
js_ReportMissingArg(JSContext *cx, const js::Value &v, uintN arg);
|
||||
|
||||
/*
|
||||
* Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
|
||||
|
@ -2740,7 +2757,7 @@ js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg);
|
|||
*/
|
||||
extern JSBool
|
||||
js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
|
||||
intN spindex, jsval v, JSString *fallback,
|
||||
intN spindex, const js::Value &v, JSString *fallback,
|
||||
const char *arg1, const char *arg2);
|
||||
|
||||
#define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \
|
||||
|
@ -2825,7 +2842,7 @@ LeaveTrace(JSContext *cx)
|
|||
static JS_INLINE void
|
||||
LeaveTraceIfGlobalObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
if (!obj->fslots[JSSLOT_PARENT])
|
||||
if (obj->fslots[JSSLOT_PARENT].isNull())
|
||||
LeaveTrace(cx);
|
||||
}
|
||||
|
||||
|
@ -2916,10 +2933,10 @@ class AutoValueVector : private AutoGCRooter
|
|||
|
||||
size_t length() const { return vector.length(); }
|
||||
|
||||
bool push(jsval v) { return vector.append(v); }
|
||||
bool push(JSString *str) { return push(STRING_TO_JSVAL(str)); }
|
||||
bool push(JSObject *obj) { return push(OBJECT_TO_JSVAL(obj)); }
|
||||
bool push(jsdouble *dp) { return push(DOUBLE_TO_JSVAL(dp)); }
|
||||
bool push(const js::Value &v) { return vector.append(v); }
|
||||
bool push(JSString *str) { return push(str); }
|
||||
bool push(JSObject *obj) { return push(obj); }
|
||||
bool push(jsdouble d) { return push(d); }
|
||||
|
||||
void pop() { vector.popBack(); }
|
||||
|
||||
|
@ -2933,16 +2950,16 @@ class AutoValueVector : private AutoGCRooter
|
|||
return vector.reserve(newLength);
|
||||
}
|
||||
|
||||
jsval &operator[](size_t i) { return vector[i]; }
|
||||
jsval operator[](size_t i) const { return vector[i]; }
|
||||
const js::Value &operator[](size_t i) { return vector[i]; }
|
||||
const js::Value &operator[](size_t i) const { return vector[i]; }
|
||||
|
||||
const jsval *buffer() const { return vector.begin(); }
|
||||
jsval *buffer() { return vector.begin(); }
|
||||
const js::Value *buffer() const { return vector.begin(); }
|
||||
const js::Value *buffer() { return vector.begin(); }
|
||||
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
|
||||
private:
|
||||
Vector<jsval, 8> vector;
|
||||
Vector<js::Value, 8> vector;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ CallStack::getCurrentFrame() const
|
|||
return isSuspended() ? getSuspendedFrame() : cx->fp;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK inline jsval *
|
||||
JS_REQUIRES_STACK inline Value *
|
||||
StackSpace::firstUnused() const
|
||||
{
|
||||
CallStack *ccs = currentCallStack;
|
||||
|
@ -82,7 +82,7 @@ StackSpace::isCurrent(JSContext *cx) const
|
|||
#endif
|
||||
|
||||
JS_ALWAYS_INLINE bool
|
||||
StackSpace::ensureSpace(JSContext *maybecx, jsval *from, ptrdiff_t nvals) const
|
||||
StackSpace::ensureSpace(JSContext *maybecx, Value *from, ptrdiff_t nvals) const
|
||||
{
|
||||
JS_ASSERT(from == firstUnused());
|
||||
#ifdef XP_WIN
|
||||
|
@ -120,14 +120,14 @@ StackSpace::ensureEnoughSpaceToEnterTrace()
|
|||
}
|
||||
|
||||
JS_ALWAYS_INLINE void
|
||||
StackSpace::popInvokeArgs(JSContext *cx, jsval *vp)
|
||||
StackSpace::popInvokeArgs(JSContext *cx, Value *vp)
|
||||
{
|
||||
JS_ASSERT(!currentCallStack->inContext());
|
||||
currentCallStack = currentCallStack->getPreviousInThread();
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK JS_ALWAYS_INLINE JSStackFrame *
|
||||
StackSpace::getInlineFrame(JSContext *cx, jsval *sp,
|
||||
StackSpace::getInlineFrame(JSContext *cx, Value *sp,
|
||||
uintN nmissing, uintN nslots) const
|
||||
{
|
||||
JS_ASSERT(isCurrent(cx) && cx->hasActiveCallStack());
|
||||
|
@ -182,7 +182,7 @@ InvokeArgsGuard::InvokeArgsGuard()
|
|||
{}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
InvokeArgsGuard::InvokeArgsGuard(jsval *vp, uintN argc)
|
||||
InvokeArgsGuard::InvokeArgsGuard(Value *vp, uintN argc)
|
||||
: cx(NULL), cs(NULL), vp(vp), argc(argc)
|
||||
{}
|
||||
|
||||
|
@ -198,7 +198,7 @@ InvokeArgsGuard::~InvokeArgsGuard()
|
|||
void
|
||||
AutoIdArray::trace(JSTracer *trc) {
|
||||
JS_ASSERT(tag == IDARRAY);
|
||||
js::TraceValues(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray");
|
||||
TraceIds(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray");
|
||||
}
|
||||
|
||||
class AutoNamespaces : protected AutoGCRooter {
|
||||
|
@ -218,7 +218,7 @@ AutoGCRooter::trace(JSTracer *trc)
|
|||
switch (tag) {
|
||||
case JSVAL:
|
||||
JS_SET_TRACING_NAME(trc, "js::AutoValueRooter.val");
|
||||
js_CallValueTracerIfGCThing(trc, static_cast<AutoValueRooter *>(this)->val);
|
||||
CallGCMarkerIfGCThing(trc, static_cast<AutoValueRooter *>(this)->val);
|
||||
return;
|
||||
|
||||
case SPROP:
|
||||
|
@ -244,7 +244,7 @@ AutoGCRooter::trace(JSTracer *trc)
|
|||
|
||||
case IDARRAY: {
|
||||
JSIdArray *ida = static_cast<AutoIdArray *>(this)->idArray;
|
||||
TraceValues(trc, ida->length, ida->vector, "js::AutoIdArray.idArray");
|
||||
TraceIds(trc, ida->length, ida->vector, "js::AutoIdArray.idArray");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -254,9 +254,12 @@ AutoGCRooter::trace(JSTracer *trc)
|
|||
for (size_t i = 0, len = descriptors.length(); i < len; i++) {
|
||||
PropertyDescriptor &desc = descriptors[i];
|
||||
|
||||
JS_CALL_VALUE_TRACER(trc, desc.value, "PropertyDescriptor::value");
|
||||
JS_CALL_VALUE_TRACER(trc, desc.get, "PropertyDescriptor::get");
|
||||
JS_CALL_VALUE_TRACER(trc, desc.set, "PropertyDescriptor::set");
|
||||
JS_SET_TRACING_NAME(trc, "PropertyDescriptor::value");
|
||||
CallGCMarkerIfGCThing(trc, desc.value);
|
||||
JS_SET_TRACING_NAME(trc, "PropertyDescriptor::get");
|
||||
CallGCMarkerIfGCThing(trc, desc.get);
|
||||
JS_SET_TRACING_NAME(trc, "PropertyDescriptor::set");
|
||||
CallGCMarkerIfGCThing(trc, desc.set);
|
||||
js_TraceId(trc, desc.id);
|
||||
}
|
||||
return;
|
||||
|
@ -276,18 +279,18 @@ AutoGCRooter::trace(JSTracer *trc)
|
|||
case OBJECT:
|
||||
if (JSObject *obj = static_cast<AutoObjectRooter *>(this)->obj) {
|
||||
JS_SET_TRACING_NAME(trc, "js::AutoObjectRooter.obj");
|
||||
js_CallGCMarker(trc, obj, JSTRACE_OBJECT);
|
||||
CallGCMarker(trc, obj, JSTRACE_OBJECT);
|
||||
}
|
||||
return;
|
||||
|
||||
case ID:
|
||||
JS_SET_TRACING_NAME(trc, "js::AutoIdRooter.val");
|
||||
js_CallValueTracerIfGCThing(trc, static_cast<AutoIdRooter *>(this)->idval);
|
||||
CallGCMarkerIfGCThing(trc, static_cast<AutoIdRooter *>(this)->idval);
|
||||
return;
|
||||
|
||||
case VECTOR: {
|
||||
js::Vector<jsval, 8> &vector = static_cast<js::AutoValueVector *>(this)->vector;
|
||||
js::TraceValues(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
|
||||
Vector<Value, 8> &vector = static_cast<AutoValueVector *>(this)->vector;
|
||||
TraceValues(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -296,6 +299,6 @@ AutoGCRooter::trace(JSTracer *trc)
|
|||
TraceValues(trc, tag, static_cast<AutoArrayRooter *>(this)->array, "js::AutoArrayRooter.array");
|
||||
}
|
||||
|
||||
}
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jscntxtinlines_h___ */
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* JS date methods.
|
||||
*/
|
||||
|
@ -71,6 +74,8 @@
|
|||
#include "jsobj.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
/*
|
||||
|
@ -499,12 +504,12 @@ const uint32 JSSLOT_LOCAL_TIME = JSSLOT_PRIVATE + 1;
|
|||
|
||||
const uint32 DATE_RESERVED_SLOTS = 2;
|
||||
|
||||
JSClass js_DateClass = {
|
||||
Class js_DateClass = {
|
||||
js_Date_str,
|
||||
JSCLASS_HAS_RESERVED_SLOTS(DATE_RESERVED_SLOTS) |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
|
||||
PropertyStub, PropertyStub, PropertyStub, PropertyStub,
|
||||
EnumerateStub, ResolveStub, ConvertStub, NULL,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
|
@ -583,7 +588,7 @@ date_msecFromDate(jsdouble year, jsdouble mon, jsdouble mday, jsdouble hour,
|
|||
#define MAXARGS 7
|
||||
|
||||
static JSBool
|
||||
date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
|
||||
date_msecFromArgs(JSContext *cx, uintN argc, Value *argv, jsdouble *rval)
|
||||
{
|
||||
uintN loop;
|
||||
jsdouble array[MAXARGS];
|
||||
|
@ -592,7 +597,7 @@ date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
|
|||
for (loop = 0; loop < MAXARGS; loop++) {
|
||||
if (loop < argc) {
|
||||
jsdouble d;
|
||||
if (!ValueToNumber(cx, argv[loop], &d))
|
||||
if (!ValueToNumber(cx, &argv[loop], &d))
|
||||
return JS_FALSE;
|
||||
/* return NaN if any arg is not finite */
|
||||
if (!JSDOUBLE_IS_FINITE(d)) {
|
||||
|
@ -623,7 +628,7 @@ date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
|
|||
* See ECMA 15.9.4.[3-10];
|
||||
*/
|
||||
static JSBool
|
||||
date_UTC(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_UTC(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble msec_time;
|
||||
|
||||
|
@ -632,7 +637,8 @@ date_UTC(JSContext *cx, uintN argc, jsval *vp)
|
|||
|
||||
msec_time = TIMECLIP(msec_time);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, msec_time, vp);
|
||||
vp->setDouble(msec_time);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1159,26 +1165,27 @@ syntax:
|
|||
}
|
||||
|
||||
static JSBool
|
||||
date_parse(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_parse(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSString *str;
|
||||
jsdouble result;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return true;
|
||||
}
|
||||
str = js_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
vp[2] = STRING_TO_JSVAL(str);
|
||||
vp[2].setString(str);
|
||||
if (!date_parseString(str, &result)) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return true;
|
||||
}
|
||||
|
||||
result = TIMECLIP(result);
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline jsdouble
|
||||
|
@ -1188,9 +1195,10 @@ NowAsMillis()
|
|||
}
|
||||
|
||||
static JSBool
|
||||
date_now(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_now(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return js_NewDoubleInRootedValue(cx, NowAsMillis(), vp);
|
||||
vp->setDouble(NowAsMillis());
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
@ -1206,38 +1214,37 @@ date_now_tn(JSContext*)
|
|||
* Date type.
|
||||
*/
|
||||
static JSBool
|
||||
GetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
|
||||
GetUTCTime(JSContext *cx, JSObject *obj, Value *vp, jsdouble *dp)
|
||||
{
|
||||
if (!JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
|
||||
if (!InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
|
||||
return JS_FALSE;
|
||||
*dp = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
|
||||
*dp = obj->fslots[JSSLOT_UTC_TIME].asDouble();
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
SetDateToNaN(JSContext *cx, JSObject *obj, jsval *vp = NULL)
|
||||
SetDateToNaN(JSContext *cx, JSObject *obj, Value *vp = NULL)
|
||||
{
|
||||
JS_ASSERT(obj->getClass() == &js_DateClass);
|
||||
|
||||
obj->fslots[JSSLOT_LOCAL_TIME] = cx->runtime->NaNValue;
|
||||
obj->fslots[JSSLOT_UTC_TIME] = cx->runtime->NaNValue;
|
||||
obj->fslots[JSSLOT_LOCAL_TIME].setDouble(js_NaN);
|
||||
obj->fslots[JSSLOT_UTC_TIME].setDouble(js_NaN);
|
||||
if (vp)
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set UTC time to a given time and invalidate cached local time.
|
||||
*/
|
||||
static JSBool
|
||||
SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, jsval *vp = NULL)
|
||||
SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, Value *vp = NULL)
|
||||
{
|
||||
JS_ASSERT(obj->getClass() == &js_DateClass);
|
||||
|
||||
obj->fslots[JSSLOT_LOCAL_TIME] = cx->runtime->NaNValue;
|
||||
if (!js_NewDoubleInRootedValue(cx, t, &obj->fslots[JSSLOT_UTC_TIME]))
|
||||
return false;
|
||||
obj->fslots[JSSLOT_LOCAL_TIME].setDouble(js_NaN);
|
||||
obj->fslots[JSSLOT_UTC_TIME].setDouble(t);
|
||||
if (vp)
|
||||
*vp = obj->fslots[JSSLOT_UTC_TIME];
|
||||
vp->setDouble(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1246,22 +1253,21 @@ SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, jsval *vp = NULL)
|
|||
* (e.g., NaN), the local time slot is set to the UTC time without conversion.
|
||||
*/
|
||||
static JSBool
|
||||
GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
|
||||
GetAndCacheLocalTime(JSContext *cx, JSObject *obj, Value *vp, jsdouble *dp)
|
||||
{
|
||||
if (!obj || !JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
|
||||
if (!obj || !InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
|
||||
return false;
|
||||
|
||||
jsval *slotp = &obj->fslots[JSSLOT_LOCAL_TIME];
|
||||
jsdouble result = *JSVAL_TO_DOUBLE(*slotp);
|
||||
Value &slot = obj->fslots[JSSLOT_LOCAL_TIME];
|
||||
jsdouble result = slot.asDouble();
|
||||
if (JSDOUBLE_IS_NaN(result)) {
|
||||
result = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
|
||||
result = obj->fslots[JSSLOT_UTC_TIME].asDouble();
|
||||
|
||||
/* if result is NaN, it couldn't be finite. */
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = LocalTime(result);
|
||||
|
||||
if (!js_NewDoubleInRootedValue(cx, result, slotp))
|
||||
return false;
|
||||
slot.setDouble(result);
|
||||
}
|
||||
|
||||
*dp = result;
|
||||
|
@ -1272,20 +1278,22 @@ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
|
|||
* See ECMA 15.9.5.4 thru 15.9.5.23
|
||||
*/
|
||||
static JSBool
|
||||
date_getTime(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getTime(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
return GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result) &&
|
||||
js_NewNumberInRootedValue(cx, result, vp);
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetYear(JSContext *cx, JSBool fullyear, jsval *vp)
|
||||
GetYear(JSContext *cx, JSBool fullyear, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result)) {
|
||||
|
@ -1296,214 +1304,228 @@ GetYear(JSContext *cx, JSBool fullyear, jsval *vp)
|
|||
result -= 1900;
|
||||
}
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getYear(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getYear(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return GetYear(cx, JS_FALSE, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getFullYear(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getFullYear(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return GetYear(cx, JS_TRUE, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getUTCFullYear(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getUTCFullYear(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = YearFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getMonth(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getMonth(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = MonthFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getUTCMonth(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getUTCMonth(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = MonthFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getDate(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getDate(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = DateFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getUTCDate(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getUTCDate(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = DateFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getDay(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getDay(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = WeekDay(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getUTCDay(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getUTCDay(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = WeekDay(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getHours(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getHours(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = HourFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getUTCHours(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getUTCHours(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = HourFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getMinutes(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getMinutes(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = MinFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getUTCMinutes(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getUTCMinutes(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = MinFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Date.getSeconds is mapped to getUTCSeconds */
|
||||
|
||||
static JSBool
|
||||
date_getUTCSeconds(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getUTCSeconds(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = SecFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Date.getMilliseconds is mapped to getUTCMilliseconds */
|
||||
|
||||
static JSBool
|
||||
date_getUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getUTCMilliseconds(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble result;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = msFromTime(result);
|
||||
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_getTimezoneOffset(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_getTimezoneOffset(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
jsdouble utctime, localtime, result;
|
||||
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
obj = ComputeThisObjectFromVp(cx, vp);
|
||||
if (!GetUTCTime(cx, obj, vp, &utctime))
|
||||
return JS_FALSE;
|
||||
if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime))
|
||||
|
@ -1515,14 +1537,15 @@ date_getTimezoneOffset(JSContext *cx, uintN argc, jsval *vp)
|
|||
* daylight savings time.
|
||||
*/
|
||||
result = (utctime - localtime) / msPerMinute;
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
vp->setDouble(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setTime(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setTime(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))
|
||||
JSObject *obj = ComputeThisObjectFromVp(cx, vp);
|
||||
if (!InstanceOf(cx, obj, &js_DateClass, vp + 2))
|
||||
return false;
|
||||
|
||||
if (argc == 0) {
|
||||
|
@ -1531,17 +1554,17 @@ date_setTime(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
jsdouble result;
|
||||
if (!ValueToNumber(cx, vp[2], &result))
|
||||
if (!ValueToNumber(cx, &vp[2], &result))
|
||||
return false;
|
||||
|
||||
return SetUTCTime(cx, obj, TIMECLIP(result), vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
||||
date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
jsval *argv;
|
||||
Value *argv;
|
||||
uintN i;
|
||||
jsdouble args[4], *argp, *stop;
|
||||
jsdouble hour, min, sec, msec;
|
||||
|
@ -1550,13 +1573,15 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
|||
jsdouble msec_time;
|
||||
jsdouble result;
|
||||
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
obj = ComputeThisObjectFromVp(cx, vp);
|
||||
if (!GetUTCTime(cx, obj, vp, &result))
|
||||
return false;
|
||||
|
||||
/* just return NaN if the date is already NaN */
|
||||
if (!JSDOUBLE_IS_FINITE(result))
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
if (!JSDOUBLE_IS_FINITE(result)) {
|
||||
vp->setDouble(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Satisfy the ECMA rule that if a function is called with
|
||||
|
@ -1577,7 +1602,7 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
|||
|
||||
argv = vp + 2;
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!ValueToNumber(cx, argv[i], &args[i]))
|
||||
if (!ValueToNumber(cx, &argv[i], &args[i]))
|
||||
return false;
|
||||
if (!JSDOUBLE_IS_FINITE(args[i])) {
|
||||
SetDateToNaN(cx, obj, vp);
|
||||
|
@ -1627,65 +1652,65 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
date_setMilliseconds(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setMilliseconds(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeTime(cx, 1, JS_TRUE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setUTCMilliseconds(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeTime(cx, 1, JS_FALSE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setSeconds(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setSeconds(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeTime(cx, 2, JS_TRUE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setUTCSeconds(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setUTCSeconds(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeTime(cx, 2, JS_FALSE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setMinutes(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setMinutes(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeTime(cx, 3, JS_TRUE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setUTCMinutes(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setUTCMinutes(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeTime(cx, 3, JS_FALSE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setHours(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setHours(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeTime(cx, 4, JS_TRUE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setUTCHours(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setUTCHours(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeTime(cx, 4, JS_FALSE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
||||
date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
jsval *argv;
|
||||
Value *argv;
|
||||
uintN i;
|
||||
jsdouble lorutime; /* local or UTC version of *date */
|
||||
jsdouble args[3], *argp, *stop;
|
||||
jsdouble year, month, day;
|
||||
jsdouble result;
|
||||
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
obj = ComputeThisObjectFromVp(cx, vp);
|
||||
if (!GetUTCTime(cx, obj, vp, &result))
|
||||
return false;
|
||||
|
||||
|
@ -1700,7 +1725,7 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
|||
|
||||
argv = vp + 2;
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!ValueToNumber(cx, argv[i], &args[i]))
|
||||
if (!ValueToNumber(cx, &argv[i], &args[i]))
|
||||
return JS_FALSE;
|
||||
if (!JSDOUBLE_IS_FINITE(args[i])) {
|
||||
SetDateToNaN(cx, obj, vp);
|
||||
|
@ -1712,8 +1737,10 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
|||
/* return NaN if date is NaN and we're not setting the year,
|
||||
* If we are, use 0 as the time. */
|
||||
if (!(JSDOUBLE_IS_FINITE(result))) {
|
||||
if (maxargs < 3)
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
if (maxargs < 3) {
|
||||
vp->setDouble(result);
|
||||
return true;
|
||||
}
|
||||
lorutime = +0.;
|
||||
} else {
|
||||
lorutime = local ? LocalTime(result) : result;
|
||||
|
@ -1746,45 +1773,45 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
date_setDate(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setDate(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeDate(cx, 1, JS_TRUE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setUTCDate(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setUTCDate(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeDate(cx, 1, JS_FALSE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setMonth(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setMonth(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeDate(cx, 2, JS_TRUE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setUTCMonth(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setUTCMonth(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeDate(cx, 2, JS_FALSE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setFullYear(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setFullYear(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeDate(cx, 3, JS_TRUE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setUTCFullYear(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setUTCFullYear(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_makeDate(cx, 3, JS_FALSE, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_setYear(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_setYear(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
JSObject *obj = ComputeThisObjectFromVp(cx, vp);
|
||||
|
||||
jsdouble result;
|
||||
if (!GetUTCTime(cx, obj, vp, &result))
|
||||
|
@ -1797,7 +1824,7 @@ date_setYear(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
jsdouble year;
|
||||
if (!ValueToNumber(cx, vp[2], &year))
|
||||
if (!ValueToNumber(cx, &vp[2], &year))
|
||||
return false;
|
||||
if (!JSDOUBLE_IS_FINITE(year)) {
|
||||
SetDateToNaN(cx, obj, vp);
|
||||
|
@ -1856,14 +1883,14 @@ print_iso_string(char* buf, size_t size, jsdouble utctime)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
date_utc_format(JSContext *cx, jsval *vp,
|
||||
date_utc_format(JSContext *cx, Value *vp,
|
||||
void (*printFunc)(char*, size_t, jsdouble))
|
||||
{
|
||||
char buf[100];
|
||||
JSString *str;
|
||||
jsdouble utctime;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!JSDOUBLE_IS_FINITE(utctime)) {
|
||||
|
@ -1874,18 +1901,18 @@ date_utc_format(JSContext *cx, jsval *vp,
|
|||
str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
vp->setString(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_toGMTString(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toGMTString(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_utc_format(cx, vp, print_gmt_string);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_toISOString(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toISOString(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_utc_format(cx, vp, print_iso_string);
|
||||
}
|
||||
|
@ -1918,7 +1945,7 @@ typedef enum formatspec {
|
|||
|
||||
/* helper function */
|
||||
static JSBool
|
||||
date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval)
|
||||
date_format(JSContext *cx, jsdouble date, formatspec format, Value *rval)
|
||||
{
|
||||
char buf[100];
|
||||
JSString *str;
|
||||
|
@ -2026,12 +2053,12 @@ date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval)
|
|||
str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
rval->setString(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
|
||||
date_toLocaleHelper(JSContext *cx, const char *format, Value *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
char buf[100];
|
||||
|
@ -2039,7 +2066,7 @@ date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
|
|||
PRMJTime split;
|
||||
jsdouble utctime;
|
||||
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
obj = ComputeThisObjectFromVp(cx, vp);
|
||||
if (!GetUTCTime(cx, obj, vp, &utctime))
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -2073,17 +2100,17 @@ date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
|
|||
}
|
||||
|
||||
if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
|
||||
return cx->localeCallbacks->localeToUnicode(cx, buf, vp);
|
||||
return cx->localeCallbacks->localeToUnicode(cx, buf, Jsvalify(vp));
|
||||
|
||||
str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
vp->setString(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toLocaleString(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
/* Use '%#c' for windows, because '%c' is
|
||||
* backward-compatible and non-y2k with msvc; '%#c' requests that a
|
||||
|
@ -2099,7 +2126,7 @@ date_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
date_toLocaleDateString(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toLocaleDateString(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
/* Use '%#x' for windows, because '%x' is
|
||||
* backward-compatible and non-y2k with msvc; '%#x' requests that a
|
||||
|
@ -2115,13 +2142,13 @@ date_toLocaleDateString(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
date_toLocaleTimeString(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toLocaleTimeString(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return date_toLocaleHelper(cx, "%X", vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toLocaleFormat(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSString *fmt;
|
||||
const char *fmtbytes;
|
||||
|
@ -2132,7 +2159,7 @@ date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
|
|||
fmt = js_ValueToString(cx, vp[2]);
|
||||
if (!fmt)
|
||||
return JS_FALSE;
|
||||
vp[2] = STRING_TO_JSVAL(fmt);
|
||||
vp[2].setString(fmt);
|
||||
fmtbytes = js_GetStringBytes(cx, fmt);
|
||||
if (!fmtbytes)
|
||||
return JS_FALSE;
|
||||
|
@ -2141,21 +2168,21 @@ date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
date_toTimeString(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toTimeString(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble utctime;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
|
||||
return JS_FALSE;
|
||||
return date_format(cx, utctime, FORMATSPEC_TIME, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_toDateString(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toDateString(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble utctime;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
|
||||
return JS_FALSE;
|
||||
return date_format(cx, utctime, FORMATSPEC_DATE, vp);
|
||||
}
|
||||
|
@ -2165,13 +2192,13 @@ date_toDateString(JSContext *cx, uintN argc, jsval *vp)
|
|||
#include "jsdtoa.h"
|
||||
|
||||
static JSBool
|
||||
date_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toSource(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble utctime;
|
||||
char buf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr, *bytes;
|
||||
JSString *str;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
|
||||
return JS_FALSE;
|
||||
|
||||
numStr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, buf, sizeof buf, DTOSTR_STANDARD, 0, utctime);
|
||||
|
@ -2191,17 +2218,17 @@ date_toSource(JSContext *cx, uintN argc, jsval *vp)
|
|||
js_free(bytes);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
vp->setString(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
date_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_toString(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble utctime;
|
||||
|
||||
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
|
||||
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
|
||||
return JS_FALSE;
|
||||
return date_format(cx, utctime, FORMATSPEC_FULL, vp);
|
||||
}
|
||||
|
@ -2210,7 +2237,7 @@ date_toString(JSContext *cx, uintN argc, jsval *vp)
|
|||
static jsval FASTCALL
|
||||
date_valueOf_tn(JSContext* cx, JSObject* obj, JSString* str)
|
||||
{
|
||||
JS_ASSERT(JS_InstanceOf(cx, obj, &js_DateClass, NULL));
|
||||
JS_ASSERT(InstanceOf(cx, obj, &js_DateClass, NULL));
|
||||
jsdouble t = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
|
||||
|
||||
JSString* number_str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
|
||||
|
@ -2227,7 +2254,7 @@ date_valueOf_tn(JSContext* cx, JSObject* obj, JSString* str)
|
|||
#endif
|
||||
|
||||
static JSBool
|
||||
date_valueOf(JSContext *cx, uintN argc, jsval *vp)
|
||||
date_valueOf(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSString *str, *number_str;
|
||||
|
||||
|
@ -2319,7 +2346,7 @@ static JSFunctionSpec date_methods[] = {
|
|||
};
|
||||
|
||||
JSBool
|
||||
js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
js_Date(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
{
|
||||
/* Date called as function. */
|
||||
if (!JS_IsConstructing(cx))
|
||||
|
@ -2330,9 +2357,9 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
if (argc == 0) {
|
||||
d = NowAsMillis();
|
||||
} else if (argc == 1) {
|
||||
if (!JSVAL_IS_STRING(argv[0])) {
|
||||
if (!argv[0].isString()) {
|
||||
/* the argument is a millisecond number */
|
||||
if (!ValueToNumber(cx, argv[0], &d))
|
||||
if (!ValueToNumber(cx, &argv[0], &d))
|
||||
return JS_FALSE;
|
||||
d = TIMECLIP(d);
|
||||
} else {
|
||||
|
@ -2340,7 +2367,7 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
JSString *str = js_ValueToString(cx, argv[0]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
argv[0] = STRING_TO_JSVAL(str);
|
||||
argv[0].setString(str);
|
||||
|
||||
if (!date_parseString(str, &d))
|
||||
d = js_NaN;
|
||||
|
@ -2368,8 +2395,9 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
|
|||
|
||||
/* set static LocalTZA */
|
||||
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
|
||||
proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS,
|
||||
NULL, date_methods, NULL, date_static_methods);
|
||||
proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date,
|
||||
MAXARGS, NULL, date_methods, NULL,
|
||||
date_static_methods);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -44,9 +44,7 @@
|
|||
#ifndef jsdate_h___
|
||||
#define jsdate_h___
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSClass js_DateClass;
|
||||
extern js::Class js_DateClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitDateClass(JSContext *cx, JSObject *obj);
|
||||
|
@ -126,8 +124,6 @@ js_IntervalNow();
|
|||
|
||||
/* Date constructor native. Exposed only so the JIT can know its address. */
|
||||
JSBool
|
||||
js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
js_Date(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
|
||||
|
||||
#endif /* jsdate_h___ */
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* JS debugging API.
|
||||
*/
|
||||
|
@ -77,7 +79,7 @@ typedef struct JSTrap {
|
|||
jsbytecode *pc;
|
||||
JSOp op;
|
||||
JSTrapHandler handler;
|
||||
void *closure;
|
||||
jsval closure;
|
||||
} JSTrap;
|
||||
|
||||
#define DBG_LOCK(rt) JS_ACQUIRE_LOCK((rt)->debuggerLock)
|
||||
|
@ -142,7 +144,7 @@ js_UntrapScriptCode(JSContext *cx, JSScript *script)
|
|||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler handler, void *closure)
|
||||
JSTrapHandler handler, jsval closure)
|
||||
{
|
||||
JSTrap *junk, *trap, *twin;
|
||||
JSRuntime *rt;
|
||||
|
@ -168,7 +170,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|||
trap = (JSTrap *) cx->malloc(sizeof *trap);
|
||||
if (!trap)
|
||||
return JS_FALSE;
|
||||
trap->closure = NULL;
|
||||
trap->closure = JSVAL_NULL;
|
||||
DBG_LOCK(rt);
|
||||
twin = (rt->debuggerMutations != sample)
|
||||
? FindTrap(rt, script, pc)
|
||||
|
@ -220,7 +222,7 @@ DestroyTrapAndUnlock(JSContext *cx, JSTrap *trap)
|
|||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler *handlerp, void **closurep)
|
||||
JSTrapHandler *handlerp, jsval *closurep)
|
||||
{
|
||||
JSTrap *trap;
|
||||
|
||||
|
@ -229,7 +231,7 @@ JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|||
if (handlerp)
|
||||
*handlerp = trap ? trap->handler : NULL;
|
||||
if (closurep)
|
||||
*closurep = trap ? trap->closure : NULL;
|
||||
*closurep = trap ? trap->closure : JSVAL_NULL;
|
||||
if (trap)
|
||||
DestroyTrapAndUnlock(cx, trap);
|
||||
else
|
||||
|
@ -295,10 +297,8 @@ js_MarkTraps(JSTracer *trc)
|
|||
for (JSTrap *trap = (JSTrap *) rt->trapList.next;
|
||||
&trap->links != &rt->trapList;
|
||||
trap = (JSTrap *) trap->links.next) {
|
||||
if (trap->closure) {
|
||||
JS_SET_TRACING_NAME(trc, "trap->closure");
|
||||
js_CallValueTracerIfGCThing(trc, (jsval) trap->closure);
|
||||
}
|
||||
JS_SET_TRACING_NAME(trc, "trap->closure");
|
||||
CallGCMarkerIfGCThing(trc, Valueify(trap->closure));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,15 +375,15 @@ LeaveTraceRT(JSRuntime *rt)
|
|||
#endif
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
|
||||
JS_SetInterrupt(JSRuntime *rt, JSInterruptHook handler, void *closure)
|
||||
{
|
||||
#ifdef JS_TRACER
|
||||
{
|
||||
AutoLockGC lock(rt);
|
||||
bool wasInhibited = rt->debuggerInhibitsJIT();
|
||||
#endif
|
||||
rt->globalDebugHooks.interruptHandler = handler;
|
||||
rt->globalDebugHooks.interruptHandlerData = closure;
|
||||
rt->globalDebugHooks.interruptHook = handler;
|
||||
rt->globalDebugHooks.interruptHookData = closure;
|
||||
#ifdef JS_TRACER
|
||||
JITInhibitingHookChange(rt, wasInhibited);
|
||||
}
|
||||
|
@ -393,18 +393,18 @@ JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep)
|
||||
JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *handlerp, void **closurep)
|
||||
{
|
||||
#ifdef JS_TRACER
|
||||
AutoLockGC lock(rt);
|
||||
bool wasInhibited = rt->debuggerInhibitsJIT();
|
||||
#endif
|
||||
if (handlerp)
|
||||
*handlerp = rt->globalDebugHooks.interruptHandler;
|
||||
*handlerp = rt->globalDebugHooks.interruptHook;
|
||||
if (closurep)
|
||||
*closurep = rt->globalDebugHooks.interruptHandlerData;
|
||||
rt->globalDebugHooks.interruptHandler = 0;
|
||||
rt->globalDebugHooks.interruptHandlerData = 0;
|
||||
*closurep = rt->globalDebugHooks.interruptHookData;
|
||||
rt->globalDebugHooks.interruptHook = 0;
|
||||
rt->globalDebugHooks.interruptHookData = 0;
|
||||
#ifdef JS_TRACER
|
||||
JITInhibitingHookChange(rt, wasInhibited);
|
||||
#endif
|
||||
|
@ -417,7 +417,7 @@ typedef struct JSWatchPoint {
|
|||
JSCList links;
|
||||
JSObject *object; /* weak link, see js_FinalizeObject */
|
||||
JSScopeProperty *sprop;
|
||||
JSPropertyOp setter;
|
||||
PropertyOp setter;
|
||||
JSWatchPointHandler handler;
|
||||
JSObject *closure;
|
||||
uintN flags;
|
||||
|
@ -438,7 +438,7 @@ DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag)
|
|||
JSBool ok;
|
||||
JSScopeProperty *sprop;
|
||||
JSScope *scope;
|
||||
JSPropertyOp setter;
|
||||
PropertyOp setter;
|
||||
|
||||
ok = JS_TRUE;
|
||||
wp->flags &= ~flag;
|
||||
|
@ -507,11 +507,11 @@ js_TraceWatchPoints(JSTracer *trc, JSObject *obj)
|
|||
if (wp->object == obj) {
|
||||
wp->sprop->trace(trc);
|
||||
if (wp->sprop->hasSetterValue() && wp->setter) {
|
||||
JS_CALL_OBJECT_TRACER(trc, js_CastAsObject(wp->setter),
|
||||
JS_CALL_OBJECT_TRACER(trc, CastAsObject(wp->setter),
|
||||
"wp->setter");
|
||||
}
|
||||
JS_SET_TRACING_NAME(trc, "wp->closure");
|
||||
js_CallValueTracerIfGCThing(trc, OBJECT_TO_JSVAL(wp->closure));
|
||||
CallGCMarkerForGCThing(trc, Value(wp->closure));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -578,11 +578,11 @@ js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id)
|
|||
* Secret handshake with DropWatchPointAndUnlock: if (!scope), we know our
|
||||
* caller has acquired rt->debuggerLock, so we don't have to.
|
||||
*/
|
||||
JSPropertyOp
|
||||
PropertyOp
|
||||
js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
|
||||
const JSScopeProperty *sprop)
|
||||
{
|
||||
JSPropertyOp setter;
|
||||
PropertyOp setter;
|
||||
JSWatchPoint *wp;
|
||||
|
||||
setter = NULL;
|
||||
|
@ -602,7 +602,7 @@ js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
|
|||
}
|
||||
|
||||
JSBool
|
||||
js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
js_watch_set(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
DBG_LOCK(rt);
|
||||
|
@ -616,17 +616,17 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
DBG_UNLOCK(rt);
|
||||
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
jsval propid = ID_TO_VALUE(sprop->id);
|
||||
jsval userid = SPROP_USERID(sprop);
|
||||
jsid propid = sprop->id;
|
||||
jsid userid = SPROP_USERID(sprop);
|
||||
JSScope *scope = obj->scope();
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
|
||||
/* NB: wp is held, so we can safely dereference it still. */
|
||||
if (!wp->handler(cx, obj, propid,
|
||||
SPROP_HAS_VALID_SLOT(sprop, scope)
|
||||
? obj->getSlotMT(cx, sprop->slot)
|
||||
? Jsvalify(obj->getSlotMT(cx, sprop->slot))
|
||||
: JSVAL_VOID,
|
||||
vp, wp->closure)) {
|
||||
Jsvalify(vp), wp->closure)) {
|
||||
DBG_LOCK(rt);
|
||||
DropWatchPointAndUnlock(cx, wp, JSWP_HELD);
|
||||
return JS_FALSE;
|
||||
|
@ -644,7 +644,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
* trusted.
|
||||
*/
|
||||
JSObject *closure = wp->closure;
|
||||
JSClass *clasp = closure->getClass();
|
||||
Class *clasp = closure->getClass();
|
||||
JSFunction *fun;
|
||||
JSScript *script;
|
||||
if (clasp == &js_FunctionClass) {
|
||||
|
@ -682,12 +682,12 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
}
|
||||
|
||||
/* Initialize slots/frame. */
|
||||
jsval *vp = frame.getvp();
|
||||
memset(vp, 0, vplen * sizeof(jsval));
|
||||
vp[0] = OBJECT_TO_JSVAL(closure);
|
||||
Value *vp = frame.getvp();
|
||||
PodZero(vp, vplen);
|
||||
SetObject(&vp[0], *closure);
|
||||
JSStackFrame *fp = frame.getFrame();
|
||||
memset(fp->slots(), 0, nslots * sizeof(jsval));
|
||||
memset(fp, 0, sizeof(JSStackFrame));
|
||||
PodZero(fp->slots(), nslots);
|
||||
PodZero(fp);
|
||||
fp->script = script;
|
||||
fp->fun = fun;
|
||||
fp->argv = vp + 2;
|
||||
|
@ -712,9 +712,9 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
JSBool ok = !wp->setter ||
|
||||
(sprop->hasSetterValue()
|
||||
? js_InternalCall(cx, obj,
|
||||
js_CastAsObjectJSVal(wp->setter),
|
||||
1, vp, vp)
|
||||
? InternalCall(cx, obj,
|
||||
ToValue(CastAsObject(wp->setter)),
|
||||
1, vp, vp)
|
||||
: wp->setter(cx, obj, userid, vp));
|
||||
|
||||
/* Evil code can cause us to have an arguments object. */
|
||||
|
@ -730,17 +730,17 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
}
|
||||
|
||||
JSBool
|
||||
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, Value *argv,
|
||||
Value *rval)
|
||||
{
|
||||
JSObject *funobj;
|
||||
JSFunction *wrapper;
|
||||
jsval userid;
|
||||
jsid userid;
|
||||
|
||||
funobj = JSVAL_TO_OBJECT(argv[-2]);
|
||||
funobj = &argv[-2].asObject();
|
||||
wrapper = GET_FUNCTION_PRIVATE(cx, funobj);
|
||||
userid = ATOM_KEY(wrapper->atom);
|
||||
*rval = argv[0];
|
||||
userid = ATOM_TO_JSID(wrapper->atom);
|
||||
rval->copy(argv[0]);
|
||||
return js_watch_set(cx, obj, userid, rval);
|
||||
}
|
||||
|
||||
|
@ -758,8 +758,8 @@ IsWatchedProperty(JSContext *cx, JSScopeProperty *sprop)
|
|||
return sprop->setterOp() == js_watch_set;
|
||||
}
|
||||
|
||||
JSPropertyOp
|
||||
js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
|
||||
PropertyOp
|
||||
js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, PropertyOp setter)
|
||||
{
|
||||
JSAtom *atom;
|
||||
JSFunction *wrapper;
|
||||
|
@ -770,26 +770,25 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
|
|||
if (JSID_IS_ATOM(id)) {
|
||||
atom = JSID_TO_ATOM(id);
|
||||
} else if (JSID_IS_INT(id)) {
|
||||
if (!js_ValueToStringId(cx, INT_JSID_TO_JSVAL(id), &id))
|
||||
if (!js_ValueToStringId(cx, IdToValue(id), &id))
|
||||
return NULL;
|
||||
atom = JSID_TO_ATOM(id);
|
||||
} else {
|
||||
atom = NULL;
|
||||
}
|
||||
wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0,
|
||||
js_CastAsObject(setter)->getParent(),
|
||||
atom);
|
||||
CastAsObject(setter)->getParent(), atom);
|
||||
if (!wrapper)
|
||||
return NULL;
|
||||
return js_CastAsPropertyOp(FUN_OBJECT(wrapper));
|
||||
return CastAsPropertyOp(FUN_OBJECT(wrapper));
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
|
||||
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSWatchPointHandler handler, void *closure)
|
||||
{
|
||||
JSObject *origobj;
|
||||
jsval v;
|
||||
Value v;
|
||||
uintN attrs;
|
||||
jsid propid;
|
||||
JSObject *pobj;
|
||||
|
@ -798,18 +797,18 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
|
|||
JSRuntime *rt;
|
||||
JSBool ok;
|
||||
JSWatchPoint *wp;
|
||||
JSPropertyOp watcher;
|
||||
PropertyOp watcher;
|
||||
|
||||
origobj = obj;
|
||||
obj = js_GetWrappedObject(cx, obj);
|
||||
OBJ_TO_INNER_OBJECT(cx, obj);
|
||||
Innerize(cx, &obj);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSVAL_IS_INT(idval)) {
|
||||
propid = INT_JSVAL_TO_JSID(idval);
|
||||
if (JSID_IS_INT(id)) {
|
||||
propid = id;
|
||||
} else {
|
||||
if (!js_ValueToStringId(cx, idval, &propid))
|
||||
if (!js_ValueToStringId(cx, IdToValue(id), &propid))
|
||||
return JS_FALSE;
|
||||
propid = js_CheckForStringIndex(propid);
|
||||
}
|
||||
|
@ -836,7 +835,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
|
|||
sprop = js_FindWatchPoint(rt, obj->scope(), propid);
|
||||
if (!sprop) {
|
||||
/* Make a new property in obj so we can watch for the first set. */
|
||||
if (!js_DefineNativeProperty(cx, obj, propid, JSVAL_VOID, NULL, NULL,
|
||||
if (!js_DefineNativeProperty(cx, obj, propid, sUndefinedValue, NULL, NULL,
|
||||
JSPROP_ENUMERATE, 0, 0, &prop)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -844,15 +843,15 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
|
|||
}
|
||||
} else if (pobj != obj) {
|
||||
/* Clone the prototype property so we can watch the right object. */
|
||||
jsval value;
|
||||
JSPropertyOp getter, setter;
|
||||
Value value;
|
||||
PropertyOp getter, setter;
|
||||
uintN attrs, flags;
|
||||
intN shortid;
|
||||
|
||||
if (pobj->isNative()) {
|
||||
value = SPROP_HAS_VALID_SLOT(sprop, pobj->scope())
|
||||
? pobj->lockedGetSlot(sprop->slot)
|
||||
: JSVAL_VOID;
|
||||
value.copy(SPROP_HAS_VALID_SLOT(sprop, pobj->scope())
|
||||
? pobj->lockedGetSlot(sprop->slot)
|
||||
: sUndefinedValue);
|
||||
getter = sprop->getter();
|
||||
setter = sprop->setter();
|
||||
attrs = sprop->attributes();
|
||||
|
@ -938,7 +937,7 @@ out:
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSWatchPointHandler *handlerp, void **closurep)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
|
@ -1029,6 +1028,43 @@ JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
|
|||
return js_LineNumberToPC(script, lineno);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uintN)
|
||||
JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return fun->nargs;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return fun->hasLocalNames();
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(jsuword *)
|
||||
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp)
|
||||
{
|
||||
*markp = JS_ARENA_MARK(&cx->tempPool);
|
||||
return js_GetLocalNameArray(cx, fun, &cx->tempPool);
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(JSAtom *)
|
||||
JS_LocalNameToAtom(jsuword w)
|
||||
{
|
||||
return JS_LOCAL_NAME_TO_ATOM(w);
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(JSString *)
|
||||
JS_AtomKey(JSAtom *atom)
|
||||
{
|
||||
return ATOM_TO_STRING(atom);
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark)
|
||||
{
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
|
@ -1038,7 +1074,7 @@ JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
|
|||
JS_PUBLIC_API(JSNative)
|
||||
JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return FUN_NATIVE(fun);
|
||||
return Jsvalify(FUN_NATIVE(fun));
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFastNative)
|
||||
|
@ -1247,13 +1283,13 @@ JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
|
|||
JS_PUBLIC_API(jsval)
|
||||
JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->rval;
|
||||
return Jsvalify(fp->rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval)
|
||||
{
|
||||
fp->rval = rval;
|
||||
fp->rval.copy(Valueify(rval));
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
@ -1367,8 +1403,8 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
|
|||
}
|
||||
}
|
||||
|
||||
ok = js_Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL,
|
||||
rval);
|
||||
ok = Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL,
|
||||
Valueify(rval));
|
||||
|
||||
if (cx->fp != fp)
|
||||
memcpy(cx->display, displayCopy, sizeof cx->display);
|
||||
|
@ -1420,19 +1456,19 @@ JS_PUBLIC_API(JSBool)
|
|||
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
||||
JSPropertyDesc *pd)
|
||||
{
|
||||
pd->id = ID_TO_VALUE(sprop->id);
|
||||
pd->id = Jsvalify(IdToValue(sprop->id));
|
||||
|
||||
JSBool wasThrowing = cx->throwing;
|
||||
AutoValueRooter lastException(cx, cx->exception);
|
||||
cx->throwing = JS_FALSE;
|
||||
|
||||
if (!js_GetProperty(cx, obj, sprop->id, &pd->value)) {
|
||||
if (!js_GetProperty(cx, obj, sprop->id, Valueify(&pd->value))) {
|
||||
if (!cx->throwing) {
|
||||
pd->flags = JSPD_ERROR;
|
||||
pd->value = JSVAL_VOID;
|
||||
} else {
|
||||
pd->flags = JSPD_EXCEPTION;
|
||||
pd->value = cx->exception;
|
||||
pd->value = Jsvalify(cx->exception);
|
||||
}
|
||||
} else {
|
||||
pd->flags = 0;
|
||||
|
@ -1440,7 +1476,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
|||
|
||||
cx->throwing = wasThrowing;
|
||||
if (wasThrowing)
|
||||
cx->exception = lastException.value();
|
||||
cx->exception.copy(lastException.value());
|
||||
|
||||
pd->flags |= (sprop->enumerable() ? JSPD_ENUMERATE : 0)
|
||||
| (!sprop->writable() ? JSPD_READONLY : 0)
|
||||
|
@ -1462,7 +1498,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
|||
JSScopeProperty *aprop;
|
||||
for (aprop = scope->lastProperty(); aprop; aprop = aprop->parent) {
|
||||
if (aprop != sprop && aprop->slot == sprop->slot) {
|
||||
pd->alias = ID_TO_VALUE(aprop->id);
|
||||
pd->alias = Jsvalify(IdToValue(aprop->id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1473,13 +1509,12 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
|||
JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
|
||||
{
|
||||
JSClass *clasp;
|
||||
JSScope *scope;
|
||||
uint32 i, n;
|
||||
JSPropertyDesc *pd;
|
||||
JSScopeProperty *sprop;
|
||||
|
||||
clasp = obj->getClass();
|
||||
Class *clasp = obj->getClass();
|
||||
if (!obj->isNative() || (clasp->flags & JSCLASS_NEW_ENUMERATE)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_CANT_DESCRIBE_PROPS, clasp->name);
|
||||
|
@ -1502,13 +1537,13 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
|
|||
return JS_FALSE;
|
||||
i = 0;
|
||||
for (sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
||||
if (!js_AddRoot(cx, &pd[i].id, NULL))
|
||||
if (!js_AddRoot(cx, Valueify(&pd[i].id), NULL))
|
||||
goto bad;
|
||||
if (!js_AddRoot(cx, &pd[i].value, NULL))
|
||||
if (!js_AddRoot(cx, Valueify(&pd[i].value), NULL))
|
||||
goto bad;
|
||||
if (!JS_GetPropertyDesc(cx, obj, sprop, &pd[i]))
|
||||
goto bad;
|
||||
if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
|
||||
if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, Valueify(&pd[i].alias), NULL))
|
||||
goto bad;
|
||||
if (++i == n)
|
||||
break;
|
||||
|
@ -1543,7 +1578,7 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
|
|||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
|
||||
{
|
||||
rt->globalDebugHooks.debuggerHandler = handler;
|
||||
rt->globalDebugHooks.debuggerHandlerData = closure;
|
||||
|
@ -1605,7 +1640,7 @@ JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure)
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure)
|
||||
JS_SetThrowHook(JSRuntime *rt, JSThrowHook hook, void *closure)
|
||||
{
|
||||
rt->globalDebugHooks.throwHook = hook;
|
||||
rt->globalDebugHooks.throwHookData = closure;
|
||||
|
@ -1630,7 +1665,7 @@ JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
|
|||
|
||||
nbytes = sizeof *obj;
|
||||
if (obj->dslots) {
|
||||
nbytes += ((uint32)obj->dslots[-1] - JS_INITIAL_NSLOTS + 1)
|
||||
nbytes += (obj->dslotLength() - JS_INITIAL_NSLOTS + 1)
|
||||
* sizeof obj->dslots[0];
|
||||
}
|
||||
if (obj->isNative()) {
|
||||
|
@ -1775,9 +1810,7 @@ JS_PUBLIC_API(JSObject *)
|
|||
JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JSObject *parent, JSBool system)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = js_NewObject(cx, clasp, proto, parent);
|
||||
JSObject *obj = js_NewObject(cx, Valueify(clasp), proto, parent);
|
||||
if (obj && system)
|
||||
obj->setSystem();
|
||||
return obj;
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
*/
|
||||
#include "jsapi.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
|
@ -59,14 +58,14 @@ js_UntrapScriptCode(JSContext *cx, JSScript *script);
|
|||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler handler, void *closure);
|
||||
JSTrapHandler handler, jsval closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSOp)
|
||||
JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler *handlerp, void **closurep);
|
||||
JSTrapHandler *handlerp, jsval *closurep);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearScriptTraps(JSContext *cx, JSScript *script);
|
||||
|
@ -78,19 +77,19 @@ extern JS_PUBLIC_API(JSTrapStatus)
|
|||
JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure);
|
||||
JS_SetInterrupt(JSRuntime *rt, JSInterruptHook handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep);
|
||||
JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *handlerp, void **closurep);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSWatchPointHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSWatchPointHandler *handlerp, void **closurep);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
|
@ -113,19 +112,23 @@ js_SweepWatchPoints(JSContext *cx);
|
|||
extern JSScopeProperty *
|
||||
js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/*
|
||||
* NB: callers outside of jsdbgapi.c must pass non-null scope.
|
||||
*/
|
||||
extern JSPropertyOp
|
||||
extern js::PropertyOp
|
||||
js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
|
||||
const JSScopeProperty *sprop);
|
||||
|
||||
extern JSBool
|
||||
js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
js_watch_set(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
|
||||
js::Value *rval);
|
||||
|
||||
#endif
|
||||
|
||||
extern JSPropertyOp
|
||||
js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter);
|
||||
|
@ -140,14 +143,39 @@ JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
|
|||
extern JS_PUBLIC_API(jsbytecode *)
|
||||
JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno);
|
||||
|
||||
extern JS_PUBLIC_API(uintN)
|
||||
JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun);
|
||||
|
||||
/*
|
||||
* N.B. The mark is in the context temp pool and thus the caller must take care
|
||||
* to call JS_ReleaseFunctionLocalNameArray in a LIFO manner (wrt to any other
|
||||
* call that may use the temp pool.
|
||||
*/
|
||||
extern JS_PUBLIC_API(jsuword *)
|
||||
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp);
|
||||
|
||||
extern JS_PUBLIC_API(JSAtom *)
|
||||
JS_LocalNameToAtom(jsuword w);
|
||||
|
||||
extern JS_PUBLIC_API(JSString *)
|
||||
JS_AtomKey(JSAtom *atom);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(JSNative)
|
||||
JS_GetFunctionNative(JSContext *cx, JSFunction *fun);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern JS_PUBLIC_API(JSFastNative)
|
||||
JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun);
|
||||
#endif
|
||||
|
||||
extern JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptPrincipals(JSContext *cx, JSScript *script);
|
||||
|
@ -297,7 +325,7 @@ JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
|||
/************************************************************************/
|
||||
|
||||
typedef struct JSPropertyDesc {
|
||||
jsval id; /* primary id, a string or int */
|
||||
jsval id; /* primary id, atomized string, or int */
|
||||
jsval value; /* property value */
|
||||
uint8 flags; /* flags, see below */
|
||||
uint8 spare; /* unused */
|
||||
|
@ -337,7 +365,7 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
|
|||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure);
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* Portable double to alphanumeric string and back converters.
|
||||
*/
|
||||
|
|
|
@ -59,13 +59,13 @@ extern void
|
|||
jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
|
||||
|
||||
extern void
|
||||
jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp);
|
||||
jsdtrace_object_create_start(JSStackFrame *fp, js::Class *clasp);
|
||||
|
||||
extern void
|
||||
jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp);
|
||||
jsdtrace_object_create_done(JSStackFrame *fp, js::Class *clasp);
|
||||
|
||||
extern void
|
||||
jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj);
|
||||
jsdtrace_object_create(JSContext *cx, js::Class *clasp, JSObject *obj);
|
||||
|
||||
extern void
|
||||
jsdtrace_object_finalize(JSObject *obj);
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* JS bytecode generation.
|
||||
*/
|
||||
|
@ -69,6 +71,8 @@
|
|||
#include "jsautooplen.h"
|
||||
#include "jsstaticcheck.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
/* Allocation chunk counts, must be powers of two in general. */
|
||||
#define BYTECODE_CHUNK 256 /* code allocation increment */
|
||||
#define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */
|
||||
|
@ -96,7 +100,8 @@ JSCodeGenerator::JSCodeGenerator(JSCompiler *jsc,
|
|||
spanDeps(NULL), jumpTargets(NULL), jtFreeList(NULL),
|
||||
numSpanDeps(0), numJumpTargets(0), spanDepTodo(0),
|
||||
arrayCompDepth(0),
|
||||
emitLevel(0)
|
||||
emitLevel(0),
|
||||
constMap(jsc->context)
|
||||
{
|
||||
flags = TCF_COMPILING;
|
||||
memset(&prolog, 0, sizeof prolog);
|
||||
|
@ -107,6 +112,11 @@ JSCodeGenerator::JSCodeGenerator(JSCompiler *jsc,
|
|||
memset(&upvarMap, 0, sizeof upvarMap);
|
||||
}
|
||||
|
||||
bool JSCodeGenerator::init()
|
||||
{
|
||||
return constMap.init();
|
||||
}
|
||||
|
||||
JSCodeGenerator::~JSCodeGenerator()
|
||||
{
|
||||
JS_ARENA_RELEASE(codePool, codeMark);
|
||||
|
@ -205,7 +215,7 @@ UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
|
|||
JS_ASSERT(nuses == 0);
|
||||
blockObj = cg->objectList.lastbox->object;
|
||||
JS_ASSERT(blockObj->getClass() == &js_BlockClass);
|
||||
JS_ASSERT(JSVAL_IS_VOID(blockObj->fslots[JSSLOT_BLOCK_DEPTH]));
|
||||
JS_ASSERT(blockObj->fslots[JSSLOT_BLOCK_DEPTH].isUndefined());
|
||||
|
||||
OBJ_SET_BLOCK_DEPTH(cx, blockObj, cg->stackDepth);
|
||||
ndefs = OBJ_BLOCK_COUNT(cx, blockObj);
|
||||
|
@ -1536,6 +1546,13 @@ js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSAtom *
|
||||
JSBOXEDWORD_TO_ATOM(jsboxedword w)
|
||||
{
|
||||
JS_STATIC_ASSERT(sizeof(jsboxedword) == sizeof(JSAtom *));
|
||||
return (JSAtom *)w;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
|
||||
JSParseNode *pn)
|
||||
|
@ -1543,29 +1560,24 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
|
|||
jsdouble dval;
|
||||
jsint ival;
|
||||
JSAtom *valueAtom;
|
||||
jsval v;
|
||||
JSAtomListElement *ale;
|
||||
|
||||
/* XXX just do numbers for now */
|
||||
if (pn->pn_type == TOK_NUMBER) {
|
||||
dval = pn->pn_dval;
|
||||
if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) {
|
||||
v = INT_TO_JSVAL(ival);
|
||||
if (JSDOUBLE_IS_INT32(dval, ival) && INT32_FITS_IN_JSBOXEDWORD(ival)) {
|
||||
valueAtom = JSBOXEDWORD_TO_ATOM(INT_TO_JSBOXEDWORD(ival));
|
||||
} else {
|
||||
/*
|
||||
* We atomize double to root a jsdouble instance that we wrap as
|
||||
* jsval and store in cg->constList. This works because atoms are
|
||||
* protected from GC during compilation.
|
||||
* jsboxedword and store in cg->constList. This works because atoms
|
||||
* are protected from GC during compilation.
|
||||
*/
|
||||
valueAtom = js_AtomizeDouble(cx, dval);
|
||||
if (!valueAtom)
|
||||
return JS_FALSE;
|
||||
v = ATOM_KEY(valueAtom);
|
||||
}
|
||||
ale = cg->constList.add(cg->compiler, atom);
|
||||
if (!ale)
|
||||
if (!cg->constMap.put(atom, valueAtom))
|
||||
return JS_FALSE;
|
||||
ALE_SET_VALUE(ale, v);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -1595,8 +1607,8 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt
|
|||
JS_ASSERT(sprop->hasShortID());
|
||||
|
||||
if (slotp) {
|
||||
JS_ASSERT(JSVAL_IS_INT(obj->fslots[JSSLOT_BLOCK_DEPTH]));
|
||||
*slotp = JSVAL_TO_INT(obj->fslots[JSSLOT_BLOCK_DEPTH]) +
|
||||
JS_ASSERT(obj->fslots[JSSLOT_BLOCK_DEPTH].isInt32());
|
||||
*slotp = obj->fslots[JSSLOT_BLOCK_DEPTH].asInt32() +
|
||||
sprop->shortid;
|
||||
}
|
||||
return stmt;
|
||||
|
@ -1616,17 +1628,46 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt
|
|||
(((attrs) & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_GETTER)) == \
|
||||
(JSPROP_READONLY | JSPROP_PERMANENT))
|
||||
|
||||
static JSAtom *NO_CONSTANT = (JSAtom *)SPECIAL_TO_JSBOXEDWORD(0xabcd);
|
||||
|
||||
/*
|
||||
* The function sets vp to JSVAL_HOLE when the atom does not corresponds to a
|
||||
* Outside of the compiler (specifically, switch statements), atoms can only be
|
||||
* interned strings. Thus, this conversion is specific to the compiler.
|
||||
*/
|
||||
static bool
|
||||
ValueToCompilerConstant(JSContext *cx, const Value &v, JSAtom **constp)
|
||||
{
|
||||
jsboxedword w;
|
||||
if (v.isNull())
|
||||
w = JSBOXEDWORD_NULL;
|
||||
else if (v.isUndefined())
|
||||
w = JSBOXEDWORD_VOID;
|
||||
else if (v.isInt32() && INT32_FITS_IN_JSBOXEDWORD(v.asInt32()))
|
||||
w = INT_TO_JSBOXEDWORD(v.asInt32());
|
||||
else if (v.isNumber())
|
||||
return (*constp = js_AtomizeDouble(cx, v.asNumber())) != NULL;
|
||||
else if (v.isString())
|
||||
w = STRING_TO_JSBOXEDWORD(v.asString());
|
||||
else if (v.isObject())
|
||||
w = OBJECT_TO_JSBOXEDWORD(&v.asObject());
|
||||
else if (v.isBoolean())
|
||||
w = BOOLEAN_TO_JSBOXEDWORD(v.asBoolean());
|
||||
else
|
||||
JS_NOT_REACHED("invalid value");
|
||||
*constp = JSBOXEDWORD_TO_ATOM(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The function sets vp to NO_CONSTANT when the atom does not corresponds to a
|
||||
* name defining a constant.
|
||||
*/
|
||||
static JSBool
|
||||
LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
|
||||
jsval *vp)
|
||||
JSAtom **constp)
|
||||
{
|
||||
JSBool ok;
|
||||
JSStmtInfo *stmt;
|
||||
JSAtomListElement *ale;
|
||||
JSObject *obj, *objbox;
|
||||
JSProperty *prop;
|
||||
uintN attrs;
|
||||
|
@ -1636,7 +1677,7 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
|
|||
* This enables propagating consts from top-level into switch cases in a
|
||||
* function compiled along with the top-level script.
|
||||
*/
|
||||
*vp = JSVAL_HOLE;
|
||||
*constp = NO_CONSTANT;
|
||||
do {
|
||||
if (cg->flags & (TCF_IN_FUNCTION | TCF_COMPILE_N_GO)) {
|
||||
/* XXX this will need revising if 'const' becomes block-scoped. */
|
||||
|
@ -1644,10 +1685,9 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
|
|||
if (stmt)
|
||||
return JS_TRUE;
|
||||
|
||||
ale = cg->constList.lookup(atom);
|
||||
if (ale) {
|
||||
JS_ASSERT(ALE_VALUE(ale) != JSVAL_HOLE);
|
||||
*vp = ALE_VALUE(ale);
|
||||
if (JSCodeGenerator::ConstMap::Ptr p = cg->constMap.lookup(atom)) {
|
||||
JS_ASSERT(p->value != NO_CONSTANT);
|
||||
*constp = p->value;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1676,8 +1716,10 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
|
|||
*/
|
||||
ok = obj->getAttributes(cx, ATOM_TO_JSID(atom), prop, &attrs);
|
||||
if (ok && IS_CONSTANT_PROPERTY(attrs)) {
|
||||
ok = obj->getProperty(cx, ATOM_TO_JSID(atom), vp);
|
||||
JS_ASSERT_IF(ok, *vp != JSVAL_HOLE);
|
||||
Value v;
|
||||
ok = obj->getProperty(cx, ATOM_TO_JSID(atom), &v);
|
||||
if (ok)
|
||||
ok = ValueToCompilerConstant(cx, v, constp);
|
||||
}
|
||||
}
|
||||
if (prop)
|
||||
|
@ -1859,15 +1901,15 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg)
|
|||
for (uintN slot = JSSLOT_FREE(&js_BlockClass),
|
||||
limit = slot + OBJ_BLOCK_COUNT(cx, blockObj);
|
||||
slot < limit; slot++) {
|
||||
jsval v = blockObj->getSlot(slot);
|
||||
const Value &v = blockObj->getSlot(slot);
|
||||
|
||||
/* Beware the empty destructuring dummy. */
|
||||
if (JSVAL_IS_VOID(v)) {
|
||||
if (v.isUndefined()) {
|
||||
JS_ASSERT(slot + 1 <= limit);
|
||||
continue;
|
||||
}
|
||||
|
||||
JSDefinition *dn = (JSDefinition *) JSVAL_TO_PRIVATE(v);
|
||||
JSDefinition *dn = (JSDefinition *) v.asPrivateVoidPtr();
|
||||
JS_ASSERT(dn->pn_defn);
|
||||
JS_ASSERT(uintN(dn->frameSlot() + depth) < JS_BIT(16));
|
||||
dn->pn_cookie += depth;
|
||||
|
@ -2856,7 +2898,7 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
|
|||
if (!BindNameToSlot(cx, cg, left))
|
||||
return JS_FALSE;
|
||||
if (left->pn_op == JSOP_ARGUMENTS &&
|
||||
JSDOUBLE_IS_INT(next->pn_dval, slot) &&
|
||||
JSDOUBLE_IS_INT32(next->pn_dval, slot) &&
|
||||
(jsuint)slot < JS_BIT(16)) {
|
||||
/*
|
||||
* arguments[i]() requires arguments object as "this".
|
||||
|
@ -2931,7 +2973,7 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
|
|||
if (!BindNameToSlot(cx, cg, left))
|
||||
return JS_FALSE;
|
||||
if (left->pn_op == JSOP_ARGUMENTS &&
|
||||
JSDOUBLE_IS_INT(right->pn_dval, slot) &&
|
||||
JSDOUBLE_IS_INT32(right->pn_dval, slot) &&
|
||||
(jsuint)slot < JS_BIT(16)) {
|
||||
left->pn_offset = right->pn_offset = top;
|
||||
EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
|
||||
|
@ -2963,7 +3005,7 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg)
|
|||
JSAtom *atom;
|
||||
JSAtomListElement *ale;
|
||||
|
||||
if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) {
|
||||
if (JSDOUBLE_IS_INT32(dval, ival)) {
|
||||
if (ival == 0)
|
||||
return js_Emit1(cx, cg, JSOP_ZERO) >= 0;
|
||||
if (ival == 1)
|
||||
|
@ -3012,7 +3054,6 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
JSParseNode **table;
|
||||
jsdouble d;
|
||||
jsint i, low, high;
|
||||
jsval v;
|
||||
JSAtom *atom;
|
||||
JSAtomListElement *ale;
|
||||
intN noteIndex;
|
||||
|
@ -3130,8 +3171,8 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
switch (pn4->pn_type) {
|
||||
case TOK_NUMBER:
|
||||
d = pn4->pn_dval;
|
||||
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
|
||||
pn3->pn_val = INT_TO_JSVAL(i);
|
||||
if (JSDOUBLE_IS_INT32(d, i) && INT32_FITS_IN_JSBOXEDWORD(i)) {
|
||||
pn3->pn_val = INT_TO_JSBOXEDWORD(i);
|
||||
} else {
|
||||
atom = js_AtomizeDouble(cx, d);
|
||||
if (!atom) {
|
||||
|
@ -3146,11 +3187,11 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
break;
|
||||
case TOK_NAME:
|
||||
if (!pn4->maybeExpr()) {
|
||||
ok = LookupCompileTimeConstant(cx, cg, pn4->pn_atom, &v);
|
||||
ok = LookupCompileTimeConstant(cx, cg, pn4->pn_atom, &atom);
|
||||
if (!ok)
|
||||
goto release;
|
||||
if (v != JSVAL_HOLE) {
|
||||
if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
if (atom != NO_CONSTANT) {
|
||||
if (!JSBOXEDWORD_IS_PRIMITIVE(ATOM_KEY(atom))) {
|
||||
/*
|
||||
* XXX JSOP_LOOKUPSWITCH does not support const-
|
||||
* propagated object values, see bug 407186.
|
||||
|
@ -3158,7 +3199,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
switchOp = JSOP_CONDSWITCH;
|
||||
continue;
|
||||
}
|
||||
pn3->pn_val = v;
|
||||
pn3->pn_val = ATOM_KEY(atom);
|
||||
constPropagated = JS_TRUE;
|
||||
break;
|
||||
}
|
||||
|
@ -3166,15 +3207,15 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
/* FALL THROUGH */
|
||||
case TOK_PRIMARY:
|
||||
if (pn4->pn_op == JSOP_TRUE) {
|
||||
pn3->pn_val = JSVAL_TRUE;
|
||||
pn3->pn_val = JSBOXEDWORD_TRUE;
|
||||
break;
|
||||
}
|
||||
if (pn4->pn_op == JSOP_FALSE) {
|
||||
pn3->pn_val = JSVAL_FALSE;
|
||||
pn3->pn_val = JSBOXEDWORD_FALSE;
|
||||
break;
|
||||
}
|
||||
if (pn4->pn_op == JSOP_NULL) {
|
||||
pn3->pn_val = JSVAL_NULL;
|
||||
pn3->pn_val = JSBOXEDWORD_NULL;
|
||||
break;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
|
@ -3183,15 +3224,15 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
continue;
|
||||
}
|
||||
|
||||
JS_ASSERT(JSVAL_IS_PRIMITIVE(pn3->pn_val));
|
||||
JS_ASSERT(JSBOXEDWORD_IS_PRIMITIVE(ATOM_KEY(pn3->pn_val)));
|
||||
|
||||
if (switchOp != JSOP_TABLESWITCH)
|
||||
continue;
|
||||
if (!JSVAL_IS_INT(pn3->pn_val)) {
|
||||
if (!JSBOXEDWORD_IS_INT(ATOM_KEY(pn3->pn_val))) {
|
||||
switchOp = JSOP_LOOKUPSWITCH;
|
||||
continue;
|
||||
}
|
||||
i = JSVAL_TO_INT(pn3->pn_val);
|
||||
i = JSBOXEDWORD_TO_INT(ATOM_KEY(pn3->pn_val));
|
||||
if ((jsuint)(i + (jsint)JS_BIT(15)) >= (jsuint)JS_BIT(16)) {
|
||||
switchOp = JSOP_LOOKUPSWITCH;
|
||||
continue;
|
||||
|
@ -3386,7 +3427,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
|
||||
if (pn3->pn_type == TOK_DEFAULT)
|
||||
continue;
|
||||
i = JSVAL_TO_INT(pn3->pn_val);
|
||||
i = JSBOXEDWORD_TO_INT(ATOM_KEY(pn3->pn_val));
|
||||
i -= low;
|
||||
JS_ASSERT((uint32)i < tableLength);
|
||||
table[i] = pn3;
|
||||
|
@ -3529,7 +3570,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
|
||||
if (pn3->pn_type == TOK_DEFAULT)
|
||||
continue;
|
||||
if (!js_AtomizePrimitiveValue(cx, pn3->pn_val, &atom))
|
||||
if (!js_AtomizePrimitiveValue(cx, ATOM_KEY(pn3->pn_val), &atom))
|
||||
goto bad;
|
||||
ale = cg->atomList.add(cg->compiler, atom);
|
||||
if (!ale)
|
||||
|
@ -4396,6 +4437,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
new (cg2space) JSCodeGenerator(cg->compiler,
|
||||
cg->codePool, cg->notePool,
|
||||
pn->pn_pos.begin.lineno);
|
||||
|
||||
if (!cg2->init())
|
||||
return JS_FALSE;
|
||||
|
||||
cg2->flags = pn->pn_funbox->tcflags | TCF_IN_FUNCTION;
|
||||
#if JS_HAS_SHARP_VARS
|
||||
if (cg2->flags & TCF_HAS_SHARPS) {
|
||||
|
|
|
@ -455,7 +455,9 @@ struct JSCodeGenerator : public JSTreeContext
|
|||
uintN arrayCompDepth; /* stack depth of array in comprehension */
|
||||
|
||||
uintN emitLevel; /* js_EmitTree recursion level */
|
||||
JSAtomList constList; /* compile time constants */
|
||||
|
||||
typedef js::HashMap<JSAtom *, JSAtom *> ConstMap;
|
||||
ConstMap constMap; /* compile time constants */
|
||||
|
||||
JSCGObjectList objectList; /* list of emitted objects */
|
||||
JSCGObjectList regexpList; /* list of emitted regexp that will be
|
||||
|
@ -473,6 +475,8 @@ struct JSCodeGenerator : public JSTreeContext
|
|||
JSArenaPool *codePool, JSArenaPool *notePool,
|
||||
uintN lineno);
|
||||
|
||||
bool init();
|
||||
|
||||
/*
|
||||
* Release cg->codePool, cg->notePool, and compiler->context->tempPool to
|
||||
* marks set by JSCodeGenerator's ctor. Note that cgs are magic: they own
|
||||
|
|
|
@ -38,10 +38,11 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* JS standard exception implementation.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
|
@ -63,11 +64,13 @@
|
|||
#include "jsscript.h"
|
||||
#include "jsstaticcheck.h"
|
||||
|
||||
#include "jscntxtinlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
/* Forward declarations for js_ErrorClass's initializer. */
|
||||
static JSBool
|
||||
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
Exception(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval);
|
||||
|
||||
static void
|
||||
exn_trace(JSTracer *trc, JSObject *obj);
|
||||
|
@ -82,12 +85,12 @@ static JSBool
|
|||
exn_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
JSObject **objp);
|
||||
|
||||
JSClass js_ErrorClass = {
|
||||
Class js_ErrorClass = {
|
||||
js_Error_str,
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_MARK_IS_TRACE |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Error),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
exn_enumerate, (JSResolveOp)exn_resolve, JS_ConvertStub, exn_finalize,
|
||||
PropertyStub, PropertyStub, PropertyStub, PropertyStub,
|
||||
exn_enumerate, (JSResolveOp)exn_resolve, ConvertStub, exn_finalize,
|
||||
NULL, NULL, NULL, Exception,
|
||||
NULL, NULL, JS_CLASS_TRACE(exn_trace), NULL
|
||||
};
|
||||
|
@ -249,10 +252,10 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
|
|||
JSString *filename, uintN lineno, JSErrorReport *report)
|
||||
{
|
||||
JSSecurityCallbacks *callbacks;
|
||||
JSCheckAccessOp checkAccess;
|
||||
CheckAccessOp checkAccess;
|
||||
JSErrorReporter older;
|
||||
JSExceptionState *state;
|
||||
jsval callerid, v;
|
||||
jsid callerid;
|
||||
JSStackFrame *fp, *fpstop;
|
||||
size_t stackDepth, valueCount, size;
|
||||
JSBool overflow;
|
||||
|
@ -271,17 +274,17 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
|
|||
*/
|
||||
callbacks = JS_GetSecurityCallbacks(cx);
|
||||
checkAccess = callbacks
|
||||
? callbacks->checkObjectAccess
|
||||
? Valueify(callbacks->checkObjectAccess)
|
||||
: NULL;
|
||||
older = JS_SetErrorReporter(cx, NULL);
|
||||
state = JS_SaveExceptionState(cx);
|
||||
|
||||
callerid = ATOM_KEY(cx->runtime->atomState.callerAtom);
|
||||
callerid = ATOM_TO_JSID(cx->runtime->atomState.callerAtom);
|
||||
stackDepth = 0;
|
||||
valueCount = 0;
|
||||
for (fp = js_GetTopStackFrame(cx); fp; fp = fp->down) {
|
||||
if (fp->fun && fp->argv) {
|
||||
v = JSVAL_NULL;
|
||||
NullValue v;
|
||||
if (checkAccess &&
|
||||
!checkAccess(cx, fp->callee(), callerid, JSACC_READ, &v)) {
|
||||
break;
|
||||
|
@ -526,13 +529,13 @@ ValueToShortSource(JSContext *cx, jsval v)
|
|||
|
||||
/* Avoid toSource bloat and fallibility for object types. */
|
||||
if (JSVAL_IS_PRIMITIVE(v)) {
|
||||
str = js_ValueToSource(cx, v);
|
||||
str = js_ValueToSource(cx, Valueify(v));
|
||||
} else if (VALUE_IS_FUNCTION(cx, v)) {
|
||||
/*
|
||||
* XXX Avoid function decompilation bloat for now.
|
||||
*/
|
||||
str = JS_GetFunctionId(JS_ValueToFunction(cx, v));
|
||||
if (!str && !(str = js_ValueToSource(cx, v))) {
|
||||
if (!str && !(str = js_ValueToSource(cx, Valueify(v)))) {
|
||||
/*
|
||||
* Continue to soldier on if the function couldn't be
|
||||
* converted into a string.
|
||||
|
@ -683,7 +686,7 @@ StringToFilename(JSContext *cx, JSString *str)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
Exception(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
||||
{
|
||||
JSString *message, *filename;
|
||||
JSStackFrame *fp;
|
||||
|
@ -696,16 +699,16 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
* js_NewObject to find the class prototype, we must get the class
|
||||
* prototype ourselves.
|
||||
*/
|
||||
if (!JSVAL_TO_OBJECT(argv[-2])->getProperty(cx,
|
||||
ATOM_TO_JSID(cx->runtime->atomState
|
||||
.classPrototypeAtom),
|
||||
rval)) {
|
||||
if (!argv[-2].asObject().getProperty(cx,
|
||||
ATOM_TO_JSID(cx->runtime->atomState
|
||||
.classPrototypeAtom),
|
||||
rval)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL);
|
||||
obj = js_NewObject(cx, &js_ErrorClass, &rval->asObject(), NULL);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
rval->setNonFunObj(*obj);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -720,7 +723,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
message = js_ValueToString(cx, argv[0]);
|
||||
if (!message)
|
||||
return JS_FALSE;
|
||||
argv[0] = STRING_TO_JSVAL(message);
|
||||
argv[0].setString(message);
|
||||
} else {
|
||||
message = cx->runtime->emptyString;
|
||||
}
|
||||
|
@ -730,7 +733,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
filename = js_ValueToString(cx, argv[1]);
|
||||
if (!filename)
|
||||
return JS_FALSE;
|
||||
argv[1] = STRING_TO_JSVAL(filename);
|
||||
argv[1].setString(filename);
|
||||
fp = NULL;
|
||||
} else {
|
||||
fp = js_GetScriptedCaller(cx, NULL);
|
||||
|
@ -746,7 +749,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
/* Set the 'lineNumber' property. */
|
||||
uint32_t lineno;
|
||||
if (argc > 2) {
|
||||
if (!ValueToECMAUint32(cx, argv[2], &lineno))
|
||||
if (!ValueToECMAUint32(cx, &argv[2], &lineno))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (!fp)
|
||||
|
@ -775,7 +778,7 @@ exn_toString(JSContext *cx, uintN argc, jsval *vp)
|
|||
size_t name_length, message_length, length;
|
||||
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), &v))
|
||||
if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), Valueify(&v)))
|
||||
return JS_FALSE;
|
||||
name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;
|
||||
*vp = STRING_TO_JSVAL(name);
|
||||
|
@ -824,32 +827,32 @@ exn_toSource(JSContext *cx, uintN argc, jsval *vp)
|
|||
{
|
||||
JSObject *obj;
|
||||
JSString *name, *message, *filename, *lineno_as_str, *result;
|
||||
jsval localroots[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
|
||||
jsval localroots[4] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
|
||||
size_t lineno_length, name_length, message_length, filename_length, length;
|
||||
jschar *chars, *cp;
|
||||
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), vp))
|
||||
if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), Valueify(vp)))
|
||||
return false;
|
||||
name = js_ValueToString(cx, *vp);
|
||||
name = js_ValueToString(cx, Valueify(*vp));
|
||||
if (!name)
|
||||
return false;
|
||||
*vp = STRING_TO_JSVAL(name);
|
||||
|
||||
{
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(localroots), localroots);
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(localroots), Valueify(localroots));
|
||||
|
||||
#ifdef __GNUC__
|
||||
message = filename = NULL;
|
||||
#endif
|
||||
if (!JS_GetProperty(cx, obj, js_message_str, &localroots[0]) ||
|
||||
!(message = js_ValueToSource(cx, localroots[0]))) {
|
||||
!(message = js_ValueToSource(cx, Valueify(localroots[0])))) {
|
||||
return false;
|
||||
}
|
||||
localroots[0] = STRING_TO_JSVAL(message);
|
||||
|
||||
if (!JS_GetProperty(cx, obj, js_fileName_str, &localroots[1]) ||
|
||||
!(filename = js_ValueToSource(cx, localroots[1]))) {
|
||||
!(filename = js_ValueToSource(cx, Valueify(localroots[1])))) {
|
||||
return false;
|
||||
}
|
||||
localroots[1] = STRING_TO_JSVAL(filename);
|
||||
|
@ -857,11 +860,12 @@ exn_toSource(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]))
|
||||
return false;
|
||||
uint32_t lineno;
|
||||
if (!ValueToECMAUint32(cx, localroots[2], &lineno))
|
||||
localroots[3] = localroots[2]; /* ValueToECMAUint32 mutates localroots[2] */
|
||||
if (!ValueToECMAUint32(cx, Valueify(&localroots[2]), &lineno))
|
||||
return false;
|
||||
|
||||
if (lineno != 0) {
|
||||
lineno_as_str = js_ValueToString(cx, localroots[2]);
|
||||
lineno_as_str = js_ValueToString(cx, Valueify(localroots[3]));
|
||||
if (!lineno_as_str)
|
||||
return false;
|
||||
lineno_length = lineno_as_str->length();
|
||||
|
@ -987,7 +991,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
|||
return NULL;
|
||||
|
||||
PodArrayZero(roots);
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots);
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), Valueify(roots));
|
||||
|
||||
#ifdef __GNUC__
|
||||
error_proto = NULL; /* quell GCC overwarning */
|
||||
|
@ -1036,7 +1040,8 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
/* Add the name property to the prototype. */
|
||||
if (!JS_DefineProperty(cx, proto, js_name_str, ATOM_KEY(atom),
|
||||
if (!JS_DefineProperty(cx, proto, js_name_str,
|
||||
STRING_TO_JSVAL(ATOM_TO_STRING(atom)),
|
||||
NULL, NULL, JSPROP_ENUMERATE)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1145,7 +1150,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
|
|||
|
||||
/* Protect the newly-created strings below from nesting GCs. */
|
||||
PodArrayZero(tv);
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(tv), tv);
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(tv), Valueify(tv));
|
||||
|
||||
/*
|
||||
* Try to get an appropriate prototype by looking up the corresponding
|
||||
|
@ -1210,7 +1215,7 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
return false;
|
||||
|
||||
PodArrayZero(roots);
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots);
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), Valueify(roots));
|
||||
|
||||
/*
|
||||
* Because js_ValueToString below could error and an exception object
|
||||
|
@ -1229,7 +1234,7 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
reportp = js_ErrorFromException(cx, exn);
|
||||
|
||||
/* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */
|
||||
str = js_ValueToString(cx, exn);
|
||||
str = js_ValueToString(cx, Valueify(exn));
|
||||
if (!str) {
|
||||
bytes = "unknown (can't convert to string)";
|
||||
} else {
|
||||
|
@ -1252,7 +1257,7 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
|
||||
if (!JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3]))
|
||||
return false;
|
||||
str = js_ValueToString(cx, roots[3]);
|
||||
str = js_ValueToString(cx, Valueify(roots[3]));
|
||||
if (!str)
|
||||
return false;
|
||||
filename = StringToFilename(cx, str);
|
||||
|
@ -1262,7 +1267,7 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
if (!JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]))
|
||||
return false;
|
||||
uint32_t lineno;
|
||||
if (!ValueToECMAUint32 (cx, roots[4], &lineno))
|
||||
if (!ValueToECMAUint32 (cx, Valueify(&roots[4]), &lineno))
|
||||
return false;
|
||||
|
||||
reportp = &report;
|
||||
|
|
|
@ -44,9 +44,7 @@
|
|||
#ifndef jsexn_h___
|
||||
#define jsexn_h___
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSClass js_ErrorClass;
|
||||
extern js::Class js_ErrorClass;
|
||||
|
||||
/*
|
||||
* Initialize the exception constructor/prototype hierarchy.
|
||||
|
@ -92,6 +90,4 @@ extern const JSErrorFormatString *
|
|||
js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
|
||||
const uintN errorNumber);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsexn_h___ */
|
||||
|
|
607
js/src/jsfun.cpp
607
js/src/jsfun.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -46,8 +46,6 @@
|
|||
#include "jspubtd.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct JSLocalNameMap JSLocalNameMap;
|
||||
|
||||
/*
|
||||
|
@ -137,8 +135,8 @@ struct JSFunction : public JSObject
|
|||
struct {
|
||||
uint16 extra; /* number of arg slots for local GC roots */
|
||||
uint16 spare; /* reserved for future use */
|
||||
JSNative native; /* native method pointer or null */
|
||||
JSClass *clasp; /* class of objects constructed
|
||||
js::Native native; /* native method pointer or null */
|
||||
js::Class *clasp; /* class of objects constructed
|
||||
by this function */
|
||||
JSNativeTraceInfo *trcinfo;
|
||||
} n;
|
||||
|
@ -231,7 +229,7 @@ struct JSFunction : public JSObject
|
|||
* Yes, this is an incompatible change, which prefigures the impending move to
|
||||
* single-threaded objects and GC heaps.
|
||||
*/
|
||||
extern JSClass js_ArgumentsClass;
|
||||
extern js::Class js_ArgumentsClass;
|
||||
|
||||
inline bool
|
||||
JSObject::isArguments() const
|
||||
|
@ -239,12 +237,12 @@ JSObject::isArguments() const
|
|||
return getClass() == &js_ArgumentsClass;
|
||||
}
|
||||
|
||||
extern JS_FRIEND_DATA(JSClass) js_CallClass;
|
||||
extern JSClass js_DeclEnvClass;
|
||||
extern JS_FRIEND_DATA(js::Class) js_CallClass;
|
||||
extern js::Class js_DeclEnvClass;
|
||||
extern const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS;
|
||||
|
||||
/* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */
|
||||
extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
|
||||
extern JS_FRIEND_DATA(js::Class) js_FunctionClass;
|
||||
|
||||
inline bool
|
||||
JSObject::isFunction() const
|
||||
|
@ -253,6 +251,7 @@ JSObject::isFunction() const
|
|||
}
|
||||
|
||||
/*
|
||||
* TODO: remove once all internal jsval use goes away.
|
||||
* NB: jsapi.h and jsobj.h must be included before any call to this macro.
|
||||
*/
|
||||
#define VALUE_IS_FUNCTION(cx, v) \
|
||||
|
@ -300,7 +299,7 @@ extern JSObject *
|
|||
js_InitArgumentsClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSFunction *
|
||||
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
||||
js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
|
||||
uintN flags, JSObject *parent, JSAtom *atom);
|
||||
|
||||
extern void
|
||||
|
@ -309,9 +308,9 @@ js_TraceFunction(JSTracer *trc, JSFunction *fun);
|
|||
extern void
|
||||
js_FinalizeFunction(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JSObject * JS_FASTCALL
|
||||
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
|
||||
JSObject *proto);
|
||||
extern JSObject *
|
||||
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, const js::Value &parent,
|
||||
const js::Value &proto);
|
||||
|
||||
inline JSObject *
|
||||
CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
|
||||
|
@ -320,8 +319,8 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
|
|||
JSObject *proto;
|
||||
if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto))
|
||||
return NULL;
|
||||
JS_ASSERT(proto);
|
||||
return js_CloneFunctionObject(cx, fun, parent, proto);
|
||||
return js_CloneFunctionObject(cx, fun, js::NonFunObjValue(*parent),
|
||||
js::FunObjValue(*proto));
|
||||
}
|
||||
|
||||
extern JS_REQUIRES_STACK JSObject *
|
||||
|
@ -331,7 +330,7 @@ extern JS_REQUIRES_STACK JSObject *
|
|||
js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JSFunction *
|
||||
js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
|
||||
js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, js::Native native,
|
||||
uintN nargs, uintN flags);
|
||||
|
||||
/*
|
||||
|
@ -344,16 +343,16 @@ js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
|
|||
#define JSV2F_SEARCH_STACK 0x10000
|
||||
|
||||
extern JSFunction *
|
||||
js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags);
|
||||
js_ValueToFunction(JSContext *cx, const js::Value *vp, uintN flags);
|
||||
|
||||
extern JSObject *
|
||||
js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags);
|
||||
js_ValueToFunctionObject(JSContext *cx, js::Value *vp, uintN flags);
|
||||
|
||||
extern JSObject *
|
||||
js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags);
|
||||
js_ValueToCallableObject(JSContext *cx, js::Value *vp, uintN flags);
|
||||
|
||||
extern void
|
||||
js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags);
|
||||
js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
|
||||
|
||||
extern JSObject *
|
||||
js_GetCallObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
@ -365,23 +364,23 @@ extern void
|
|||
js_PutCallObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JSBool JS_FASTCALL
|
||||
js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs, jsval *argv,
|
||||
uint32 nvars, jsval *slots);
|
||||
js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs,
|
||||
js::Value *argv, uint32 nvars, js::Value *slots);
|
||||
|
||||
extern JSFunction *
|
||||
js_GetCallObjectFunction(JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
SetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
SetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
/*
|
||||
* js_SetCallArg and js_SetCallVar are extern fastcall copies of the setter
|
||||
|
@ -390,23 +389,23 @@ SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
|||
* property ops map.
|
||||
*/
|
||||
extern JSBool JS_FASTCALL
|
||||
js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval v);
|
||||
js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, const js::Value &v);
|
||||
|
||||
extern JSBool JS_FASTCALL
|
||||
js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v);
|
||||
js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, const js::Value &v);
|
||||
|
||||
/*
|
||||
* Slower version of js_GetCallVar used when call_resolve detects an attempt to
|
||||
* leak an optimized closure via indirect or debugger eval.
|
||||
*/
|
||||
extern JSBool
|
||||
js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, const js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp);
|
||||
js_GetArgsValue(JSContext *cx, JSStackFrame *fp, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp);
|
||||
js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, js::Value *vp);
|
||||
|
||||
extern JSObject *
|
||||
js_GetArgsObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
@ -455,34 +454,30 @@ const uint32 ARGS_FIXED_RESERVED_SLOTS = JSSLOT_ARGS_START - JSSLOT_ARGS_LENGTH;
|
|||
const uint32 JS_ARGS_LENGTH_MAX = JS_BIT(19) - 1024;
|
||||
|
||||
/*
|
||||
* JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as int jsval.
|
||||
* Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must fit JSVAL_INT_MAX. To assert that
|
||||
* we check first that the shift does not overflow uint32.
|
||||
* JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as int value.
|
||||
* Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must into an int32.
|
||||
*/
|
||||
JS_STATIC_ASSERT(JS_ARGS_LENGTH_MAX <= JS_BIT(30));
|
||||
JS_STATIC_ASSERT(jsval((JS_ARGS_LENGTH_MAX << 1) | 1) <= JSVAL_INT_MAX);
|
||||
|
||||
namespace js {
|
||||
|
||||
inline jsval
|
||||
inline const Value &
|
||||
GetArgsSlot(JSObject *argsobj, uint32 arg)
|
||||
{
|
||||
return argsobj->dslots[arg];
|
||||
}
|
||||
|
||||
inline void
|
||||
SetArgsSlot(JSObject *argsobj, uint32 arg, jsval v)
|
||||
SetArgsSlot(JSObject *argsobj, uint32 arg, const Value &v)
|
||||
{
|
||||
argsobj->dslots[arg] = v;
|
||||
argsobj->dslots[arg].copy(v);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsOverriddenArgsLength(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->isArguments());
|
||||
|
||||
jsval v = obj->fslots[JSSLOT_ARGS_LENGTH];
|
||||
return (JSVAL_TO_INT(v) & 1) != 0;
|
||||
return (obj->fslots[JSSLOT_ARGS_LENGTH].asInt32() & 1) != 0;
|
||||
}
|
||||
|
||||
inline uint32
|
||||
|
@ -490,7 +485,7 @@ GetArgsLength(JSObject *obj)
|
|||
{
|
||||
JS_ASSERT(obj->isArguments());
|
||||
|
||||
uint32 argc = uint32(JSVAL_TO_INT(obj->fslots[JSSLOT_ARGS_LENGTH])) >> 1;
|
||||
uint32 argc = uint32(obj->fslots[JSSLOT_ARGS_LENGTH].asInt32()) >> 1;
|
||||
JS_ASSERT(argc <= JS_ARGS_LENGTH_MAX);
|
||||
return argc;
|
||||
}
|
||||
|
@ -538,7 +533,7 @@ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
|
|||
* If nameWord does not name a formal parameter, use JS_LOCAL_NAME_IS_CONST to
|
||||
* check if nameWord corresponds to the const declaration.
|
||||
*/
|
||||
extern JS_FRIEND_API(jsuword *)
|
||||
extern jsuword *
|
||||
js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool);
|
||||
|
||||
#define JS_LOCAL_NAME_TO_ATOM(nameWord) \
|
||||
|
@ -551,12 +546,9 @@ extern void
|
|||
js_FreezeLocalNames(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JSBool
|
||||
js_fun_apply(JSContext *cx, uintN argc, jsval *vp);
|
||||
js_fun_apply(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_fun_call(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
|
||||
JS_END_EXTERN_C
|
||||
js_fun_call(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
#endif /* jsfun_h___ */
|
||||
|
|
313
js/src/jsgc.cpp
313
js/src/jsgc.cpp
|
@ -38,6 +38,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* JS Mark-and-Sweep Garbage Collector.
|
||||
*
|
||||
|
@ -115,20 +117,15 @@ using namespace js;
|
|||
* JSTRACE_STRING.
|
||||
*/
|
||||
JS_STATIC_ASSERT(JSTRACE_OBJECT == 0);
|
||||
JS_STATIC_ASSERT(JSTRACE_DOUBLE == 1);
|
||||
JS_STATIC_ASSERT(JSTRACE_STRING == 2);
|
||||
JS_STATIC_ASSERT(JSTRACE_STRING == 1);
|
||||
JS_STATIC_ASSERT(JSTRACE_DOUBLE == 2);
|
||||
JS_STATIC_ASSERT(JSTRACE_XML == 3);
|
||||
|
||||
/*
|
||||
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_STRING is the last non-xml
|
||||
* trace kind when JS_HAS_XML_SUPPORT is false.
|
||||
*/
|
||||
JS_STATIC_ASSERT(JSTRACE_STRING + 1 == JSTRACE_XML);
|
||||
|
||||
/*
|
||||
* Check that we can use memset(p, 0, ...) to implement JS_CLEAR_WEAK_ROOTS.
|
||||
*/
|
||||
JS_STATIC_ASSERT(JSVAL_NULL == 0);
|
||||
JS_STATIC_ASSERT(JSTRACE_DOUBLE + 1 == JSTRACE_XML);
|
||||
|
||||
/*
|
||||
* Check consistency of external string constants from JSFinalizeGCThingKind.
|
||||
|
@ -900,13 +897,6 @@ js_IsAboutToBeFinalized(void *thing)
|
|||
return !IsMarkedGCThing(a, thing);
|
||||
}
|
||||
|
||||
/* This is compatible with JSDHashEntryStub. */
|
||||
typedef struct JSGCRootHashEntry {
|
||||
JSDHashEntryHdr hdr;
|
||||
void *root;
|
||||
const char *name;
|
||||
} JSGCRootHashEntry;
|
||||
|
||||
/*
|
||||
* Initial size of the gcRootsHash and gcLocksHash tables (SWAG, small enough
|
||||
* to amortize).
|
||||
|
@ -923,11 +913,8 @@ JSBool
|
|||
js_InitGC(JSRuntime *rt, uint32 maxbytes)
|
||||
{
|
||||
InitGCArenaLists(rt);
|
||||
if (!JS_DHashTableInit(&rt->gcRootsHash, JS_DHashGetStubOps(), NULL,
|
||||
sizeof(JSGCRootHashEntry), GC_ROOTS_SIZE)) {
|
||||
rt->gcRootsHash.ops = NULL;
|
||||
if (!rt->gcRootsHash.init(GC_ROOTS_SIZE))
|
||||
return false;
|
||||
}
|
||||
if (!JS_DHashTableInit(&rt->gcLocksHash, JS_DHashGetStubOps(), NULL,
|
||||
sizeof(JSGCLockHashEntry), GC_ROOTS_SIZE)) {
|
||||
rt->gcLocksHash.ops = NULL;
|
||||
|
@ -1150,12 +1137,10 @@ js_FinishGC(JSRuntime *rt)
|
|||
rt->gcIteratorTable.clear();
|
||||
FinishGCArenaLists(rt);
|
||||
|
||||
if (rt->gcRootsHash.ops) {
|
||||
if (rt->gcRootsHash.initialized()) {
|
||||
#ifdef DEBUG
|
||||
CheckLeakedRoots(rt);
|
||||
#endif
|
||||
JS_DHashTableFinish(&rt->gcRootsHash);
|
||||
rt->gcRootsHash.ops = NULL;
|
||||
}
|
||||
if (rt->gcLocksHash.ops) {
|
||||
JS_DHashTableFinish(&rt->gcLocksHash);
|
||||
|
@ -1164,20 +1149,26 @@ js_FinishGC(JSRuntime *rt)
|
|||
}
|
||||
|
||||
JSBool
|
||||
js_AddRoot(JSContext *cx, void *rp, const char *name)
|
||||
js_AddRoot(JSContext *cx, Value *vp, const char *name)
|
||||
{
|
||||
JSBool ok = js_AddRootRT(cx->runtime, rp, name);
|
||||
JSBool ok = js_AddRootRT(cx->runtime, vp, name);
|
||||
if (!ok)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_AddRootRT(JSRuntime *rt, void *rp, const char *name)
|
||||
js_AddGCThingRoot(JSContext *cx, void **rp, const char *name)
|
||||
{
|
||||
JSBool ok;
|
||||
JSGCRootHashEntry *rhe;
|
||||
JSBool ok = js_AddGCThingRootRT(cx->runtime, rp, name);
|
||||
if (!ok)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_AddRootRT(JSRuntime *rt, Value *vp, const char *name)
|
||||
{
|
||||
/*
|
||||
* Due to the long-standing, but now removed, use of rt->gcLock across the
|
||||
* bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking
|
||||
|
@ -1187,16 +1178,26 @@ js_AddRootRT(JSRuntime *rt, void *rp, const char *name)
|
|||
*/
|
||||
AutoLockGC lock(rt);
|
||||
js_WaitForGC(rt);
|
||||
rhe = (JSGCRootHashEntry *)
|
||||
JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_ADD);
|
||||
if (rhe) {
|
||||
rhe->root = rp;
|
||||
rhe->name = name;
|
||||
ok = JS_TRUE;
|
||||
} else {
|
||||
ok = JS_FALSE;
|
||||
}
|
||||
return ok;
|
||||
|
||||
void *key = vp;
|
||||
return !!rt->gcRootsHash.put(key, JSRootInfo(name, JS_GC_ROOT_VALUE_PTR));
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_AddRootRT(JSRuntime *rt, void **rp, const char *name)
|
||||
{
|
||||
/*
|
||||
* Due to the long-standing, but now removed, use of rt->gcLock across the
|
||||
* bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking
|
||||
* properly with a racing GC, without calling JS_AddRoot from a request.
|
||||
* We have to preserve API compatibility here, now that we avoid holding
|
||||
* rt->gcLock across the mark phase (including the root hashtable mark).
|
||||
*/
|
||||
AutoLockGC lock(rt);
|
||||
js_WaitForGC(rt);
|
||||
|
||||
void *key = rp;
|
||||
return !!rt->gcRootsHash.put(key, JSRootInfo(name, JS_GC_ROOT_GCTHING_PTR));
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -1208,35 +1209,31 @@ js_RemoveRoot(JSRuntime *rt, void *rp)
|
|||
*/
|
||||
AutoLockGC lock(rt);
|
||||
js_WaitForGC(rt);
|
||||
(void) JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_REMOVE);
|
||||
rt->gcRootsHash.remove(rp);
|
||||
rt->gcPoke = JS_TRUE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
typedef JSRootedValueMap::Range RootRange;
|
||||
typedef JSRootedValueMap::Entry RootEntry;
|
||||
typedef JSRootedValueMap::Enum RootEnum;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static JSDHashOperator
|
||||
js_root_printer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 i, void *arg)
|
||||
{
|
||||
uint32 *leakedroots = (uint32 *)arg;
|
||||
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
|
||||
|
||||
(*leakedroots)++;
|
||||
fprintf(stderr,
|
||||
"JS engine warning: leaking GC root \'%s\' at %p\n",
|
||||
rhe->name ? (char *)rhe->name : "", rhe->root);
|
||||
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static void
|
||||
CheckLeakedRoots(JSRuntime *rt)
|
||||
{
|
||||
uint32 leakedroots = 0;
|
||||
|
||||
/* Warn (but don't assert) debug builds of any remaining roots. */
|
||||
JS_DHashTableEnumerate(&rt->gcRootsHash, js_root_printer,
|
||||
&leakedroots);
|
||||
for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront()) {
|
||||
RootEntry &entry = r.front();
|
||||
leakedroots++;
|
||||
fprintf(stderr,
|
||||
"JS engine warning: leaking GC root \'%s\' at %p\n",
|
||||
entry.value.name ? entry.value.name : "", entry.key);
|
||||
}
|
||||
|
||||
if (leakedroots > 0) {
|
||||
if (leakedroots == 1) {
|
||||
fprintf(stderr,
|
||||
|
@ -1254,74 +1251,38 @@ CheckLeakedRoots(JSRuntime *rt)
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct NamedRootDumpArgs {
|
||||
void (*dump)(const char *name, void *rp, void *data);
|
||||
void *data;
|
||||
} NamedRootDumpArgs;
|
||||
|
||||
static JSDHashOperator
|
||||
js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
|
||||
void *arg)
|
||||
{
|
||||
NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg;
|
||||
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
|
||||
|
||||
if (rhe->name)
|
||||
args->dump(rhe->name, rhe->root, args->data);
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
js_DumpNamedRoots(JSRuntime *rt,
|
||||
void (*dump)(const char *name, void *rp, void *data),
|
||||
void (*dump)(const char *name, void *rp, JSGCRootType type, void *data),
|
||||
void *data)
|
||||
{
|
||||
NamedRootDumpArgs args;
|
||||
|
||||
args.dump = dump;
|
||||
args.data = data;
|
||||
JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args);
|
||||
for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront()) {
|
||||
RootEntry &entry = r.front();
|
||||
if (const char *name = entry.value.name)
|
||||
dump(name, entry.key, entry.value.type, data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
typedef struct GCRootMapArgs {
|
||||
JSGCRootMapFun map;
|
||||
void *data;
|
||||
} GCRootMapArgs;
|
||||
|
||||
static JSDHashOperator
|
||||
js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
|
||||
void *arg)
|
||||
{
|
||||
GCRootMapArgs *args = (GCRootMapArgs *) arg;
|
||||
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
|
||||
intN mapflags;
|
||||
int op;
|
||||
|
||||
mapflags = args->map(rhe->root, rhe->name, args->data);
|
||||
|
||||
#if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT && \
|
||||
JS_MAP_GCROOT_STOP == JS_DHASH_STOP && \
|
||||
JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE
|
||||
op = (JSDHashOperator)mapflags;
|
||||
#else
|
||||
op = JS_DHASH_NEXT;
|
||||
if (mapflags & JS_MAP_GCROOT_STOP)
|
||||
op |= JS_DHASH_STOP;
|
||||
if (mapflags & JS_MAP_GCROOT_REMOVE)
|
||||
op |= JS_DHASH_REMOVE;
|
||||
#endif
|
||||
|
||||
return (JSDHashOperator) op;
|
||||
}
|
||||
|
||||
uint32
|
||||
js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
|
||||
{
|
||||
GCRootMapArgs args = {map, data};
|
||||
AutoLockGC lock(rt);
|
||||
return JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args);
|
||||
int ct = 0;
|
||||
for (RootEnum e(rt->gcRootsHash); !e.empty(); e.popFront()) {
|
||||
RootEntry &entry = e.front();
|
||||
|
||||
ct++;
|
||||
intN mapflags = map(entry.key, entry.value.type, entry.value.name, data);
|
||||
|
||||
if (mapflags & JS_MAP_GCROOT_REMOVE)
|
||||
e.removeFront();
|
||||
if (mapflags & JS_MAP_GCROOT_STOP)
|
||||
break;
|
||||
}
|
||||
|
||||
return ct;
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -1582,7 +1543,7 @@ js_NewFinalizableGCThing(JSContext *cx, unsigned thingKind)
|
|||
* this reference, allowing thing to be GC'd if it has no other refs.
|
||||
* See JS_EnterLocalRootScope and related APIs.
|
||||
*/
|
||||
if (js_PushLocalRoot(cx, lrs, (jsval) thing) < 0) {
|
||||
if (js_PushLocalRoot(cx, lrs, thing) < 0) {
|
||||
JS_ASSERT(thing->link == *freeListp);
|
||||
*freeListp = thing;
|
||||
return NULL;
|
||||
|
@ -1728,8 +1689,8 @@ RefillDoubleFreeList(JSContext *cx)
|
|||
return MakeNewArenaFreeList(a, sizeof(jsdouble));
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
|
||||
jsdouble *
|
||||
js_NewWeaklyRootedDoubleAtom(JSContext *cx, jsdouble d)
|
||||
{
|
||||
/* Updates of metering counters here are not thread-safe. */
|
||||
METER(cx->runtime->gcStats.doubleArenaStats.alloc++);
|
||||
|
@ -1744,8 +1705,8 @@ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
|
|||
|
||||
jsdouble *dp = reinterpret_cast<jsdouble *>(thing);
|
||||
*dp = d;
|
||||
*vp = DOUBLE_TO_JSVAL(dp);
|
||||
return true;
|
||||
cx->weakRoots.newbornDouble = dp;
|
||||
return dp;
|
||||
}
|
||||
|
||||
JSLocalRootStack *lrs = JS_THREAD_DATA(cx)->localRootStack;
|
||||
|
@ -1769,7 +1730,7 @@ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
|
|||
js_ReportOutOfMemory(cx);
|
||||
METER(cx->runtime->gcStats.doubleArenaStats.fail++);
|
||||
}
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CheckGCFreeListLink(thing);
|
||||
|
@ -1777,19 +1738,11 @@ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
|
|||
|
||||
jsdouble *dp = reinterpret_cast<jsdouble *>(thing);
|
||||
*dp = d;
|
||||
*vp = DOUBLE_TO_JSVAL(dp);
|
||||
return !lrs || js_PushLocalRoot(cx, lrs, *vp) >= 0;
|
||||
}
|
||||
|
||||
jsdouble *
|
||||
js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d)
|
||||
{
|
||||
jsval v;
|
||||
if (!js_NewDoubleInRootedValue(cx, d, &v))
|
||||
return NULL;
|
||||
|
||||
jsdouble *dp = JSVAL_TO_DOUBLE(v);
|
||||
cx->weakRoots.newbornDouble = dp;
|
||||
/*
|
||||
* N.B. We any active local root scope, since this function is called only
|
||||
* from the compiler to create double atoms.
|
||||
*/
|
||||
return dp;
|
||||
}
|
||||
|
||||
|
@ -2049,8 +2002,10 @@ MarkDelayedChildren(JSTracer *trc)
|
|||
JS_ASSERT(rt->gcMarkLaterCount == 0);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
void
|
||||
js_CallGCMarker(JSTracer *trc, void *thing, uint32 kind)
|
||||
CallGCMarker(JSTracer *trc, void *thing, uint32 kind)
|
||||
{
|
||||
JSContext *cx;
|
||||
JSRuntime *rt;
|
||||
|
@ -2152,40 +2107,42 @@ js_CallGCMarker(JSTracer *trc, void *thing, uint32 kind)
|
|||
}
|
||||
|
||||
void
|
||||
js_CallValueTracerIfGCThing(JSTracer *trc, jsval v)
|
||||
CallGCMarkerForGCThing(JSTracer *trc, void *thing)
|
||||
{
|
||||
void *thing;
|
||||
uint32 kind;
|
||||
|
||||
if (JSVAL_IS_DOUBLE(v) || JSVAL_IS_STRING(v)) {
|
||||
thing = JSVAL_TO_TRACEABLE(v);
|
||||
kind = JSVAL_TRACE_KIND(v);
|
||||
JS_ASSERT(kind == js_GetGCThingTraceKind(thing));
|
||||
} else if (JSVAL_IS_OBJECT(v) && v != JSVAL_NULL) {
|
||||
/* v can be an arbitrary GC thing reinterpreted as an object. */
|
||||
thing = JSVAL_TO_OBJECT(v);
|
||||
kind = js_GetGCThingTraceKind(thing);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* The incoming thing should be a real gc-thing, not a boxed, word-sized
|
||||
* primitive value.
|
||||
*/
|
||||
jsboxedword w = (jsboxedword)thing;
|
||||
JS_ASSERT(JSBOXEDWORD_IS_OBJECT(w));
|
||||
#endif
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
}
|
||||
js_CallGCMarker(trc, thing, kind);
|
||||
|
||||
uint32 kind = js_GetGCThingTraceKind(thing);
|
||||
CallGCMarker(trc, thing, kind);
|
||||
}
|
||||
|
||||
static JSDHashOperator
|
||||
gc_root_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
|
||||
void *arg)
|
||||
{
|
||||
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
|
||||
JSTracer *trc = (JSTracer *)arg;
|
||||
jsval *rp = (jsval *)rhe->root;
|
||||
jsval v = *rp;
|
||||
} /* namespace js */
|
||||
|
||||
/* Ignore null reference, scalar values, and static strings. */
|
||||
if (JSVAL_IS_TRACEABLE(v)) {
|
||||
static void
|
||||
gc_root_traversal(JSTracer *trc, const RootEntry &entry)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!JSString::isStatic(JSVAL_TO_GCTHING(v))) {
|
||||
void *ptr;
|
||||
if (entry.value.type == JS_GC_ROOT_GCTHING_PTR) {
|
||||
ptr = entry.key;
|
||||
} else {
|
||||
Value *vp = static_cast<Value *>(entry.key);
|
||||
ptr = vp->isGCThing() ? vp->asGCThing() : NULL;
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
if (!JSString::isStatic(ptr)) {
|
||||
bool root_points_to_gcArenaList = false;
|
||||
jsuword thing = (jsuword) JSVAL_TO_GCTHING(v);
|
||||
jsuword thing = (jsuword) ptr;
|
||||
JSRuntime *rt = trc->context->runtime;
|
||||
for (unsigned i = 0; i != FINALIZE_LIMIT; i++) {
|
||||
JSGCArenaList *arenaList = &rt->gcArenaList[i];
|
||||
|
@ -2209,21 +2166,23 @@ gc_root_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!root_points_to_gcArenaList && rhe->name) {
|
||||
if (!root_points_to_gcArenaList && entry.value.name) {
|
||||
fprintf(stderr,
|
||||
"JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n"
|
||||
"invalid jsval. This is usually caused by a missing call to JS_RemoveRoot.\n"
|
||||
"invalid gcthing. This is usually caused by a missing call to JS_RemoveRoot.\n"
|
||||
"The root's name is \"%s\".\n",
|
||||
rhe->name);
|
||||
entry.value.name);
|
||||
}
|
||||
JS_ASSERT(root_points_to_gcArenaList);
|
||||
}
|
||||
#endif
|
||||
JS_SET_TRACING_NAME(trc, rhe->name ? rhe->name : "root");
|
||||
js_CallValueTracerIfGCThing(trc, v);
|
||||
}
|
||||
#endif
|
||||
|
||||
return JS_DHASH_NEXT;
|
||||
JS_SET_TRACING_NAME(trc, entry.value.name ? entry.value.name : "root");
|
||||
if (entry.value.type == JS_GC_ROOT_GCTHING_PTR)
|
||||
CallGCMarkerForGCThing(trc, entry.key);
|
||||
else
|
||||
CallGCMarkerIfGCThing(trc, *static_cast<Value *>(entry.key));
|
||||
}
|
||||
|
||||
static JSDHashOperator
|
||||
|
@ -2249,7 +2208,7 @@ TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len)
|
|||
for (uint32 i = 0; i < len; i++) {
|
||||
if (JSObject *obj = vec[i]) {
|
||||
JS_SET_TRACING_INDEX(trc, "vector", i);
|
||||
js_CallGCMarker(trc, obj, JSTRACE_OBJECT);
|
||||
CallGCMarker(trc, obj, JSTRACE_OBJECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2263,14 +2222,13 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
|
|||
if (fp->callobj)
|
||||
JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call");
|
||||
if (fp->argsobj)
|
||||
JS_CALL_OBJECT_TRACER(trc, JSVAL_TO_OBJECT(fp->argsobj), "arguments");
|
||||
JS_CALL_OBJECT_TRACER(trc, fp->argsobj, "arguments");
|
||||
if (fp->script)
|
||||
js_TraceScript(trc, fp->script);
|
||||
|
||||
/* Allow for primitive this parameter due to JSFUN_THISP_* flags. */
|
||||
JS_CALL_VALUE_TRACER(trc, fp->thisv, "this");
|
||||
|
||||
JS_CALL_VALUE_TRACER(trc, fp->rval, "rval");
|
||||
CallGCMarkerIfGCThing(trc, fp->thisv, "this");
|
||||
CallGCMarkerIfGCThing(trc, fp->rval, "rval");
|
||||
if (fp->scopeChain)
|
||||
JS_CALL_OBJECT_TRACER(trc, fp->scopeChain, "scope chain");
|
||||
}
|
||||
|
@ -2305,9 +2263,8 @@ JSWeakRoots::mark(JSTracer *trc)
|
|||
}
|
||||
if (newbornDouble)
|
||||
JS_CALL_DOUBLE_TRACER(trc, newbornDouble, "newborn_double");
|
||||
JS_CALL_VALUE_TRACER(trc, lastAtom, "lastAtom");
|
||||
JS_SET_TRACING_NAME(trc, "lastInternalResult");
|
||||
js_CallValueTracerIfGCThing(trc, lastInternalResult);
|
||||
CallGCMarkerIfGCThing(trc, ATOM_TO_JSID(lastAtom), "lastAtom");
|
||||
CallGCMarkerForGCThing(trc, lastInternalResult, "lastInternalResult");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2320,10 +2277,10 @@ js_TraceContext(JSTracer *trc, JSContext *acx)
|
|||
JS_CALL_OBJECT_TRACER(trc, acx->globalObject, "global object");
|
||||
acx->weakRoots.mark(trc);
|
||||
if (acx->throwing) {
|
||||
JS_CALL_VALUE_TRACER(trc, acx->exception, "exception");
|
||||
CallGCMarkerIfGCThing(trc, acx->exception, "exception");
|
||||
} else {
|
||||
/* Avoid keeping GC-ed junk stored in JSContext.exception. */
|
||||
acx->exception = JSVAL_NULL;
|
||||
acx->exception.setNull();
|
||||
}
|
||||
|
||||
for (js::AutoGCRooter *gcr = acx->autoGCRooters; gcr; gcr = gcr->down)
|
||||
|
@ -2350,7 +2307,9 @@ js_TraceRuntime(JSTracer *trc, JSBool allAtoms)
|
|||
JSRuntime *rt = trc->context->runtime;
|
||||
JSContext *iter, *acx;
|
||||
|
||||
JS_DHashTableEnumerate(&rt->gcRootsHash, gc_root_traversal, trc);
|
||||
for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront())
|
||||
gc_root_traversal(trc, r.front());
|
||||
|
||||
JS_DHashTableEnumerate(&rt->gcLocksHash, gc_lock_traversal, trc);
|
||||
js_TraceAtomState(trc, allAtoms);
|
||||
js_TraceRuntimeNumberState(trc);
|
||||
|
@ -2406,12 +2365,12 @@ ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
|
|||
ssr->cycle = true;
|
||||
return;
|
||||
}
|
||||
pobj = JSVAL_TO_OBJECT(pobj->getSlot(slot));
|
||||
pobj = pobj->getSlot(slot).asObjectOrNull();
|
||||
}
|
||||
|
||||
pobj = ssr->pobj;
|
||||
if (slot == JSSLOT_PROTO) {
|
||||
obj->setProto(pobj);
|
||||
obj->setProto(ToObjPtr(pobj));
|
||||
} else {
|
||||
JS_ASSERT(slot == JSSLOT_PARENT);
|
||||
obj->setParent(pobj);
|
||||
|
@ -2443,7 +2402,7 @@ FinalizeObject(JSContext *cx, JSObject *obj, unsigned thingKind)
|
|||
return;
|
||||
|
||||
/* Finalize obj first, in case it needs map and slots. */
|
||||
JSClass *clasp = obj->getClass();
|
||||
Class *clasp = obj->getClass();
|
||||
if (clasp->finalize)
|
||||
clasp->finalize(cx, obj);
|
||||
|
||||
|
|
121
js/src/jsgc.h
121
js/src/jsgc.h
|
@ -50,6 +50,7 @@
|
|||
#include "jstask.h"
|
||||
#include "jsversion.h"
|
||||
|
||||
#define JSTRACE_DOUBLE 2
|
||||
#define JSTRACE_XML 3
|
||||
|
||||
/*
|
||||
|
@ -98,10 +99,16 @@ js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
|
|||
JSStringFinalizeOp newop);
|
||||
|
||||
extern JSBool
|
||||
js_AddRoot(JSContext *cx, void *rp, const char *name);
|
||||
js_AddRoot(JSContext *cx, js::Value *vp, const char *name);
|
||||
|
||||
extern JSBool
|
||||
js_AddRootRT(JSRuntime *rt, void *rp, const char *name);
|
||||
js_AddRootRT(JSRuntime *rt, js::Value *vp, const char *name);
|
||||
|
||||
extern JSBool
|
||||
js_AddGCThingRoot(JSContext *cx, void **rp, const char *name);
|
||||
|
||||
extern JSBool
|
||||
js_AddGCThingRootRT(JSRuntime *rt, void **rp, const char *name);
|
||||
|
||||
extern JSBool
|
||||
js_RemoveRoot(JSRuntime *rt, void *rp);
|
||||
|
@ -109,7 +116,7 @@ js_RemoveRoot(JSRuntime *rt, void *rp);
|
|||
#ifdef DEBUG
|
||||
extern void
|
||||
js_DumpNamedRoots(JSRuntime *rt,
|
||||
void (*dump)(const char *name, void *rp, void *data),
|
||||
void (*dump)(const char *name, void *rp, JSGCRootType type, void *data),
|
||||
void *data);
|
||||
#endif
|
||||
|
||||
|
@ -125,19 +132,12 @@ typedef struct JSPtrTable {
|
|||
extern JSBool
|
||||
js_RegisterCloseableIterator(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Allocate a new double jsval and store the result in *vp. vp must be a root.
|
||||
* The function does not copy the result into any weak root.
|
||||
*/
|
||||
extern JSBool
|
||||
js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
|
||||
|
||||
/*
|
||||
* Return a pointer to a new GC-allocated and weakly-rooted jsdouble number,
|
||||
* or null when the allocation fails.
|
||||
*/
|
||||
extern jsdouble *
|
||||
js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d);
|
||||
js_NewWeaklyRootedDoubleAtom(JSContext *cx, jsdouble d);
|
||||
|
||||
#ifdef JS_TRACER
|
||||
extern JSBool
|
||||
|
@ -162,17 +162,9 @@ js_IsAboutToBeFinalized(void *thing);
|
|||
#if JS_HAS_XML_SUPPORT
|
||||
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) < JSTRACE_LIMIT)
|
||||
#else
|
||||
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_STRING)
|
||||
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_DOUBLE)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Trace jsval when JSVAL_IS_OBJECT(v) can be a GC thing pointer tagged as a
|
||||
* jsval. NB: punning an arbitrary JSString * as an untagged (object-tagged)
|
||||
* jsval no longer works due to static int and unit strings!
|
||||
*/
|
||||
extern void
|
||||
js_CallValueTracerIfGCThing(JSTracer *trc, jsval v);
|
||||
|
||||
extern void
|
||||
js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp);
|
||||
|
||||
|
@ -229,9 +221,6 @@ typedef enum JSGCInvocationKind {
|
|||
extern void
|
||||
js_GC(JSContext *cx, JSGCInvocationKind gckind);
|
||||
|
||||
extern void
|
||||
js_CallGCMarker(JSTracer *trc, void *thing, uint32 kind);
|
||||
|
||||
/*
|
||||
* The kind of GC thing with a finalizer. The external strings follow the
|
||||
* ordinary string to simplify js_GetExternalStringGCType.
|
||||
|
@ -346,14 +335,14 @@ js_DestroyScriptsToGC(JSContext *cx, JSThreadData *data);
|
|||
|
||||
struct JSWeakRoots {
|
||||
/* Most recently created things by type, members of the GC's root set. */
|
||||
void *finalizableNewborns[FINALIZE_LIMIT];
|
||||
jsdouble *newbornDouble;
|
||||
void *finalizableNewborns[FINALIZE_LIMIT];
|
||||
jsdouble *newbornDouble;
|
||||
|
||||
/* Atom root for the last-looked-up atom on this context. */
|
||||
jsval lastAtom;
|
||||
JSAtom *lastAtom;
|
||||
|
||||
/* Root for the result of the most recent js_InternalInvoke call. */
|
||||
jsval lastInternalResult;
|
||||
void *lastInternalResult;
|
||||
|
||||
void mark(JSTracer *trc);
|
||||
};
|
||||
|
@ -453,29 +442,87 @@ js_MarkTraps(JSTracer *trc);
|
|||
|
||||
namespace js {
|
||||
|
||||
void
|
||||
CallGCMarker(JSTracer *trc, void *thing, uint32 kind);
|
||||
|
||||
static inline void
|
||||
CallGCMarkerForGCThing(JSTracer *trc, const js::Value &v)
|
||||
{
|
||||
CallGCMarker(trc, v.asGCThing(), v.traceKind());
|
||||
}
|
||||
|
||||
void
|
||||
CallGCMarkerForGCThing(JSTracer *trc, void *thing);
|
||||
|
||||
static inline void
|
||||
CallGCMarkerForGCThing(JSTracer *trc, void *thing, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
CallGCMarkerForGCThing(trc, thing);
|
||||
}
|
||||
|
||||
static inline void
|
||||
CallGCMarkerIfGCThing(JSTracer *trc, const js::Value &v)
|
||||
{
|
||||
if (v.isGCThing())
|
||||
CallGCMarkerForGCThing(trc, v);
|
||||
}
|
||||
|
||||
static inline void
|
||||
CallGCMarkerIfGCThing(JSTracer *trc, const js::Value &v, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
if (v.isGCThing())
|
||||
CallGCMarkerForGCThing(trc, v);
|
||||
}
|
||||
|
||||
static inline void
|
||||
CallGCMarkerIfGCThing(JSTracer *trc, jsid id)
|
||||
{
|
||||
if (JSID_IS_GCTHING(id))
|
||||
CallGCMarker(trc, JSID_TO_GCTHING(id), JSID_TRACE_KIND(id));
|
||||
}
|
||||
|
||||
static inline void
|
||||
CallGCMarkerIfGCThing(JSTracer *trc, jsid id, const char *name)
|
||||
{
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
if (JSID_IS_GCTHING(id))
|
||||
CallGCMarker(trc, JSID_TO_GCTHING(id), JSID_TRACE_KIND(id));
|
||||
}
|
||||
|
||||
void
|
||||
TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len);
|
||||
|
||||
inline void
|
||||
TraceValues(JSTracer *trc, jsval *beg, jsval *end, const char *name)
|
||||
TraceValues(JSTracer *trc, Value *beg, Value *end, const char *name)
|
||||
{
|
||||
for (jsval *vp = beg; vp < end; ++vp) {
|
||||
jsval v = *vp;
|
||||
if (JSVAL_IS_TRACEABLE(v)) {
|
||||
for (Value *vp = beg; vp < end; ++vp) {
|
||||
if (vp->isGCThing()) {
|
||||
JS_SET_TRACING_INDEX(trc, name, vp - beg);
|
||||
js_CallGCMarker(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
|
||||
CallGCMarkerForGCThing(trc, *vp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
TraceValues(JSTracer *trc, size_t len, jsval *vec, const char *name)
|
||||
TraceValues(JSTracer *trc, size_t len, Value *vec, const char *name)
|
||||
{
|
||||
for (jsval *vp = vec, *end = vp + len; vp < end; vp++) {
|
||||
jsval v = *vp;
|
||||
if (JSVAL_IS_TRACEABLE(v)) {
|
||||
for (Value *vp = vec, *end = vp + len; vp < end; vp++) {
|
||||
if (vp->isGCThing()) {
|
||||
JS_SET_TRACING_INDEX(trc, name, vp - vec);
|
||||
js_CallGCMarker(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
|
||||
CallGCMarkerForGCThing(trc, *vp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
TraceIds(JSTracer *trc, size_t len, jsid *vec, const char *name)
|
||||
{
|
||||
for (jsid *idp = vec, *end = idp + len; idp < end; idp++) {
|
||||
if (JSID_IS_GCTHING(*idp)) {
|
||||
JS_SET_TRACING_INDEX(trc, name, idp - vec);
|
||||
CallGCMarker(trc, JSID_TO_GCTHING(*idp), JSID_TRACE_KIND(*idp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ class HashTable : AllocPolicy
|
|||
return cur == end;
|
||||
}
|
||||
|
||||
const T &front() const {
|
||||
T &front() const {
|
||||
JS_ASSERT(!empty());
|
||||
return cur->t;
|
||||
}
|
||||
|
@ -313,6 +313,8 @@ class HashTable : AllocPolicy
|
|||
return true;
|
||||
}
|
||||
|
||||
bool initialized() const { return table; }
|
||||
|
||||
~HashTable()
|
||||
{
|
||||
if (table)
|
||||
|
@ -721,6 +723,7 @@ class HashMap
|
|||
*/
|
||||
HashMap(AllocPolicy a = AllocPolicy()) : impl(a) {}
|
||||
bool init(uint32 cap = 0) { return impl.init(cap); }
|
||||
bool initialized() const { return impl.initialized(); }
|
||||
|
||||
/*
|
||||
* Return whether the given lookup value is present in the map. E.g.:
|
||||
|
@ -868,6 +871,7 @@ class HashSet
|
|||
*/
|
||||
HashSet(AllocPolicy a = AllocPolicy()) : impl(a) {}
|
||||
bool init(uint32 cap = 0) { return impl.init(cap); }
|
||||
bool initialized() const { return impl.initialized(); }
|
||||
|
||||
/*
|
||||
* Return whether the given lookup value is present in the map. E.g.:
|
||||
|
|
1100
js/src/jsinterp.cpp
1100
js/src/jsinterp.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -49,11 +49,9 @@
|
|||
#include "jsopcode.h"
|
||||
#include "jsscript.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct JSFrameRegs {
|
||||
jsbytecode *pc; /* program counter */
|
||||
jsval *sp; /* stack pointer */
|
||||
js::Value *sp; /* stack pointer */
|
||||
} JSFrameRegs;
|
||||
|
||||
/* JS stack frame flags. */
|
||||
|
@ -82,16 +80,17 @@ typedef struct JSFrameRegs {
|
|||
*/
|
||||
struct JSStackFrame
|
||||
{
|
||||
/* N.B. alignment (TODO: remove these members) */
|
||||
js::Value thisv; /* "this" pointer if in method */
|
||||
js::Value rval; /* function return value */
|
||||
|
||||
jsbytecode *imacpc; /* null or interpreter macro call pc */
|
||||
JSObject *callobj; /* lazily created Call object */
|
||||
jsval argsobj; /* lazily created arguments object, must be
|
||||
JSVAL_OBJECT */
|
||||
JSObject *argsobj; /* lazily created arguments object */
|
||||
JSScript *script; /* script being interpreted */
|
||||
JSFunction *fun; /* function being called or null */
|
||||
jsval thisv; /* "this" pointer if in method */
|
||||
uintN argc; /* actual argument count */
|
||||
jsval *argv; /* base of argument stack slots */
|
||||
jsval rval; /* function return value */
|
||||
js::Value *argv; /* base of argument stack slots */
|
||||
void *annotation; /* used by Java security */
|
||||
|
||||
/* Maintained by StackSpace operations */
|
||||
|
@ -138,10 +137,7 @@ struct JSStackFrame
|
|||
* also used in some other cases --- entering 'with' blocks, for
|
||||
* example.
|
||||
*/
|
||||
union {
|
||||
JSObject *scopeChain;
|
||||
jsval scopeChainVal;
|
||||
};
|
||||
JSObject *scopeChain;
|
||||
JSObject *blockChain;
|
||||
|
||||
uint32 flags; /* frame flags -- see below */
|
||||
|
@ -168,26 +164,25 @@ struct JSStackFrame
|
|||
/* Get the frame's current bytecode, assuming |this| is in |cx|. */
|
||||
jsbytecode *pc(JSContext *cx) const;
|
||||
|
||||
jsval *argEnd() const {
|
||||
return (jsval *)this;
|
||||
js::Value *argEnd() const {
|
||||
return (js::Value *)this;
|
||||
}
|
||||
|
||||
jsval *slots() const {
|
||||
return (jsval *)(this + 1);
|
||||
js::Value *slots() const {
|
||||
return (js::Value *)(this + 1);
|
||||
}
|
||||
|
||||
jsval calleeValue() {
|
||||
js::Value *base() const {
|
||||
return slots() + script->nfixed;
|
||||
}
|
||||
|
||||
const js::Value &calleeValue() {
|
||||
JS_ASSERT(argv);
|
||||
return argv[-2];
|
||||
}
|
||||
|
||||
JSObject *calleeObject() {
|
||||
JS_ASSERT(argv);
|
||||
return JSVAL_TO_OBJECT(argv[-2]);
|
||||
}
|
||||
|
||||
JSObject *callee() {
|
||||
return argv ? JSVAL_TO_OBJECT(argv[-2]) : NULL;
|
||||
return argv ? &argv[-2].asObject() : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -200,7 +195,7 @@ struct JSStackFrame
|
|||
/* Short for: varobj(cx->activeCallStack()). */
|
||||
JSObject *varobj(JSContext *cx) const;
|
||||
|
||||
inline JSObject *getThisObject(JSContext *cx);
|
||||
inline js::ObjPtr getThisObject(JSContext *cx);
|
||||
|
||||
bool isGenerator() const { return flags & JSFRAME_GENERATOR; }
|
||||
bool isFloatingGenerator() const {
|
||||
|
@ -211,16 +206,10 @@ struct JSStackFrame
|
|||
|
||||
namespace js {
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSStackFrame) % sizeof(jsval) == 0);
|
||||
static const size_t ValuesPerStackFrame = sizeof(JSStackFrame) / sizeof(jsval);
|
||||
JS_STATIC_ASSERT(sizeof(JSStackFrame) % sizeof(Value) == 0);
|
||||
static const size_t ValuesPerStackFrame = sizeof(JSStackFrame) / sizeof(Value);
|
||||
|
||||
}
|
||||
|
||||
static JS_INLINE jsval *
|
||||
StackBase(JSStackFrame *fp)
|
||||
{
|
||||
return fp->slots() + fp->script->nfixed;
|
||||
}
|
||||
} /* namespace js */
|
||||
|
||||
static JS_INLINE uintN
|
||||
GlobalVarCount(JSStackFrame *fp)
|
||||
|
@ -246,10 +235,12 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp);
|
|||
* instance of clasp and extract its private slot value to return via *thisvp.
|
||||
*
|
||||
* NB: this function loads and uses *vp before storing *thisvp, so the two may
|
||||
* alias the same jsval.
|
||||
* alias the same Value.
|
||||
*/
|
||||
extern JSBool
|
||||
js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp);
|
||||
js_GetPrimitiveThis(JSContext *cx, js::Value *vp, js::Class *clasp, js::Value *thisvp);
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* For a call with arguments argv including argv[-1] (nominal |this|) and
|
||||
|
@ -258,15 +249,43 @@ js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp);
|
|||
* objects as, per ECMA-262, they may not be referred to by |this|. argv[-1]
|
||||
* must not be a JSVAL_VOID.
|
||||
*/
|
||||
extern JSObject *
|
||||
js_ComputeThis(JSContext *cx, jsval *argv);
|
||||
extern bool
|
||||
ComputeThisFromArgv(JSContext *cx, js::Value *argv);
|
||||
|
||||
extern const uint16 js_PrimitiveTestFlags[];
|
||||
JS_ALWAYS_INLINE JSObject *
|
||||
ComputeThisObjectFromVp(JSContext *cx, js::Value *vp)
|
||||
{
|
||||
extern bool ComputeThisFromArgv(JSContext *, js::Value *);
|
||||
return ComputeThisFromArgv(cx, vp + 2) ? &vp->asObject() : NULL;
|
||||
}
|
||||
|
||||
#define PRIMITIVE_THIS_TEST(fun,thisv) \
|
||||
(JS_ASSERT(!JSVAL_IS_VOID(thisv)), \
|
||||
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \
|
||||
js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1]))
|
||||
JS_ALWAYS_INLINE bool
|
||||
ComputeThisValueFromVp(JSContext *cx, js::Value *vp, js::Value **thisvpp)
|
||||
{
|
||||
extern bool ComputeThisFromArgv(JSContext *, js::Value *);
|
||||
if (ComputeThisFromArgv(cx, vp + 2)) {
|
||||
*thisvpp = vp + 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class PrimitiveValue
|
||||
{
|
||||
static const unsigned THISP_MASK = 0x7;
|
||||
static const unsigned THISP_ARRAY_SIZE = 8;
|
||||
static const unsigned THISP_SHIFT = 8;
|
||||
|
||||
JS_STATIC_ASSERT(JSFUN_THISP_PRIMITIVE >> THISP_SHIFT == THISP_MASK);
|
||||
JS_STATIC_ASSERT(THISP_MASK == THISP_ARRAY_SIZE - 1);
|
||||
|
||||
static const Value::MaskType Masks[THISP_ARRAY_SIZE];
|
||||
|
||||
public:
|
||||
static bool test(JSFunction *fun, const Value &v) {
|
||||
return bool(Masks[(fun->flags >> THISP_SHIFT) & THISP_MASK] & v.mask);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The js::InvokeArgumentsGuard passed to js_Invoke must come from an
|
||||
|
@ -276,8 +295,11 @@ extern const uint16 js_PrimitiveTestFlags[];
|
|||
* and the range [args.getvp() + 2, args.getvp() + 2 + args.getArgc()) should
|
||||
* be initialized actual arguments.
|
||||
*/
|
||||
extern JS_REQUIRES_STACK JS_FRIEND_API(JSBool)
|
||||
js_Invoke(JSContext *cx, const js::InvokeArgsGuard &args, uintN flags);
|
||||
extern JS_REQUIRES_STACK bool
|
||||
Invoke(JSContext *cx, const InvokeArgsGuard &args, uintN flags);
|
||||
|
||||
extern JS_REQUIRES_STACK JS_FRIEND_API(bool)
|
||||
InvokeFriendAPI(JSContext *cx, const InvokeArgsGuard &args, uintN flags);
|
||||
|
||||
/*
|
||||
* Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that
|
||||
|
@ -300,56 +322,79 @@ js_Invoke(JSContext *cx, const js::InvokeArgsGuard &args, uintN flags);
|
|||
*/
|
||||
#define JSINVOKE_FUNFLAGS (JSINVOKE_CONSTRUCT | JSINVOKE_ITERATOR)
|
||||
|
||||
/*
|
||||
* "Internal" calls may come from C or C++ code using a JSContext on which no
|
||||
* JS is running (!cx->fp), so they may need to push a dummy JSStackFrame.
|
||||
*/
|
||||
#define js_InternalCall(cx,obj,fval,argc,argv,rval) \
|
||||
js_InternalInvoke(cx, obj, fval, 0, argc, argv, rval)
|
||||
extern bool
|
||||
InternalInvoke(JSContext *cx, JSObject *obj, const Value &fval, uintN flags,
|
||||
uintN argc, const Value *argv, Value *rval);
|
||||
|
||||
#define js_InternalConstruct(cx,obj,fval,argc,argv,rval) \
|
||||
js_InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval)
|
||||
static JS_ALWAYS_INLINE bool
|
||||
InternalCall(JSContext *cx, JSObject *obj, const Value &fval, uintN argc,
|
||||
const Value *argv, Value *rval)
|
||||
{
|
||||
return InternalInvoke(cx, obj, fval, 0, argc, argv, rval);
|
||||
}
|
||||
|
||||
extern JSBool
|
||||
js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
|
||||
uintN argc, jsval *argv, jsval *rval);
|
||||
static JS_ALWAYS_INLINE bool
|
||||
InternalConstruct(JSContext *cx, JSObject *obj, const Value &fval, uintN argc,
|
||||
const Value *argv, Value *rval)
|
||||
{
|
||||
return InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval);
|
||||
}
|
||||
|
||||
extern JSBool
|
||||
js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
|
||||
JSAccessMode mode, uintN argc, jsval *argv, jsval *rval);
|
||||
extern bool
|
||||
InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
|
||||
JSAccessMode mode, uintN argc, const Value *argv, Value *rval);
|
||||
|
||||
extern JS_FORCES_STACK JSBool
|
||||
js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
|
||||
JSStackFrame *down, uintN flags, jsval *result);
|
||||
extern JS_FORCES_STACK bool
|
||||
Execute(JSContext *cx, JSObject *chain, JSScript *script,
|
||||
JSStackFrame *down, uintN flags, Value *result);
|
||||
|
||||
extern JS_REQUIRES_STACK JSBool
|
||||
js_InvokeConstructor(JSContext *cx, const js::InvokeArgsGuard &args,
|
||||
JSBool clampReturn);
|
||||
extern JS_REQUIRES_STACK bool
|
||||
InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args,
|
||||
JSBool clampReturn);
|
||||
|
||||
extern JS_REQUIRES_STACK JSBool
|
||||
js_Interpret(JSContext *cx);
|
||||
extern JS_REQUIRES_STACK bool
|
||||
Interpret(JSContext *cx);
|
||||
|
||||
#define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */
|
||||
|
||||
extern JSBool
|
||||
js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
|
||||
JSObject **objp, JSProperty **propp);
|
||||
extern bool
|
||||
CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
|
||||
JSObject **objp, JSProperty **propp);
|
||||
|
||||
extern JSBool
|
||||
js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval);
|
||||
extern bool
|
||||
StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval);
|
||||
|
||||
/* === except that NaN is the same as NaN and -0 is not the same as +0. */
|
||||
extern JSBool
|
||||
js_SameValue(jsval v1, jsval v2, JSContext *cx);
|
||||
extern bool
|
||||
SameValue(JSContext *cx, const Value &v1, const Value &v2);
|
||||
|
||||
extern JSBool
|
||||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp);
|
||||
JSType
|
||||
TypeOfValue(JSContext *cx, const js::Value &v);
|
||||
|
||||
inline bool
|
||||
InstanceOf(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
|
||||
{
|
||||
if (obj && obj->getClass() == clasp)
|
||||
return true;
|
||||
extern bool InstanceOfSlow(JSContext *, JSObject *, Class *, Value *);
|
||||
return InstanceOfSlow(cx, obj, clasp, argv);
|
||||
}
|
||||
|
||||
inline void *
|
||||
GetInstancePrivate(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
|
||||
{
|
||||
if (!InstanceOf(cx, obj, clasp, argv))
|
||||
return NULL;
|
||||
return obj->getPrivate();
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* Given an active context, a static scope level, and an upvar cookie, return
|
||||
* the value of the upvar.
|
||||
*/
|
||||
extern jsval&
|
||||
extern const js::Value &
|
||||
js_GetUpvar(JSContext *cx, uintN level, uintN cookie);
|
||||
|
||||
/*
|
||||
|
@ -378,31 +423,13 @@ js_GetUpvar(JSContext *cx, uintN level, uintN cookie);
|
|||
#else
|
||||
# define JS_STATIC_INTERPRET
|
||||
|
||||
/*
|
||||
* ECMA requires "the global object", but in embeddings such as the browser,
|
||||
* which have multiple top-level objects (windows, frames, etc. in the DOM),
|
||||
* we prefer fun's parent. An example that causes this code to run:
|
||||
*
|
||||
* // in window w1
|
||||
* function f() { return this }
|
||||
* function g() { return f }
|
||||
*
|
||||
* // in window w2
|
||||
* var h = w1.g()
|
||||
* alert(h() == w1)
|
||||
*
|
||||
* The alert should display "true".
|
||||
*/
|
||||
extern JSObject *
|
||||
js_ComputeGlobalThis(JSContext *cx, jsval *argv);
|
||||
|
||||
extern JS_REQUIRES_STACK JSBool
|
||||
js_EnterWith(JSContext *cx, jsint stackIndex);
|
||||
|
||||
extern JS_REQUIRES_STACK void
|
||||
js_LeaveWith(JSContext *cx);
|
||||
|
||||
extern JS_REQUIRES_STACK JSClass *
|
||||
extern JS_REQUIRES_STACK js::Class *
|
||||
js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth);
|
||||
|
||||
/*
|
||||
|
@ -413,7 +440,7 @@ extern JS_REQUIRES_STACK JSBool
|
|||
js_UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind);
|
||||
|
||||
extern JSBool
|
||||
js_OnUnknownMethod(JSContext *cx, jsval *vp);
|
||||
js_OnUnknownMethod(JSContext *cx, js::Value *vp);
|
||||
|
||||
/*
|
||||
* Find the results of incrementing or decrementing *vp. For pre-increments,
|
||||
|
@ -422,7 +449,7 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp);
|
|||
* the result. Both vp and vp2 must be roots.
|
||||
*/
|
||||
extern JSBool
|
||||
js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2);
|
||||
js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, js::Value *vp, js::Value *vp2);
|
||||
|
||||
/*
|
||||
* Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the
|
||||
|
@ -442,19 +469,16 @@ js_MeterSlotOpcode(JSOp op, uint32 slot);
|
|||
|
||||
#endif /* JS_LONE_INTERPRET */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
inline JSObject *
|
||||
inline js::ObjPtr
|
||||
JSStackFrame::getThisObject(JSContext *cx)
|
||||
{
|
||||
if (flags & JSFRAME_COMPUTED_THIS)
|
||||
return JSVAL_TO_OBJECT(thisv); /* JSVAL_COMPUTED_THIS invariant */
|
||||
JSObject* obj = js_ComputeThis(cx, argv);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
thisv = OBJECT_TO_JSVAL(obj);
|
||||
return thisv.asObjPtr(); /* JSVAL_COMPUTED_THIS invariant */
|
||||
if (!js::ComputeThisFromArgv(cx, argv))
|
||||
return js::NullObjPtr();
|
||||
thisv.copy(argv[-1]);
|
||||
flags |= JSFRAME_COMPUTED_THIS;
|
||||
return obj;
|
||||
return thisv.asObjPtr();
|
||||
}
|
||||
|
||||
#endif /* jsinterp_h___ */
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
/*
|
||||
* JavaScript iterators.
|
||||
*/
|
||||
|
|
|
@ -71,17 +71,17 @@ const uint32 JSSLOT_ITER_FLAGS = JSSLOT_PRIVATE + 1;
|
|||
* iterator will never be exposed to scripts.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp);
|
||||
js_ValueToIterator(JSContext *cx, uintN flags, js::Value *vp);
|
||||
|
||||
extern JS_FRIEND_API(JSBool) JS_FASTCALL
|
||||
js_CloseIterator(JSContext *cx, jsval v);
|
||||
js_CloseIterator(JSContext *cx, const js::Value &v);
|
||||
|
||||
/*
|
||||
* Given iterobj, call iterobj.next(). If the iterator stopped, set *rval to
|
||||
* JSVAL_HOLE. Otherwise set it to the result of the next call.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_CallIteratorNext(JSContext *cx, JSObject *iterobj, jsval *rval);
|
||||
js_CallIteratorNext(JSContext *cx, JSObject *iterobj, js::Value *rval);
|
||||
|
||||
/*
|
||||
* Close iterobj, whose class must be js_IteratorClass.
|
||||
|
@ -160,15 +160,14 @@ js_LiveFrameIfGenerator(JSStackFrame *fp)
|
|||
}
|
||||
#endif
|
||||
|
||||
extern JS_FRIEND_API(JSClass) js_GeneratorClass;
|
||||
extern JSClass js_IteratorClass;
|
||||
extern JSClass js_StopIterationClass;
|
||||
extern JS_FRIEND_API(js::Class) js_GeneratorClass;
|
||||
extern js::Class js_IteratorClass;
|
||||
extern js::Class js_StopIterationClass;
|
||||
|
||||
static inline bool
|
||||
js_ValueIsStopIteration(jsval v)
|
||||
js_ValueIsStopIteration(const js::Value &v)
|
||||
{
|
||||
return !JSVAL_IS_PRIMITIVE(v) &&
|
||||
JSVAL_TO_OBJECT(v)->getClass() == &js_StopIterationClass;
|
||||
return v.isObject() && v.asObject().getClass() == &js_StopIterationClass;
|
||||
}
|
||||
|
||||
extern JSObject *
|
||||
|
|
|
@ -43,9 +43,7 @@
|
|||
* JS math functions.
|
||||
*/
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSClass js_MathClass;
|
||||
extern js::Class js_MathClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitMathClass(JSContext *cx, JSObject *obj);
|
||||
|
@ -68,6 +66,4 @@ js_math_min(JSContext *cx, uintN argc, jsval *vp);
|
|||
extern JSBool
|
||||
js_math_round(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsmath_h___ */
|
||||
|
|
|
@ -800,29 +800,6 @@ js_InitNumberClass(JSContext *cx, JSObject *obj)
|
|||
return proto;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
|
||||
{
|
||||
jsint i;
|
||||
|
||||
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
|
||||
*vp = INT_TO_JSVAL(i);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return js_NewDoubleInRootedValue(cx, d, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NewWeaklyRootedNumber(JSContext *cx, jsdouble d, jsval *rval)
|
||||
{
|
||||
jsint i;
|
||||
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
|
||||
*rval = INT_TO_JSVAL(i);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_NewDoubleValue(cx, d, rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a number to C string. The buf must be large enough to accommodate
|
||||
* the result, including '-' and '\0', if base == 10 or d is an integer that
|
||||
|
@ -936,8 +913,8 @@ js_NumberValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb)
|
|||
|
||||
namespace js {
|
||||
|
||||
jsval
|
||||
ValueToNumberSlow(JSContext *cx, jsval v, double *out)
|
||||
bool
|
||||
ValueToNumberSlow(JSContext *cx, Value *vp, double *out)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_INT(v) && !JSVAL_IS_DOUBLE(v));
|
||||
goto skip_int_double;
|
||||
|
@ -999,24 +976,7 @@ ValueToNumberSlow(JSContext *cx, jsval v, double *out)
|
|||
}
|
||||
|
||||
bool
|
||||
ValueToNumberValueSlow(JSContext *cx, jsval *vp, double *out)
|
||||
{
|
||||
jsval v = *vp = ValueToNumberSlow(cx, *vp, out);
|
||||
return !JSVAL_IS_NULL(v) &&
|
||||
(v != JSVAL_TRUE || js_NewNumberInRootedValue(cx, *out, vp));
|
||||
}
|
||||
|
||||
bool
|
||||
ValueToNumberValueSlow(JSContext *cx, jsval *vp)
|
||||
{
|
||||
double d;
|
||||
jsval v = *vp = ValueToNumberSlow(cx, *vp, &d);
|
||||
return !JSVAL_IS_NULL(v) &&
|
||||
(v != JSVAL_TRUE || js_NewNumberInRootedValue(cx, d, vp));
|
||||
}
|
||||
|
||||
bool
|
||||
ValueToECMAInt32Slow(JSContext *cx, jsval v, int32_t *out)
|
||||
ValueToECMAInt32Slow(JSContext *cx, js::Value *vp, int32_t *out)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_INT(v));
|
||||
jsdouble d;
|
||||
|
@ -1031,7 +991,7 @@ ValueToECMAInt32Slow(JSContext *cx, jsval v, int32_t *out)
|
|||
}
|
||||
|
||||
bool
|
||||
ValueToECMAUint32Slow(JSContext *cx, jsval v, uint32_t *out)
|
||||
ValueToECMAUint32Slow(JSContext *cx, js::Value *vp, uint32_t *out)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_INT(v));
|
||||
jsdouble d;
|
||||
|
@ -1079,7 +1039,7 @@ js_DoubleToECMAUint32(jsdouble d)
|
|||
namespace js {
|
||||
|
||||
bool
|
||||
ValueToInt32Slow(JSContext *cx, jsval v, int32_t *out)
|
||||
ValueToInt32Slow(JSContext *cx, js::Value *vp, int32_t *out)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_INT(v));
|
||||
jsdouble d;
|
||||
|
@ -1105,7 +1065,7 @@ ValueToInt32Slow(JSContext *cx, jsval v, int32_t *out)
|
|||
}
|
||||
|
||||
bool
|
||||
ValueToUint16Slow(JSContext *cx, jsval v, uint16_t *out)
|
||||
ValueToUint16Slow(JSContext *cx, js::Value *vp, uint16_t *out)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_INT(v));
|
||||
jsdouble d;
|
||||
|
|
151
js/src/jsnum.h
151
js/src/jsnum.h
|
@ -132,15 +132,15 @@ JSDOUBLE_IS_NEGZERO(jsdouble d)
|
|||
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
|
||||
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
|
||||
|
||||
static inline int
|
||||
JSDOUBLE_IS_INT(jsdouble d, jsint& i)
|
||||
static inline bool
|
||||
JSDOUBLE_IS_INT32(jsdouble d, int32_t& i)
|
||||
{
|
||||
if (JSDOUBLE_IS_NEGZERO(d))
|
||||
return false;
|
||||
return d == (i = jsint(d));
|
||||
return d == (i = int32_t(d));
|
||||
}
|
||||
|
||||
static inline int
|
||||
static inline bool
|
||||
JSDOUBLE_IS_NEG(jsdouble d)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
@ -184,9 +184,9 @@ extern void
|
|||
js_FinishRuntimeNumberState(JSContext *cx);
|
||||
|
||||
/* Initialize the Number class, returning its prototype object. */
|
||||
extern JSClass js_NumberClass;
|
||||
extern js::Class js_NumberClass;
|
||||
|
||||
extern "C" JSObject *
|
||||
extern JSObject *
|
||||
js_InitNumberClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
|
@ -199,19 +199,6 @@ extern const char js_isFinite_str[];
|
|||
extern const char js_parseFloat_str[];
|
||||
extern const char js_parseInt_str[];
|
||||
|
||||
/*
|
||||
* vp must be a root.
|
||||
*/
|
||||
extern JSBool
|
||||
js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
|
||||
|
||||
/*
|
||||
* Create a weakly rooted integer or double jsval as appropriate for the given
|
||||
* jsdouble.
|
||||
*/
|
||||
extern JSBool
|
||||
js_NewWeaklyRootedNumber(JSContext *cx, jsdouble d, jsval *vp);
|
||||
|
||||
/* Convert a number to a GC'ed string. */
|
||||
extern JSString * JS_FASTCALL
|
||||
js_NumberToString(JSContext *cx, jsdouble d);
|
||||
|
@ -227,106 +214,77 @@ namespace js {
|
|||
|
||||
/*
|
||||
* Convert a value to a number, returning the converted value in 'out' if the
|
||||
* conversion succeeds. v most be a copy of a rooted jsval.
|
||||
* conversion succeeds. As a side effect, *vp will be mutated to match *out.
|
||||
*/
|
||||
JS_ALWAYS_INLINE bool
|
||||
ValueToNumber(JSContext *cx, jsval v, double *out)
|
||||
ValueToNumber(JSContext *cx, js::Value *vp, double *out)
|
||||
{
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
*out = JSVAL_TO_INT(v);
|
||||
if (vp->isInt32()) {
|
||||
*out = vp->asInt32();
|
||||
return true;
|
||||
}
|
||||
if (JSVAL_IS_DOUBLE(v)) {
|
||||
*out = *JSVAL_TO_DOUBLE(v);
|
||||
if (vp->isDouble()) {
|
||||
*out = vp->asDouble();
|
||||
return true;
|
||||
}
|
||||
extern jsval ValueToNumberSlow(JSContext *, jsval, double *);
|
||||
return !JSVAL_IS_NULL(ValueToNumberSlow(cx, v, out));
|
||||
extern bool ValueToNumberSlow(JSContext *, js::Value *, double *);
|
||||
return ValueToNumberSlow(cx, vp, out);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a value to a number, replacing 'vp' with the converted value and
|
||||
* returning the value as a double in 'out'. vp must point to a rooted jsval.
|
||||
*
|
||||
* N.B. this function will allocate a new double if needed; callers needing
|
||||
* only a double, not a value, should use ValueToNumber instead.
|
||||
*/
|
||||
/* Convert a value to a number, replacing 'vp' with the converted value. */
|
||||
JS_ALWAYS_INLINE bool
|
||||
ValueToNumberValue(JSContext *cx, jsval *vp, double *out)
|
||||
ValueToNumber(JSContext *cx, js::Value *vp)
|
||||
{
|
||||
jsval v = *vp;
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
*out = JSVAL_TO_INT(v);
|
||||
if (vp->isInt32())
|
||||
return true;
|
||||
}
|
||||
if (JSVAL_IS_DOUBLE(v)) {
|
||||
*out = *JSVAL_TO_DOUBLE(v);
|
||||
if (vp->isDouble())
|
||||
return true;
|
||||
}
|
||||
extern bool ValueToNumberValueSlow(JSContext *, jsval *, double *);
|
||||
return ValueToNumberValueSlow(cx, vp, out);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a value to a number, replacing 'vp' with the converted value. vp
|
||||
* must point to a rooted jsval.
|
||||
*
|
||||
* N.B. this function will allocate a new double if needed; callers needing
|
||||
* only a double, not a value, should use ValueToNumber instead.
|
||||
*/
|
||||
JS_ALWAYS_INLINE bool
|
||||
ValueToNumberValue(JSContext *cx, jsval *vp)
|
||||
{
|
||||
jsval v = *vp;
|
||||
if (JSVAL_IS_INT(v))
|
||||
return true;
|
||||
if (JSVAL_IS_DOUBLE(v))
|
||||
return true;
|
||||
extern bool ValueToNumberValueSlow(JSContext *, jsval *);
|
||||
return ValueToNumberValueSlow(cx, vp);
|
||||
double _;
|
||||
extern bool ValueToNumberSlow(JSContext *, js::Value *, double *);
|
||||
return ValueToNumberSlow(cx, vp, &_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a value to an int32 or uint32, according to the ECMA rules for
|
||||
* ToInt32 and ToUint32. Return converted value on success, !ok on failure. v
|
||||
* must be a copy of a rooted jsval.
|
||||
* ToInt32 and ToUint32. Return converted value in *out on success, !ok on
|
||||
* failure. As a side effect, *vp will be mutated to match *out.
|
||||
*/
|
||||
JS_ALWAYS_INLINE bool
|
||||
ValueToECMAInt32(JSContext *cx, jsval v, int32_t *out)
|
||||
ValueToECMAInt32(JSContext *cx, js::Value *vp, int32_t *out)
|
||||
{
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
*out = JSVAL_TO_INT(v);
|
||||
if (vp->isInt32()) {
|
||||
*out = vp->asInt32();
|
||||
return true;
|
||||
}
|
||||
extern bool ValueToECMAInt32Slow(JSContext *, jsval, int32_t *);
|
||||
return ValueToECMAInt32Slow(cx, v, out);
|
||||
extern bool ValueToECMAInt32Slow(JSContext *, js::Value *, int32_t *);
|
||||
return ValueToECMAInt32Slow(cx, vp, out);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE bool
|
||||
ValueToECMAUint32(JSContext *cx, jsval v, uint32_t *out)
|
||||
ValueToECMAUint32(JSContext *cx, js::Value *vp, uint32_t *out)
|
||||
{
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
*out = (uint32_t)JSVAL_TO_INT(v);
|
||||
if (vp->isInt32()) {
|
||||
*out = (uint32_t)vp->asInt32();
|
||||
return true;
|
||||
}
|
||||
extern bool ValueToECMAUint32Slow(JSContext *, jsval, uint32_t *);
|
||||
return ValueToECMAUint32Slow(cx, v, out);
|
||||
extern bool ValueToECMAUint32Slow(JSContext *, js::Value *, uint32_t *);
|
||||
return ValueToECMAUint32Slow(cx, vp, out);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a value to a number, then to an int32 if it fits by rounding to
|
||||
* nearest. Return converted value on success, !ok on failure. v must be a copy
|
||||
* of a rooted jsval.
|
||||
* nearest. Return converted value in *out on success, !ok on failure. As a
|
||||
* side effect, *vp will be mutated to match *out.
|
||||
*/
|
||||
JS_ALWAYS_INLINE bool
|
||||
ValueToInt32(JSContext *cx, jsval v, int32_t *out)
|
||||
ValueToInt32(JSContext *cx, js::Value *vp, int32_t *out)
|
||||
{
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
*out = JSVAL_TO_INT(v);
|
||||
if (vp->isInt32()) {
|
||||
*out = vp->asInt32();
|
||||
return true;
|
||||
}
|
||||
extern bool ValueToInt32Slow(JSContext *, jsval, int32_t *);
|
||||
return ValueToInt32Slow(cx, v, out);
|
||||
extern bool ValueToInt32Slow(JSContext *, js::Value *, int32_t *);
|
||||
return ValueToInt32Slow(cx, vp, out);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -335,14 +293,14 @@ ValueToInt32(JSContext *cx, jsval v, int32_t *out)
|
|||
* copy of a rooted jsval.
|
||||
*/
|
||||
JS_ALWAYS_INLINE bool
|
||||
ValueToUint16(JSContext *cx, jsval v, uint16_t *out)
|
||||
ValueToUint16(JSContext *cx, js::Value *vp, uint16_t *out)
|
||||
{
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
*out = (uint16_t)JSVAL_TO_INT(v);
|
||||
if (vp->isInt32()) {
|
||||
*out = (uint16_t)vp->asInt32();
|
||||
return true;
|
||||
}
|
||||
extern bool ValueToUint16Slow(JSContext *, jsval, uint16_t *);
|
||||
return ValueToUint16Slow(cx, v, out);
|
||||
extern bool ValueToUint16Slow(JSContext *, js::Value *, uint16_t *);
|
||||
return ValueToUint16Slow(cx, vp, out);
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
@ -508,6 +466,25 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
|
|||
|
||||
namespace js {
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
ValueFitsInInt32(const Value &v, int32_t *pi)
|
||||
{
|
||||
if (v.isInt32()) {
|
||||
*pi = v.asInt32();
|
||||
return true;
|
||||
}
|
||||
return v.isDouble() && JSDOUBLE_IS_INT32(v.asDouble(), *pi);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
Uint32ToValue(uint32_t u, Value *vp)
|
||||
{
|
||||
if (JS_UNLIKELY(u > INT32_MAX))
|
||||
vp->setDouble(u);
|
||||
else
|
||||
vp->setInt32((int32_t)u);
|
||||
}
|
||||
|
||||
template<typename T> struct NumberTraits { };
|
||||
template<> struct NumberTraits<int32> {
|
||||
static JS_ALWAYS_INLINE int32 NaN() { return 0; }
|
||||
|
|
1480
js/src/jsobj.cpp
1480
js/src/jsobj.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
435
js/src/jsobj.h
435
js/src/jsobj.h
|
@ -52,7 +52,38 @@
|
|||
#include "jspubtd.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
namespace js { class AutoDescriptorArray; }
|
||||
namespace js {
|
||||
|
||||
class AutoDescriptorArray;
|
||||
|
||||
static inline PropertyOp
|
||||
CastAsPropertyOp(JSObject *object)
|
||||
{
|
||||
return JS_DATA_TO_FUNC_PTR(PropertyOp, object);
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
CastAsObject(PropertyOp op)
|
||||
{
|
||||
return JS_FUNC_TO_DATA_PTR(JSObject *, op);
|
||||
}
|
||||
|
||||
extern JSBool
|
||||
PropertyStub(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
||||
|
||||
extern JSBool
|
||||
EnumerateStub(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
ResolveStub(JSContext *cx, JSObject *obj, jsid id);
|
||||
|
||||
extern JSBool
|
||||
ConvertStub(JSContext *cx, JSObject *obj, JSType type, Value *vp);
|
||||
|
||||
extern void
|
||||
FinalizeStub(JSContext *cx, JSObject *obj);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* A representation of ECMA-262 ed. 5's internal property descriptor data
|
||||
|
@ -66,7 +97,7 @@ struct PropertyDescriptor {
|
|||
|
||||
public:
|
||||
/* 8.10.5 ToPropertyDescriptor(Obj) */
|
||||
bool initialize(JSContext* cx, jsid id, jsval v);
|
||||
bool initialize(JSContext* cx, jsid id, const js::Value &v);
|
||||
|
||||
/* 8.10.1 IsAccessorDescriptor(desc) */
|
||||
bool isAccessorDescriptor() const {
|
||||
|
@ -96,31 +127,31 @@ struct PropertyDescriptor {
|
|||
}
|
||||
|
||||
JSObject* getterObject() const {
|
||||
return get != JSVAL_VOID ? JSVAL_TO_OBJECT(get) : NULL;
|
||||
return get.isUndefined() ? NULL : &get.asObject();
|
||||
}
|
||||
JSObject* setterObject() const {
|
||||
return set != JSVAL_VOID ? JSVAL_TO_OBJECT(set) : NULL;
|
||||
return set.isUndefined() ? NULL : &set.asObject();
|
||||
}
|
||||
|
||||
jsval getterValue() const {
|
||||
const js::Value &getterValue() const {
|
||||
return get;
|
||||
}
|
||||
jsval setterValue() const {
|
||||
const js::Value &setterValue() const {
|
||||
return set;
|
||||
}
|
||||
|
||||
JSPropertyOp getter() const {
|
||||
return js_CastAsPropertyOp(getterObject());
|
||||
js::PropertyOp getter() const {
|
||||
return js::CastAsPropertyOp(getterObject());
|
||||
}
|
||||
JSPropertyOp setter() const {
|
||||
return js_CastAsPropertyOp(setterObject());
|
||||
js::PropertyOp setter() const {
|
||||
return js::CastAsPropertyOp(setterObject());
|
||||
}
|
||||
|
||||
static void traceDescriptorArray(JSTracer* trc, JSObject* obj);
|
||||
static void finalizeDescriptorArray(JSContext* cx, JSObject* obj);
|
||||
|
||||
jsid id;
|
||||
jsval value, get, set;
|
||||
js::Value value, get, set;
|
||||
|
||||
/* Property descriptor boolean fields. */
|
||||
uint8 attrs;
|
||||
|
@ -134,8 +165,6 @@ struct PropertyDescriptor {
|
|||
bool hasConfigurable : 1;
|
||||
};
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/* For detailed comments on these function pointer types, see jsprvtd.h. */
|
||||
struct JSObjectOps {
|
||||
/*
|
||||
|
@ -147,24 +176,24 @@ struct JSObjectOps {
|
|||
|
||||
/* Mandatory non-null function pointer members. */
|
||||
JSLookupPropOp lookupProperty;
|
||||
JSDefinePropOp defineProperty;
|
||||
JSPropertyIdOp getProperty;
|
||||
JSPropertyIdOp setProperty;
|
||||
js::DefinePropOp defineProperty;
|
||||
js::PropertyIdOp getProperty;
|
||||
js::PropertyIdOp setProperty;
|
||||
JSAttributesOp getAttributes;
|
||||
JSAttributesOp setAttributes;
|
||||
JSPropertyIdOp deleteProperty;
|
||||
JSConvertOp defaultValue;
|
||||
JSNewEnumerateOp enumerate;
|
||||
JSCheckAccessIdOp checkAccess;
|
||||
js::PropertyIdOp deleteProperty;
|
||||
js::ConvertOp defaultValue;
|
||||
js::NewEnumerateOp enumerate;
|
||||
js::CheckAccessIdOp checkAccess;
|
||||
JSTypeOfOp typeOf;
|
||||
JSTraceOp trace;
|
||||
|
||||
/* Optionally non-null members start here. */
|
||||
JSObjectOp thisObject;
|
||||
JSPropertyRefOp dropProperty;
|
||||
JSNative call;
|
||||
JSNative construct;
|
||||
JSHasInstanceOp hasInstance;
|
||||
js::Native call;
|
||||
js::Native construct;
|
||||
js::HasInstanceOp hasInstance;
|
||||
JSFinalizeOp clear;
|
||||
|
||||
bool inline isNative() const;
|
||||
|
@ -204,7 +233,7 @@ const uint32 JSSLOT_PARENT = 1;
|
|||
|
||||
/*
|
||||
* The first available slot to store generic value. For JSCLASS_HAS_PRIVATE
|
||||
* classes the slot stores a pointer to private data reinterpreted as jsval.
|
||||
* classes the slot stores a pointer to private data stuffed in a Value.
|
||||
* Such pointer is stored as is without an overhead of PRIVATE_TO_JSVAL
|
||||
* tagging and should be accessed using the (get|set)Private methods of
|
||||
* JSObject.
|
||||
|
@ -213,18 +242,11 @@ const uint32 JSSLOT_PRIVATE = 2;
|
|||
|
||||
const uint32 JSSLOT_PRIMITIVE_THIS = JSSLOT_PRIVATE;
|
||||
|
||||
const uintptr_t JSSLOT_CLASS_MASK_BITS = 3;
|
||||
|
||||
/*
|
||||
* JSObject struct, with members sized to fit in 32 bytes on 32-bit targets,
|
||||
* 64 bytes on 64-bit systems. The JSFunction struct is an extension of this
|
||||
* struct allocated from a larger GC size-class.
|
||||
*
|
||||
* The classword member stores the JSClass pointer for this object, with the
|
||||
* least two bits encoding whether this object is a "delegate" or a "system"
|
||||
* object. We do *not* synchronize updates of classword -- API clients must
|
||||
* take care.
|
||||
*
|
||||
* An object is a delegate if it is on another object's prototype (linked by
|
||||
* JSSLOT_PROTO) or scope (JSSLOT_PARENT) chain, and therefore the delegate
|
||||
* might be asked implicitly to get or set a property on behalf of another
|
||||
|
@ -240,11 +262,11 @@ const uintptr_t JSSLOT_CLASS_MASK_BITS = 3;
|
|||
* to be complementary to this bit, but it is up to the API client to implement
|
||||
* any such association.
|
||||
*
|
||||
* Both these classword tag bits are initially zero; they may be set or queried
|
||||
* using the (is|set)(Delegate|System) inline methods.
|
||||
* Both these flags are initially zero; they may be set or queried using the
|
||||
* (is|set)(Delegate|System) inline methods.
|
||||
*
|
||||
* The dslots member is null or a pointer into a dynamically allocated vector
|
||||
* of jsvals for reserved and dynamic slots. If dslots is not null, dslots[-1]
|
||||
* of Values for reserved and dynamic slots. If dslots is not null, dslots[-1]
|
||||
* records the number of available slots.
|
||||
*/
|
||||
struct JSObject {
|
||||
|
@ -255,29 +277,32 @@ struct JSObject {
|
|||
friend class js::TraceRecorder;
|
||||
|
||||
JSObjectMap *map; /* property map, see jsscope.h */
|
||||
jsuword classword; /* JSClass ptr | bits, see above */
|
||||
jsval fslots[JS_INITIAL_NSLOTS]; /* small number of fixed slots */
|
||||
jsval *dslots; /* dynamically allocated slots */
|
||||
private:
|
||||
js::Class *clasp; /* class pointer */
|
||||
jsuword flags; /* see above */
|
||||
public:
|
||||
js::Value *dslots; /* dynamically allocated slots */
|
||||
js::Value fslots[JS_INITIAL_NSLOTS]; /* small number of fixed slots */
|
||||
|
||||
bool isNative() const { return map->ops->isNative(); }
|
||||
|
||||
JSClass *getClass() const {
|
||||
return (JSClass *) (classword & ~JSSLOT_CLASS_MASK_BITS);
|
||||
js::Class *getClass() const {
|
||||
return clasp;
|
||||
}
|
||||
|
||||
bool hasClass(const JSClass *clasp) const {
|
||||
return clasp == getClass();
|
||||
bool hasClass(const js::Class *c) const {
|
||||
return c == clasp;
|
||||
}
|
||||
|
||||
inline JSScope *scope() const;
|
||||
inline uint32 shape() const;
|
||||
|
||||
bool isDelegate() const {
|
||||
return (classword & jsuword(1)) != jsuword(0);
|
||||
return (flags & jsuword(1)) != jsuword(0);
|
||||
}
|
||||
|
||||
void setDelegate() {
|
||||
classword |= jsuword(1);
|
||||
flags |= jsuword(1);
|
||||
}
|
||||
|
||||
static void setDelegateNullSafe(JSObject *obj) {
|
||||
|
@ -286,42 +311,46 @@ struct JSObject {
|
|||
}
|
||||
|
||||
bool isSystem() const {
|
||||
return (classword & jsuword(2)) != jsuword(0);
|
||||
return (flags & jsuword(2)) != jsuword(0);
|
||||
}
|
||||
|
||||
void setSystem() {
|
||||
classword |= jsuword(2);
|
||||
flags |= jsuword(2);
|
||||
}
|
||||
|
||||
uint32 dslotLength() const {
|
||||
return dslots[-1].asPrivateUint32();
|
||||
}
|
||||
|
||||
uint32 numSlots(void) {
|
||||
return dslots ? (uint32)dslots[-1] : (uint32)JS_INITIAL_NSLOTS;
|
||||
return dslots ? dslotLength() : (uint32)JS_INITIAL_NSLOTS;
|
||||
}
|
||||
|
||||
jsval& getSlotRef(uintN slot) {
|
||||
js::Value& getSlotRef(uintN slot) {
|
||||
return (slot < JS_INITIAL_NSLOTS)
|
||||
? fslots[slot]
|
||||
: (JS_ASSERT(slot < (uint32)dslots[-1]),
|
||||
: (JS_ASSERT(slot < dslotLength()),
|
||||
dslots[slot - JS_INITIAL_NSLOTS]);
|
||||
}
|
||||
|
||||
jsval getSlot(uintN slot) const {
|
||||
const js::Value &getSlot(uintN slot) const {
|
||||
return (slot < JS_INITIAL_NSLOTS)
|
||||
? fslots[slot]
|
||||
: (JS_ASSERT(slot < (uint32)dslots[-1]),
|
||||
: (JS_ASSERT(slot < dslotLength()),
|
||||
dslots[slot - JS_INITIAL_NSLOTS]);
|
||||
}
|
||||
|
||||
void setSlot(uintN slot, jsval value) {
|
||||
void setSlot(uintN slot, const js::Value &value) {
|
||||
if (slot < JS_INITIAL_NSLOTS) {
|
||||
fslots[slot] = value;
|
||||
fslots[slot].copy(value);
|
||||
} else {
|
||||
JS_ASSERT(slot < (uint32)dslots[-1]);
|
||||
dslots[slot - JS_INITIAL_NSLOTS] = value;
|
||||
JS_ASSERT(slot < dslotLength());
|
||||
dslots[slot - JS_INITIAL_NSLOTS].copy(value);
|
||||
}
|
||||
}
|
||||
|
||||
inline jsval lockedGetSlot(uintN slot) const;
|
||||
inline void lockedSetSlot(uintN slot, jsval value);
|
||||
inline const js::Value &lockedGetSlot(uintN slot) const;
|
||||
inline void lockedSetSlot(uintN slot, const js::Value &value);
|
||||
|
||||
/*
|
||||
* These ones are for multi-threaded ("MT") objects. Use getSlot(),
|
||||
|
@ -329,33 +358,41 @@ struct JSObject {
|
|||
* one thread can access obj, or when accessing read-only slots within
|
||||
* JS_INITIAL_NSLOTS.
|
||||
*/
|
||||
inline jsval getSlotMT(JSContext *cx, uintN slot);
|
||||
inline void setSlotMT(JSContext *cx, uintN slot, jsval value);
|
||||
inline const js::Value &getSlotMT(JSContext *cx, uintN slot);
|
||||
inline void setSlotMT(JSContext *cx, uintN slot, const js::Value &value);
|
||||
|
||||
JSObject *getProto() const {
|
||||
return JSVAL_TO_OBJECT(fslots[JSSLOT_PROTO]);
|
||||
return fslots[JSSLOT_PROTO].asObjectOrNull();
|
||||
}
|
||||
|
||||
const js::Value &getProtoValue() const {
|
||||
return fslots[JSSLOT_PROTO];
|
||||
}
|
||||
|
||||
void clearProto() {
|
||||
fslots[JSSLOT_PROTO] = JSVAL_NULL;
|
||||
fslots[JSSLOT_PROTO].setNull();
|
||||
}
|
||||
|
||||
void setProto(JSObject *newProto) {
|
||||
void setProto(js::ObjPtr newProto) {
|
||||
setDelegateNullSafe(newProto);
|
||||
fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(newProto);
|
||||
fslots[JSSLOT_PROTO].copy(newProto);
|
||||
}
|
||||
|
||||
JSObject *getParent() const {
|
||||
return JSVAL_TO_OBJECT(fslots[JSSLOT_PARENT]);
|
||||
return fslots[JSSLOT_PARENT].asObjectOrNull();
|
||||
}
|
||||
|
||||
const js::Value &getParentValue() const {
|
||||
return fslots[JSSLOT_PARENT];
|
||||
}
|
||||
|
||||
void clearParent() {
|
||||
fslots[JSSLOT_PARENT] = JSVAL_NULL;
|
||||
fslots[JSSLOT_PARENT].setNull();
|
||||
}
|
||||
|
||||
void setParent(JSObject *newParent) {
|
||||
setDelegateNullSafe(newParent);
|
||||
fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(newParent);
|
||||
fslots[JSSLOT_PARENT].setNonFunObjOrNull(newParent);
|
||||
}
|
||||
|
||||
void traceProtoAndParent(JSTracer *trc) const {
|
||||
|
@ -372,22 +409,21 @@ struct JSObject {
|
|||
|
||||
void *getPrivate() const {
|
||||
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
|
||||
jsval v = fslots[JSSLOT_PRIVATE];
|
||||
JS_ASSERT((v & jsval(1)) == jsval(0));
|
||||
return reinterpret_cast<void *>(v);
|
||||
void *priv = fslots[JSSLOT_PRIVATE].asPrivateVoidPtr();
|
||||
JS_ASSERT((size_t(priv) & 1) == 0);
|
||||
return priv;
|
||||
}
|
||||
|
||||
void setPrivate(void *data) {
|
||||
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
|
||||
jsval v = reinterpret_cast<jsval>(data);
|
||||
JS_ASSERT((v & jsval(1)) == jsval(0));
|
||||
fslots[JSSLOT_PRIVATE] = v;
|
||||
JS_ASSERT((size_t(data) & 1) == 0);
|
||||
fslots[JSSLOT_PRIVATE].setPrivateVoidPtr(data);
|
||||
}
|
||||
|
||||
static jsval defaultPrivate(JSClass *clasp) {
|
||||
static const js::Value &defaultPrivate(js::Class *clasp) {
|
||||
return (clasp->flags & JSCLASS_HAS_PRIVATE)
|
||||
? JSVAL_NULL
|
||||
: JSVAL_VOID;
|
||||
? js::sNullValue
|
||||
: js::sUndefinedValue;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -413,7 +449,6 @@ struct JSObject {
|
|||
inline void voidDenseArrayCount();
|
||||
inline void incArrayCountBy(uint32 posDelta);
|
||||
inline void decArrayCountBy(uint32 negDelta);
|
||||
inline void voidArrayUnused();
|
||||
|
||||
/*
|
||||
* Back to generic stuff.
|
||||
|
@ -422,22 +457,22 @@ struct JSObject {
|
|||
bool isCallable();
|
||||
|
||||
/* The map field is not initialized here and should be set separately. */
|
||||
void init(JSClass *clasp, JSObject *proto, JSObject *parent,
|
||||
jsval privateSlotValue) {
|
||||
void init(js::Class *c, js::ObjPtr proto, JSObject *parent,
|
||||
const js::Value &privateSlotValue) {
|
||||
JS_ASSERT(((jsuword) clasp & 3) == 0);
|
||||
JS_STATIC_ASSERT(JSSLOT_PRIVATE + 3 == JS_INITIAL_NSLOTS);
|
||||
JS_ASSERT_IF(clasp->flags & JSCLASS_HAS_PRIVATE,
|
||||
(privateSlotValue & jsval(1)) == jsval(0));
|
||||
(size_t(privateSlotValue.asPrivateVoidPtr()) & 1) == 0);
|
||||
|
||||
classword = jsuword(clasp);
|
||||
clasp = c;
|
||||
JS_ASSERT(!isDelegate());
|
||||
JS_ASSERT(!isSystem());
|
||||
|
||||
setProto(proto);
|
||||
setParent(parent);
|
||||
fslots[JSSLOT_PRIVATE] = privateSlotValue;
|
||||
fslots[JSSLOT_PRIVATE + 1] = JSVAL_VOID;
|
||||
fslots[JSSLOT_PRIVATE + 2] = JSVAL_VOID;
|
||||
fslots[JSSLOT_PRIVATE].copy(privateSlotValue);
|
||||
fslots[JSSLOT_PRIVATE + 1].setUndefined();
|
||||
fslots[JSSLOT_PRIVATE + 2].setUndefined();
|
||||
dslots = NULL;
|
||||
}
|
||||
|
||||
|
@ -445,8 +480,9 @@ struct JSObject {
|
|||
* Like init, but also initializes map. The catch: proto must be the result
|
||||
* of a call to js_InitClass(...clasp, ...).
|
||||
*/
|
||||
inline void initSharingEmptyScope(JSClass *clasp, JSObject *proto, JSObject *parent,
|
||||
jsval privateSlotValue);
|
||||
inline void initSharingEmptyScope(js::Class *clasp,
|
||||
js::ObjPtr proto, JSObject *parent,
|
||||
const js::Value &privateSlotValue);
|
||||
|
||||
inline bool hasSlotsArray() const { return !!dslots; }
|
||||
|
||||
|
@ -458,18 +494,18 @@ struct JSObject {
|
|||
return map->ops->lookupProperty(cx, this, id, objp, propp);
|
||||
}
|
||||
|
||||
JSBool defineProperty(JSContext *cx, jsid id, jsval value,
|
||||
JSPropertyOp getter = JS_PropertyStub,
|
||||
JSPropertyOp setter = JS_PropertyStub,
|
||||
JSBool defineProperty(JSContext *cx, jsid id, const js::Value &value,
|
||||
js::PropertyOp getter = js::PropertyStub,
|
||||
js::PropertyOp setter = js::PropertyStub,
|
||||
uintN attrs = JSPROP_ENUMERATE) {
|
||||
return map->ops->defineProperty(cx, this, id, value, getter, setter, attrs);
|
||||
return map->ops->defineProperty(cx, this, id, &value, getter, setter, attrs);
|
||||
}
|
||||
|
||||
JSBool getProperty(JSContext *cx, jsid id, jsval *vp) {
|
||||
JSBool getProperty(JSContext *cx, jsid id, js::Value *vp) {
|
||||
return map->ops->getProperty(cx, this, id, vp);
|
||||
}
|
||||
|
||||
JSBool setProperty(JSContext *cx, jsid id, jsval *vp) {
|
||||
JSBool setProperty(JSContext *cx, jsid id, js::Value *vp) {
|
||||
return map->ops->setProperty(cx, this, id, vp);
|
||||
}
|
||||
|
||||
|
@ -483,20 +519,20 @@ struct JSObject {
|
|||
return map->ops->setAttributes(cx, this, id, prop, attrsp);
|
||||
}
|
||||
|
||||
JSBool deleteProperty(JSContext *cx, jsid id, jsval *rval) {
|
||||
JSBool deleteProperty(JSContext *cx, jsid id, js::Value *rval) {
|
||||
return map->ops->deleteProperty(cx, this, id, rval);
|
||||
}
|
||||
|
||||
JSBool defaultValue(JSContext *cx, JSType hint, jsval *vp) {
|
||||
JSBool defaultValue(JSContext *cx, JSType hint, js::Value *vp) {
|
||||
return map->ops->defaultValue(cx, this, hint, vp);
|
||||
}
|
||||
|
||||
JSBool enumerate(JSContext *cx, JSIterateOp op, jsval *statep,
|
||||
JSBool enumerate(JSContext *cx, JSIterateOp op, js::Value *statep,
|
||||
jsid *idp) {
|
||||
return map->ops->enumerate(cx, this, op, statep, idp);
|
||||
}
|
||||
|
||||
JSBool checkAccess(JSContext *cx, jsid id, JSAccessMode mode, jsval *vp,
|
||||
JSBool checkAccess(JSContext *cx, jsid id, JSAccessMode mode, js::Value *vp,
|
||||
uintN *attrsp) {
|
||||
return map->ops->checkAccess(cx, this, id, mode, vp, attrsp);
|
||||
}
|
||||
|
@ -505,10 +541,8 @@ struct JSObject {
|
|||
return map->ops->typeOf(cx, this);
|
||||
}
|
||||
|
||||
/* These four are time-optimized to avoid stub calls. */
|
||||
JSObject *thisObject(JSContext *cx) {
|
||||
return map->ops->thisObject ? map->ops->thisObject(cx, this) : this;
|
||||
}
|
||||
inline JSObject *thisObject(JSContext *cx);
|
||||
static inline js::ObjPtr thisObject(JSContext *cx, js::ObjPtr obj);
|
||||
|
||||
void dropProperty(JSContext *cx, JSProperty *prop) {
|
||||
if (map->ops->dropProperty)
|
||||
|
@ -524,6 +558,10 @@ struct JSObject {
|
|||
inline bool isXML() const;
|
||||
|
||||
inline bool unbrand(JSContext *cx);
|
||||
|
||||
inline void initArrayClass();
|
||||
inline void changeClassToSlowArray();
|
||||
inline void changeClassToFastArray();
|
||||
};
|
||||
|
||||
#define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \
|
||||
|
@ -538,8 +576,8 @@ struct JSObject {
|
|||
* obj->dslots[-1] that is used to store the length of the vector biased by
|
||||
* JS_INITIAL_NSLOTS (and again net of the slot at index -1).
|
||||
*/
|
||||
#define MAX_DSLOTS_LENGTH (JS_MAX(~uint32(0), ~size_t(0)) / sizeof(jsval) - 1)
|
||||
#define MAX_DSLOTS_LENGTH32 (~uint32(0) / sizeof(jsval) - 1)
|
||||
#define MAX_DSLOTS_LENGTH (JS_MAX(~uint32(0), ~size_t(0)) / sizeof(js::Value) - 1)
|
||||
#define MAX_DSLOTS_LENGTH32 (~uint32(0) / sizeof(js::Value) - 1)
|
||||
|
||||
#define OBJ_CHECK_SLOT(obj,slot) \
|
||||
(JS_ASSERT((obj)->isNative()), JS_ASSERT(slot < (obj)->scope()->freeslot))
|
||||
|
@ -559,37 +597,22 @@ struct JSObject {
|
|||
|
||||
#endif /* JS_THREADSAFE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* N.B. There is a corresponding OBJ_TO_OUTER_OBJ in jsd/jsd_val.c. */
|
||||
inline void
|
||||
OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj)
|
||||
Innerize(JSContext *cx, JSObject **ppobj)
|
||||
{
|
||||
JSClass *clasp = obj->getClass();
|
||||
JSObject *pobj = *ppobj;
|
||||
js::Class *clasp = pobj->getClass();
|
||||
if (clasp->flags & JSCLASS_IS_EXTENDED) {
|
||||
JSExtendedClass *xclasp = (JSExtendedClass *) clasp;
|
||||
if (xclasp->innerObject)
|
||||
obj = xclasp->innerObject(cx, obj);
|
||||
*ppobj = xclasp->innerObject(cx, pobj);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function has been copied to jsd/jsd_val.c. If making changes to
|
||||
* OBJ_TO_OUTER_OBJECT, please update jsd/jsd_val.c as well.
|
||||
*/
|
||||
inline void
|
||||
OBJ_TO_OUTER_OBJECT(JSContext *cx, JSObject *&obj)
|
||||
{
|
||||
JSClass *clasp = obj->getClass();
|
||||
if (clasp->flags & JSCLASS_IS_EXTENDED) {
|
||||
JSExtendedClass *xclasp = (JSExtendedClass *) clasp;
|
||||
if (xclasp->outerObject)
|
||||
obj = xclasp->outerObject(cx, obj);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
extern JSClass js_ObjectClass;
|
||||
extern JSClass js_WithClass;
|
||||
extern JSClass js_BlockClass;
|
||||
extern js::Class js_ObjectClass;
|
||||
extern js::Class js_WithClass;
|
||||
extern js::Class js_BlockClass;
|
||||
|
||||
/*
|
||||
* Block scope object macros. The slots reserved by js_BlockClass are:
|
||||
|
@ -620,9 +643,9 @@ js_DefineBlockVariable(JSContext *cx, JSObject *obj, jsid id, intN index);
|
|||
#define OBJ_BLOCK_COUNT(cx,obj) \
|
||||
((OBJ_IS_CLONED_BLOCK(obj) ? obj->getProto() : obj)->scope()->entryCount)
|
||||
#define OBJ_BLOCK_DEPTH(cx,obj) \
|
||||
JSVAL_TO_INT(obj->getSlot(JSSLOT_BLOCK_DEPTH))
|
||||
obj->getSlot(JSSLOT_BLOCK_DEPTH).asInt32()
|
||||
#define OBJ_SET_BLOCK_DEPTH(cx,obj,depth) \
|
||||
obj->setSlot(JSSLOT_BLOCK_DEPTH, INT_TO_JSVAL(depth))
|
||||
obj->setSlot(JSSLOT_BLOCK_DEPTH, Value((int32_t)depth))
|
||||
|
||||
/*
|
||||
* To make sure this slot is well-defined, always call js_NewWithObject to
|
||||
|
@ -684,14 +707,14 @@ js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map);
|
|||
|
||||
extern JSBool
|
||||
js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc,
|
||||
jsval *vp);
|
||||
js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
|
||||
JSObject **objp, JSProperty **propp);
|
||||
|
||||
extern JSBool
|
||||
js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSObject *
|
||||
js_InitEval(JSContext *cx, JSObject *obj);
|
||||
|
@ -701,7 +724,7 @@ js_InitObjectClass(JSContext *cx, JSObject *obj);
|
|||
|
||||
extern JSObject *
|
||||
js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
JSClass *clasp, JSNative constructor, uintN nargs,
|
||||
js::Class *clasp, js::Native constructor, uintN nargs,
|
||||
JSPropertySpec *ps, JSFunctionSpec *fs,
|
||||
JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
|
||||
|
||||
|
@ -719,14 +742,14 @@ extern const char js_lookupGetter_str[];
|
|||
extern const char js_lookupSetter_str[];
|
||||
|
||||
extern JSObject *
|
||||
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JSObject *parent, size_t objectSize = 0);
|
||||
js_NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
|
||||
size_t objectSize = 0);
|
||||
|
||||
/*
|
||||
* See jsapi.h, JS_NewObjectWithGivenProto.
|
||||
*/
|
||||
extern JSObject *
|
||||
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
js_NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto,
|
||||
JSObject *parent, size_t objectSize = 0);
|
||||
|
||||
/*
|
||||
|
@ -742,8 +765,8 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
* object, not by the parent of its .prototype object value.
|
||||
*/
|
||||
extern JSObject*
|
||||
js_NewObjectWithClassProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
jsval privateSlotValue);
|
||||
js_NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto,
|
||||
const js::Value &privateSlotValue);
|
||||
|
||||
/*
|
||||
* Fast access to immutable standard objects (constructors and prototypes).
|
||||
|
@ -753,19 +776,20 @@ js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
|
|||
JSObject **objp);
|
||||
|
||||
extern JSBool
|
||||
js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject *cobj);
|
||||
js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
|
||||
JSObject *cobj);
|
||||
|
||||
/*
|
||||
* If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
|
||||
* JSProto_Null, clasp must non-null.
|
||||
*/
|
||||
extern JSBool
|
||||
js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey key, jsval *vp,
|
||||
JSClass *clasp = NULL);
|
||||
js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey key,
|
||||
js::Value *vp, js::Class *clasp = NULL);
|
||||
|
||||
extern JSObject *
|
||||
js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JSObject *parent, uintN argc, jsval *argv);
|
||||
js_ConstructObject(JSContext *cx, js::Class *clasp, JSObject *proto,
|
||||
JSObject *parent, uintN argc, js::Value *argv);
|
||||
|
||||
extern JSBool
|
||||
js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp);
|
||||
|
@ -784,7 +808,7 @@ js_ShrinkSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
|||
* slots. The function can be called only for native objects just created with
|
||||
* js_NewObject or its forms. In particular, the object should not be shared
|
||||
* between threads and its dslots array must be null. nreserved must match the
|
||||
* value that JSClass.reserveSlots (if any) would return after the object is
|
||||
* value that Class.reserveSlots (if any) would return after the object is
|
||||
* fully initialized.
|
||||
*/
|
||||
bool
|
||||
|
@ -817,7 +841,7 @@ js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
|
|||
*/
|
||||
extern JSScopeProperty *
|
||||
js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
|
||||
js::PropertyOp getter, js::PropertyOp setter, uint32 slot,
|
||||
uintN attrs, uintN flags, intN shortid);
|
||||
|
||||
/*
|
||||
|
@ -828,14 +852,15 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
|
|||
extern JSScopeProperty *
|
||||
js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
|
||||
JSScopeProperty *sprop, uintN attrs, uintN mask,
|
||||
JSPropertyOp getter, JSPropertyOp setter);
|
||||
js::PropertyOp getter, js::PropertyOp setter);
|
||||
|
||||
extern JSBool
|
||||
js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
|
||||
js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
|
||||
js::PropertyOp getter, js::PropertyOp setter, uintN attrs);
|
||||
|
||||
extern JSBool
|
||||
js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, JSBool *bp);
|
||||
js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
const js::Value &descriptor, JSBool *bp);
|
||||
|
||||
/*
|
||||
* Flags for the defineHow parameter of js_DefineNativeProperty.
|
||||
|
@ -854,8 +879,8 @@ const uintN JSDNP_SET_METHOD = 4; /* js_{DefineNativeProperty,SetPropertyHelpe
|
|||
* the held property, and to release the lock on obj.
|
||||
*/
|
||||
extern JSBool
|
||||
js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
|
||||
js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value &value,
|
||||
js::PropertyOp getter, js::PropertyOp setter, uintN attrs,
|
||||
uintN flags, intN shortid, JSProperty **propp,
|
||||
uintN defineHow = 0);
|
||||
|
||||
|
@ -888,11 +913,11 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
|||
static inline bool
|
||||
js_IsCacheableNonGlobalScope(JSObject *obj)
|
||||
{
|
||||
extern JS_FRIEND_DATA(JSClass) js_CallClass;
|
||||
extern JS_FRIEND_DATA(JSClass) js_DeclEnvClass;
|
||||
extern JS_FRIEND_DATA(js::Class) js_CallClass;
|
||||
extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
|
||||
JS_ASSERT(obj->getParent());
|
||||
|
||||
JSClass *clasp = obj->getClass();
|
||||
js::Class *clasp = obj->getClass();
|
||||
bool cacheable = (clasp == &js_CallClass ||
|
||||
clasp == &js_BlockClass ||
|
||||
clasp == &js_DeclEnvClass);
|
||||
|
@ -947,24 +972,24 @@ const uintN JSGET_NO_METHOD_BARRIER = 2; // call to joined function can't leak
|
|||
*/
|
||||
extern JSBool
|
||||
js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
|
||||
JSScopeProperty *sprop, uintN getHow, jsval *vp);
|
||||
JSScopeProperty *sprop, uintN getHow, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added,
|
||||
jsval *vp);
|
||||
js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN getHow,
|
||||
jsval *vp);
|
||||
js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, jsval *vp);
|
||||
js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, js::Value *vp);
|
||||
|
||||
/*
|
||||
* Check whether it is OK to assign an undeclared property of the global
|
||||
|
@ -975,10 +1000,10 @@ js_CheckUndeclaredVarAssignment(JSContext *cx);
|
|||
|
||||
extern JSBool
|
||||
js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
|
||||
jsval *vp);
|
||||
js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
|
||||
|
@ -989,44 +1014,45 @@ js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
|
|||
uintN *attrsp);
|
||||
|
||||
extern JSBool
|
||||
js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval);
|
||||
js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *rval);
|
||||
|
||||
extern JSBool
|
||||
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
|
||||
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp);
|
||||
js::Value *statep, jsid *idp);
|
||||
|
||||
extern void
|
||||
js_MarkEnumeratorState(JSTracer *trc, JSObject *obj, jsval state);
|
||||
js_MarkEnumeratorState(JSTracer *trc, JSObject *obj, const js::Value &v);
|
||||
|
||||
extern void
|
||||
js_PurgeCachedNativeEnumerators(JSContext *cx, JSThreadData *data);
|
||||
|
||||
extern JSBool
|
||||
js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
jsval *vp, uintN *attrsp);
|
||||
js::Value *vp, uintN *attrsp);
|
||||
|
||||
extern JSType
|
||||
js_TypeOf(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
js_Call(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
|
||||
js::Value *rval);
|
||||
|
||||
extern JSBool
|
||||
js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
js_Construct(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
|
||||
js::Value *rval);
|
||||
|
||||
extern JSBool
|
||||
js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
js_HasInstance(JSContext *cx, JSObject *obj, const js::Value *v, JSBool *bp);
|
||||
|
||||
extern JSBool
|
||||
js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
|
||||
JSBool checkForCycles);
|
||||
|
||||
extern JSBool
|
||||
js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
extern bool
|
||||
js_IsDelegate(JSContext *cx, JSObject *obj, const js::Value &v);
|
||||
|
||||
/*
|
||||
* If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
|
||||
|
@ -1034,7 +1060,7 @@ js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
|||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey,
|
||||
JSObject **protop, JSClass *clasp = NULL);
|
||||
JSObject **protop, js::Class *clasp = NULL);
|
||||
|
||||
extern JSBool
|
||||
js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
|
||||
|
@ -1045,20 +1071,28 @@ js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
|
|||
* *vp must not be an object, null or undefined.
|
||||
*/
|
||||
extern JSBool
|
||||
js_PrimitiveToObject(JSContext *cx, jsval *vp);
|
||||
js_PrimitiveToObject(JSContext *cx, js::Value *vp);
|
||||
|
||||
/*
|
||||
* v and vp may alias. On successful return, vp->isObjectOrNull(). If vp is not
|
||||
* rooted, the caller must root vp before the next possible GC.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ValueToObjectOrNull(JSContext *cx, const js::Value &v, js::Value *vp);
|
||||
|
||||
/*
|
||||
* v and vp may alias. On successful return, vp->isObject(). If vp is not
|
||||
* rooted, the caller must root vp before the next possible GC.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ValueToNonNullObject(JSContext *cx, const js::Value &v, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
|
||||
|
||||
extern JSObject *
|
||||
js_ValueToNonNullObject(JSContext *cx, jsval v);
|
||||
|
||||
extern JSBool
|
||||
js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval);
|
||||
js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, js::Value *rval);
|
||||
|
||||
extern JSBool
|
||||
js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
|
||||
uintN argc, jsval *argv, jsval *rval);
|
||||
uintN argc, js::Value *argv, js::Value *rval);
|
||||
|
||||
extern JSBool
|
||||
js_XDRObject(JSXDRState *xdr, JSObject **objp);
|
||||
|
@ -1082,10 +1116,10 @@ js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop);
|
|||
#endif
|
||||
|
||||
extern bool
|
||||
js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp);
|
||||
js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, js::Value *vp);
|
||||
|
||||
bool
|
||||
js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v);
|
||||
js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, const js::Value &v);
|
||||
|
||||
/*
|
||||
* Precondition: obj must be locked.
|
||||
|
@ -1115,24 +1149,26 @@ js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
|
|||
JSPrincipals *principals, uintN *linenop);
|
||||
|
||||
static inline bool
|
||||
js_IsCallable(jsval v) {
|
||||
return !JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isCallable();
|
||||
js_IsCallable(const js::Value &v) {
|
||||
return v.isObject() && v.asObject().isCallable();
|
||||
}
|
||||
|
||||
extern JSBool
|
||||
js_ReportGetterOnlyAssignment(JSContext *cx);
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_FRIEND_API(void) js_DumpChars(const jschar *s, size_t n);
|
||||
JS_FRIEND_API(void) js_DumpString(JSString *str);
|
||||
JS_FRIEND_API(void) js_DumpAtom(JSAtom *atom);
|
||||
JS_FRIEND_API(void) js_DumpValue(jsval val);
|
||||
JS_FRIEND_API(void) js_DumpId(jsid id);
|
||||
JS_FRIEND_API(void) js_DumpObject(JSObject *obj);
|
||||
JS_FRIEND_API(void) js_DumpStackFrameChain(JSContext *cx, JSStackFrame *start = NULL);
|
||||
namespace js {
|
||||
JS_FRIEND_API(void) DumpChars(const jschar *s, size_t n);
|
||||
JS_FRIEND_API(void) DumpString(JSString *str);
|
||||
JS_FRIEND_API(void) DumpAtom(JSAtom *atom);
|
||||
JS_FRIEND_API(void) DumpValue(const js::Value &val);
|
||||
JS_FRIEND_API(void) DumpId(jsid id);
|
||||
JS_FRIEND_API(void) DumpObject(JSObject *obj);
|
||||
JS_FRIEND_API(void) DumpStackFrameChain(JSContext *cx, JSStackFrame *start = NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern uintN
|
||||
|
@ -1140,8 +1176,23 @@ js_InferFlags(JSContext *cx, uintN defaultFlags);
|
|||
|
||||
/* Object constructor native. Exposed only so the JIT can know its address. */
|
||||
JSBool
|
||||
js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
js_Object(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Convenience functions for manipulating objects and values. To be inlined,
|
||||
* these functions need to be in jsobj.h, so they cannot be member functions.
|
||||
*/
|
||||
|
||||
JS_ALWAYS_INLINE ObjPtr ToObjPtr(JSObject *pobj);
|
||||
JS_ALWAYS_INLINE ObjPtr ToObjPtr(JSObject &obj);
|
||||
JS_ALWAYS_INLINE Value ToValue(JSObject *pobj);
|
||||
JS_ALWAYS_INLINE Value ToValue(JSObject &obj);
|
||||
JS_ALWAYS_INLINE void SetObject(ObjPtr *vp, JSObject *pobj);
|
||||
JS_ALWAYS_INLINE void SetObject(Value *vp, JSObject *pobj);
|
||||
JS_ALWAYS_INLINE void SetObject(ObjPtr *vp, JSObject &obj);
|
||||
JS_ALWAYS_INLINE void SetObject(Value *vp, JSObject &obj);
|
||||
|
||||
} /* namespace js */
|
||||
#endif /* jsobj_h___ */
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#include "jsobj.h"
|
||||
#include "jsscope.h"
|
||||
|
||||
inline jsval
|
||||
inline const js::Value &
|
||||
JSObject::getSlotMT(JSContext *cx, uintN slot)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
|
@ -54,7 +54,7 @@ JSObject::getSlotMT(JSContext *cx, uintN slot)
|
|||
* (obj->scope()->ownercx == cx), to avoid needlessly switching from
|
||||
* lock-free to lock-full scope when doing GC on a different context
|
||||
* from the last one to own the scope. The caller in this case is
|
||||
* probably a JSClass.mark function, e.g., fun_mark, or maybe a
|
||||
* probably a Class.mark function, e.g., fun_mark, or maybe a
|
||||
* finalizer.
|
||||
*/
|
||||
OBJ_CHECK_SLOT(this, slot);
|
||||
|
@ -67,7 +67,7 @@ JSObject::getSlotMT(JSContext *cx, uintN slot)
|
|||
}
|
||||
|
||||
inline void
|
||||
JSObject::setSlotMT(JSContext *cx, uintN slot, jsval value)
|
||||
JSObject::setSlotMT(JSContext *cx, uintN slot, const js::Value &value)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Thread-safe way to set a slot. */
|
||||
|
@ -90,61 +90,55 @@ inline uint32
|
|||
JSObject::getArrayLength() const
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
return uint32(fslots[JSSLOT_ARRAY_LENGTH]);
|
||||
return fslots[JSSLOT_ARRAY_LENGTH].asPrivateUint32();
|
||||
}
|
||||
|
||||
inline uint32
|
||||
JSObject::getArrayCount() const
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
return uint32(fslots[JSSLOT_ARRAY_COUNT]);
|
||||
return fslots[JSSLOT_ARRAY_COUNT].asPrivateUint32();
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setArrayLength(uint32 length)
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_LENGTH] = length;
|
||||
fslots[JSSLOT_ARRAY_LENGTH].setPrivateUint32(length);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setArrayCount(uint32 count)
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] = count;
|
||||
fslots[JSSLOT_ARRAY_COUNT].setPrivateUint32(count);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::voidDenseArrayCount()
|
||||
{
|
||||
JS_ASSERT(isDenseArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID;
|
||||
fslots[JSSLOT_ARRAY_COUNT].setUndefined();
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::incArrayCountBy(uint32 posDelta)
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] += posDelta;
|
||||
fslots[JSSLOT_ARRAY_COUNT].asPrivateUint32Ref() += posDelta;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::decArrayCountBy(uint32 negDelta)
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] -= negDelta;
|
||||
fslots[JSSLOT_ARRAY_COUNT].asPrivateUint32Ref() -= negDelta;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::voidArrayUnused()
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initSharingEmptyScope(JSClass *clasp, JSObject *proto, JSObject *parent,
|
||||
jsval privateSlotValue)
|
||||
JSObject::initSharingEmptyScope(js::Class *clasp,
|
||||
js::ObjPtr proto, JSObject *parent,
|
||||
const js::Value &privateSlotValue)
|
||||
{
|
||||
init(clasp, proto, parent, privateSlotValue);
|
||||
|
||||
|
@ -158,7 +152,7 @@ inline void
|
|||
JSObject::freeSlotsArray(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(hasSlotsArray());
|
||||
JS_ASSERT(size_t(dslots[-1]) > JS_INITIAL_NSLOTS);
|
||||
JS_ASSERT(dslotLength() > JS_INITIAL_NSLOTS);
|
||||
cx->free(dslots - 1);
|
||||
}
|
||||
|
||||
|
@ -181,6 +175,46 @@ JSObject::unbrand(JSContext *cx)
|
|||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initArrayClass()
|
||||
{
|
||||
clasp = &js_ArrayClass;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::changeClassToSlowArray()
|
||||
{
|
||||
JS_ASSERT(clasp == &js_ArrayClass);
|
||||
clasp = &js_SlowArrayClass;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::changeClassToFastArray()
|
||||
{
|
||||
JS_ASSERT(clasp == &js_SlowArrayClass);
|
||||
clasp = &js_ArrayClass;
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSObject::thisObject(JSContext *cx)
|
||||
{
|
||||
if (JSObjectOp thisOp = map->ops->thisObject)
|
||||
return thisOp(cx, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
inline js::ObjPtr
|
||||
JSObject::thisObject(JSContext *cx, js::ObjPtr obj)
|
||||
{
|
||||
if (JSObjectOp thisOp = obj->map->ops->thisObject) {
|
||||
JSObject *o = thisOp(cx, obj);
|
||||
if (!o)
|
||||
return js::NullObjPtr();
|
||||
SetObject(&obj, *o);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
typedef Vector<PropertyDescriptor, 1> PropertyDescriptorArray;
|
||||
|
@ -209,6 +243,82 @@ class AutoDescriptorArray : private AutoGCRooter
|
|||
PropertyDescriptorArray descriptors;
|
||||
};
|
||||
|
||||
JS_ALWAYS_INLINE ObjPtr
|
||||
ToObjPtr(JSObject *pobj)
|
||||
{
|
||||
if (pobj)
|
||||
return NullObjPtr();
|
||||
if (pobj->isFunction())
|
||||
return FunObjPtr(*pobj);
|
||||
return NonFunObjPtr(*pobj);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE ObjPtr
|
||||
ToObjPtr(JSObject &obj)
|
||||
{
|
||||
if (obj.isFunction())
|
||||
return FunObjPtr(obj);
|
||||
return NonFunObjPtr(obj);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE Value
|
||||
ToValue(JSObject *pobj)
|
||||
{
|
||||
if (pobj)
|
||||
return NullValue();
|
||||
if (pobj->isFunction())
|
||||
return FunObjValue(*pobj);
|
||||
return NonFunObjValue(*pobj);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE Value
|
||||
ToValue(JSObject &obj)
|
||||
{
|
||||
if (obj.isFunction())
|
||||
return FunObjValue(obj);
|
||||
return NonFunObjValue(obj);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE void
|
||||
SetObject(ObjPtr *vp, JSObject *pobj)
|
||||
{
|
||||
if (!pobj)
|
||||
vp->setNull();
|
||||
else if (pobj->isFunction())
|
||||
vp->setFunObj(*pobj);
|
||||
else
|
||||
vp->setNonFunObj(*pobj);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE void
|
||||
SetObject(Value *vp, JSObject *pobj)
|
||||
{
|
||||
if (!pobj)
|
||||
vp->setNull();
|
||||
if (pobj->isFunction())
|
||||
vp->setFunObj(*pobj);
|
||||
else
|
||||
vp->setNonFunObj(*pobj);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE void
|
||||
SetObject(ObjPtr *vp, JSObject &obj)
|
||||
{
|
||||
if (obj.isFunction())
|
||||
vp->setFunObj(obj);
|
||||
else
|
||||
vp->setNonFunObj(obj);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE void
|
||||
SetObject(Value *vp, JSObject &obj)
|
||||
{
|
||||
if (obj.isFunction())
|
||||
vp->setFunObj(obj);
|
||||
else
|
||||
vp->setNonFunObj(obj);
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsobjinlines_h___ */
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSClass js_JSONClass;
|
||||
extern js::Class js_JSONClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitJSONClass(JSContext *cx, JSObject *obj);
|
||||
|
|
|
@ -100,7 +100,7 @@ typedef enum JSOp {
|
|||
#define JOF_INCDEC (3U<<10) /* increment or decrement opcode */
|
||||
#define JOF_POST (1U<<12) /* postorder increment or decrement */
|
||||
#define JOF_FOR (1U<<13) /* for-in property op (akin to JOF_SET) */
|
||||
#define JOF_ASSIGNING JOF_SET /* hint for JSClass.resolve, used for ops
|
||||
#define JOF_ASSIGNING JOF_SET /* hint for Class.resolve, used for ops
|
||||
that do simplex assignment */
|
||||
#define JOF_DETECTING (1U<<14) /* object detection for JSNewResolveOp */
|
||||
#define JOF_BACKPATCH (1U<<15) /* backpatch placeholder during codegen */
|
||||
|
@ -457,7 +457,7 @@ js_DecompileToString(JSContext *cx, const char *name, JSFunction *fun,
|
|||
* The caller must call JS_free on the result after a succsesful call.
|
||||
*/
|
||||
extern char *
|
||||
js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
|
||||
js_DecompileValueGenerator(JSContext *cx, intN spindex, const jsval *v,
|
||||
JSString *fallback);
|
||||
|
||||
#define JSDVG_IGNORE_STACK 0
|
||||
|
|
2534
js/src/jsops.cpp
2534
js/src/jsops.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -760,7 +760,6 @@ JSCompiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *cal
|
|||
JSString *source /* = NULL */,
|
||||
unsigned staticLevel /* = 0 */)
|
||||
{
|
||||
JSCompiler jsc(cx, principals, callerFrame);
|
||||
JSArenaPool codePool, notePool;
|
||||
TokenKind tt;
|
||||
JSParseNode *pn;
|
||||
|
@ -780,6 +779,7 @@ JSCompiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *cal
|
|||
JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO);
|
||||
JS_ASSERT_IF(staticLevel != 0, callerFrame);
|
||||
|
||||
JSCompiler jsc(cx, principals, callerFrame);
|
||||
if (!jsc.init(chars, length, file, filename, lineno))
|
||||
return NULL;
|
||||
|
||||
|
@ -789,6 +789,8 @@ JSCompiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *cal
|
|||
&cx->scriptStackQuota);
|
||||
|
||||
JSCodeGenerator cg(&jsc, &codePool, ¬ePool, jsc.tokenStream.getLineno());
|
||||
if (!cg.init())
|
||||
return NULL;
|
||||
|
||||
MUST_FLOW_THROUGH("out");
|
||||
|
||||
|
@ -1561,6 +1563,9 @@ JSCompiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *pr
|
|||
&cx->scriptStackQuota);
|
||||
|
||||
JSCodeGenerator funcg(&jsc, &codePool, ¬ePool, jsc.tokenStream.getLineno());
|
||||
if (!funcg.init())
|
||||
return NULL;
|
||||
|
||||
funcg.flags |= TCF_IN_FUNCTION;
|
||||
funcg.fun = fun;
|
||||
if (!GenerateBlockId(&funcg, funcg.bodyid))
|
||||
|
|
|
@ -320,7 +320,7 @@ struct JSParseNode {
|
|||
struct { /* two kids if binary */
|
||||
JSParseNode *left;
|
||||
JSParseNode *right;
|
||||
jsval val; /* switch case value */
|
||||
jsboxedword val; /* switch case value */
|
||||
uintN iflags; /* JSITER_* flags for TOK_FOR node */
|
||||
} binary;
|
||||
struct { /* one kid if unary */
|
||||
|
|
|
@ -94,10 +94,9 @@ class PCVal
|
|||
bool isNull() const { return v == 0; }
|
||||
void setNull() { v = 0; }
|
||||
|
||||
bool isObject() const { return (v & TAG) == OBJECT; }
|
||||
JSObject *toObject() const { JS_ASSERT(isObject()); return reinterpret_cast<JSObject *>(v); }
|
||||
jsval toJsval() const { return OBJECT_TO_JSVAL(toObject()); }
|
||||
void setObject(JSObject *obj) { v = reinterpret_cast<jsuword>(obj); }
|
||||
bool isFunObj() const { return (v & TAG) == OBJECT; }
|
||||
JSObject &toFunObj() const { JS_ASSERT(isFunObj()); return *reinterpret_cast<JSObject *>(v); }
|
||||
void setFunObj(JSObject &obj) { v = reinterpret_cast<jsuword>(&obj); }
|
||||
|
||||
bool isSlot() const { return v & SLOT; }
|
||||
uint32 toSlot() const { JS_ASSERT(isSlot()); return uint32(v) >> 1; }
|
||||
|
|
105
js/src/jsprvtd.h
105
js/src/jsprvtd.h
|
@ -57,26 +57,6 @@
|
|||
#include "jspubtd.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
/* Internal identifier (jsid) macros. */
|
||||
|
||||
#define JSID_IS_ATOM(id) JSVAL_IS_STRING((jsval)(id))
|
||||
#define JSID_TO_ATOM(id) ((JSAtom *)(id))
|
||||
#define ATOM_TO_JSID(atom) (JS_ASSERT(ATOM_IS_STRING(atom)), \
|
||||
(jsid)(atom))
|
||||
|
||||
#define JSID_IS_INT(id) JSVAL_IS_INT((jsval)(id))
|
||||
#define JSID_TO_INT(id) JSVAL_TO_INT((jsval)(id))
|
||||
#define INT_TO_JSID(i) ((jsid)INT_TO_JSVAL(i))
|
||||
#define INT_JSVAL_TO_JSID(v) ((jsid)(v))
|
||||
#define INT_JSID_TO_JSVAL(id) ((jsval)(id))
|
||||
|
||||
#define JSID_IS_OBJECT(id) JSVAL_IS_OBJECT((jsval)(id))
|
||||
#define JSID_TO_OBJECT(id) JSVAL_TO_OBJECT((jsval)(id))
|
||||
#define OBJECT_TO_JSID(obj) ((jsid)OBJECT_TO_JSVAL(obj))
|
||||
#define OBJECT_JSVAL_TO_JSID(v) ((jsid)v)
|
||||
|
||||
#define ID_TO_VALUE(id) ((jsval)(id))
|
||||
|
||||
/*
|
||||
* Convenience constants.
|
||||
*/
|
||||
|
@ -179,17 +159,12 @@ class DeflatedStringCache;
|
|||
|
||||
class PropertyCache;
|
||||
struct PropertyCacheEntry;
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/* Common instantiations. */
|
||||
typedef js::Vector<jschar, 32> JSCharBuffer;
|
||||
|
||||
static inline JSPropertyOp
|
||||
js_CastAsPropertyOp(JSObject *object)
|
||||
{
|
||||
return JS_DATA_TO_FUNC_PTR(JSPropertyOp, object);
|
||||
}
|
||||
|
||||
} /* export "C++" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
@ -204,10 +179,21 @@ typedef enum JSTrapStatus {
|
|||
|
||||
typedef JSTrapStatus
|
||||
(* JSTrapHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure);
|
||||
jsval closure);
|
||||
|
||||
typedef JSTrapStatus
|
||||
(* JSInterruptHook)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure);
|
||||
typedef JSTrapStatus
|
||||
(* JSDebuggerHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure);
|
||||
|
||||
typedef JSTrapStatus
|
||||
(* JSThrowHook)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure);
|
||||
|
||||
typedef JSBool
|
||||
(* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsval id, jsval old,
|
||||
(* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsid id, jsval old,
|
||||
jsval *newp, void *closure);
|
||||
|
||||
/* called just after script creation */
|
||||
|
@ -266,13 +252,13 @@ typedef JSBool
|
|||
void *closure);
|
||||
|
||||
typedef struct JSDebugHooks {
|
||||
JSTrapHandler interruptHandler;
|
||||
void *interruptHandlerData;
|
||||
JSInterruptHook interruptHook;
|
||||
void *interruptHookData;
|
||||
JSNewScriptHook newScriptHook;
|
||||
void *newScriptHookData;
|
||||
JSDestroyScriptHook destroyScriptHook;
|
||||
void *destroyScriptHookData;
|
||||
JSTrapHandler debuggerHandler;
|
||||
JSDebuggerHandler debuggerHandler;
|
||||
void *debuggerHandlerData;
|
||||
JSSourceHandler sourceHandler;
|
||||
void *sourceHandlerData;
|
||||
|
@ -282,7 +268,7 @@ typedef struct JSDebugHooks {
|
|||
void *callHookData;
|
||||
JSObjectHook objectHook;
|
||||
void *objectHookData;
|
||||
JSTrapHandler throwHook;
|
||||
JSThrowHook throwHook;
|
||||
void *throwHookData;
|
||||
JSDebugErrorHook debugErrorHook;
|
||||
void *debugErrorHookData;
|
||||
|
@ -316,7 +302,7 @@ typedef JSBool
|
|||
* value, with the specified getter, setter, and attributes.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSDefinePropOp)(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
(* JSDefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const jsval *value,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
|
||||
|
||||
/*
|
||||
|
@ -368,4 +354,57 @@ typedef void
|
|||
extern JSBool js_CStringsAreUTF8;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace js {
|
||||
|
||||
class Value;
|
||||
|
||||
typedef JSBool
|
||||
(* DefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
|
||||
PropertyOp getter, PropertyOp setter, uintN attrs);
|
||||
typedef JSBool
|
||||
(* CheckAccessIdOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
Value *vp, uintN *attrsp);
|
||||
typedef JSBool
|
||||
(* WatchPointHandler)(JSContext *cx, JSObject *obj, jsid id,
|
||||
const Value *old, Value *newp, void *closure);
|
||||
typedef JSBool
|
||||
(* PropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
||||
|
||||
/*
|
||||
* Since jsval and Value are layout-compatible, pointers to otherwise-identical
|
||||
* functions can be cast back and forth. To avoid widespread casting, the
|
||||
* following safe casts are provided.
|
||||
*
|
||||
* See also Valueify and Jsvalify overloads in jspubtd.h.
|
||||
*/
|
||||
|
||||
static inline DefinePropOp Valueify(JSDefinePropOp f) { return (DefinePropOp)f; }
|
||||
static inline JSDefinePropOp Jsvalify(DefinePropOp f) { return (JSDefinePropOp)f; }
|
||||
static inline CheckAccessIdOp Valueify(JSCheckAccessIdOp f) { return (CheckAccessIdOp)f; }
|
||||
static inline JSCheckAccessIdOp Jsvalify(CheckAccessIdOp f) { return (JSCheckAccessIdOp)f; }
|
||||
static inline WatchPointHandler Valueify(JSWatchPointHandler f) { return (WatchPointHandler)f; }
|
||||
static inline JSWatchPointHandler Jsvalify(WatchPointHandler f) { return (JSWatchPointHandler)f; }
|
||||
static inline PropertyIdOp Valueify(JSPropertyIdOp f); /* Same type as JSPropertyOp */
|
||||
static inline JSPropertyIdOp Jsvalify(PropertyIdOp f); /* Same type as PropertyOp */
|
||||
|
||||
/*
|
||||
* Internal utilities
|
||||
*/
|
||||
static JS_ALWAYS_INLINE void
|
||||
SetValueRangeToUndefined(Value *vec, Value *end)
|
||||
{
|
||||
for (Value *v = vec; v != end; ++v)
|
||||
v->setUndefined();
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
SetValueRangeToUndefined(Value *vec, uintN len)
|
||||
{
|
||||
return SetValueRangeToUndefined(vec, vec + len);
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* jsprvtd_h___ */
|
||||
|
|
407
js/src/jspubtd.h
407
js/src/jspubtd.h
|
@ -42,8 +42,8 @@
|
|||
/*
|
||||
* JS public API typedefs.
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include "jscompat.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
|
@ -52,8 +52,6 @@ typedef uint16 jschar;
|
|||
typedef int32 jsint;
|
||||
typedef uint32 jsuint;
|
||||
typedef float64 jsdouble;
|
||||
typedef jsword jsval;
|
||||
typedef jsword jsid;
|
||||
typedef int32 jsrefcount; /* PRInt32 if JS_THREADSAFE, see jslock.h */
|
||||
|
||||
/*
|
||||
|
@ -155,6 +153,340 @@ typedef struct JSLocaleCallbacks JSLocaleCallbacks;
|
|||
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
|
||||
typedef struct JSONParser JSONParser;
|
||||
|
||||
/*
|
||||
* JavaScript engine unboxed value representation
|
||||
*/
|
||||
|
||||
/*
|
||||
* A jsval has an abstract type which is represented by a mask which assigns a
|
||||
* bit to each type. This allows fast set-membership queries. However, we give
|
||||
* one type (null) a mask of 0 for two reasons:
|
||||
* 1. memset'ing values to 0 produces a valid value. This was true of the old,
|
||||
* boxed jsvals (and now jsboxedwords) and eases the transition.
|
||||
* 2. Testing for null can often be compiled to slightly shorter/faster code.
|
||||
*
|
||||
* The down-side is that set-membership queries need to be done more carefully.
|
||||
* E.g., to test whether a value v is undefined or null, the correct test is:
|
||||
* (v.mask & ~UndefinedMask) == 0
|
||||
* instead of the intuitive (but incorrect) test:
|
||||
* (v.mask & (NullMask | UndefinedMask)) != 0
|
||||
* Since the value representation is kept a private detail of js::Value and
|
||||
* only exposed to a few functions through friendship, this type of error
|
||||
* should be hidden behind simple inline methods like v.isNullOrUndefined().
|
||||
*/
|
||||
|
||||
/*
|
||||
* Types are unsigned machine-words. On 32-bit systems, values are padded with
|
||||
* an extra word so that double payloads are aligned properly.
|
||||
*/
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
typedef uint32 JSValueMaskType;
|
||||
# define JSVAL_TYPE_BITS 32
|
||||
# define JS_INSERT_VALUE_PADDING() uint32 padding;
|
||||
#elif JS_BITS_PER_WORD == 64
|
||||
typedef JSUint64 JSValueMaskType;
|
||||
# define JSVAL_TYPE_BITS 32
|
||||
# define JS_INSERT_VALUE_PADDING()
|
||||
#else
|
||||
# error "Unsupported word size"
|
||||
#endif
|
||||
|
||||
#define JSVAL_NULL_MASK ((JSValueMaskType)0x00)
|
||||
#define JSVAL_UNDEFINED_MASK ((JSValueMaskType)0x01)
|
||||
#define JSVAL_INT32_MASK ((JSValueMaskType)0x02)
|
||||
#define JSVAL_DOUBLE_MASK ((JSValueMaskType)0x04)
|
||||
#define JSVAL_STRING_MASK ((JSValueMaskType)0x08)
|
||||
#define JSVAL_NONFUNOBJ_MASK ((JSValueMaskType)0x10)
|
||||
#define JSVAL_FUNOBJ_MASK ((JSValueMaskType)0x20)
|
||||
#define JSVAL_BOOLEAN_MASK ((JSValueMaskType)0x40)
|
||||
#define JSVAL_MAGIC_MASK ((JSValueMaskType)0x80)
|
||||
|
||||
/*
|
||||
* Magic value enumeration (private engine detail)
|
||||
*
|
||||
* This enumeration provides a debug-only code describing the source of an
|
||||
* invalid value. These codes can be used to assert that the different sources
|
||||
* of invalid never mix.
|
||||
*/
|
||||
typedef enum JSWhyMagic
|
||||
{
|
||||
JS_ARRAY_HOLE, /* a hole in a dense array */
|
||||
JS_ARGS_HOLE, /* a hole in the args object's array */
|
||||
JS_STOP_ITERATION, /* value returned by iterator to stop */
|
||||
JS_STOP_ITERATION_EXCEPTION /* value of cx->exception for a StopIteration exception */
|
||||
} JSWhyMagic;
|
||||
|
||||
typedef union jsval_data
|
||||
{
|
||||
int32 i32;
|
||||
uint32 u32;
|
||||
double dbl;
|
||||
JSString * str;
|
||||
JSObject * obj;
|
||||
void * ptr;
|
||||
JSBool boo;
|
||||
#ifdef DEBUG
|
||||
JSWhyMagic why;
|
||||
#endif
|
||||
struct { int32 first; int32 second; } bits;
|
||||
} jsval_data;
|
||||
|
||||
/* See js::Value. */
|
||||
typedef struct jsval
|
||||
{
|
||||
JSValueMaskType mask;
|
||||
JS_INSERT_VALUE_PADDING()
|
||||
jsval_data data;
|
||||
} jsval;
|
||||
|
||||
/*
|
||||
* Boxed word macros (private engine detail)
|
||||
*
|
||||
* N.B. jsboxedword and the JSBOXEDWORD macros are engine-private. Callers
|
||||
* should use only JSID macros (below) instead.
|
||||
*
|
||||
* The jsboxedword type is used by atoms and jsids. Eventually, the ability to
|
||||
* atomize any primitive will be removed and atoms will simply be unboxed,
|
||||
* interned JSString*s. However, jsids will always need boxing. Using a
|
||||
* one-word boxing scheme instead of the normal jsval 16-byte unboxed scheme
|
||||
* allows jsids to be passed by value without penalty, since jsids never are
|
||||
* doubles nor are jsids used to build typemaps for entering/leaving trace.
|
||||
*/
|
||||
|
||||
typedef jsword jsboxedword;
|
||||
|
||||
#define JSBOXEDWORD_TYPE_OBJECT 0x0
|
||||
#define JSBOXEDWORD_TYPE_INT 0x1
|
||||
#define JSBOXEDWORD_TYPE_DOUBLE 0x2
|
||||
#define JSBOXEDWORD_TYPE_STRING 0x4
|
||||
#define JSBOXEDWORD_TYPE_SPECIAL 0x6
|
||||
|
||||
/* Type tag bitfield length and derived macros. */
|
||||
#define JSBOXEDWORD_TAGBITS 3
|
||||
#define JSBOXEDWORD_TAGMASK ((jsboxedword) JS_BITMASK(JSBOXEDWORD_TAGBITS))
|
||||
#define JSBOXEDWORD_ALIGN JS_BIT(JSBOXEDWORD_TAGBITS)
|
||||
|
||||
static const jsboxedword JSBOXEDWORD_NULL = (jsboxedword)0x0;
|
||||
static const jsboxedword JSBOXEDWORD_FALSE = (jsboxedword)0x6;
|
||||
static const jsboxedword JSBOXEDWORD_TRUE = (jsboxedword)0xe;
|
||||
static const jsboxedword JSBOXEDWORD_VOID = (jsboxedword)0x16;
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_NULL(jsboxedword w)
|
||||
{
|
||||
return w == JSBOXEDWORD_NULL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_VOID(jsboxedword w)
|
||||
{
|
||||
return w == JSBOXEDWORD_VOID;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE unsigned
|
||||
JSBOXEDWORD_TAG(jsboxedword w)
|
||||
{
|
||||
return (unsigned)(w & JSBOXEDWORD_TAGMASK);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
JSBOXEDWORD_SETTAG(jsboxedword w, unsigned t)
|
||||
{
|
||||
return w | t;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
JSBOXEDWORD_CLRTAG(jsboxedword w)
|
||||
{
|
||||
return w & ~(jsboxedword)JSBOXEDWORD_TAGMASK;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_DOUBLE(jsboxedword w)
|
||||
{
|
||||
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_DOUBLE;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE double *
|
||||
JSBOXEDWORD_TO_DOUBLE(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_DOUBLE(w));
|
||||
return (double *)JSBOXEDWORD_CLRTAG(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
DOUBLE_TO_JSBOXEDWORD(double *d)
|
||||
{
|
||||
JS_ASSERT(((JSUword)d & JSBOXEDWORD_TAGMASK) == 0);
|
||||
return (jsboxedword)((JSUword)d | JSBOXEDWORD_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_STRING(jsboxedword w)
|
||||
{
|
||||
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_STRING;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSString *
|
||||
JSBOXEDWORD_TO_STRING(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_STRING(w));
|
||||
return (JSString *)JSBOXEDWORD_CLRTAG(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_SPECIAL(jsboxedword w)
|
||||
{
|
||||
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_SPECIAL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsint
|
||||
JSBOXEDWORD_TO_SPECIAL(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_SPECIAL(w));
|
||||
return w >> JSBOXEDWORD_TAGBITS;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
SPECIAL_TO_JSBOXEDWORD(jsint i)
|
||||
{
|
||||
return (i << JSBOXEDWORD_TAGBITS) | JSBOXEDWORD_TYPE_SPECIAL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_BOOLEAN(jsboxedword w)
|
||||
{
|
||||
return (w & ~((jsboxedword)1 << JSBOXEDWORD_TAGBITS)) == JSBOXEDWORD_TYPE_SPECIAL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_TO_BOOLEAN(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(w == JSBOXEDWORD_TRUE || w == JSBOXEDWORD_FALSE);
|
||||
return JSBOXEDWORD_TO_SPECIAL(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
BOOLEAN_TO_JSBOXEDWORD(JSBool b)
|
||||
{
|
||||
JS_ASSERT(b == JS_TRUE || b == JS_FALSE);
|
||||
return SPECIAL_TO_JSBOXEDWORD(b);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
STRING_TO_JSBOXEDWORD(JSString *str)
|
||||
{
|
||||
JS_ASSERT(((JSUword)str & JSBOXEDWORD_TAGMASK) == 0);
|
||||
return (jsboxedword)str | JSBOXEDWORD_TYPE_STRING;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_GCTHING(jsboxedword w)
|
||||
{
|
||||
return !(w & JSBOXEDWORD_TYPE_INT) &&
|
||||
JSBOXEDWORD_TAG(w) != JSBOXEDWORD_TYPE_SPECIAL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void *
|
||||
JSBOXEDWORD_TO_GCTHING(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_GCTHING(w));
|
||||
return (void *)JSBOXEDWORD_CLRTAG(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_OBJECT(jsboxedword w)
|
||||
{
|
||||
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSObject *
|
||||
JSBOXEDWORD_TO_OBJECT(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_OBJECT(w));
|
||||
return (JSObject *)JSBOXEDWORD_TO_GCTHING(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
OBJECT_TO_JSBOXEDWORD(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(((JSUword)obj & JSBOXEDWORD_TAGMASK) == 0);
|
||||
return (jsboxedword)obj | JSBOXEDWORD_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_PRIMITIVE(jsboxedword w)
|
||||
{
|
||||
return !JSBOXEDWORD_IS_OBJECT(w) || JSBOXEDWORD_IS_NULL(w);
|
||||
}
|
||||
|
||||
/* Domain limits for the jsboxedword int type. */
|
||||
#define JSBOXEDWORD_INT_BITS 31
|
||||
#define JSBOXEDWORD_INT_POW2(n) ((jsboxedword)1 << (n))
|
||||
#define JSBOXEDWORD_INT_MIN (-JSBOXEDWORD_INT_POW2(30))
|
||||
#define JSBOXEDWORD_INT_MAX (JSBOXEDWORD_INT_POW2(30) - 1)
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
INT32_FITS_IN_JSBOXEDWORD(jsint i)
|
||||
{
|
||||
return ((jsuint)(i) - (jsuint)JSBOXEDWORD_INT_MIN <=
|
||||
(jsuint)(JSBOXEDWORD_INT_MAX - JSBOXEDWORD_INT_MIN));
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_INT(jsboxedword w)
|
||||
{
|
||||
return w & JSBOXEDWORD_TYPE_INT;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsint
|
||||
JSBOXEDWORD_TO_INT(jsboxedword v)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_INT(v));
|
||||
return (jsint)(v >> 1);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
INT_TO_JSBOXEDWORD(jsint i)
|
||||
{
|
||||
JS_ASSERT(INT32_FITS_IN_JSBOXEDWORD(i));
|
||||
return (i << 1) | JSBOXEDWORD_TYPE_INT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Identifier (jsid) macros.
|
||||
*/
|
||||
|
||||
typedef jsboxedword jsid;
|
||||
|
||||
#define JSID_NULL ((jsid)JSBOXEDWORD_NULL)
|
||||
#define JSID_VOID ((jsid)JSBOXEDWORD_VOID)
|
||||
#define JSID_IS_NULL(id) JSBOXEDWORD_IS_NULL((jsboxedword)(id))
|
||||
#define JSID_IS_VOID(id) JSBOXEDWORD_IS_VOID((jsboxedword)(id))
|
||||
#define JSID_IS_ATOM(id) JSBOXEDWORD_IS_STRING((jsboxedword)(id))
|
||||
#define JSID_TO_ATOM(id) ((JSAtom *)(id))
|
||||
#define ATOM_TO_JSID(atom) (JS_ASSERT(ATOM_IS_STRING(atom)), \
|
||||
(jsid)(atom))
|
||||
|
||||
#define INT32_FITS_IN_JSID(id) INT32_FITS_IN_JSBOXEDWORD(id)
|
||||
#define JSID_IS_INT(id) JSBOXEDWORD_IS_INT((jsboxedword)(id))
|
||||
#define JSID_TO_INT(id) JSBOXEDWORD_TO_INT((jsboxedword)(id))
|
||||
#define INT_TO_JSID(i) ((jsid)INT_TO_JSBOXEDWORD((i)))
|
||||
|
||||
#define JSID_IS_OBJECT(id) JSBOXEDWORD_IS_OBJECT((jsboxedword)(id))
|
||||
#define JSID_TO_OBJECT(id) JSBOXEDWORD_TO_OBJECT((jsboxedword)(id))
|
||||
#define OBJECT_TO_JSID(obj) ((jsid)OBJECT_TO_JSBOXEDWORD((obj)))
|
||||
|
||||
/* Objects and strings (no doubles in jsids). */
|
||||
#define JSID_IS_GCTHING(id) (((id) & 0x3) == 0)
|
||||
#define JSID_TO_GCTHING(id) (JS_ASSERT(JSID_IS_GCTHING((id))), \
|
||||
JSBOXEDWORD_TO_GCTHING((jsboxedword)(id)))
|
||||
#define JSID_TRACE_KIND(id) (JS_ASSERT(JSID_IS_GCTHING((id))), \
|
||||
(JSBOXEDWORD_TAG((jsboxedword)(id)) == JSBOXEDWORD_TYPE_STRING))
|
||||
|
||||
JS_PUBLIC_API(jsval)
|
||||
JSID_TO_JSVAL(jsid id);
|
||||
|
||||
/* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */
|
||||
|
||||
/*
|
||||
|
@ -165,7 +497,7 @@ typedef struct JSONParser JSONParser;
|
|||
* obj[id] can't be deleted (because it's permanent).
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
/*
|
||||
* This function type is used for callbacks that enumerate the properties of
|
||||
|
@ -218,7 +550,7 @@ typedef JSBool
|
|||
* NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSResolveOp)(JSContext *cx, JSObject *obj, jsval id);
|
||||
(* JSResolveOp)(JSContext *cx, JSObject *obj, jsid id);
|
||||
|
||||
/*
|
||||
* Like JSResolveOp, but flags provide contextual information as follows:
|
||||
|
@ -250,7 +582,7 @@ typedef JSBool
|
|||
* *objp without a new JSClass flag.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
JSObject **objp);
|
||||
|
||||
/*
|
||||
|
@ -317,7 +649,7 @@ typedef JSObjectOps *
|
|||
* specialize access checks.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode,
|
||||
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
jsval *vp);
|
||||
|
||||
/*
|
||||
|
@ -333,7 +665,7 @@ typedef JSBool
|
|||
* *bp otherwise.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
|
||||
|
||||
/*
|
||||
* Deprecated function type for JSClass.mark. All new code should define
|
||||
|
@ -420,7 +752,7 @@ typedef uint32
|
|||
/* JSExtendedClass function pointer typedefs. */
|
||||
|
||||
typedef JSBool
|
||||
(* JSEqualityOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
|
||||
|
||||
/*
|
||||
* A generic type for functions mapping an object to another object, or null
|
||||
|
@ -443,7 +775,6 @@ typedef JSBool
|
|||
(* JSNative)(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
/* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros. */
|
||||
typedef JSBool
|
||||
(* JSFastNative)(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
|
@ -593,4 +924,60 @@ typedef JSBool
|
|||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace js {
|
||||
|
||||
class Value;
|
||||
class Class;
|
||||
|
||||
typedef JSBool
|
||||
(* Native)(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval);
|
||||
typedef JSBool
|
||||
(* FastNative)(JSContext *cx, uintN argc, Value *vp);
|
||||
typedef JSBool
|
||||
(* PropertyOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
||||
typedef JSBool
|
||||
(* ConvertOp)(JSContext *cx, JSObject *obj, JSType type, Value *vp);
|
||||
typedef JSBool
|
||||
(* NewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
Value *statep, jsid *idp);
|
||||
typedef JSBool
|
||||
(* HasInstanceOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp);
|
||||
typedef JSBool
|
||||
(* CheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
Value *vp);
|
||||
typedef JSObjectOps *
|
||||
(* GetObjectOps)(JSContext *cx, Class *clasp);
|
||||
typedef JSBool
|
||||
(* EqualityOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp);
|
||||
|
||||
/*
|
||||
* Since jsval and Value are layout-compatible, pointers to otherwise-identical
|
||||
* functions can be cast back and forth. To avoid widespread casting, the
|
||||
* following safe casts are provided.
|
||||
*
|
||||
* See also Valueify and Jsvalify overloads in jsprvtd.h.
|
||||
*/
|
||||
|
||||
static inline Native Valueify(JSNative f) { return (Native)f; }
|
||||
static inline JSNative Jsvalify(Native f) { return (JSNative)f; }
|
||||
static inline FastNative Valueify(JSFastNative f) { return (FastNative)f; }
|
||||
static inline JSFastNative Jsvalify(FastNative f) { return (JSFastNative)f; }
|
||||
static inline PropertyOp Valueify(JSPropertyOp f) { return (PropertyOp)f; }
|
||||
static inline JSPropertyOp Jsvalify(PropertyOp f) { return (JSPropertyOp)f; }
|
||||
static inline ConvertOp Valueify(JSConvertOp f) { return (ConvertOp)f; }
|
||||
static inline JSConvertOp Jsvalify(ConvertOp f) { return (JSConvertOp)f; }
|
||||
static inline NewEnumerateOp Valueify(JSNewEnumerateOp f) { return (NewEnumerateOp)f; }
|
||||
static inline JSNewEnumerateOp Jsvalify(NewEnumerateOp f) { return (JSNewEnumerateOp)f; }
|
||||
static inline HasInstanceOp Valueify(JSHasInstanceOp f) { return (HasInstanceOp)f; }
|
||||
static inline JSHasInstanceOp Jsvalify(HasInstanceOp f) { return (JSHasInstanceOp)f; }
|
||||
static inline CheckAccessOp Valueify(JSCheckAccessOp f) { return (CheckAccessOp)f; }
|
||||
static inline JSCheckAccessOp Jsvalify(CheckAccessOp f) { return (JSCheckAccessOp)f; }
|
||||
static inline GetObjectOps Valueify(JSGetObjectOps f) { return (GetObjectOps)f; }
|
||||
static inline JSGetObjectOps Jsvalify(GetObjectOps f) { return (JSGetObjectOps)f; }
|
||||
static inline EqualityOp Valueify(JSEqualityOp f); /* Same type as JSHasInstanceOp */
|
||||
static inline JSEqualityOp Jsvalify(EqualityOp f); /* Same type as HasInstanceOp */
|
||||
|
||||
} /* namespace js */
|
||||
#endif /* __cplusplus */
|
||||
#endif /* jspubtd_h___ */
|
||||
|
|
|
@ -50,8 +50,6 @@
|
|||
#include "jsdhash.h"
|
||||
#endif
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
struct JSRegExpStatics {
|
||||
JSString *input; /* input string to match (perl $_, GC root) */
|
||||
JSBool multiline; /* whether input contains newlines (perl $*) */
|
||||
|
@ -153,7 +151,7 @@ js_FreeRegExpStatics(JSContext *cx);
|
|||
#define VALUE_IS_REGEXP(cx, v) \
|
||||
(!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isRegExp())
|
||||
|
||||
extern JSClass js_RegExpClass;
|
||||
extern js::Class js_RegExpClass;
|
||||
|
||||
inline bool
|
||||
JSObject::isRegExp() const
|
||||
|
@ -202,13 +200,11 @@ static inline void
|
|||
js_ClearRegExpLastIndex(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->getClass() == &js_RegExpClass);
|
||||
obj->fslots[JSSLOT_REGEXP_LAST_INDEX] = JSVAL_ZERO;
|
||||
obj->fslots[JSSLOT_REGEXP_LAST_INDEX].setInt32(0);
|
||||
}
|
||||
|
||||
/* Return whether the given character array contains RegExp meta-characters. */
|
||||
extern bool
|
||||
js_ContainsRegExpMetaChars(const jschar *chars, size_t length);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsregexp_h___ */
|
||||
|
|
158
js/src/jsscope.h
158
js/src/jsscope.h
|
@ -63,8 +63,6 @@
|
|||
#pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
|
||||
#endif
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* Given P independent, non-unique properties each of size S words mapped by
|
||||
* all scopes in a runtime, construct a property tree of N nodes each of size
|
||||
|
@ -281,10 +279,10 @@ struct JSScope : public JSObjectMap
|
|||
void generateOwnShape(JSContext *cx);
|
||||
JSScopeProperty **searchTable(jsid id, bool adding);
|
||||
inline JSScopeProperty **search(jsid id, bool adding);
|
||||
inline JSEmptyScope *createEmptyScope(JSContext *cx, JSClass *clasp);
|
||||
inline JSEmptyScope *createEmptyScope(JSContext *cx, js::Class *clasp);
|
||||
|
||||
JSScopeProperty *addPropertyHelper(JSContext *cx, jsid id,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
js::PropertyOp getter, js::PropertyOp setter,
|
||||
uint32 slot, uintN attrs,
|
||||
uintN flags, intN shortid,
|
||||
JSScopeProperty **spp);
|
||||
|
@ -295,7 +293,7 @@ struct JSScope : public JSObjectMap
|
|||
|
||||
/* Create a mutable, owned, empty scope. */
|
||||
static JSScope *create(JSContext *cx, const JSObjectOps *ops,
|
||||
JSClass *clasp, JSObject *obj, uint32 shape);
|
||||
js::Class *clasp, JSObject *obj, uint32 shape);
|
||||
|
||||
void destroy(JSContext *cx);
|
||||
|
||||
|
@ -306,11 +304,11 @@ struct JSScope : public JSObjectMap
|
|||
* If |this| is the scope of an object |proto|, the resulting scope can be
|
||||
* used as the scope of a new object whose prototype is |proto|.
|
||||
*/
|
||||
inline JSEmptyScope *getEmptyScope(JSContext *cx, JSClass *clasp);
|
||||
inline JSEmptyScope *getEmptyScope(JSContext *cx, js::Class *clasp);
|
||||
|
||||
inline bool ensureEmptyScope(JSContext *cx, JSClass *clasp);
|
||||
inline bool ensureEmptyScope(JSContext *cx, js::Class *clasp);
|
||||
|
||||
inline bool canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp);
|
||||
inline bool canProvideEmptyScope(JSObjectOps *ops, js::Class *clasp);
|
||||
|
||||
JSScopeProperty *lookup(jsid id);
|
||||
|
||||
|
@ -319,7 +317,7 @@ struct JSScope : public JSObjectMap
|
|||
|
||||
/* Add a property whose id is not yet in this scope. */
|
||||
JSScopeProperty *addProperty(JSContext *cx, jsid id,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
js::PropertyOp getter, js::PropertyOp setter,
|
||||
uint32 slot, uintN attrs,
|
||||
uintN flags, intN shortid);
|
||||
|
||||
|
@ -331,14 +329,14 @@ struct JSScope : public JSObjectMap
|
|||
|
||||
/* Add or overwrite a property for id in this scope. */
|
||||
JSScopeProperty *putProperty(JSContext *cx, jsid id,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
js::PropertyOp getter, js::PropertyOp setter,
|
||||
uint32 slot, uintN attrs,
|
||||
uintN flags, intN shortid);
|
||||
|
||||
/* Change the given property into a sibling with the same id in this scope. */
|
||||
JSScopeProperty *changeProperty(JSContext *cx, JSScopeProperty *sprop,
|
||||
uintN attrs, uintN mask,
|
||||
JSPropertyOp getter, JSPropertyOp setter);
|
||||
js::PropertyOp getter, js::PropertyOp setter);
|
||||
|
||||
/* Remove id from this scope. */
|
||||
bool removeProperty(JSContext *cx, jsid id);
|
||||
|
@ -354,7 +352,7 @@ struct JSScope : public JSObjectMap
|
|||
* Defined in jsscopeinlines.h, but not declared inline per standard style
|
||||
* in order to avoid gcc warnings.
|
||||
*/
|
||||
bool methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp);
|
||||
bool methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, js::Value *vp);
|
||||
|
||||
/*
|
||||
* Write barrier to check for a method value change. Defined inline below
|
||||
|
@ -363,14 +361,14 @@ struct JSScope : public JSObjectMap
|
|||
* flags show this is necessary. The methodShapeChange overload (directly
|
||||
* below) parallels this.
|
||||
*/
|
||||
bool methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, jsval v);
|
||||
bool methodWriteBarrier(JSContext *cx, uint32 slot, jsval v);
|
||||
bool methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, const js::Value &v);
|
||||
bool methodWriteBarrier(JSContext *cx, uint32 slot, const js::Value &v);
|
||||
|
||||
void trace(JSTracer *trc);
|
||||
|
||||
void deletingShapeChange(JSContext *cx, JSScopeProperty *sprop);
|
||||
bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval);
|
||||
bool methodShapeChange(JSContext *cx, uint32 slot, jsval toval);
|
||||
bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, const js::Value &toval);
|
||||
bool methodShapeChange(JSContext *cx, uint32 slot, const js::Value &toval);
|
||||
void protoShapeChange(JSContext *cx);
|
||||
void shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop);
|
||||
|
||||
|
@ -420,7 +418,7 @@ struct JSScope : public JSObjectMap
|
|||
*/
|
||||
bool branded() { JS_ASSERT(!generic()); return flags & BRANDED; }
|
||||
|
||||
bool brand(JSContext *cx, uint32 slot, jsval v) {
|
||||
bool brand(JSContext *cx, uint32 slot) {
|
||||
JS_ASSERT(!branded());
|
||||
generateOwnShape(cx);
|
||||
if (js_IsPropertyCacheDisabled(cx)) // check for rt->shapeGen overflow
|
||||
|
@ -501,10 +499,10 @@ struct JSScope : public JSObjectMap
|
|||
|
||||
struct JSEmptyScope : public JSScope
|
||||
{
|
||||
JSClass * const clasp;
|
||||
jsrefcount nrefs; /* count of all referencing objects */
|
||||
js::Class * const clasp;
|
||||
jsrefcount nrefs; /* count of all referencing objects */
|
||||
|
||||
JSEmptyScope(JSContext *cx, const JSObjectOps *ops, JSClass *clasp);
|
||||
JSEmptyScope(JSContext *cx, const JSObjectOps *ops, js::Class *clasp);
|
||||
|
||||
void hold() {
|
||||
/* The method is only called for already held objects. */
|
||||
|
@ -554,7 +552,7 @@ JSObject::shape() const
|
|||
return map->shape;
|
||||
}
|
||||
|
||||
inline jsval
|
||||
inline const js::Value &
|
||||
JSObject::lockedGetSlot(uintN slot) const
|
||||
{
|
||||
OBJ_CHECK_SLOT(this, slot);
|
||||
|
@ -562,28 +560,12 @@ JSObject::lockedGetSlot(uintN slot) const
|
|||
}
|
||||
|
||||
inline void
|
||||
JSObject::lockedSetSlot(uintN slot, jsval value)
|
||||
JSObject::lockedSetSlot(uintN slot, const js::Value &value)
|
||||
{
|
||||
OBJ_CHECK_SLOT(this, slot);
|
||||
this->setSlot(slot, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers for reinterpreting JSPropertyOp as JSObject* for scripted getters
|
||||
* and setters.
|
||||
*/
|
||||
inline JSObject *
|
||||
js_CastAsObject(JSPropertyOp op)
|
||||
{
|
||||
return JS_FUNC_TO_DATA_PTR(JSObject *, op);
|
||||
}
|
||||
|
||||
inline jsval
|
||||
js_CastAsObjectJSVal(JSPropertyOp op)
|
||||
{
|
||||
return OBJECT_TO_JSVAL(JS_FUNC_TO_DATA_PTR(JSObject *, op));
|
||||
}
|
||||
|
||||
namespace js {
|
||||
class PropertyTree;
|
||||
}
|
||||
|
@ -595,23 +577,23 @@ struct JSScopeProperty {
|
|||
uint32 number, void *arg);
|
||||
friend void js::SweepScopeProperties(JSContext *cx);
|
||||
|
||||
jsid id; /* int-tagged jsval/untagged JSAtom* */
|
||||
jsid id;
|
||||
|
||||
private:
|
||||
union {
|
||||
JSPropertyOp rawGetter; /* getter and setter hooks or objects */
|
||||
js::PropertyOp rawGetter; /* getter and setter hooks or objects */
|
||||
JSScopeProperty *next; /* next node in freelist */
|
||||
};
|
||||
|
||||
union {
|
||||
JSPropertyOp rawSetter; /* getter is JSObject* and setter is 0
|
||||
js::PropertyOp rawSetter; /* getter is JSObject* and setter is 0
|
||||
if sprop->isMethod() */
|
||||
JSScopeProperty **prevp; /* pointer to previous node's next, or
|
||||
pointer to head of freelist */
|
||||
};
|
||||
|
||||
void insertFree(JSScopeProperty *&list) {
|
||||
id = JSVAL_NULL;
|
||||
id = JSID_NULL;
|
||||
next = list;
|
||||
prevp = &list;
|
||||
if (list)
|
||||
|
@ -620,7 +602,7 @@ struct JSScopeProperty {
|
|||
}
|
||||
|
||||
void removeFree() {
|
||||
JS_ASSERT(JSVAL_IS_NULL(id));
|
||||
JS_ASSERT(JSID_IS_NULL(id));
|
||||
*prevp = next;
|
||||
if (next)
|
||||
next->prevp = prevp;
|
||||
|
@ -665,15 +647,15 @@ struct JSScopeProperty {
|
|||
IN_DICTIONARY = 0x20
|
||||
};
|
||||
|
||||
JSScopeProperty(jsid id, JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
|
||||
JSScopeProperty(jsid id, js::PropertyOp getter, js::PropertyOp setter, uint32 slot,
|
||||
uintN attrs, uintN flags, intN shortid)
|
||||
: id(id), rawGetter(getter), rawSetter(setter), slot(slot), attrs(uint8(attrs)),
|
||||
flags(uint8(flags)), shortid(int16(shortid))
|
||||
{
|
||||
JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER),
|
||||
JSVAL_TO_OBJECT(getterValue())->isCallable());
|
||||
getterObject()->isCallable());
|
||||
JS_ASSERT_IF(setter && (attrs & JSPROP_SETTER),
|
||||
JSVAL_TO_OBJECT(setterValue())->isCallable());
|
||||
setterObject()->isCallable());
|
||||
}
|
||||
|
||||
bool marked() const { return (flags & MARK) != 0; }
|
||||
|
@ -702,50 +684,55 @@ struct JSScopeProperty {
|
|||
|
||||
JSObject *methodObject() const {
|
||||
JS_ASSERT(isMethod());
|
||||
return js_CastAsObject(rawGetter);
|
||||
return CastAsObject(rawGetter);
|
||||
}
|
||||
jsval methodValue() const {
|
||||
js::Value methodValue() const {
|
||||
JS_ASSERT(isMethod());
|
||||
return js_CastAsObjectJSVal(rawGetter);
|
||||
return js::FunObjValue(*CastAsObject(rawGetter));
|
||||
}
|
||||
|
||||
JSPropertyOp getter() const { return rawGetter; }
|
||||
js::PropertyOp getter() const { return rawGetter; }
|
||||
bool hasDefaultGetter() const { return !rawGetter; }
|
||||
JSPropertyOp getterOp() const {
|
||||
js::PropertyOp getterOp() const {
|
||||
JS_ASSERT(!hasGetterValue());
|
||||
return rawGetter;
|
||||
}
|
||||
JSObject *getterObject() const {
|
||||
JS_ASSERT(hasGetterValue());
|
||||
return js_CastAsObject(rawGetter);
|
||||
return CastAsObject(rawGetter);
|
||||
}
|
||||
jsval getterValue() const {
|
||||
js::Value getterValue() const {
|
||||
JS_ASSERT(hasGetterValue());
|
||||
return rawGetter ? js_CastAsObjectJSVal(rawGetter) : JSVAL_VOID;
|
||||
if (rawGetter)
|
||||
return js::FunObjValue(*CastAsObject(rawGetter));
|
||||
return js::UndefinedValue();
|
||||
}
|
||||
|
||||
JSPropertyOp setter() const { return rawSetter; }
|
||||
js::PropertyOp setter() const { return rawSetter; }
|
||||
bool hasDefaultSetter() const { return !rawSetter; }
|
||||
JSPropertyOp setterOp() const {
|
||||
js::PropertyOp setterOp() const {
|
||||
JS_ASSERT(!hasSetterValue());
|
||||
return rawSetter;
|
||||
}
|
||||
JSObject *setterObject() const {
|
||||
JS_ASSERT(hasSetterValue() && rawSetter);
|
||||
return js_CastAsObject(rawSetter);
|
||||
return CastAsObject(rawSetter);
|
||||
}
|
||||
jsval setterValue() const {
|
||||
js::Value setterValue() const {
|
||||
JS_ASSERT(hasSetterValue());
|
||||
return rawSetter ? js_CastAsObjectJSVal(rawSetter) : JSVAL_VOID;
|
||||
if (rawSetter)
|
||||
return js::FunObjValue(*CastAsObject(rawSetter));
|
||||
return js::UndefinedValue();
|
||||
}
|
||||
|
||||
inline JSDHashNumber hash() const;
|
||||
inline bool matches(const JSScopeProperty *p) const;
|
||||
inline bool matchesParamsAfterId(JSPropertyOp agetter, JSPropertyOp asetter, uint32 aslot,
|
||||
uintN aattrs, uintN aflags, intN ashortid) const;
|
||||
inline bool matchesParamsAfterId(js::PropertyOp agetter, js::PropertyOp asetter,
|
||||
uint32 aslot, uintN aattrs, uintN aflags,
|
||||
intN ashortid) const;
|
||||
|
||||
bool get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp);
|
||||
bool set(JSContext* cx, JSObject* obj, jsval* vp);
|
||||
bool get(JSContext* cx, JSObject *obj, JSObject *pobj, js::Value* vp);
|
||||
bool set(JSContext* cx, JSObject *obj, js::Value* vp);
|
||||
|
||||
inline bool isSharedPermanent() const;
|
||||
|
||||
|
@ -815,7 +802,7 @@ JSScope::hasProperty(JSScopeProperty *sprop)
|
|||
inline JSScopeProperty *
|
||||
JSScope::lastProperty() const
|
||||
{
|
||||
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id));
|
||||
JS_ASSERT_IF(lastProp, !JSID_IS_NULL(lastProp->id));
|
||||
return lastProp;
|
||||
}
|
||||
|
||||
|
@ -826,8 +813,8 @@ JSScope::lastProperty() const
|
|||
inline void
|
||||
JSScope::setLastProperty(JSScopeProperty *sprop)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
|
||||
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id));
|
||||
JS_ASSERT(!JSID_IS_NULL(sprop->id));
|
||||
JS_ASSERT_IF(lastProp, !JSID_IS_NULL(lastProp->id));
|
||||
|
||||
lastProp = sprop;
|
||||
}
|
||||
|
@ -836,7 +823,7 @@ inline void
|
|||
JSScope::removeLastProperty()
|
||||
{
|
||||
JS_ASSERT(!inDictionaryMode());
|
||||
JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id));
|
||||
JS_ASSERT_IF(lastProp->parent, !JSID_IS_NULL(lastProp->parent->id));
|
||||
|
||||
lastProp = lastProp->parent;
|
||||
--entryCount;
|
||||
|
@ -848,12 +835,12 @@ JSScope::removeDictionaryProperty(JSScopeProperty *sprop)
|
|||
JS_ASSERT(inDictionaryMode());
|
||||
JS_ASSERT(sprop->inDictionary());
|
||||
JS_ASSERT(sprop->childp);
|
||||
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
|
||||
JS_ASSERT(!JSID_IS_NULL(sprop->id));
|
||||
|
||||
JS_ASSERT(lastProp->inDictionary());
|
||||
JS_ASSERT(lastProp->childp == &lastProp);
|
||||
JS_ASSERT_IF(lastProp != sprop, !JSVAL_IS_NULL(lastProp->id));
|
||||
JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id));
|
||||
JS_ASSERT_IF(lastProp != sprop, !JSID_IS_NULL(lastProp->id));
|
||||
JS_ASSERT_IF(lastProp->parent, !JSID_IS_NULL(lastProp->parent->id));
|
||||
|
||||
if (sprop->parent)
|
||||
sprop->parent->childp = sprop->childp;
|
||||
|
@ -871,12 +858,12 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
|
|||
*/
|
||||
JS_ASSERT(sprop->inDictionary());
|
||||
JS_ASSERT(!sprop->childp);
|
||||
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
|
||||
JS_ASSERT(!JSID_IS_NULL(sprop->id));
|
||||
|
||||
JS_ASSERT_IF(*childp, (*childp)->inDictionary());
|
||||
JS_ASSERT_IF(lastProp, lastProp->inDictionary());
|
||||
JS_ASSERT_IF(lastProp, lastProp->childp == &lastProp);
|
||||
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id));
|
||||
JS_ASSERT_IF(lastProp, !JSID_IS_NULL(lastProp->id));
|
||||
|
||||
sprop->parent = *childp;
|
||||
*childp = sprop;
|
||||
|
@ -891,8 +878,8 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
|
|||
* than id when calling sprop's getter or setter.
|
||||
*/
|
||||
#define SPROP_USERID(sprop) \
|
||||
((sprop)->hasShortID() ? INT_TO_JSVAL((sprop)->shortid) \
|
||||
: ID_TO_VALUE((sprop)->id))
|
||||
((sprop)->hasShortID() ? INT_TO_JSID((sprop)->shortid) \
|
||||
: (sprop)->id)
|
||||
|
||||
#define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot)
|
||||
#define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope)
|
||||
|
@ -961,7 +948,7 @@ JSScope::search(jsid id, bool adding)
|
|||
#undef METER
|
||||
|
||||
inline bool
|
||||
JSScope::canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp)
|
||||
JSScope::canProvideEmptyScope(JSObjectOps *ops, js::Class *clasp)
|
||||
{
|
||||
/*
|
||||
* An empty scope cannot provide another empty scope, or wrongful two-level
|
||||
|
@ -973,19 +960,18 @@ JSScope::canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp)
|
|||
}
|
||||
|
||||
inline bool
|
||||
JSScopeProperty::get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp)
|
||||
JSScopeProperty::get(JSContext* cx, JSObject *obj, JSObject *pobj, js::Value* vp)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_NULL(this->id));
|
||||
JS_ASSERT(!JSID_IS_NULL(this->id));
|
||||
JS_ASSERT(!hasDefaultGetter());
|
||||
|
||||
if (hasGetterValue()) {
|
||||
JS_ASSERT(!isMethod());
|
||||
jsval fval = getterValue();
|
||||
return js_InternalGetOrSet(cx, obj, id, fval, JSACC_READ, 0, 0, vp);
|
||||
return js::InternalGetOrSet(cx, obj, id, getterValue(), JSACC_READ, 0, 0, vp);
|
||||
}
|
||||
|
||||
if (isMethod()) {
|
||||
*vp = methodValue();
|
||||
vp->copy(methodValue());
|
||||
|
||||
JSScope *scope = pobj->scope();
|
||||
JS_ASSERT(scope->object == pobj);
|
||||
|
@ -999,19 +985,17 @@ JSScopeProperty::get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp)
|
|||
* but with objects do.
|
||||
*/
|
||||
if (obj->getClass() == &js_WithClass)
|
||||
obj = obj->map->ops->thisObject(cx, obj);
|
||||
obj = obj->thisObject(cx);
|
||||
return getterOp()(cx, obj, SPROP_USERID(this), vp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScopeProperty::set(JSContext* cx, JSObject* obj, jsval* vp)
|
||||
JSScopeProperty::set(JSContext* cx, JSObject *obj, js::Value* vp)
|
||||
{
|
||||
JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
|
||||
|
||||
if (attrs & JSPROP_SETTER) {
|
||||
jsval fval = setterValue();
|
||||
return js_InternalGetOrSet(cx, obj, id, fval, JSACC_WRITE, 1, vp, vp);
|
||||
}
|
||||
if (attrs & JSPROP_SETTER)
|
||||
return js::InternalGetOrSet(cx, obj, id, setterValue(), JSACC_WRITE, 1, vp, vp);
|
||||
|
||||
if (attrs & JSPROP_GETTER)
|
||||
return !!js_ReportGetterOnlyAssignment(cx);
|
||||
|
@ -1034,8 +1018,6 @@ js_GetMutableScope(JSContext *cx, JSObject *obj);
|
|||
extern void
|
||||
js_TraceId(JSTracer *trc, jsid id);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#pragma warning(pop)
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "jsscope.h"
|
||||
|
||||
inline JSEmptyScope *
|
||||
JSScope::createEmptyScope(JSContext *cx, JSClass *clasp)
|
||||
JSScope::createEmptyScope(JSContext *cx, js::Class *clasp)
|
||||
{
|
||||
JS_ASSERT(!emptyScope);
|
||||
emptyScope = cx->create<JSEmptyScope>(cx, ops, clasp);
|
||||
|
@ -55,7 +55,7 @@ JSScope::createEmptyScope(JSContext *cx, JSClass *clasp)
|
|||
}
|
||||
|
||||
inline JSEmptyScope *
|
||||
JSScope::getEmptyScope(JSContext *cx, JSClass *clasp)
|
||||
JSScope::getEmptyScope(JSContext *cx, js::Class *clasp)
|
||||
{
|
||||
if (emptyScope) {
|
||||
JS_ASSERT(clasp == emptyScope->clasp);
|
||||
|
@ -66,7 +66,7 @@ JSScope::getEmptyScope(JSContext *cx, JSClass *clasp)
|
|||
}
|
||||
|
||||
inline bool
|
||||
JSScope::ensureEmptyScope(JSContext *cx, JSClass *clasp)
|
||||
JSScope::ensureEmptyScope(JSContext *cx, js::Class *clasp)
|
||||
{
|
||||
if (emptyScope) {
|
||||
JS_ASSERT(clasp == emptyScope->clasp);
|
||||
|
@ -114,44 +114,50 @@ JSScope::extend(JSContext *cx, JSScopeProperty *sprop)
|
|||
* objects optimized as typically non-escaping, ad-hoc methods in obj.
|
||||
*/
|
||||
inline bool
|
||||
JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp)
|
||||
JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, js::Value *vp)
|
||||
{
|
||||
JS_ASSERT(hasMethodBarrier());
|
||||
JS_ASSERT(hasProperty(sprop));
|
||||
JS_ASSERT(sprop->isMethod());
|
||||
JS_ASSERT(sprop->methodValue() == *vp);
|
||||
JS_ASSERT(sprop->methodValue().isSame(*vp));
|
||||
JS_ASSERT(object->getClass() == &js_ObjectClass);
|
||||
|
||||
JSObject *funobj = JSVAL_TO_OBJECT(*vp);
|
||||
JSObject *funobj = &vp->asFunObj();
|
||||
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
|
||||
JS_ASSERT(FUN_OBJECT(fun) == funobj && FUN_NULL_CLOSURE(fun));
|
||||
|
||||
funobj = CloneFunctionObject(cx, fun, funobj->getParent());
|
||||
if (!funobj)
|
||||
return false;
|
||||
*vp = OBJECT_TO_JSVAL(funobj);
|
||||
vp->setFunObj(*funobj);
|
||||
return !!js_SetPropertyHelper(cx, object, sprop->id, 0, vp);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
ChangesMethodValue(const js::Value &prev, const js::Value &v)
|
||||
{
|
||||
return prev.isFunObj() &&
|
||||
(!v.isFunObj() || &v.asFunObj() != &prev.asFunObj());
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScope::methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, jsval v)
|
||||
JSScope::methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop,
|
||||
const js::Value &v)
|
||||
{
|
||||
if (flags & (BRANDED | METHOD_BARRIER)) {
|
||||
jsval prev = object->lockedGetSlot(sprop->slot);
|
||||
|
||||
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
|
||||
const js::Value &prev = object->lockedGetSlot(sprop->slot);
|
||||
if (ChangesMethodValue(prev, v))
|
||||
return methodShapeChange(cx, sprop, v);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScope::methodWriteBarrier(JSContext *cx, uint32 slot, jsval v)
|
||||
JSScope::methodWriteBarrier(JSContext *cx, uint32 slot, const js::Value &v)
|
||||
{
|
||||
if (flags & (BRANDED | METHOD_BARRIER)) {
|
||||
jsval prev = object->lockedGetSlot(slot);
|
||||
|
||||
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
|
||||
const js::Value &prev = object->lockedGetSlot(slot);
|
||||
if (ChangesMethodValue(prev, v))
|
||||
return methodShapeChange(cx, slot, v);
|
||||
}
|
||||
return true;
|
||||
|
@ -231,18 +237,18 @@ JSScopeProperty::hash() const
|
|||
inline bool
|
||||
JSScopeProperty::matches(const JSScopeProperty *p) const
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_NULL(id));
|
||||
JS_ASSERT(!JSVAL_IS_NULL(p->id));
|
||||
JS_ASSERT(!JSID_IS_NULL(id));
|
||||
JS_ASSERT(!JSID_IS_NULL(p->id));
|
||||
return id == p->id &&
|
||||
matchesParamsAfterId(p->rawGetter, p->rawSetter, p->slot, p->attrs, p->flags,
|
||||
p->shortid);
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScopeProperty::matchesParamsAfterId(JSPropertyOp agetter, JSPropertyOp asetter, uint32 aslot,
|
||||
JSScopeProperty::matchesParamsAfterId(js::PropertyOp agetter, js::PropertyOp asetter, uint32 aslot,
|
||||
uintN aattrs, uintN aflags, intN ashortid) const
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_NULL(id));
|
||||
JS_ASSERT(!JSID_IS_NULL(id));
|
||||
return rawGetter == agetter &&
|
||||
rawSetter == asetter &&
|
||||
slot == aslot &&
|
||||
|
|
|
@ -402,7 +402,7 @@ script_trace(JSTracer *trc, JSObject *obj)
|
|||
js_TraceScript(trc, script);
|
||||
}
|
||||
|
||||
JSClass js_ScriptClass = {
|
||||
Class js_ScriptClass = {
|
||||
"Script",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSCRIPT_RESERVED_SLOTS) |
|
||||
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
|
||||
|
|
|
@ -227,7 +227,7 @@ StackDepth(JSScript *script)
|
|||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
extern JS_FRIEND_DATA(JSClass) js_ScriptClass;
|
||||
extern JS_FRIEND_DATA(js::Class) js_ScriptClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitScriptClass(JSContext *cx, JSObject *obj);
|
||||
|
|
|
@ -799,7 +799,7 @@ str_substring(JSContext *cx, uintN argc, jsval *vp)
|
|||
static JSString* FASTCALL
|
||||
String_p_toString(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
if (!JS_InstanceOf(cx, obj, &js_StringClass, NULL))
|
||||
if (!InstanceOf(cx, obj, &js_StringClass, NULL))
|
||||
return NULL;
|
||||
jsval v = obj->fslots[JSSLOT_PRIMITIVE_THIS];
|
||||
JS_ASSERT(JSVAL_IS_STRING(v));
|
||||
|
@ -3230,8 +3230,8 @@ js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun)
|
|||
return js_GetStringBytes(cx, str);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSString *)
|
||||
js_ValueToString(JSContext *cx, jsval v)
|
||||
JSString *
|
||||
js_ValueToString(JSContext *cx, const Value &v)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
|
@ -3265,7 +3265,7 @@ AppendAtom(JSAtom *atom, JSCharBuffer &cb)
|
|||
}
|
||||
|
||||
/* This function implements E-262-3 section 9.8, toString. */
|
||||
JS_FRIEND_API(JSBool)
|
||||
JSBool
|
||||
js_ValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb)
|
||||
{
|
||||
if (!JSVAL_IS_PRIMITIVE(v) && !JSVAL_TO_OBJECT(v)->defaultValue(cx, JSTYPE_STRING, &v))
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
#include "jshashtable.h"
|
||||
#include "jslock.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#define JSSTRING_BIT(n) ((size_t)1 << (n))
|
||||
#define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1)
|
||||
|
||||
|
@ -471,7 +469,7 @@ JS_ISSPACE(jschar c)
|
|||
#define JS7_ISLET(c) ((c) < 128 && isalpha(c))
|
||||
|
||||
/* Initialize the String class, returning its prototype object. */
|
||||
extern JSClass js_StringClass;
|
||||
extern js::Class js_StringClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitStringClass(JSContext *cx, JSObject *obj);
|
||||
|
@ -511,10 +509,10 @@ js_NewStringCopyZ(JSContext *cx, const jschar *s);
|
|||
/*
|
||||
* Convert a value to a printable C string.
|
||||
*/
|
||||
typedef JSString *(*JSValueToStringFun)(JSContext *cx, jsval v);
|
||||
typedef JSString *(*JSValueToStringFun)(JSContext *cx, const js::Value &v);
|
||||
|
||||
extern JS_FRIEND_API(const char *)
|
||||
js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun);
|
||||
js_ValueToPrintable(JSContext *cx, const js::Value &, JSValueToStringFun v2sfun);
|
||||
|
||||
#define js_ValueToPrintableString(cx,v) \
|
||||
js_ValueToPrintable(cx, v, js_ValueToString)
|
||||
|
@ -526,23 +524,23 @@ js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun);
|
|||
* Convert a value to a string, returning null after reporting an error,
|
||||
* otherwise returning a new string reference.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSString *)
|
||||
js_ValueToString(JSContext *cx, jsval v);
|
||||
extern JSString *
|
||||
js_ValueToString(JSContext *cx, const js::Value &v);
|
||||
|
||||
/*
|
||||
* This function implements E-262-3 section 9.8, toString. Convert the given
|
||||
* value to a string of jschars appended to the given buffer. On error, the
|
||||
* passed buffer may have partial results appended.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_ValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb);
|
||||
extern JSBool
|
||||
js_ValueToCharBuffer(JSContext *cx, const js::Value &v, JSCharBuffer &cb);
|
||||
|
||||
/*
|
||||
* Convert a value to its source expression, returning null after reporting
|
||||
* an error, otherwise returning a new string reference.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSString *)
|
||||
js_ValueToSource(JSContext *cx, jsval v);
|
||||
js_ValueToSource(JSContext *cx, const js::Value &v);
|
||||
|
||||
/*
|
||||
* Compute a hash function from str. The caller can call this function even if
|
||||
|
@ -713,8 +711,6 @@ js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
|
|||
extern JSBool
|
||||
js_String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
namespace js {
|
||||
|
||||
class DeflatedStringCache {
|
||||
|
|
|
@ -343,6 +343,44 @@ PodArrayZero(T (&t)[N])
|
|||
memset(t, 0, N * sizeof(T));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class AlignedPtrAndFlag
|
||||
{
|
||||
uintptr_t bits;
|
||||
|
||||
public:
|
||||
AlignedPtrAndFlag(T *t, bool flag) {
|
||||
JS_ASSERT((uintptr_t(t) & 1) == 0);
|
||||
bits = uintptr_t(t) | flag;
|
||||
}
|
||||
|
||||
T *ptr() const {
|
||||
return (T *)(bits & ~uintptr_t(1));
|
||||
}
|
||||
|
||||
bool flag() const {
|
||||
return (bits & 1) != 0;
|
||||
}
|
||||
|
||||
void setPtr(T *t) const {
|
||||
JS_ASSERT((uintptr_t(t) & 1) == 0);
|
||||
bits = uintptr_t(t) | flag();
|
||||
}
|
||||
|
||||
void setFlag() {
|
||||
bits |= 1;
|
||||
}
|
||||
|
||||
void unsetFlag() {
|
||||
bits &= ~uintptr_t(1);
|
||||
}
|
||||
|
||||
void set(T *t, bool flag) {
|
||||
JS_ASSERT((uintptr_t(t) & 1) == 0);
|
||||
bits = uintptr_t(t) | flag;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jstl_h_ */
|
||||
|
|
|
@ -11976,7 +11976,7 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex)
|
|||
LIns* idx_ins = get(&idx);
|
||||
LIns* v_ins = get(&v);
|
||||
|
||||
if (JS_InstanceOf(cx, obj, &js_ArgumentsClass, NULL))
|
||||
if (InstanceOf(cx, obj, &js_ArgumentsClass, NULL))
|
||||
RETURN_STOP_A("can't trace setting elements of the |arguments| object");
|
||||
|
||||
if (!JSVAL_IS_INT(idx)) {
|
||||
|
@ -14564,7 +14564,7 @@ TraceRecorder::record_JSOP_CALLPROP()
|
|||
|
||||
if (JSVAL_IS_PRIMITIVE(l)) {
|
||||
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, pcval.toObject());
|
||||
if (!PRIMITIVE_THIS_TEST(fun, l))
|
||||
if (!PrimitiveThisTest(fun, l))
|
||||
RETURN_STOP_A("callee does not accept primitive |this|");
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace js {
|
|||
* TypedArray with a size.
|
||||
*/
|
||||
struct JS_FRIEND_API(ArrayBuffer) {
|
||||
static JSClass jsclass;
|
||||
static js::Class jsclass;
|
||||
static JSPropertySpec jsprops[];
|
||||
|
||||
static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
@ -113,11 +113,11 @@ struct JS_FRIEND_API(TypedArray) {
|
|||
};
|
||||
|
||||
// and MUST NOT be used to construct new objects.
|
||||
static JSClass fastClasses[TYPE_MAX];
|
||||
static js::Class fastClasses[TYPE_MAX];
|
||||
|
||||
// These are the slow/original classes, used
|
||||
// fo constructing new objects
|
||||
static JSClass slowClasses[TYPE_MAX];
|
||||
static js::Class slowClasses[TYPE_MAX];
|
||||
|
||||
static JSPropertySpec jsprops[];
|
||||
|
||||
|
|
|
@ -103,6 +103,18 @@
|
|||
|
||||
# ifdef HAVE_VISIBILITY_ATTRIBUTE
|
||||
# define JS_EXTERNAL_VIS __attribute__((visibility ("default")))
|
||||
# if defined(__GNUC__) && __GNUC__ <= 4 && __GNUC_MINOR__ < 5
|
||||
/*
|
||||
* GCC wrongly produces a warning when a type with hidden visibility
|
||||
* (e.g. js::Value) is a member of a local class of a static function.
|
||||
* This is apparently fixed with GCC 4.5 and above. See:
|
||||
*
|
||||
* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40145.
|
||||
*/
|
||||
# define DEFINE_LOCAL_CLASS_OF_STATIC_FUNCTION(Name) class __attribute__((visibility ("hidden"))) Name
|
||||
# else
|
||||
# define DEFINE_LOCAL_CLASS_OF_STATIC_FUNCTION class Name
|
||||
# endif
|
||||
# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# define JS_EXTERNAL_VIS __global
|
||||
# else
|
||||
|
|
|
@ -110,7 +110,7 @@ struct JSXDRState {
|
|||
JSXDRMode mode;
|
||||
JSXDROps *ops;
|
||||
JSContext *cx;
|
||||
JSClass **registry;
|
||||
js::Class **registry;
|
||||
uintN numclasses;
|
||||
uintN maxclasses;
|
||||
void *reghash;
|
||||
|
@ -173,12 +173,12 @@ extern JS_PUBLIC_API(JSBool)
|
|||
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *lp);
|
||||
JS_XDRRegisterClass(JSXDRState *xdr, js::Class *clasp, uint32 *lp);
|
||||
|
||||
extern JS_PUBLIC_API(uint32)
|
||||
JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name);
|
||||
|
||||
extern JS_PUBLIC_API(JSClass *)
|
||||
extern JS_PUBLIC_API(js::Class *)
|
||||
JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
|
||||
|
||||
/*
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern const char js_AnyName_str[];
|
||||
extern const char js_AttributeName_str[];
|
||||
extern const char js_isXMLName_str[];
|
||||
|
@ -59,7 +57,7 @@ typedef JSBool
|
|||
struct JSXMLArray {
|
||||
uint32 length;
|
||||
uint32 capacity;
|
||||
void **vector;
|
||||
js::Value *vector;
|
||||
JSXMLArrayCursor *cursors;
|
||||
};
|
||||
|
||||
|
@ -69,11 +67,12 @@ struct JSXMLArrayCursor
|
|||
uint32 index;
|
||||
JSXMLArrayCursor *next;
|
||||
JSXMLArrayCursor **prevp;
|
||||
void *root;
|
||||
js::Value root;
|
||||
js::Value null;
|
||||
|
||||
JSXMLArrayCursor(JSXMLArray *array)
|
||||
: array(array), index(0), next(array->cursors), prevp(&array->cursors),
|
||||
root(NULL)
|
||||
root(), null()
|
||||
{
|
||||
if (next)
|
||||
next->prevp = &next;
|
||||
|
@ -91,16 +90,18 @@ struct JSXMLArrayCursor
|
|||
array = NULL;
|
||||
}
|
||||
|
||||
void *getNext() {
|
||||
const js::Value &getNext() {
|
||||
if (!array || index >= array->length)
|
||||
return NULL;
|
||||
return root = array->vector[index++];
|
||||
return null;
|
||||
root.copy(array->vector[index++]);
|
||||
return root;
|
||||
}
|
||||
|
||||
void *getCurrent() {
|
||||
const js::Value &getCurrent() {
|
||||
if (!array || index >= array->length)
|
||||
return NULL;
|
||||
return root = array->vector[index];
|
||||
return null;
|
||||
root.copy(array->vector[index]);
|
||||
return root;
|
||||
}
|
||||
|
||||
void trace(JSTracer *trc) {
|
||||
|
@ -108,9 +109,8 @@ struct JSXMLArrayCursor
|
|||
size_t index = 0;
|
||||
#endif
|
||||
for (JSXMLArrayCursor *cursor = this; cursor; cursor = cursor->next) {
|
||||
void *root = cursor->root;
|
||||
JS_SET_TRACING_INDEX(trc, "cursor_root", index++);
|
||||
js_CallValueTracerIfGCThing(trc, jsval(root));
|
||||
CallGCMarkerIfGCThing(trc, cursor->root);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -173,7 +173,7 @@ struct JSXML {
|
|||
} u;
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSXML) % JSVAL_ALIGN == 0);
|
||||
JS_STATIC_ASSERT(sizeof(JSXML) % JSBOXEDWORD_ALIGN == 0);
|
||||
|
||||
/* union member shorthands */
|
||||
#define xml_kids u.list.kids
|
||||
|
@ -209,13 +209,13 @@ js_NewXMLObject(JSContext *cx, JSXMLClass xml_class);
|
|||
extern JSObject *
|
||||
js_GetXMLObject(JSContext *cx, JSXML *xml);
|
||||
|
||||
extern JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps;
|
||||
extern JS_FRIEND_DATA(JSClass) js_XMLClass;
|
||||
extern JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass;
|
||||
extern JS_FRIEND_DATA(JSExtendedClass) js_QNameClass;
|
||||
extern JS_FRIEND_DATA(JSClass) js_AttributeNameClass;
|
||||
extern JS_FRIEND_DATA(JSClass) js_AnyNameClass;
|
||||
extern JSClass js_XMLFilterClass;
|
||||
extern JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps;
|
||||
extern JS_FRIEND_DATA(js::Class) js_XMLClass;
|
||||
extern JS_FRIEND_DATA(js::ExtendedClass) js_NamespaceClass;
|
||||
extern JS_FRIEND_DATA(js::ExtendedClass) js_QNameClass;
|
||||
extern JS_FRIEND_DATA(js::Class) js_AttributeNameClass;
|
||||
extern JS_FRIEND_DATA(js::Class) js_AnyNameClass;
|
||||
extern js::Class js_XMLFilterClass;
|
||||
|
||||
/*
|
||||
* Methods to test whether an object or a value is of type "xml" (per typeof).
|
||||
|
@ -231,8 +231,8 @@ JSObject::isXML() const
|
|||
}
|
||||
|
||||
#define OBJECT_IS_XML(cx,obj) (obj)->isXML()
|
||||
#define VALUE_IS_XML(cx,v) (!JSVAL_IS_PRIMITIVE(v) && \
|
||||
JSVAL_TO_OBJECT(v)->isXML())
|
||||
#define VALUE_IS_XML(cx,v) ((v).isObject() && \
|
||||
(v).asObject().isXML())
|
||||
|
||||
extern JSObject *
|
||||
js_InitNamespaceClass(JSContext *cx, JSObject *obj);
|
||||
|
@ -253,7 +253,7 @@ extern JSObject *
|
|||
js_InitXMLClasses(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
js_GetFunctionNamespace(JSContext *cx, jsval *vp);
|
||||
js_GetFunctionNamespace(JSContext *cx, const js::Value *vp);
|
||||
|
||||
/*
|
||||
* If obj is QName corresponding to function::name, set *funidp to name's id,
|
||||
|
@ -266,7 +266,7 @@ extern JSBool
|
|||
js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_SetDefaultXMLNamespace(JSContext *cx, jsval v);
|
||||
js_SetDefaultXMLNamespace(JSContext *cx, const js::Value &v);
|
||||
|
||||
/*
|
||||
* Return true if v is a XML QName object, or if it converts to a string that
|
||||
|
@ -277,7 +277,7 @@ extern JSBool
|
|||
js_IsXMLName(JSContext *cx, jsval v);
|
||||
|
||||
extern JSBool
|
||||
js_ToAttributeName(JSContext *cx, jsval *vp);
|
||||
js_ToAttributeName(JSContext *cx, js::Value *vp);
|
||||
|
||||
extern JSString *
|
||||
js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote);
|
||||
|
@ -290,25 +290,26 @@ extern JSString *
|
|||
js_EscapeElementValue(JSContext *cx, JSString *str);
|
||||
|
||||
extern JSString *
|
||||
js_ValueToXMLString(JSContext *cx, jsval v);
|
||||
js_ValueToXMLString(JSContext *cx, const js::Value &v);
|
||||
|
||||
extern JSObject *
|
||||
js_ConstructXMLQNameObject(JSContext *cx, jsval nsval, jsval lnval);
|
||||
js_ConstructXMLQNameObject(JSContext *cx, const js::Value & nsval,
|
||||
const js::Value & lnval);
|
||||
|
||||
extern JSBool
|
||||
js_GetAnyName(JSContext *cx, jsval *vp);
|
||||
js_GetAnyName(JSContext *cx, js::Value *vp);
|
||||
|
||||
/*
|
||||
* Note: nameval must be either QName, AttributeName, or AnyName.
|
||||
*/
|
||||
extern JSBool
|
||||
js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid *idp);
|
||||
js_FindXMLProperty(JSContext *cx, const js::Value &nameval, JSObject **objp, jsid *idp);
|
||||
|
||||
extern JSBool
|
||||
js_GetXMLMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_DeleteXMLListElements(JSContext *cx, JSObject *listobj);
|
||||
|
@ -317,10 +318,10 @@ extern JSBool
|
|||
js_StepXMLListFilter(JSContext *cx, JSBool initialized);
|
||||
|
||||
extern JSObject *
|
||||
js_ValueToXMLObject(JSContext *cx, jsval v);
|
||||
js_ValueToXMLObject(JSContext *cx, const js::Value &v);
|
||||
|
||||
extern JSObject *
|
||||
js_ValueToXMLListObject(JSContext *cx, jsval v);
|
||||
js_ValueToXMLListObject(JSContext *cx, const js::Value &v);
|
||||
|
||||
extern JSObject *
|
||||
js_CloneXMLObject(JSContext *cx, JSObject *obj);
|
||||
|
@ -343,11 +344,10 @@ js_EnumerateXMLValues(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
|||
jsval *statep, jsid *idp, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_TestXMLEquality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
js_TestXMLEquality(JSContext *cx, const js::Value &v1, const js::Value &v2,
|
||||
JSBool *bp);
|
||||
|
||||
extern JSBool
|
||||
js_ConcatenateXML(JSContext *cx, JSObject *obj, jsval v, jsval *vp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
js_ConcatenateXML(JSContext *cx, JSObject *obj1, JSObject *obj2, js::Value *vp);
|
||||
|
||||
#endif /* jsxml_h___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче