зеркало из https://github.com/mozilla/gecko-dev.git
Fast natives and related optimizations (385393, r=igor).
This commit is contained in:
Родитель
daca981d3e
Коммит
b36bbabdb0
111
js/src/js.c
111
js/src/js.c
|
@ -625,7 +625,7 @@ Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
* Provides a hook for scripts to read a line from stdin.
|
||||
*/
|
||||
static JSBool
|
||||
ReadLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
ReadLine(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
#define BUFSIZE 256
|
||||
FILE *from;
|
||||
|
@ -669,7 +669,7 @@ ReadLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
|
||||
/* Treat the empty string specially. */
|
||||
if (buflength == 0) {
|
||||
*rval = feof(from) ? JSVAL_NULL : JS_GetEmptyStringValue(cx);
|
||||
*vp = feof(from) ? JSVAL_NULL : JS_GetEmptyStringValue(cx);
|
||||
JS_free(cx, buf);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -693,7 +693,7 @@ ReadLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -730,7 +730,7 @@ Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
GC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
GC(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
uint32 preBytes;
|
||||
|
@ -750,18 +750,20 @@ GC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
#ifdef JS_GCMETER
|
||||
js_DumpGCStats(rt, stdout);
|
||||
#endif
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
static JSBool
|
||||
GCZeal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
GCZeal(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
uintN zeal;
|
||||
|
||||
if (!JS_ValueToECMAUint32(cx, argv[0], &zeal))
|
||||
if (!JS_ValueToECMAUint32(cx, vp[2], &zeal))
|
||||
return JS_FALSE;
|
||||
JS_SetGCZeal(cx, zeal);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif /* JS_GC_ZEAL */
|
||||
|
@ -1030,7 +1032,7 @@ SrcNotes(JSContext *cx, JSScript *script)
|
|||
|
||||
index = js_GetSrcNoteOffset(sn, 0);
|
||||
JS_GET_SCRIPT_OBJECT(script, index, obj);
|
||||
fun = (JSFunction *)JS_GetPrivate(cx, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
|
||||
bytes = str ? JS_GetStringBytes(str) : "N/A";
|
||||
fprintf(gOutFile, " function %u (%s)", index, bytes);
|
||||
|
@ -1619,13 +1621,14 @@ ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
#endif
|
||||
|
||||
static JSBool
|
||||
BuildDate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
BuildDate(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
char version[20] = "\n";
|
||||
#if JS_VERSION < 150
|
||||
sprintf(version, " for version %d\n", JS_VERSION);
|
||||
#endif
|
||||
fprintf(gOutFile, "built on %s at %s%s", __DATE__, __TIME__, version);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1639,17 +1642,18 @@ Clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
Intern(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
Intern(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
str = JS_ValueToString(cx, argv[0]);
|
||||
str = JS_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
if (!JS_InternUCStringN(cx, JS_GetStringChars(str),
|
||||
JS_GetStringLength(str))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1690,7 +1694,7 @@ Seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
GetPDA(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
GetPDA(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *vobj, *aobj, *pdobj;
|
||||
JSBool ok;
|
||||
|
@ -1699,7 +1703,7 @@ GetPDA(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
uint32 i;
|
||||
jsval v;
|
||||
|
||||
if (!JS_ValueToObject(cx, argv[0], &vobj))
|
||||
if (!JS_ValueToObject(cx, vp[2], &vobj))
|
||||
return JS_FALSE;
|
||||
if (!vobj)
|
||||
return JS_TRUE;
|
||||
|
@ -1707,7 +1711,7 @@ GetPDA(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
aobj = JS_NewArrayObject(cx, 0, NULL);
|
||||
if (!aobj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(aobj);
|
||||
*vp = OBJECT_TO_JSVAL(aobj);
|
||||
|
||||
ok = JS_GetPropertyDescArray(cx, vobj, &pda);
|
||||
if (!ok)
|
||||
|
@ -1740,25 +1744,25 @@ GetPDA(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
GetSLX(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
GetSLX(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSScript *script;
|
||||
|
||||
script = ValueToScript(cx, argv[0]);
|
||||
script = ValueToScript(cx, vp[2]);
|
||||
if (!script)
|
||||
return JS_FALSE;
|
||||
*rval = INT_TO_JSVAL(js_GetScriptLineExtent(script));
|
||||
*vp = INT_TO_JSVAL(js_GetScriptLineExtent(script));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ToInt32(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
ToInt32(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
if (!JS_ValueToInt32(cx, argv[0], &i))
|
||||
if (!JS_ValueToInt32(cx, vp[2], &i))
|
||||
return JS_FALSE;
|
||||
return JS_NewNumberValue(cx, i, rval);
|
||||
return JS_NewNumberValue(cx, i, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -2224,49 +2228,50 @@ out:
|
|||
return ok;
|
||||
}
|
||||
|
||||
/* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
|
||||
static JSFunctionSpec shell_functions[] = {
|
||||
{"version", Version, 0,0,0},
|
||||
{"options", Options, 0,0,0},
|
||||
{"load", Load, 1,0,0},
|
||||
{"readline", ReadLine, 0,0,0},
|
||||
{"print", Print, 0,0,0},
|
||||
{"help", Help, 0,0,0},
|
||||
{"quit", Quit, 0,0,0},
|
||||
{"gc", GC, 0,0,0},
|
||||
JS_FS("version", Version, 0,0,0),
|
||||
JS_FS("options", Options, 0,0,0),
|
||||
JS_FS("load", Load, 1,0,0),
|
||||
JS_FN("readline", ReadLine, 0,0,0,0),
|
||||
JS_FS("print", Print, 0,0,0),
|
||||
JS_FS("help", Help, 0,0,0),
|
||||
JS_FS("quit", Quit, 0,0,0),
|
||||
JS_FN("gc", GC, 0,0,0,0),
|
||||
#ifdef JS_GC_ZEAL
|
||||
{"gczeal", GCZeal, 1,0,0},
|
||||
JS_FN("gczeal", GCZeal, 1,1,0,0),
|
||||
#endif
|
||||
{"trap", Trap, 3,0,0},
|
||||
{"untrap", Untrap, 2,0,0},
|
||||
{"line2pc", LineToPC, 0,0,0},
|
||||
{"pc2line", PCToLine, 0,0,0},
|
||||
{"stringsAreUTF8", StringsAreUTF8, 0,0,0},
|
||||
{"testUTF8", TestUTF8, 1,0,0},
|
||||
{"throwError", ThrowError, 0,0,0},
|
||||
JS_FS("trap", Trap, 3,0,0),
|
||||
JS_FS("untrap", Untrap, 2,0,0),
|
||||
JS_FS("line2pc", LineToPC, 0,0,0),
|
||||
JS_FS("pc2line", PCToLine, 0,0,0),
|
||||
JS_FS("stringsAreUTF8", StringsAreUTF8, 0,0,0),
|
||||
JS_FS("testUTF8", TestUTF8, 1,0,0),
|
||||
JS_FS("throwError", ThrowError, 0,0,0),
|
||||
#ifdef DEBUG
|
||||
{"dis", Disassemble, 1,0,0},
|
||||
{"dissrc", DisassWithSrc, 1,0,0},
|
||||
{"dumpHeap", DumpHeap, 5,0,0},
|
||||
{"notes", Notes, 1,0,0},
|
||||
{"tracing", Tracing, 0,0,0},
|
||||
{"stats", DumpStats, 1,0,0},
|
||||
JS_FS("dis", Disassemble, 1,0,0),
|
||||
JS_FS("dissrc", DisassWithSrc, 1,0,0),
|
||||
JS_FS("dumpHeap", DumpHeap, 5,0,0),
|
||||
JS_FS("notes", Notes, 1,0,0),
|
||||
JS_FS("tracing", Tracing, 0,0,0),
|
||||
JS_FS("stats", DumpStats, 1,0,0),
|
||||
#endif
|
||||
#ifdef TEST_EXPORT
|
||||
{"xport", DoExport, 2,0,0},
|
||||
JS_FS("xport", DoExport, 2,0,0),
|
||||
#endif
|
||||
#ifdef TEST_CVTARGS
|
||||
{"cvtargs", ConvertArgs, 0,0,12},
|
||||
JS_FS("cvtargs", ConvertArgs, 0,0,12),
|
||||
#endif
|
||||
{"build", BuildDate, 0,0,0},
|
||||
{"clear", Clear, 0,0,0},
|
||||
{"intern", Intern, 1,0,0},
|
||||
{"clone", Clone, 1,0,0},
|
||||
{"seal", Seal, 1,0,1},
|
||||
{"getpda", GetPDA, 1,0,0},
|
||||
{"getslx", GetSLX, 1,0,0},
|
||||
{"toint32", ToInt32, 1,0,0},
|
||||
{"evalcx", EvalInContext, 1,0,0},
|
||||
{NULL,NULL,0,0,0}
|
||||
JS_FN("build", BuildDate, 0,0,0,0),
|
||||
JS_FS("clear", Clear, 0,0,0),
|
||||
JS_FN("intern", Intern, 1,1,0,0),
|
||||
JS_FS("clone", Clone, 1,0,0),
|
||||
JS_FS("seal", Seal, 1,0,1),
|
||||
JS_FN("getpda", GetPDA, 1,1,0,0),
|
||||
JS_FN("getslx", GetSLX, 1,1,0,0),
|
||||
JS_FN("toint32", ToInt32, 1,1,0,0),
|
||||
JS_FS("evalcx", EvalInContext, 1,0,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
/* NOTE: These must be kept in sync with the above. */
|
||||
|
|
|
@ -4106,6 +4106,65 @@ JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
|
|||
return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval fsv;
|
||||
JSFunctionSpec *fs;
|
||||
JSObject *tmp;
|
||||
JSStackFrame *fp;
|
||||
|
||||
if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(*vp), 0, &fsv))
|
||||
return JS_FALSE;
|
||||
fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
|
||||
JS_ASSERT((~fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) == 0);
|
||||
|
||||
/*
|
||||
* We know that vp[2] is valid because JS_DefineFunctions, which is our
|
||||
* only (indirect) referrer, defined us as requiring at least one argument
|
||||
* (notice how it passes fs->nargs + 1 as the next-to-last argument to
|
||||
* JS_DefineFunction).
|
||||
*/
|
||||
if (JSVAL_IS_PRIMITIVE(vp[2])) {
|
||||
/*
|
||||
* Make sure that this is an object or null, as required by the generic
|
||||
* functions.
|
||||
*/
|
||||
if (!js_ValueToObject(cx, vp[2], &tmp))
|
||||
return JS_FALSE;
|
||||
vp[2] = OBJECT_TO_JSVAL(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy all actual (argc) arguments down over our |this| parameter, vp[1],
|
||||
* which is almost always the class constructor object, e.g. Array. Then
|
||||
* call the corresponding prototype native method with our first argument
|
||||
* passed as |this|.
|
||||
*/
|
||||
memmove(vp + 1, vp + 2, argc * sizeof(jsval));
|
||||
|
||||
/*
|
||||
* Follow Function.prototype.apply and .call by using the global object as
|
||||
* the 'this' param if no args.
|
||||
*/
|
||||
fp = cx->fp;
|
||||
JS_ASSERT((fp->flags & JSFRAME_IN_FAST_CALL) || fp->argv == vp + 2);
|
||||
if (!js_ComputeThis(cx, vp + 2))
|
||||
return JS_FALSE;
|
||||
if (!(fp->flags & JSFRAME_IN_FAST_CALL))
|
||||
fp->thisp = JSVAL_TO_OBJECT(vp[1]);
|
||||
|
||||
/*
|
||||
* Protect against argc underflowing. By calling js_ComputeThis, we made
|
||||
* it as if the static was called with one parameter, the explicit |this|
|
||||
* object.
|
||||
*/
|
||||
if (argc != 0)
|
||||
--argc;
|
||||
|
||||
return ((JSFastNative) fs->call)(cx, argc, vp);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
|
||||
uintN argc, jsval *argv, jsval *rval)
|
||||
|
@ -4114,9 +4173,13 @@ js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
|
|||
JSFunctionSpec *fs;
|
||||
JSObject *tmp;
|
||||
|
||||
JS_ASSERT(!(cx->fp->flags & JSFRAME_IN_FAST_CALL));
|
||||
|
||||
if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), 0, &fsv))
|
||||
return JS_FALSE;
|
||||
fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
|
||||
JS_ASSERT((fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) ==
|
||||
JSFUN_GENERIC_NATIVE);
|
||||
|
||||
/*
|
||||
* We know that argv[0] is valid because JS_DefineFunctions, which is our
|
||||
|
@ -4135,12 +4198,12 @@ js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
|
|||
}
|
||||
|
||||
/*
|
||||
* Copy all actual (argc) and required but missing (fs->nargs + 1 - argc)
|
||||
* args down over our |this| parameter, argv[-1], which is almost always
|
||||
* the class constructor object, e.g. Array. Then call the corresponding
|
||||
* prototype native method with our first argument passed as |this|.
|
||||
* Copy all actual (argc) arguments down over our |this| parameter,
|
||||
* argv[-1], which is almost always the class constructor object, e.g.
|
||||
* Array. Then call the corresponding prototype native method with our
|
||||
* first argument passed as |this|.
|
||||
*/
|
||||
memmove(argv - 1, argv, JS_MAX(fs->nargs + 1U, argc) * sizeof(jsval));
|
||||
memmove(argv - 1, argv, argc * sizeof(jsval));
|
||||
|
||||
/*
|
||||
* Follow Function.prototype.apply and .call by using the global object as
|
||||
|
@ -4152,13 +4215,14 @@ js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
|
|||
cx->fp->thisp = JSVAL_TO_OBJECT(argv[-1]);
|
||||
|
||||
/*
|
||||
* Protect against argc - 1 underflowing below. By calling js_ComputeThis,
|
||||
* we made it as if the static was called with one parameter.
|
||||
* Protect against argc underflowing. By calling js_ComputeThis, we made
|
||||
* it as if the static was called with one parameter, the explicit |this|
|
||||
* object.
|
||||
*/
|
||||
if (argc == 0)
|
||||
argc = 1;
|
||||
if (argc != 0)
|
||||
--argc;
|
||||
|
||||
return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc - 1, argv, rval);
|
||||
return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc, argv, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -4171,9 +4235,6 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
|
|||
CHECK_REQUEST(cx);
|
||||
ctor = NULL;
|
||||
for (; fs->name; fs++) {
|
||||
|
||||
/* High bits of fs->extra are reserved. */
|
||||
JS_ASSERT((fs->extra & 0xFFFF0000) == 0);
|
||||
flags = fs->flags;
|
||||
|
||||
/*
|
||||
|
@ -4189,11 +4250,15 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
|
|||
|
||||
flags &= ~JSFUN_GENERIC_NATIVE;
|
||||
fun = JS_DefineFunction(cx, ctor, fs->name,
|
||||
js_generic_native_method_dispatcher,
|
||||
(flags & JSFUN_FAST_NATIVE)
|
||||
? (JSNative)
|
||||
js_generic_fast_native_method_dispatcher
|
||||
: js_generic_native_method_dispatcher,
|
||||
fs->nargs + 1, flags);
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
fun->u.n.extra = (uint16)fs->extra;
|
||||
fun->u.n.minargs = (uint16)(fs->extra >> 16);
|
||||
|
||||
/*
|
||||
* As jsapi.h notes, fs must point to storage that lives as long
|
||||
|
@ -4203,10 +4268,13 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_ASSERT(!(flags & JSFUN_FAST_NATIVE) ||
|
||||
(uint16)(fs->extra >> 16) <= fs->nargs);
|
||||
fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
fun->u.n.extra = (uint16)fs->extra;
|
||||
fun->u.n.minargs = (uint16)(fs->extra >> 16);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -4867,6 +4935,7 @@ JS_IsRunning(JSContext *cx)
|
|||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsConstructing(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(!cx->fp || !(cx->fp->flags & JSFRAME_IN_FAST_CALL));
|
||||
return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);
|
||||
}
|
||||
|
||||
|
@ -4876,6 +4945,7 @@ JS_IsAssigning(JSContext *cx)
|
|||
JSStackFrame *fp;
|
||||
jsbytecode *pc;
|
||||
|
||||
JS_ASSERT(!cx->fp || !(cx->fp->flags & JSFRAME_IN_FAST_CALL));
|
||||
for (fp = cx->fp; fp && !fp->script; fp = fp->down)
|
||||
continue;
|
||||
if (!fp || !(pc = fp->pc))
|
||||
|
@ -4901,6 +4971,7 @@ JS_SaveFrameChain(JSContext *cx)
|
|||
if (!fp)
|
||||
return fp;
|
||||
|
||||
JS_ASSERT(!(fp->flags & JSFRAME_IN_FAST_CALL));
|
||||
JS_ASSERT(!fp->dormantNext);
|
||||
fp->dormantNext = cx->dormantFrameChain;
|
||||
cx->dormantFrameChain = fp;
|
||||
|
|
|
@ -180,7 +180,9 @@ JS_BEGIN_EXTERN_C
|
|||
#define JSFUN_THISP_BOOLEAN 0x0400 /* |this| may be a primitive boolean */
|
||||
#define JSFUN_THISP_PRIMITIVE 0x0700 /* |this| may be any primitive value */
|
||||
|
||||
#define JSFUN_FLAGS_MASK 0x07f8 /* overlay JSFUN_* attributes --
|
||||
#define JSFUN_FAST_NATIVE 0x0800 /* JSFastNative needs no JSStackFrame */
|
||||
|
||||
#define JSFUN_FLAGS_MASK 0x0ff8 /* overlay JSFUN_* attributes --
|
||||
note that bit #15 is used internally
|
||||
to flag interpreted functions */
|
||||
|
||||
|
@ -642,6 +644,29 @@ JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
|
|||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetScopeChain(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Macros to hide interpreter stack layout details from a JSFastNative using
|
||||
* its jsval *vp parameter. The stack layout underlying invocation can't change
|
||||
* without breaking source and binary compatibility (argv[-2] is well-known to
|
||||
* be the callee jsval, and argv[-1] is as well known to be |this|).
|
||||
*
|
||||
* NB: there is an anti-dependency between JS_CALLEE and JS_SET_RVAL: native
|
||||
* methods that may inspect their callee must defer setting their return value
|
||||
* until after any such possible inspection. Otherwise the return value will be
|
||||
* inspected instead of the callee function object.
|
||||
*
|
||||
* WARNING: These are not (yet) mandatory macros, but new code outside of the
|
||||
* engine should use them. In the Mozilla 2.0 milestone their definitions may
|
||||
* change incompatibly.
|
||||
*/
|
||||
#define JS_CALLEE(cx,vp) ((vp)[0])
|
||||
#define JS_ARGV_CALLEE(argv) ((argv)[-2])
|
||||
#define JS_THIS(cx,vp) ((vp)[1])
|
||||
#define JS_THIS_OBJECT(cx,vp) ((JSObject *) JS_THIS(cx,vp))
|
||||
#define JS_ARGV(cx,vp) ((vp) + 2)
|
||||
#define JS_RVAL(cx,vp) (*(vp))
|
||||
#define JS_SET_RVAL(cx,vp,v) (*(vp) = (v))
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_malloc(JSContext *cx, size_t nbytes);
|
||||
|
||||
|
@ -1375,13 +1400,39 @@ struct JSFunctionSpec {
|
|||
#else
|
||||
uint16 nargs;
|
||||
uint16 flags;
|
||||
uint32 extra; /* extra & 0xFFFF:
|
||||
number of arg slots for local GC roots
|
||||
extra >> 16:
|
||||
reserved, must be zero */
|
||||
|
||||
/*
|
||||
* extra & 0xFFFF: number of arg slots for local GC roots;
|
||||
* extra >> 16: reserved, must be zero.
|
||||
*/
|
||||
uint32 extra;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Terminating sentinel initializer to put at the end of a JSFunctionSpec array
|
||||
* that's passed to JS_DefineFunctions or JS_InitClass.
|
||||
*/
|
||||
#define JS_FS_END JS_FS(NULL,NULL,0,0,0)
|
||||
|
||||
/*
|
||||
* Initializer macro for a row in a JSFunctionSpec array. This is the original
|
||||
* kind of native function specifier initializer. Use JS_FN ("fast native", see
|
||||
* JSFastNative in jspubtd.h) for all functions that do not need a stack frame
|
||||
* when activated.
|
||||
*/
|
||||
#define JS_FS(name,call,nargs,flags,extra) \
|
||||
{name, call, nargs, flags, extra}
|
||||
|
||||
/*
|
||||
* "Fast native" initializer macro for a JSFunctionSpec array element. Use this
|
||||
* in preference to JS_FS if the native in question does not need its own stack
|
||||
* frame when activated.
|
||||
*/
|
||||
#define JS_FN(name,fastcall,minargs,nargs,flags,extra) \
|
||||
{name, (JSNative)(fastcall), nargs, (flags) | JSFUN_FAST_NATIVE, \
|
||||
(minargs) << 16 | (uint16)(extra)}
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
JSClass *clasp, JSNative constructor, uintN nargs,
|
||||
|
|
472
js/src/jsarray.c
472
js/src/jsarray.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -61,6 +61,8 @@ js_InitArrayClass(JSContext *cx, JSObject *obj);
|
|||
extern JSObject *
|
||||
js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector);
|
||||
|
||||
#define JSSLOT_ARRAY_LENGTH JSSLOT_PRIVATE
|
||||
|
||||
extern JSBool
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
|
||||
|
|
|
@ -300,7 +300,6 @@ extern const char js_next_str[];
|
|||
extern const char js_noSuchMethod_str[];
|
||||
extern const char js_object_str[];
|
||||
extern const char js_parent_str[];
|
||||
extern const char js_private_str[];
|
||||
extern const char js_proto_str[];
|
||||
extern const char js_ptagc_str[];
|
||||
extern const char js_qualifier_str[];
|
||||
|
|
|
@ -66,78 +66,57 @@ JSClass js_BooleanClass = {
|
|||
#include "jsprf.h"
|
||||
|
||||
static JSBool
|
||||
bool_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
bool_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval v;
|
||||
char buf[32];
|
||||
JSString *str;
|
||||
|
||||
if (JSVAL_IS_BOOLEAN((jsval)obj)) {
|
||||
v = (jsval)obj;
|
||||
} else {
|
||||
if (!JS_InstanceOf(cx, obj, &js_BooleanClass, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
if (!JSVAL_IS_BOOLEAN(v))
|
||||
return js_obj_toSource(cx, obj, argc, argv, rval);
|
||||
}
|
||||
if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
|
||||
JS_snprintf(buf, sizeof buf, "(new %s(%s))",
|
||||
js_BooleanClass.name,
|
||||
js_boolean_strs[JSVAL_TO_BOOLEAN(v) ? 1 : 0]);
|
||||
str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
bool_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
bool_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval v;
|
||||
JSAtom *atom;
|
||||
JSString *str;
|
||||
|
||||
if (JSVAL_IS_BOOLEAN((jsval)obj)) {
|
||||
v = (jsval)obj;
|
||||
} else {
|
||||
if (!JS_InstanceOf(cx, obj, &js_BooleanClass, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
if (!JSVAL_IS_BOOLEAN(v))
|
||||
return js_obj_toString(cx, obj, argc, argv, rval);
|
||||
}
|
||||
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];
|
||||
str = ATOM_TO_STRING(atom);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
bool_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
bool_valueOf(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (JSVAL_IS_BOOLEAN((jsval)obj)) {
|
||||
*rval = (jsval)obj;
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!JS_InstanceOf(cx, obj, &js_BooleanClass, argv))
|
||||
return JS_FALSE;
|
||||
*rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
return JS_TRUE;
|
||||
return js_GetPrimitiveThis(cx, vp, &js_BooleanClass, vp);
|
||||
}
|
||||
|
||||
static JSFunctionSpec boolean_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, bool_toSource, 0,JSFUN_THISP_BOOLEAN,0},
|
||||
JS_FN(js_toSource_str, bool_toSource, 0, 0, JSFUN_THISP_BOOLEAN,0),
|
||||
#endif
|
||||
{js_toString_str, bool_toString, 0,JSFUN_THISP_BOOLEAN,0},
|
||||
{js_valueOf_str, bool_valueOf, 0,JSFUN_THISP_BOOLEAN,0},
|
||||
{0,0,0,0,0}
|
||||
JS_FN(js_toString_str, bool_toString, 0, 0, JSFUN_THISP_BOOLEAN,0),
|
||||
JS_FN(js_valueOf_str, bool_valueOf, 0, 0, JSFUN_THISP_BOOLEAN,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static JSBool
|
||||
|
|
|
@ -422,6 +422,14 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
|||
*/
|
||||
js_FinishDeflatedStringCache(rt);
|
||||
|
||||
/*
|
||||
* Free unit string storage only after the last GC has completed, so
|
||||
* that js_FinalizeStringRT can detect unit strings and avoid calling
|
||||
* free on their chars storage.
|
||||
*/
|
||||
free(rt->unitStrings);
|
||||
rt->unitStrings = NULL;
|
||||
|
||||
/* Take the runtime down, now that it has no contexts or atoms. */
|
||||
JS_LOCK_GC(rt);
|
||||
rt->state = JSRTS_DOWN;
|
||||
|
|
|
@ -248,8 +248,12 @@ struct JSRuntime {
|
|||
uint32 deflatedStringCacheBytes;
|
||||
#endif
|
||||
|
||||
/* Empty string held for use by this runtime's contexts. */
|
||||
/*
|
||||
* Empty and unit-length strings held for use by this runtime's contexts.
|
||||
* The unitStrings array and its elements are created on demand.
|
||||
*/
|
||||
JSString *emptyString;
|
||||
JSString **unitStrings;
|
||||
|
||||
/* List of active contexts sharing this runtime; protected by gcLock. */
|
||||
JSCList contextList;
|
||||
|
@ -638,6 +642,9 @@ struct JSContext {
|
|||
* property values associated with this context's global object.
|
||||
*/
|
||||
uint8 xmlSettingFlags;
|
||||
uint8 padding;
|
||||
#else
|
||||
uint16 padding;
|
||||
#endif
|
||||
|
||||
/* Runtime version control identifier. */
|
||||
|
|
574
js/src/jsdate.c
574
js/src/jsdate.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -525,7 +525,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
closure = (JSObject *) wp->closure;
|
||||
clasp = OBJ_GET_CLASS(cx, closure);
|
||||
if (clasp == &js_FunctionClass) {
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, closure);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, closure);
|
||||
script = FUN_SCRIPT(fun);
|
||||
} else if (clasp == &js_ScriptClass) {
|
||||
fun = NULL;
|
||||
|
@ -537,7 +537,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
nslots = 2;
|
||||
if (fun) {
|
||||
nslots += fun->nargs;
|
||||
nslots += FUN_MINARGS(fun);
|
||||
if (FUN_NATIVE(fun))
|
||||
nslots += fun->u.n.extra;
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
|
||||
funobj = JSVAL_TO_OBJECT(argv[-2]);
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass);
|
||||
wrapper = (JSFunction *) JS_GetPrivate(cx, funobj);
|
||||
wrapper = (JSFunction *) OBJ_GET_PRIVATE(cx, funobj);
|
||||
userid = ATOM_KEY(wrapper->atom);
|
||||
*rval = argv[0];
|
||||
return js_watch_set(cx, obj, userid, rval);
|
||||
|
@ -879,6 +879,12 @@ JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
|
|||
return FUN_NATIVE(fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFastNative)
|
||||
JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return FUN_FAST_NATIVE(fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptPrincipals(JSContext *cx, JSScript *script)
|
||||
{
|
||||
|
@ -1051,7 +1057,13 @@ JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
|
|||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->argv && fp->fun ? JSVAL_TO_OBJECT(fp->argv[-2]) : NULL;
|
||||
if (fp->argv && fp->fun) {
|
||||
JSObject *obj = JSVAL_TO_OBJECT(fp->argv[-2]);
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_FunctionClass);
|
||||
JS_ASSERT(OBJ_GET_PRIVATE(cx, obj) == fp->fun);
|
||||
return obj;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
|
|
@ -137,6 +137,9 @@ JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
|
|||
extern JS_PUBLIC_API(JSNative)
|
||||
JS_GetFunctionNative(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(JSFastNative)
|
||||
JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptPrincipals(JSContext *cx, JSScript *script);
|
||||
|
||||
|
|
|
@ -1761,7 +1761,6 @@ EmitIndexOp(JSContext *cx, JSOp op, uintN index, JSCodeGenerator *cg)
|
|||
/*
|
||||
* Slight sugar for EmitIndexOp, again accessing cx and cg from the macro
|
||||
* caller's lexical environment, and embedding a false return on error.
|
||||
* XXXbe hey, who checks for fun->nvars and fun->nargs overflow?!
|
||||
*/
|
||||
#define EMIT_INDEX_OP(op, index) \
|
||||
JS_BEGIN_MACRO \
|
||||
|
@ -2113,7 +2112,7 @@ CheckSideEffects(JSContext *cx, JSTreeContext *tc, JSParseNode *pn,
|
|||
* name in that scope object. See comments at case JSOP_NAMEDFUNOBJ:
|
||||
* in jsinterp.c.
|
||||
*/
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, pn->pn_funpob->object);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, pn->pn_funpob->object);
|
||||
if (fun->atom)
|
||||
*answer = JS_TRUE;
|
||||
break;
|
||||
|
@ -2305,7 +2304,7 @@ EmitNameOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
if (op == JSOP_ARGUMENTS) {
|
||||
if (js_Emit1(cx, cg, op) < 0)
|
||||
return JS_FALSE;
|
||||
if (callContext && js_Emit1(cx, cg, JSOP_NULL) < 0)
|
||||
if (callContext && js_Emit1(cx, cg, JSOP_GLOBALTHIS) < 0)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (pn->pn_slot >= 0) {
|
||||
|
@ -4029,7 +4028,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
}
|
||||
cg2->treeContext.flags = (uint16) (pn->pn_flags | TCF_IN_FUNCTION);
|
||||
cg2->parent = cg;
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, pn->pn_funpob->object);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, pn->pn_funpob->object);
|
||||
if (!js_EmitFunctionBody(cx, cg2, pn->pn_body, fun))
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -5928,11 +5927,14 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
/* FALL THROUGH */
|
||||
default:
|
||||
/*
|
||||
* Push null after the expression as this object for the function
|
||||
* call. js_ComputeThis replaces null by a proper object.
|
||||
* Push the appropriate global object after the expression as the
|
||||
* |this| parameter for the function call. ECMA-262 specifies that
|
||||
* this happens after actual argument evaluation, but the result
|
||||
* can't be affected by argument evaluation so we do it early and
|
||||
* avoid null testing in js_ComputeThis.
|
||||
*/
|
||||
if (!js_EmitTree(cx, cg, pn2) ||
|
||||
!js_Emit1(cx, cg, JSOP_NULL) < 0) {
|
||||
!js_Emit1(cx, cg, JSOP_GLOBALTHIS) < 0) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -5947,8 +5949,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
*/
|
||||
oldflags = cg->treeContext.flags;
|
||||
cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
|
||||
for (pn2 = pn2->pn_next; pn2; pn2 = pn2->pn_next) {
|
||||
if (!js_EmitTree(cx, cg, pn2))
|
||||
for (pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
|
||||
if (!js_EmitTree(cx, cg, pn3))
|
||||
return JS_FALSE;
|
||||
}
|
||||
cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
|
||||
|
|
|
@ -811,20 +811,22 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
* number information along with this message.
|
||||
*/
|
||||
static JSBool
|
||||
exn_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
exn_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
jsval v;
|
||||
JSString *name, *message, *result;
|
||||
jschar *chars, *cp;
|
||||
size_t name_length, message_length, length;
|
||||
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!OBJ_GET_PROPERTY(cx, obj,
|
||||
ATOM_TO_JSID(cx->runtime->atomState.nameAtom),
|
||||
&v)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;
|
||||
*rval = STRING_TO_JSVAL(name);
|
||||
*vp = STRING_TO_JSVAL(name);
|
||||
|
||||
if (!JS_GetProperty(cx, obj, js_message_str, &v))
|
||||
return JS_FALSE;
|
||||
|
@ -857,7 +859,7 @@ exn_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
result = name;
|
||||
}
|
||||
|
||||
*rval = STRING_TO_JSVAL(result);
|
||||
*vp = STRING_TO_JSVAL(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -866,45 +868,47 @@ exn_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
* Return a string that may eval to something similar to the original object.
|
||||
*/
|
||||
static JSBool
|
||||
exn_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
exn_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval *vp;
|
||||
jsval *localroots;
|
||||
JSObject *obj;
|
||||
JSString *name, *message, *filename, *lineno_as_str, *result;
|
||||
uint32 lineno;
|
||||
size_t lineno_length, name_length, message_length, filename_length, length;
|
||||
jschar *chars, *cp;
|
||||
|
||||
vp = argv + argc; /* beginning of explicit local roots */
|
||||
localroots = JS_ARGV(cx, vp) + argc;
|
||||
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!OBJ_GET_PROPERTY(cx, obj,
|
||||
ATOM_TO_JSID(cx->runtime->atomState.nameAtom),
|
||||
rval)) {
|
||||
vp)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
name = js_ValueToString(cx, *rval);
|
||||
name = js_ValueToString(cx, *vp);
|
||||
if (!name)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(name);
|
||||
*vp = STRING_TO_JSVAL(name);
|
||||
|
||||
if (!JS_GetProperty(cx, obj, js_message_str, &vp[0]) ||
|
||||
!(message = js_ValueToSource(cx, vp[0]))) {
|
||||
if (!JS_GetProperty(cx, obj, js_message_str, &localroots[0]) ||
|
||||
!(message = js_ValueToSource(cx, localroots[0]))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
vp[0] = STRING_TO_JSVAL(message);
|
||||
localroots[0] = STRING_TO_JSVAL(message);
|
||||
|
||||
if (!JS_GetProperty(cx, obj, js_fileName_str, &vp[1]) ||
|
||||
!(filename = js_ValueToSource(cx, vp[1]))) {
|
||||
if (!JS_GetProperty(cx, obj, js_fileName_str, &localroots[1]) ||
|
||||
!(filename = js_ValueToSource(cx, localroots[1]))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
vp[1] = STRING_TO_JSVAL(filename);
|
||||
localroots[1] = STRING_TO_JSVAL(filename);
|
||||
|
||||
if (!JS_GetProperty(cx, obj, js_lineNumber_str, &vp[2]) ||
|
||||
!js_ValueToECMAUint32 (cx, vp[2], &lineno)) {
|
||||
if (!JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]) ||
|
||||
!js_ValueToECMAUint32 (cx, localroots[2], &lineno)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (lineno != 0) {
|
||||
lineno_as_str = js_ValueToString(cx, vp[2]);
|
||||
lineno_as_str = js_ValueToString(cx, localroots[2]);
|
||||
if (!lineno_as_str)
|
||||
return JS_FALSE;
|
||||
lineno_length = JSSTRING_LENGTH(lineno_as_str);
|
||||
|
@ -977,17 +981,17 @@ exn_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
JS_free(cx, chars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*rval = STRING_TO_JSVAL(result);
|
||||
*vp = STRING_TO_JSVAL(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSFunctionSpec exception_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, exn_toSource, 0,0,3},
|
||||
JS_FN(js_toSource_str, exn_toSource, 0,0,0,3),
|
||||
#endif
|
||||
{js_toString_str, exn_toString, 0,0,0},
|
||||
{0,0,0,0,0}
|
||||
JS_FN(js_toString_str, exn_toString, 0,0,0,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
JSObject *
|
||||
|
@ -1239,7 +1243,7 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
{
|
||||
jsval exn;
|
||||
JSObject *exnObject;
|
||||
jsval vp[5];
|
||||
jsval roots[5];
|
||||
JSTempValueRooter tvr;
|
||||
JSErrorReport *reportp, report;
|
||||
JSString *str;
|
||||
|
@ -1252,8 +1256,8 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
if (!JS_GetPendingException(cx, &exn))
|
||||
return JS_FALSE;
|
||||
|
||||
memset(vp, 0, sizeof vp);
|
||||
JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(vp), vp, &tvr);
|
||||
memset(roots, 0, sizeof roots);
|
||||
JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(roots), roots, &tvr);
|
||||
|
||||
/*
|
||||
* Because js_ValueToString below could error and an exception object
|
||||
|
@ -1265,7 +1269,7 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
exnObject = NULL;
|
||||
} else {
|
||||
exnObject = JSVAL_TO_OBJECT(exn);
|
||||
vp[0] = exn;
|
||||
roots[0] = exn;
|
||||
}
|
||||
|
||||
JS_ClearPendingException(cx);
|
||||
|
@ -1276,7 +1280,7 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
if (!str) {
|
||||
bytes = "unknown (can't convert to string)";
|
||||
} else {
|
||||
vp[1] = STRING_TO_JSVAL(str);
|
||||
roots[1] = STRING_TO_JSVAL(str);
|
||||
bytes = js_GetStringBytes(cx, str);
|
||||
if (!bytes) {
|
||||
ok = JS_FALSE;
|
||||
|
@ -1291,21 +1295,21 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
const char *filename;
|
||||
uint32 lineno;
|
||||
|
||||
ok = JS_GetProperty(cx, exnObject, js_message_str, &vp[2]);
|
||||
ok = JS_GetProperty(cx, exnObject, js_message_str, &roots[2]);
|
||||
if (!ok)
|
||||
goto out;
|
||||
if (JSVAL_IS_STRING(vp[2])) {
|
||||
bytes = js_GetStringBytes(cx, JSVAL_TO_STRING(vp[2]));
|
||||
if (JSVAL_IS_STRING(roots[2])) {
|
||||
bytes = js_GetStringBytes(cx, JSVAL_TO_STRING(roots[2]));
|
||||
if (!bytes) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ok = JS_GetProperty(cx, exnObject, js_fileName_str, &vp[3]);
|
||||
ok = JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3]);
|
||||
if (!ok)
|
||||
goto out;
|
||||
str = js_ValueToString(cx, vp[3]);
|
||||
str = js_ValueToString(cx, roots[3]);
|
||||
if (!str) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
|
@ -1316,10 +1320,10 @@ js_ReportUncaughtException(JSContext *cx)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ok = JS_GetProperty(cx, exnObject, js_lineNumber_str, &vp[4]);
|
||||
ok = JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]);
|
||||
if (!ok)
|
||||
goto out;
|
||||
ok = js_ValueToECMAUint32 (cx, vp[4], &lineno);
|
||||
ok = js_ValueToECMAUint32 (cx, roots[4], &lineno);
|
||||
if (!ok)
|
||||
goto out;
|
||||
|
||||
|
|
151
js/src/jsfun.c
151
js/src/jsfun.c
|
@ -207,7 +207,7 @@ js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp)
|
|||
/*
|
||||
* Per ECMA-262 Ed. 3, 10.1.8, last bulleted item, do not share
|
||||
* storage between the formal parameter and arguments[k] for all
|
||||
* k >= fp->argc && k < fp->fun->nargs. For example, in
|
||||
* fp->argc <= k && k < fp->fun->nargs. For example, in
|
||||
*
|
||||
* function f(x) { x = 42; return arguments[0]; }
|
||||
* f();
|
||||
|
@ -848,7 +848,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
funobj = fp->argv ? JSVAL_TO_OBJECT(fp->argv[-2]) : fp->fun->object;
|
||||
if (!funobj)
|
||||
return JS_TRUE;
|
||||
JS_ASSERT((JSFunction *) JS_GetPrivate(cx, funobj) == fp->fun);
|
||||
JS_ASSERT((JSFunction *) OBJ_GET_PRIVATE(cx, funobj) == fp->fun);
|
||||
|
||||
str = JSVAL_TO_STRING(id);
|
||||
atom = js_AtomizeString(cx, str, 0);
|
||||
|
@ -872,7 +872,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
/* Ensure we found an arg or var property for the same function. */
|
||||
if ((sprop->flags & SPROP_IS_HIDDEN) &&
|
||||
(obj2 == funobj ||
|
||||
(JSFunction *) JS_GetPrivate(cx, obj2) == fp->fun)) {
|
||||
(JSFunction *) OBJ_GET_PRIVATE(cx, obj2) == fp->fun)) {
|
||||
if (getter == js_GetArgument) {
|
||||
vp = fp->argv;
|
||||
nslots = JS_MAX(fp->argc, fp->fun->nargs);
|
||||
|
@ -1316,7 +1316,7 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
|
|||
* (return true, no error report) in case one does due to API pilot
|
||||
* or internal error.
|
||||
*/
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, *objp);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, *objp);
|
||||
if (!fun)
|
||||
return JS_TRUE;
|
||||
if (!FUN_INTERPRETED(fun)) {
|
||||
|
@ -1510,7 +1510,7 @@ fun_trace(JSTracer *trc, JSObject *obj)
|
|||
{
|
||||
JSFunction *fun;
|
||||
|
||||
fun = (JSFunction *) JS_GetPrivate(trc->context, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
if (fun) {
|
||||
JS_CALL_TRACER(trc, fun, JSTRACE_FUNCTION, "private");
|
||||
if (fun->object != obj)
|
||||
|
@ -1553,85 +1553,83 @@ JS_FRIEND_DATA(JSClass) js_FunctionClass = {
|
|||
JS_CLASS_TRACE(fun_trace), fun_reserveSlots
|
||||
};
|
||||
|
||||
JSBool
|
||||
js_fun_toString(JSContext *cx, JSObject *obj, uint32 indent,
|
||||
uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool
|
||||
fun_toStringHelper(JSContext *cx, uint32 indent, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval fval;
|
||||
JSObject *obj;
|
||||
JSFunction *fun;
|
||||
JSString *str;
|
||||
|
||||
if (!argv) {
|
||||
JS_ASSERT(JS_ObjectIsFunction(cx, obj));
|
||||
} else {
|
||||
fval = argv[-1];
|
||||
if (!VALUE_IS_FUNCTION(cx, fval)) {
|
||||
/*
|
||||
* If we don't have a function to start off with, try converting
|
||||
* the object to a function. If that doesn't work, complain.
|
||||
*/
|
||||
if (JSVAL_IS_OBJECT(fval)) {
|
||||
obj = JSVAL_TO_OBJECT(fval);
|
||||
if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, JSTYPE_FUNCTION,
|
||||
&fval)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
argv[-1] = fval;
|
||||
}
|
||||
if (!VALUE_IS_FUNCTION(cx, fval)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_PROTO,
|
||||
js_Function_str, js_toString_str,
|
||||
JS_GetTypeName(cx,
|
||||
JS_TypeOfValue(cx, fval)));
|
||||
fval = vp[1];
|
||||
if (!VALUE_IS_FUNCTION(cx, fval)) {
|
||||
/*
|
||||
* If we don't have a function to start off with, try converting the
|
||||
* object to a function. If that doesn't work, complain.
|
||||
*/
|
||||
if (!JSVAL_IS_PRIMITIVE(fval)) {
|
||||
obj = JSVAL_TO_OBJECT(fval);
|
||||
if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, JSTYPE_FUNCTION,
|
||||
&fval)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
vp[1] = fval;
|
||||
}
|
||||
if (!VALUE_IS_FUNCTION(cx, fval)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_PROTO,
|
||||
js_Function_str, js_toString_str,
|
||||
JS_GetTypeName(cx, JS_TypeOfValue(cx, fval)));
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
obj = JSVAL_TO_OBJECT(fval);
|
||||
}
|
||||
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
obj = JSVAL_TO_OBJECT(fval);
|
||||
if (argc != 0 && !js_ValueToECMAUint32(cx, vp[2], &indent))
|
||||
return JS_FALSE;
|
||||
|
||||
JS_ASSERT(JS_ObjectIsFunction(cx, obj));
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
if (!fun)
|
||||
return JS_TRUE;
|
||||
if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent))
|
||||
return JS_FALSE;
|
||||
str = JS_DecompileFunction(cx, fun, (uintN)indent);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
fun_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
fun_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return js_fun_toString(cx, obj, 0, argc, argv, rval);
|
||||
return fun_toStringHelper(cx, 0, argc, vp);
|
||||
}
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
static JSBool
|
||||
fun_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
fun_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return js_fun_toString(cx, obj, JS_DONT_PRETTY_PRINT, argc, argv, rval);
|
||||
return fun_toStringHelper(cx, JS_DONT_PRETTY_PRINT, argc, vp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char call_str[] = "call";
|
||||
|
||||
static JSBool
|
||||
fun_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
fun_call(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval fval, *sp, *oldsp;
|
||||
JSObject *obj;
|
||||
jsval fval, *argv, *sp, *oldsp;
|
||||
JSString *str;
|
||||
void *mark;
|
||||
uintN i;
|
||||
JSStackFrame *fp;
|
||||
JSBool ok;
|
||||
|
||||
if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &argv[-1]))
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))
|
||||
return JS_FALSE;
|
||||
fval = argv[-1];
|
||||
fval = vp[1];
|
||||
|
||||
if (!VALUE_IS_FUNCTION(cx, fval)) {
|
||||
str = JS_ValueToString(cx, fval);
|
||||
|
@ -1648,6 +1646,7 @@ fun_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
argv = vp + 2;
|
||||
if (argc == 0) {
|
||||
/* Call fun with its global object as the 'this' param if no args. */
|
||||
obj = NULL;
|
||||
|
@ -1676,21 +1675,24 @@ fun_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
fp = cx->fp;
|
||||
oldsp = fp->sp;
|
||||
fp->sp = sp;
|
||||
ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER);
|
||||
ok = js_Invoke(cx, argc,
|
||||
(fp->flags & JSFRAME_IN_FAST_CALL)
|
||||
? JSINVOKE_INTERNAL
|
||||
: JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER);
|
||||
|
||||
/* Store rval and pop stack back to our frame's sp. */
|
||||
*rval = fp->sp[-1];
|
||||
*vp = fp->sp[-1];
|
||||
fp->sp = oldsp;
|
||||
js_FreeStack(cx, mark);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
fun_apply(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
fun_apply(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj, *aobj;
|
||||
jsval fval, *sp, *oldsp;
|
||||
JSString *str;
|
||||
JSObject *aobj;
|
||||
jsuint length;
|
||||
JSBool arraylike, ok;
|
||||
void *mark;
|
||||
|
@ -1699,12 +1701,13 @@ fun_apply(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
|
||||
if (argc == 0) {
|
||||
/* Will get globalObject as 'this' and no other arguments. */
|
||||
return fun_call(cx, obj, argc, argv, rval);
|
||||
return fun_call(cx, argc, vp);
|
||||
}
|
||||
|
||||
if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &argv[-1]))
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))
|
||||
return JS_FALSE;
|
||||
fval = argv[-1];
|
||||
fval = vp[1];
|
||||
|
||||
if (!VALUE_IS_FUNCTION(cx, fval)) {
|
||||
str = JS_ValueToString(cx, fval);
|
||||
|
@ -1727,13 +1730,13 @@ fun_apply(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
|
||||
if (argc >= 2) {
|
||||
/* If the 2nd arg is null or void, call the function with 0 args. */
|
||||
if (JSVAL_IS_NULL(argv[1]) || JSVAL_IS_VOID(argv[1])) {
|
||||
if (JSVAL_IS_NULL(vp[3]) || JSVAL_IS_VOID(vp[3])) {
|
||||
argc = 0;
|
||||
} else {
|
||||
/* The second arg must be an array (or arguments object). */
|
||||
arraylike = JS_FALSE;
|
||||
if (!JSVAL_IS_PRIMITIVE(argv[1])) {
|
||||
aobj = JSVAL_TO_OBJECT(argv[1]);
|
||||
if (!JSVAL_IS_PRIMITIVE(vp[3])) {
|
||||
aobj = JSVAL_TO_OBJECT(vp[3]);
|
||||
if (!js_IsArrayLike(cx, aobj, &arraylike, &length))
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -1746,9 +1749,9 @@ fun_apply(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
}
|
||||
|
||||
/* Convert the first arg to 'this' and skip over it. */
|
||||
if (!JSVAL_IS_PRIMITIVE(argv[0]))
|
||||
obj = JSVAL_TO_OBJECT(argv[0]);
|
||||
else if (!js_ValueToObject(cx, argv[0], &obj))
|
||||
if (!JSVAL_IS_PRIMITIVE(vp[2]))
|
||||
obj = JSVAL_TO_OBJECT(vp[2]);
|
||||
else if (!js_ValueToObject(cx, vp[2], &obj))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Allocate stack space for fval, obj, and the args. */
|
||||
|
@ -1771,10 +1774,13 @@ fun_apply(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
fp = cx->fp;
|
||||
oldsp = fp->sp;
|
||||
fp->sp = sp;
|
||||
ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER);
|
||||
ok = js_Invoke(cx, argc,
|
||||
(fp->flags & JSFRAME_IN_FAST_CALL)
|
||||
? JSINVOKE_INTERNAL
|
||||
: JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER);
|
||||
|
||||
/* Store rval and pop stack back to our frame's sp. */
|
||||
*rval = fp->sp[-1];
|
||||
*vp = fp->sp[-1];
|
||||
fp->sp = oldsp;
|
||||
out:
|
||||
js_FreeStack(cx, mark);
|
||||
|
@ -1783,8 +1789,7 @@ out:
|
|||
|
||||
#ifdef NARCISSUS
|
||||
static JSBool
|
||||
fun_applyConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
fun_applyConstructor(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *aobj;
|
||||
uintN length, i;
|
||||
|
@ -1793,8 +1798,8 @@ fun_applyConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
JSStackFrame *fp;
|
||||
JSBool ok;
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(argv[0]) ||
|
||||
(aobj = JSVAL_TO_OBJECT(argv[0]),
|
||||
if (JSVAL_IS_PRIMITIVE(vp[2]) ||
|
||||
(aobj = JSVAL_TO_OBJECT(vp[2]),
|
||||
OBJ_GET_CLASS(cx, aobj) != &js_ArrayClass &&
|
||||
OBJ_GET_CLASS(cx, aobj) != &js_ArgumentsClass)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
|
@ -1813,7 +1818,7 @@ fun_applyConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
|
||||
fp = cx->fp;
|
||||
oldsp = fp->sp;
|
||||
*sp++ = OBJECT_TO_JSVAL(obj);
|
||||
*sp++ = vp[1];
|
||||
*sp++ = JSVAL_NULL; /* This is filled automagically. */
|
||||
for (i = 0; i < length; i++) {
|
||||
ok = JS_GetElement(cx, aobj, (jsint)i, sp);
|
||||
|
@ -1826,7 +1831,7 @@ fun_applyConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
fp->sp = sp;
|
||||
ok = js_InvokeConstructor(cx, newsp, length);
|
||||
|
||||
*rval = fp->sp[-1];
|
||||
*vp = fp->sp[-1];
|
||||
fp->sp = oldsp;
|
||||
out:
|
||||
js_FreeStack(cx, mark);
|
||||
|
@ -1836,15 +1841,15 @@ out:
|
|||
|
||||
static JSFunctionSpec function_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, fun_toSource, 0,0,0},
|
||||
JS_FN(js_toSource_str, fun_toSource, 0,0,0,0),
|
||||
#endif
|
||||
{js_toString_str, fun_toString, 1,0,0},
|
||||
{"apply", fun_apply, 2,0,0},
|
||||
{call_str, fun_call, 1,0,0},
|
||||
JS_FN(js_toString_str, fun_toString, 0,0,0,0),
|
||||
JS_FN("apply", fun_apply, 0,2,0,0),
|
||||
JS_FN(call_str, fun_call, 0,1,0,0),
|
||||
#ifdef NARCISSUS
|
||||
{"__applyConstructor__", fun_applyConstructor, 1,0,0},
|
||||
JS_FN("__applyConstructor__", fun_applyConstructor, 0,1,0,0),
|
||||
#endif
|
||||
{0,0,0,0,0}
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static JSBool
|
||||
|
@ -2209,7 +2214,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
|||
fun->flags = flags & JSFUN_FLAGS_MASK;
|
||||
fun->u.n.native = native;
|
||||
fun->u.n.extra = 0;
|
||||
fun->u.n.spare = 0;
|
||||
fun->u.n.minargs = 0;
|
||||
fun->atom = atom;
|
||||
fun->clasp = NULL;
|
||||
|
||||
|
|
|
@ -49,12 +49,14 @@ JS_BEGIN_EXTERN_C
|
|||
|
||||
struct JSFunction {
|
||||
JSObject *object; /* back-pointer to GC'ed object header */
|
||||
uint16 nargs; /* minimum number of actual arguments */
|
||||
uint16 nargs; /* maximum number of specified arguments,
|
||||
reflected as f.length/f.arity */
|
||||
uint16 flags; /* bound method and other flags, see jsapi.h */
|
||||
union {
|
||||
struct {
|
||||
uint16 extra; /* number of arg slots for local GC roots */
|
||||
uint16 spare; /* reserved for future use */
|
||||
uint16 minargs; /* minimum number of specified arguments, used
|
||||
only when calling fast native */
|
||||
JSNative native; /* native method pointer or null */
|
||||
} n;
|
||||
struct {
|
||||
|
@ -70,9 +72,18 @@ struct JSFunction {
|
|||
#define JSFUN_EXPR_CLOSURE 0x4000 /* expression closure: function(x)x*x */
|
||||
#define JSFUN_INTERPRETED 0x8000 /* use u.i if set, u.n if unset */
|
||||
|
||||
#define JSFUN_SCRIPT_OR_FAST_NATIVE (JSFUN_INTERPRETED | JSFUN_FAST_NATIVE)
|
||||
|
||||
#define FUN_INTERPRETED(fun) ((fun)->flags & JSFUN_INTERPRETED)
|
||||
#define FUN_NATIVE(fun) (FUN_INTERPRETED(fun) ? NULL : (fun)->u.n.native)
|
||||
#define FUN_SLOW_NATIVE(fun) (!((fun)->flags & JSFUN_SCRIPT_OR_FAST_NATIVE))
|
||||
#define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL)
|
||||
#define FUN_NATIVE(fun) (FUN_SLOW_NATIVE(fun) ? (fun)->u.n.native : NULL)
|
||||
#define FUN_FAST_NATIVE(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
|
||||
? (JSFastNative) (fun)->u.n.native \
|
||||
: NULL)
|
||||
#define FUN_MINARGS(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
|
||||
? (fun)->u.n.minargs \
|
||||
: (fun)->nargs)
|
||||
|
||||
extern JSClass js_ArgumentsClass;
|
||||
extern JSClass js_CallClass;
|
||||
|
@ -87,10 +98,6 @@ extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
|
|||
(!JSVAL_IS_PRIMITIVE(v) && \
|
||||
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass)
|
||||
|
||||
extern JSBool
|
||||
js_fun_toString(JSContext *cx, JSObject *obj, uint32 indent,
|
||||
uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
extern JSObject *
|
||||
js_InitFunctionClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
|
|
|
@ -1943,7 +1943,8 @@ gc_lock_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
|
|||
void
|
||||
js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
|
||||
{
|
||||
uintN depth, nslots;
|
||||
uintN depth, nslots, minargs;
|
||||
|
||||
if (fp->callobj)
|
||||
JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call");
|
||||
if (fp->argsobj)
|
||||
|
@ -2000,8 +2001,9 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
|
|||
if (fp->argv) {
|
||||
nslots = fp->argc;
|
||||
if (fp->fun) {
|
||||
if (fp->fun->nargs > nslots)
|
||||
nslots = fp->fun->nargs;
|
||||
minargs = FUN_MINARGS(fp->fun);
|
||||
if (minargs > nslots)
|
||||
nslots = minargs;
|
||||
if (!FUN_INTERPRETED(fp->fun))
|
||||
nslots += fp->fun->u.n.extra;
|
||||
}
|
||||
|
|
|
@ -506,67 +506,101 @@ PutBlockObjects(JSContext *cx, JSStackFrame *fp)
|
|||
}
|
||||
|
||||
JSBool
|
||||
js_ComputeThis(JSContext *cx, jsval *argv)
|
||||
js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp)
|
||||
{
|
||||
jsval v;
|
||||
JSObject *obj;
|
||||
|
||||
v = vp[1];
|
||||
if (JSVAL_IS_OBJECT(v)) {
|
||||
obj = JSVAL_TO_OBJECT(v);
|
||||
if (!JS_InstanceOf(cx, obj, clasp, vp + 2))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
}
|
||||
*thisvp = v;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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".
|
||||
*/
|
||||
static JSBool
|
||||
ComputeGlobalThis(JSContext *cx, jsval *argv)
|
||||
{
|
||||
JSObject *thisp;
|
||||
|
||||
if (!JSVAL_IS_OBJECT(argv[-1]))
|
||||
return js_PrimitiveToObject(cx, &argv[-1]);
|
||||
|
||||
thisp = JSVAL_TO_OBJECT(argv[-1]);
|
||||
if (thisp && OBJ_GET_CLASS(cx, thisp) != &js_CallClass) {
|
||||
if (!thisp->map->ops->thisObject)
|
||||
return JS_TRUE;
|
||||
|
||||
/* Some objects (e.g., With) delegate 'this' to another object. */
|
||||
thisp = OBJ_THIS_OBJECT(cx, thisp);
|
||||
if (!thisp)
|
||||
return JS_FALSE;
|
||||
if (JSVAL_IS_PRIMITIVE(argv[-2]) ||
|
||||
!OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]))) {
|
||||
thisp = cx->globalObject;
|
||||
} else {
|
||||
/*
|
||||
* ECMA requires "the global object", but in the presence of multiple
|
||||
* top-level objects (windows, frames, or certain layers in the client
|
||||
* object model), 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".
|
||||
*/
|
||||
if (JSVAL_IS_PRIMITIVE(argv[-2]) ||
|
||||
!OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]))) {
|
||||
thisp = cx->globalObject;
|
||||
} else {
|
||||
jsid id;
|
||||
jsval v;
|
||||
uintN attrs;
|
||||
JSObject *parent;
|
||||
jsid id;
|
||||
jsval v;
|
||||
uintN attrs;
|
||||
JSObject *parent;
|
||||
|
||||
/* Walk up the parent chain. */
|
||||
thisp = JSVAL_TO_OBJECT(argv[-2]);
|
||||
id = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);
|
||||
for (;;) {
|
||||
if (!OBJ_CHECK_ACCESS(cx, thisp, id, JSACC_PARENT, &v, &attrs))
|
||||
return JS_FALSE;
|
||||
parent = JSVAL_IS_VOID(v)
|
||||
? OBJ_GET_PARENT(cx, thisp)
|
||||
: JSVAL_TO_OBJECT(v);
|
||||
if (!parent)
|
||||
break;
|
||||
thisp = parent;
|
||||
}
|
||||
/* Walk up the parent chain. */
|
||||
thisp = JSVAL_TO_OBJECT(argv[-2]);
|
||||
id = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);
|
||||
for (;;) {
|
||||
if (!OBJ_CHECK_ACCESS(cx, thisp, id, JSACC_PARENT, &v, &attrs))
|
||||
return JS_FALSE;
|
||||
parent = JSVAL_IS_VOID(v)
|
||||
? OBJ_GET_PARENT(cx, thisp)
|
||||
: JSVAL_TO_OBJECT(v);
|
||||
if (!parent)
|
||||
break;
|
||||
thisp = parent;
|
||||
}
|
||||
}
|
||||
argv[-1] = OBJECT_TO_JSVAL(thisp);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ComputeThis(JSContext *cx, jsval *argv)
|
||||
{
|
||||
JSObject *thisp;
|
||||
|
||||
JS_ASSERT(!JSVAL_IS_NULL(argv[-1]));
|
||||
if (!JSVAL_IS_OBJECT(argv[-1]))
|
||||
return js_PrimitiveToObject(cx, &argv[-1]);
|
||||
|
||||
thisp = JSVAL_TO_OBJECT(argv[-1]);
|
||||
if (OBJ_GET_CLASS(cx, thisp) == &js_CallClass)
|
||||
return ComputeGlobalThis(cx, argv);
|
||||
|
||||
if (!thisp->map->ops->thisObject)
|
||||
return JS_TRUE;
|
||||
|
||||
/* Some objects (e.g., With) delegate 'this' to another object. */
|
||||
thisp = thisp->map->ops->thisObject(cx, thisp);
|
||||
if (!thisp)
|
||||
return JS_FALSE;
|
||||
argv[-1] = OBJECT_TO_JSVAL(thisp);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_ComputeThis(JSContext *cx, jsval *argv)
|
||||
{
|
||||
if (JSVAL_IS_NULL(argv[-1]))
|
||||
return ComputeGlobalThis(cx, argv);
|
||||
return ComputeThis(cx, argv);
|
||||
}
|
||||
|
||||
#if JS_HAS_NO_SUCH_METHOD
|
||||
|
||||
static JSBool
|
||||
|
@ -581,24 +615,9 @@ NoSuchMethod(JSContext *cx, JSStackFrame *fp, jsval *vp, uint32 flags,
|
|||
JSBool ok;
|
||||
jsbytecode *pc;
|
||||
|
||||
/*
|
||||
* We must call js_ComputeThis here to censor Call objects. A performance
|
||||
* hit, since we'll call it again in the normal sequence of invoke events,
|
||||
* but at least it's idempotent.
|
||||
*
|
||||
* Normally, we call ComputeThis after all frame members have been set,
|
||||
* and in particular, after any revision of the callee value at *vp due
|
||||
* to clasp->convert (see below). This matters because ComputeThis may
|
||||
* access *vp via fp->argv[-2], to follow the parent chain to a global
|
||||
* object to use as the 'this' parameter.
|
||||
*
|
||||
* Obviously, here in the JSVAL_IS_PRIMITIVE(v) case, there can't be any
|
||||
* such defaulting of 'this' to callee (v, *vp) ancestor.
|
||||
*/
|
||||
/* NB: js_ComputeThis or equivalent must have been called already. */
|
||||
JS_ASSERT(JSVAL_IS_PRIMITIVE(vp[0]));
|
||||
if (!js_ComputeThis(cx, vp + 2))
|
||||
return JS_FALSE;
|
||||
|
||||
JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));
|
||||
RESTORE_SP(fp);
|
||||
|
||||
/* From here on, control must flow through label out: to return. */
|
||||
|
@ -883,7 +902,7 @@ LogCall(JSContext *cx, jsval callee, uintN argc, jsval *argv)
|
|||
key.lineno = 0;
|
||||
name = "";
|
||||
if (VALUE_IS_FUNCTION(cx, callee)) {
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(callee));
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, JSVAL_TO_OBJECT(callee));
|
||||
if (fun->atom)
|
||||
name = js_AtomToPrintableString(cx, fun->atom);
|
||||
if (FUN_INTERPRETED(fun)) {
|
||||
|
@ -973,7 +992,7 @@ LogCall(JSContext *cx, jsval callee, uintN argc, jsval *argv)
|
|||
break;
|
||||
case JSTYPE_FUNCTION:
|
||||
if (VALUE_IS_FUNCTION(cx, argval)) {
|
||||
fun = (JSFunction *)JS_GetPrivate(cx, JSVAL_TO_OBJECT(argval));
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, JSVAL_TO_OBJECT(argval));
|
||||
if (fun && fun->atom) {
|
||||
str = ATOM_TO_STRING(fun->atom);
|
||||
break;
|
||||
|
@ -1010,6 +1029,35 @@ LogCall(JSContext *cx, jsval callee, uintN argc, jsval *argv)
|
|||
# define ASSERT_NOT_THROWING(cx) /* nothing */
|
||||
#endif
|
||||
|
||||
#define START_FAST_CALL(fp) (JS_ASSERT(!((fp)->flags & JSFRAME_IN_FAST_CALL)),\
|
||||
(fp)->flags |= JSFRAME_IN_FAST_CALL)
|
||||
#define END_FAST_CALL(fp) (JS_ASSERT((fp)->flags & JSFRAME_IN_FAST_CALL), \
|
||||
(fp)->flags &= ~JSFRAME_IN_FAST_CALL)
|
||||
|
||||
/*
|
||||
* We check if the function accepts a primitive value as |this|. For that we
|
||||
* use a table that maps value's tag into the corresponding function flag.
|
||||
*/
|
||||
JS_STATIC_ASSERT(JSVAL_INT == 1);
|
||||
JS_STATIC_ASSERT(JSVAL_DOUBLE == 2);
|
||||
JS_STATIC_ASSERT(JSVAL_STRING == 4);
|
||||
JS_STATIC_ASSERT(JSVAL_BOOLEAN == 6);
|
||||
|
||||
static const uint16 PrimitiveTestFlags[] = {
|
||||
JSFUN_THISP_NUMBER, /* INT */
|
||||
JSFUN_THISP_NUMBER, /* DOUBLE */
|
||||
JSFUN_THISP_NUMBER, /* INT */
|
||||
JSFUN_THISP_STRING, /* STRING */
|
||||
JSFUN_THISP_NUMBER, /* INT */
|
||||
JSFUN_THISP_BOOLEAN, /* BOOLEAN */
|
||||
JSFUN_THISP_NUMBER /* INT */
|
||||
};
|
||||
|
||||
#define PRIMITIVE_THIS_TEST(fun,thisv) \
|
||||
(JS_ASSERT(thisv != JSVAL_VOID), \
|
||||
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \
|
||||
PrimitiveTestFlags[JSVAL_TAG(thisv) - 1]))
|
||||
|
||||
/*
|
||||
* Find a function reference and its 'this' object implicit first parameter
|
||||
* under argc arguments on cx's stack, and call the function. Push missing
|
||||
|
@ -1121,8 +1169,9 @@ js_Invoke(JSContext *cx, uintN argc, uintN flags)
|
|||
} else {
|
||||
have_fun:
|
||||
/* Get private data and set derived locals from it. */
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, funobj);
|
||||
nslots = (fun->nargs > argc) ? fun->nargs - argc : 0;
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, funobj);
|
||||
nalloc = FUN_MINARGS(fun);
|
||||
nslots = (nalloc > argc) ? nalloc - argc : 0;
|
||||
if (FUN_INTERPRETED(fun)) {
|
||||
native = NULL;
|
||||
script = fun->u.i.script;
|
||||
|
@ -1138,31 +1187,8 @@ have_fun:
|
|||
/* Handle bound method special case. */
|
||||
vp[1] = OBJECT_TO_JSVAL(parent);
|
||||
} else if (!JSVAL_IS_OBJECT(vp[1])) {
|
||||
/*
|
||||
* We check if the function accepts a primitive value as |this|.
|
||||
* For that we use a table that maps value's tag into the
|
||||
* corresponding function flag.
|
||||
*/
|
||||
uintN flagToTest;
|
||||
|
||||
JS_STATIC_ASSERT(JSVAL_INT == 1);
|
||||
JS_STATIC_ASSERT(JSVAL_DOUBLE == 2);
|
||||
JS_STATIC_ASSERT(JSVAL_STRING == 4);
|
||||
JS_STATIC_ASSERT(JSVAL_BOOLEAN == 6);
|
||||
static const uint16 PrimitiveTestFlags[] = {
|
||||
JSFUN_THISP_NUMBER, /* INT */
|
||||
JSFUN_THISP_NUMBER, /* DOUBLE */
|
||||
JSFUN_THISP_NUMBER, /* INT */
|
||||
JSFUN_THISP_STRING, /* STRING */
|
||||
JSFUN_THISP_NUMBER, /* INT */
|
||||
JSFUN_THISP_BOOLEAN, /* BOOLEAN */
|
||||
JSFUN_THISP_NUMBER /* INT */
|
||||
};
|
||||
|
||||
JS_ASSERT(!(flags & JSINVOKE_CONSTRUCT));
|
||||
JS_ASSERT(vp[1] != JSVAL_VOID);
|
||||
flagToTest = PrimitiveTestFlags[JSVAL_TAG(vp[1]) - 1];
|
||||
if (JSFUN_THISP_TEST(JSFUN_THISP_FLAGS(fun->flags), flagToTest))
|
||||
if (PRIMITIVE_THIS_TEST(fun, vp[1]))
|
||||
goto init_frame;
|
||||
}
|
||||
}
|
||||
|
@ -1172,6 +1198,11 @@ have_fun:
|
|||
JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));
|
||||
frame.rval = vp[1];
|
||||
} else {
|
||||
/*
|
||||
* We must call js_ComputeThis in case we are not called from the
|
||||
* interpreter, where a prior bytecode has computed an appropriate
|
||||
* |this| already.
|
||||
*/
|
||||
ok = js_ComputeThis(cx, vp + 2);
|
||||
if (!ok)
|
||||
goto out2;
|
||||
|
@ -1182,7 +1213,7 @@ have_fun:
|
|||
* Initialize the rest of frame, except for sp (set by SAVE_SP later).
|
||||
*
|
||||
* To set thisp we use an explicit cast and not JSVAL_TO_OBJECT, as vp[1]
|
||||
* can be a primitive value here for native functions specified with
|
||||
* can be a primitive value here for those native functions specified with
|
||||
* JSFUN_THISP_(NUMBER|STRING|BOOLEAN) flags.
|
||||
*/
|
||||
frame.thisp = (JSObject *)vp[1];
|
||||
|
@ -1309,7 +1340,43 @@ have_fun:
|
|||
/* But ensure that we have a scope chain. */
|
||||
if (!frame.scopeChain)
|
||||
frame.scopeChain = parent;
|
||||
ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval);
|
||||
|
||||
if (fun && (fun->flags & JSFUN_FAST_NATIVE)) {
|
||||
/*
|
||||
* Note the lack of START/END_FAST_CALL bracketing here. Unlike
|
||||
* the other JSFastNative call (see the JSOP_CALL special case in
|
||||
* js_Interpret), we have a full stack frame for this call.
|
||||
*/
|
||||
ok = ((JSFastNative) native)(cx, argc, frame.argv - 2);
|
||||
frame.rval = frame.argv[-2];
|
||||
} else {
|
||||
#ifdef DEBUG_brendan
|
||||
static FILE *fp;
|
||||
if (!fp) {
|
||||
fp = fopen("/tmp/slow-natives.dump", "w");
|
||||
if (fp)
|
||||
setlinebuf(fp);
|
||||
}
|
||||
if (fp) {
|
||||
fprintf(fp, "%p %s.%s\n",
|
||||
native,
|
||||
JSVAL_IS_OBJECT(vp[1])
|
||||
? ((OBJ_GET_CLASS(cx, frame.thisp) == &js_FunctionClass)
|
||||
? JS_GetFunctionName(JS_GetPrivate(cx, frame.thisp))
|
||||
: OBJ_GET_CLASS(cx, frame.thisp)->name)
|
||||
: JSVAL_IS_BOOLEAN(vp[1])
|
||||
? js_BooleanClass.name
|
||||
: JSVAL_IS_STRING(vp[1])
|
||||
? js_StringClass.name
|
||||
: js_NumberClass.name,
|
||||
fun && fun->atom
|
||||
? JS_GetFunctionName(fun)
|
||||
: "???");
|
||||
}
|
||||
#endif
|
||||
ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval);
|
||||
}
|
||||
|
||||
JS_RUNTIME_METER(cx->runtime, nativeCalls);
|
||||
#ifdef DEBUG_NOT_THROWING
|
||||
if (ok && !alreadyThrowing)
|
||||
|
@ -1875,7 +1942,7 @@ js_InvokeConstructor(JSContext *cx, jsval *vp, uintN argc)
|
|||
parent = OBJ_GET_PARENT(cx, obj2);
|
||||
|
||||
if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) {
|
||||
funclasp = ((JSFunction *)JS_GetPrivate(cx, obj2))->clasp;
|
||||
funclasp = ((JSFunction *) OBJ_GET_PRIVATE(cx, obj2))->clasp;
|
||||
if (funclasp)
|
||||
clasp = funclasp;
|
||||
}
|
||||
|
@ -3815,8 +3882,8 @@ interrupt:
|
|||
|
||||
BEGIN_CASE(JSOP_CALLELEM)
|
||||
/*
|
||||
* XXX callelem should call getMethod on XML objects as CALLPROP
|
||||
* does. See bug 362910.
|
||||
* FIXME: JSOP_CALLELEM should call getMethod on XML objects as
|
||||
* CALLPROP does. See bug 362910.
|
||||
*/
|
||||
ELEMENT_OP(-1, ok = OBJ_GET_PROPERTY(cx, obj, id, &rval));
|
||||
STORE_OPND(-2, rval);
|
||||
|
@ -3848,185 +3915,221 @@ interrupt:
|
|||
vp = sp - (argc + 2);
|
||||
lval = *vp;
|
||||
SAVE_SP_AND_PC(fp);
|
||||
if (VALUE_IS_FUNCTION(cx, lval) &&
|
||||
(obj = JSVAL_TO_OBJECT(lval),
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj),
|
||||
FUN_INTERPRETED(fun)))
|
||||
/* inline_call: */
|
||||
{
|
||||
uintN nframeslots, nvars, nslots, missing;
|
||||
JSArena *a;
|
||||
jsuword avail, nbytes;
|
||||
JSBool overflow;
|
||||
void *newmark;
|
||||
jsval *rvp;
|
||||
JSInlineFrame *newifp;
|
||||
JSInterpreterHook hook;
|
||||
if (VALUE_IS_FUNCTION(cx, lval)) {
|
||||
obj = JSVAL_TO_OBJECT(lval);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
|
||||
/* Restrict recursion of lightweight functions. */
|
||||
if (inlineCallCount == MAX_INLINE_CALL_COUNT) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_OVER_RECURSED);
|
||||
if (fun->flags & JSFUN_FAST_NATIVE) {
|
||||
uintN nargs = JS_MAX(argc, fun->u.n.minargs);
|
||||
|
||||
nargs += fun->u.n.extra;
|
||||
if (argc < nargs) {
|
||||
/*
|
||||
* If we can't fit missing args and local roots in
|
||||
* this frame's operand stack, take the slow path.
|
||||
*/
|
||||
nargs -= argc;
|
||||
if (sp + nargs > fp->spbase + depth)
|
||||
goto do_invoke;
|
||||
do {
|
||||
PUSH(JSVAL_VOID);
|
||||
} while (--nargs != 0);
|
||||
SAVE_SP(fp);
|
||||
}
|
||||
|
||||
JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]) ||
|
||||
PRIMITIVE_THIS_TEST(fun, vp[1]));
|
||||
|
||||
START_FAST_CALL(fp);
|
||||
ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp);
|
||||
END_FAST_CALL(fp);
|
||||
if (!ok)
|
||||
goto out;
|
||||
sp = vp + 1;
|
||||
vp[-depth] = (jsval)pc;
|
||||
goto end_call;
|
||||
}
|
||||
|
||||
if (fun->flags & JSFUN_INTERPRETED) {
|
||||
uintN nframeslots, nvars, nslots, missing;
|
||||
JSArena *a;
|
||||
jsuword avail, nbytes;
|
||||
JSBool overflow;
|
||||
void *newmark;
|
||||
jsval *rvp;
|
||||
JSInlineFrame *newifp;
|
||||
JSInterpreterHook hook;
|
||||
|
||||
/* Restrict recursion of lightweight functions. */
|
||||
if (inlineCallCount == MAX_INLINE_CALL_COUNT) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_OVER_RECURSED);
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Compute the total number of stack slots needed by fun. */
|
||||
nframeslots = JS_HOWMANY(sizeof(JSInlineFrame),
|
||||
sizeof(jsval));
|
||||
nvars = fun->u.i.nvars;
|
||||
script = fun->u.i.script;
|
||||
depth = (jsint) script->depth;
|
||||
atoms = script->atomMap.vector;
|
||||
nslots = nframeslots + nvars + 2 * depth;
|
||||
|
||||
/* Allocate missing expected args adjacent to actuals. */
|
||||
missing = (fun->nargs > argc) ? fun->nargs - argc : 0;
|
||||
a = cx->stackPool.current;
|
||||
avail = a->avail;
|
||||
newmark = (void *) avail;
|
||||
if (missing) {
|
||||
newsp = sp + missing;
|
||||
overflow = (jsuword) newsp > a->limit;
|
||||
if (overflow)
|
||||
nslots += 2 + argc + missing;
|
||||
else if ((jsuword) newsp > avail)
|
||||
avail = a->avail = (jsuword) newsp;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
else overflow = JS_FALSE; /* suppress bogus gcc warnings */
|
||||
#endif
|
||||
|
||||
/* Allocate the inline frame with its vars and operands. */
|
||||
newsp = (jsval *) avail;
|
||||
nbytes = nslots * sizeof(jsval);
|
||||
avail += nbytes;
|
||||
if (avail <= a->limit) {
|
||||
a->avail = avail;
|
||||
} else {
|
||||
JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool,
|
||||
nbytes);
|
||||
if (!newsp) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_STACK_OVERFLOW,
|
||||
(fp && fp->fun)
|
||||
? JS_GetFunctionName(fp->fun)
|
||||
: "script");
|
||||
goto bad_inline_call;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Move args if missing overflow arena a, then push any
|
||||
* missing args.
|
||||
*/
|
||||
rvp = vp;
|
||||
if (missing) {
|
||||
if (overflow) {
|
||||
memcpy(newsp, vp, (2 + argc) * sizeof(jsval));
|
||||
vp = newsp;
|
||||
sp = vp + 2 + argc;
|
||||
newsp = sp + missing;
|
||||
}
|
||||
do {
|
||||
PUSH(JSVAL_VOID);
|
||||
} while (--missing != 0);
|
||||
}
|
||||
|
||||
/* Claim space for the stack frame and initialize it. */
|
||||
newifp = (JSInlineFrame *) newsp;
|
||||
newsp += nframeslots;
|
||||
newifp->frame.callobj = NULL;
|
||||
newifp->frame.argsobj = NULL;
|
||||
newifp->frame.varobj = NULL;
|
||||
newifp->frame.script = script;
|
||||
newifp->frame.fun = fun;
|
||||
newifp->frame.argc = argc;
|
||||
newifp->frame.argv = vp + 2;
|
||||
newifp->frame.rval = JSVAL_VOID;
|
||||
newifp->frame.nvars = nvars;
|
||||
newifp->frame.vars = newsp;
|
||||
newifp->frame.down = fp;
|
||||
newifp->frame.annotation = NULL;
|
||||
newifp->frame.scopeChain = parent = OBJ_GET_PARENT(cx, obj);
|
||||
newifp->frame.sharpDepth = 0;
|
||||
newifp->frame.sharpArray = NULL;
|
||||
newifp->frame.flags = 0;
|
||||
newifp->frame.dormantNext = NULL;
|
||||
newifp->frame.xmlNamespace = NULL;
|
||||
newifp->frame.blockChain = NULL;
|
||||
newifp->rvp = rvp;
|
||||
newifp->mark = newmark;
|
||||
|
||||
/* Compute the 'this' parameter now that argv is set. */
|
||||
JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));
|
||||
JS_ASSERT(!PRIMITIVE_THIS_TEST(fun, vp[1]));
|
||||
newifp->frame.thisp = (JSObject *)vp[1];
|
||||
#ifdef DUMP_CALL_TABLE
|
||||
LogCall(cx, *vp, argc, vp + 2);
|
||||
#endif
|
||||
|
||||
/* Push void to initialize local variables. */
|
||||
sp = newsp;
|
||||
while (nvars--)
|
||||
PUSH(JSVAL_VOID);
|
||||
sp += depth;
|
||||
newifp->frame.spbase = sp;
|
||||
SAVE_SP(&newifp->frame);
|
||||
|
||||
/* Call the debugger hook if present. */
|
||||
hook = cx->debugHooks->callHook;
|
||||
if (hook) {
|
||||
newifp->frame.pc = NULL;
|
||||
newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
|
||||
cx->debugHooks->callHookData);
|
||||
LOAD_INTERRUPT_HANDLER(cx);
|
||||
} else {
|
||||
newifp->hookData = NULL;
|
||||
}
|
||||
|
||||
/* Scope with a call object parented by callee's parent. */
|
||||
if (JSFUN_HEAVYWEIGHT_TEST(fun->flags) &&
|
||||
!js_GetCallObject(cx, &newifp->frame, parent)) {
|
||||
goto bad_inline_call;
|
||||
}
|
||||
|
||||
/* Switch version if currentVersion wasn't overridden. */
|
||||
newifp->callerVersion = (JSVersion) cx->version;
|
||||
if (JS_LIKELY(cx->version == currentVersion)) {
|
||||
currentVersion = (JSVersion) script->version;
|
||||
if (currentVersion != cx->version)
|
||||
js_SetVersion(cx, currentVersion);
|
||||
}
|
||||
|
||||
/* Push the frame and set interpreter registers. */
|
||||
cx->fp = fp = &newifp->frame;
|
||||
pc = script->code;
|
||||
#if !JS_THREADED_INTERP
|
||||
endpc = pc + script->length;
|
||||
#endif
|
||||
inlineCallCount++;
|
||||
JS_RUNTIME_METER(rt, inlineCalls);
|
||||
|
||||
/* Load first op and dispatch it (safe since JSOP_STOP). */
|
||||
op = (JSOp) *pc;
|
||||
DO_OP();
|
||||
|
||||
bad_inline_call:
|
||||
RESTORE_SP(fp);
|
||||
JS_ASSERT(fp->pc == pc);
|
||||
script = fp->script;
|
||||
depth = (jsint) script->depth;
|
||||
atoms = script->atomMap.vector;
|
||||
js_FreeRawStack(cx, newmark);
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Compute the total number of stack slots needed for fun. */
|
||||
nframeslots = JS_HOWMANY(sizeof(JSInlineFrame), sizeof(jsval));
|
||||
nvars = fun->u.i.nvars;
|
||||
script = fun->u.i.script;
|
||||
depth = (jsint) script->depth;
|
||||
atoms = script->atomMap.vector;
|
||||
nslots = nframeslots + nvars + 2 * depth;
|
||||
|
||||
/* Allocate missing expected args adjacent to actual args. */
|
||||
missing = (fun->nargs > argc) ? fun->nargs - argc : 0;
|
||||
a = cx->stackPool.current;
|
||||
avail = a->avail;
|
||||
newmark = (void *) avail;
|
||||
if (missing) {
|
||||
newsp = sp + missing;
|
||||
overflow = (jsuword) newsp > a->limit;
|
||||
if (overflow)
|
||||
nslots += 2 + argc + missing;
|
||||
else if ((jsuword) newsp > avail)
|
||||
avail = a->avail = (jsuword) newsp;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
else overflow = JS_FALSE; /* suppress bogus gcc warnings */
|
||||
#endif
|
||||
|
||||
/* Allocate the inline frame with its vars and operand slots. */
|
||||
newsp = (jsval *) avail;
|
||||
nbytes = nslots * sizeof(jsval);
|
||||
avail += nbytes;
|
||||
if (avail <= a->limit) {
|
||||
a->avail = avail;
|
||||
} else {
|
||||
JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool,
|
||||
nbytes);
|
||||
if (!newsp) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_STACK_OVERFLOW,
|
||||
(fp && fp->fun)
|
||||
? JS_GetFunctionName(fp->fun)
|
||||
: "script");
|
||||
goto bad_inline_call;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move args if missing overflow arena a, push missing args. */
|
||||
rvp = vp;
|
||||
if (missing) {
|
||||
if (overflow) {
|
||||
memcpy(newsp, vp, (2 + argc) * sizeof(jsval));
|
||||
vp = newsp;
|
||||
sp = vp + 2 + argc;
|
||||
newsp = sp + missing;
|
||||
}
|
||||
do {
|
||||
PUSH(JSVAL_VOID);
|
||||
} while (--missing != 0);
|
||||
}
|
||||
|
||||
/* Claim space for the stack frame and initialize it. */
|
||||
newifp = (JSInlineFrame *) newsp;
|
||||
newsp += nframeslots;
|
||||
newifp->frame.callobj = NULL;
|
||||
newifp->frame.argsobj = NULL;
|
||||
newifp->frame.varobj = NULL;
|
||||
newifp->frame.script = script;
|
||||
newifp->frame.fun = fun;
|
||||
newifp->frame.argc = argc;
|
||||
newifp->frame.argv = vp + 2;
|
||||
newifp->frame.rval = JSVAL_VOID;
|
||||
newifp->frame.nvars = nvars;
|
||||
newifp->frame.vars = newsp;
|
||||
newifp->frame.down = fp;
|
||||
newifp->frame.annotation = NULL;
|
||||
newifp->frame.scopeChain = parent = OBJ_GET_PARENT(cx, obj);
|
||||
newifp->frame.sharpDepth = 0;
|
||||
newifp->frame.sharpArray = NULL;
|
||||
newifp->frame.flags = 0;
|
||||
newifp->frame.dormantNext = NULL;
|
||||
newifp->frame.xmlNamespace = NULL;
|
||||
newifp->frame.blockChain = NULL;
|
||||
newifp->rvp = rvp;
|
||||
newifp->mark = newmark;
|
||||
|
||||
/* Compute the 'this' parameter now that argv is set. */
|
||||
if (JSFUN_BOUND_METHOD_TEST(fun->flags))
|
||||
vp[1] = OBJECT_TO_JSVAL(parent);
|
||||
if (!js_ComputeThis(cx, vp + 2))
|
||||
goto bad_inline_call;
|
||||
newifp->frame.thisp = JSVAL_TO_OBJECT(vp[1]);
|
||||
#ifdef DUMP_CALL_TABLE
|
||||
LogCall(cx, *vp, argc, vp + 2);
|
||||
#endif
|
||||
|
||||
/* Push void to initialize local variables. */
|
||||
sp = newsp;
|
||||
while (nvars--)
|
||||
PUSH(JSVAL_VOID);
|
||||
sp += depth;
|
||||
newifp->frame.spbase = sp;
|
||||
SAVE_SP(&newifp->frame);
|
||||
|
||||
/* Call the debugger hook if present. */
|
||||
hook = cx->debugHooks->callHook;
|
||||
if (hook) {
|
||||
newifp->frame.pc = NULL;
|
||||
newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
|
||||
cx->debugHooks->callHookData);
|
||||
LOAD_INTERRUPT_HANDLER(cx);
|
||||
} else {
|
||||
newifp->hookData = NULL;
|
||||
}
|
||||
|
||||
/* Scope with a call object parented by the callee's parent. */
|
||||
if (JSFUN_HEAVYWEIGHT_TEST(fun->flags) &&
|
||||
!js_GetCallObject(cx, &newifp->frame, parent)) {
|
||||
goto bad_inline_call;
|
||||
}
|
||||
|
||||
/* Switch to new version if currentVersion wasn't overridden. */
|
||||
newifp->callerVersion = (JSVersion) cx->version;
|
||||
if (JS_LIKELY(cx->version == currentVersion)) {
|
||||
currentVersion = (JSVersion) script->version;
|
||||
if (currentVersion != cx->version)
|
||||
js_SetVersion(cx, currentVersion);
|
||||
}
|
||||
|
||||
/* Push the frame and set interpreter registers. */
|
||||
cx->fp = fp = &newifp->frame;
|
||||
pc = script->code;
|
||||
#if !JS_THREADED_INTERP
|
||||
endpc = pc + script->length;
|
||||
#endif
|
||||
inlineCallCount++;
|
||||
JS_RUNTIME_METER(rt, inlineCalls);
|
||||
|
||||
/* Load first opcode and dispatch it (safe since JSOP_STOP). */
|
||||
op = (JSOp) *pc;
|
||||
DO_OP();
|
||||
|
||||
bad_inline_call:
|
||||
RESTORE_SP(fp);
|
||||
JS_ASSERT(fp->pc == pc);
|
||||
script = fp->script;
|
||||
depth = (jsint) script->depth;
|
||||
atoms = script->atomMap.vector;
|
||||
js_FreeRawStack(cx, newmark);
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
do_invoke:
|
||||
ok = js_Invoke(cx, argc, 0);
|
||||
RESTORE_SP(fp);
|
||||
LOAD_INTERRUPT_HANDLER(cx);
|
||||
if (!ok)
|
||||
goto out;
|
||||
JS_RUNTIME_METER(rt, nonInlineCalls);
|
||||
|
||||
end_call:
|
||||
#if JS_HAS_LVALUE_RETURN
|
||||
if (cx->rval2set) {
|
||||
/*
|
||||
|
@ -4110,8 +4213,13 @@ interrupt:
|
|||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
}
|
||||
PUSH_OPND(rval);
|
||||
if (op == JSOP_CALLNAME)
|
||||
if (op == JSOP_CALLNAME) {
|
||||
PUSH_OPND(OBJECT_TO_JSVAL(obj));
|
||||
SAVE_SP(fp);
|
||||
ok = ComputeThis(cx, sp);
|
||||
if (!ok)
|
||||
goto out;
|
||||
}
|
||||
END_CASE(JSOP_NAME)
|
||||
|
||||
BEGIN_CASE(JSOP_UINT16)
|
||||
|
@ -4576,6 +4684,19 @@ interrupt:
|
|||
PUSH_OPND(rval);
|
||||
END_CASE(JSOP_ARGCNT)
|
||||
|
||||
#define PUSH_GLOBAL_THIS(cx,sp) \
|
||||
JS_BEGIN_MACRO \
|
||||
PUSH_OPND(JSVAL_NULL); \
|
||||
SAVE_SP_AND_PC(fp); \
|
||||
ok = ComputeGlobalThis(cx, sp); \
|
||||
if (!ok) \
|
||||
goto out; \
|
||||
JS_END_MACRO
|
||||
|
||||
BEGIN_CASE(JSOP_GLOBALTHIS)
|
||||
PUSH_GLOBAL_THIS(cx, sp);
|
||||
END_CASE(JSOP_GLOBALTHIS)
|
||||
|
||||
BEGIN_CASE(JSOP_GETARG)
|
||||
BEGIN_CASE(JSOP_CALLARG)
|
||||
slot = GET_ARGNO(pc);
|
||||
|
@ -4583,7 +4704,7 @@ interrupt:
|
|||
METER_SLOT_OP(op, slot);
|
||||
PUSH_OPND(fp->argv[slot]);
|
||||
if (op == JSOP_CALLARG)
|
||||
PUSH_OPND(JSVAL_NULL);
|
||||
PUSH_GLOBAL_THIS(cx, sp);
|
||||
END_CASE(JSOP_GETARG)
|
||||
|
||||
BEGIN_CASE(JSOP_SETARG)
|
||||
|
@ -4602,7 +4723,7 @@ interrupt:
|
|||
METER_SLOT_OP(op, slot);
|
||||
PUSH_OPND(fp->vars[slot]);
|
||||
if (op == JSOP_CALLVAR)
|
||||
PUSH_OPND(JSVAL_NULL);
|
||||
PUSH_GLOBAL_THIS(cx, sp);
|
||||
END_CASE(JSOP_GETVAR)
|
||||
|
||||
BEGIN_CASE(JSOP_SETVAR)
|
||||
|
@ -4722,7 +4843,7 @@ interrupt:
|
|||
|
||||
BEGIN_CASE(JSOP_DEFFUN)
|
||||
LOAD_FUNCTION(0);
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
id = ATOM_TO_JSID(fun->atom);
|
||||
|
||||
/*
|
||||
|
@ -4963,7 +5084,7 @@ interrupt:
|
|||
* name is [fun->atom, the identifier parsed by the compiler],
|
||||
* value is Result(3), and attributes are { DontDelete, ReadOnly }.
|
||||
*/
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
attrs = JSFUN_GSFLAG2ATTR(fun->flags);
|
||||
if (attrs) {
|
||||
attrs |= JSPROP_SHARED;
|
||||
|
@ -5037,7 +5158,7 @@ interrupt:
|
|||
* unless fun is a getter or setter (in which case, obj is cast to
|
||||
* a JSPropertyOp and passed accordingly).
|
||||
*/
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
attrs = JSFUN_GSFLAG2ATTR(fun->flags);
|
||||
if (attrs) {
|
||||
attrs |= JSPROP_SHARED;
|
||||
|
@ -5515,8 +5636,13 @@ interrupt:
|
|||
if (!ok)
|
||||
goto out;
|
||||
STORE_OPND(-1, rval);
|
||||
if (op == JSOP_CALLXMLNAME)
|
||||
if (op == JSOP_CALLXMLNAME) {
|
||||
PUSH_OPND(OBJECT_TO_JSVAL(obj));
|
||||
SAVE_SP(fp);
|
||||
ok = ComputeThis(cx, sp);
|
||||
if (!ok)
|
||||
goto out;
|
||||
}
|
||||
END_CASE(JSOP_XMLNAME)
|
||||
|
||||
BEGIN_CASE(JSOP_DESCENDANTS)
|
||||
|
@ -5661,10 +5787,10 @@ interrupt:
|
|||
/* Get an immediate atom naming the property. */
|
||||
LOAD_ATOM(0);
|
||||
id = ATOM_TO_JSID(atom);
|
||||
lval = FETCH_OPND(-1);
|
||||
PUSH(JSVAL_NULL);
|
||||
SAVE_SP_AND_PC(fp);
|
||||
lval = FETCH_OPND(-2);
|
||||
if (!JSVAL_IS_PRIMITIVE(lval)) {
|
||||
STORE_OPND(-1, lval);
|
||||
obj = JSVAL_TO_OBJECT(lval);
|
||||
|
||||
/* Special-case XML object method lookup, per ECMA-357. */
|
||||
|
@ -5678,6 +5804,13 @@ interrupt:
|
|||
} else {
|
||||
ok = OBJ_GET_PROPERTY(cx, obj, id, &rval);
|
||||
}
|
||||
if (!ok)
|
||||
goto out;
|
||||
STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
|
||||
STORE_OPND(-2, rval);
|
||||
ok = ComputeThis(cx, sp);
|
||||
if (!ok)
|
||||
goto out;
|
||||
} else {
|
||||
if (JSVAL_IS_STRING(lval)) {
|
||||
i = JSProto_String;
|
||||
|
@ -5692,18 +5825,27 @@ interrupt:
|
|||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(i), &obj);
|
||||
if (!ok)
|
||||
goto out;
|
||||
JS_ASSERT(obj);
|
||||
STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
|
||||
ok = OBJ_GET_PROPERTY(cx, obj, id, &rval);
|
||||
obj = (JSObject *) lval; /* keep tagged as non-object */
|
||||
if (!ok)
|
||||
goto out;
|
||||
STORE_OPND(-1, lval);
|
||||
STORE_OPND(-2, rval);
|
||||
|
||||
/* Wrap primitive lval in object clothing if necessary. */
|
||||
if (!VALUE_IS_FUNCTION(cx, rval) ||
|
||||
(obj = JSVAL_TO_OBJECT(rval),
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj),
|
||||
!PRIMITIVE_THIS_TEST(fun, lval))) {
|
||||
ok = js_PrimitiveToObject(cx, &sp[-1]);
|
||||
if (!ok)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
goto out;
|
||||
STORE_OPND(-1, rval);
|
||||
PUSH_OPND(OBJECT_TO_JSVAL(obj));
|
||||
END_CASE(JSOP_CALLPROP)
|
||||
|
||||
BEGIN_CASE(JSOP_GETFUNNS)
|
||||
|
@ -5810,7 +5952,7 @@ interrupt:
|
|||
JS_ASSERT(slot < (uintN)depth);
|
||||
PUSH_OPND(fp->spbase[slot]);
|
||||
if (op == JSOP_CALLLOCAL)
|
||||
PUSH_OPND(JSVAL_NULL);
|
||||
PUSH_GLOBAL_THIS(cx, sp);
|
||||
END_CASE(JSOP_GETLOCAL)
|
||||
|
||||
BEGIN_CASE(JSOP_SETLOCAL)
|
||||
|
@ -5906,8 +6048,21 @@ interrupt:
|
|||
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ArrayClass);
|
||||
rval = FETCH_OPND(-1);
|
||||
|
||||
/* We know that the array is created with only a 'length' slot. */
|
||||
i = obj->map->freeslot - (JSSLOT_FREE(&js_ArrayClass) + 1);
|
||||
/*
|
||||
* We know that the array is created with only a 'length' private
|
||||
* data slot at JSSLOT_ARRAY_LENGTH, and that previous iterations
|
||||
* of the comprehension have added the only properties directly in
|
||||
* the array object.
|
||||
*/
|
||||
lval = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
JS_ASSERT(JSVAL_IS_INT(lval));
|
||||
i = JSVAL_TO_INT(lval);
|
||||
if (i == ARRAY_INIT_LIMIT) {
|
||||
JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_ARRAY_INIT_TOO_BIG);
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
id = INT_TO_JSID(i);
|
||||
|
||||
SAVE_SP_AND_PC(fp);
|
||||
|
@ -5932,7 +6087,6 @@ interrupt:
|
|||
#if JS_THREADED_INTERP
|
||||
L_JSOP_BACKPATCH:
|
||||
L_JSOP_BACKPATCH_POP:
|
||||
L_JSOP_UNUSED117:
|
||||
#else
|
||||
default:
|
||||
#endif
|
||||
|
|
|
@ -110,6 +110,8 @@ typedef struct JSInlineFrame {
|
|||
#define JSFRAME_ITERATOR 0x800 /* trying to get an iterator for for-in */
|
||||
#define JSFRAME_POP_BLOCKS 0x1000 /* scope chain contains blocks to pop */
|
||||
#define JSFRAME_GENERATOR 0x2000 /* frame belongs to generator-iterator */
|
||||
#define JSFRAME_IN_FAST_CALL 0x4000 /* calling frame is calling a fast native */
|
||||
#define JSFRAME_DID_SET_RVAL 0x8000 /* fast native used JS_SET_RVAL(cx, vp) */
|
||||
|
||||
#define JSFRAME_OVERRIDE_SHIFT 24 /* override bit-set params; see jsfun.c */
|
||||
#define JSFRAME_OVERRIDE_BITS 8
|
||||
|
@ -151,6 +153,18 @@ extern void js_DumpCallTable(JSContext *cx);
|
|||
extern JSObject *
|
||||
js_GetScopeChain(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
/*
|
||||
* Given a context and a vector of [callee, this, args...] for a function that
|
||||
* was specified with a JSFUN_THISP_PRIMITIVE flag, get the primitive value of
|
||||
* |this| into *thisvp. In doing so, if |this| is an object, insist it is an
|
||||
* 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.
|
||||
*/
|
||||
extern JSBool
|
||||
js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp);
|
||||
|
||||
/*
|
||||
* For a call with arguments argv including argv[-1] (nominal |this|) and
|
||||
* argv[-2] (callee) replace null |this| with callee's parent, replace
|
||||
|
|
|
@ -282,17 +282,19 @@ js_ThrowStopIteration(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
iterator_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
iterator_next(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (!JS_InstanceOf(cx, obj, &js_IteratorClass, argv))
|
||||
JSObject *obj;
|
||||
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!JS_InstanceOf(cx, obj, &js_IteratorClass, vp + 2))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!IteratorNextImpl(cx, obj, rval))
|
||||
if (!IteratorNextImpl(cx, obj, vp))
|
||||
return JS_FALSE;
|
||||
|
||||
if (*rval == JSVAL_HOLE) {
|
||||
*rval = JSVAL_NULL;
|
||||
if (*vp == JSVAL_HOLE) {
|
||||
*vp = JSVAL_NULL;
|
||||
js_ThrowStopIteration(cx, obj);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -300,17 +302,18 @@ iterator_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
}
|
||||
|
||||
static JSBool
|
||||
iterator_self(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
iterator_self(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
*vp = vp[1];
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#define JSPROP_ROPERM (JSPROP_READONLY | JSPROP_PERMANENT)
|
||||
|
||||
static JSFunctionSpec iterator_methods[] = {
|
||||
{js_iterator_str, iterator_self, 0,JSPROP_READONLY|JSPROP_PERMANENT,0},
|
||||
{js_next_str, iterator_next, 0,JSPROP_READONLY|JSPROP_PERMANENT,0},
|
||||
{0,0,0,0,0}
|
||||
JS_FN(js_iterator_str, iterator_self, 0,0,JSPROP_ROPERM,0),
|
||||
JS_FN(js_next_str, iterator_next, 0,0,JSPROP_ROPERM,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
uintN
|
||||
|
@ -900,8 +903,10 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
|
|||
|
||||
if (ok) {
|
||||
/* Returned, explicitly or by falling off the end. */
|
||||
if (op == JSGENOP_CLOSE)
|
||||
if (op == JSGENOP_CLOSE) {
|
||||
*rval = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
return js_ThrowStopIteration(cx, obj);
|
||||
}
|
||||
|
||||
|
@ -916,6 +921,7 @@ static JSBool
|
|||
CloseGenerator(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSGenerator *gen;
|
||||
jsval junk;
|
||||
|
||||
JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_GeneratorClass);
|
||||
gen = (JSGenerator *) JS_GetPrivate(cx, obj);
|
||||
|
@ -927,21 +933,22 @@ CloseGenerator(JSContext *cx, JSObject *obj)
|
|||
if (gen->state == JSGEN_CLOSED)
|
||||
return JS_TRUE;
|
||||
|
||||
/* We pass null as rval since SendToGenerator never uses it with CLOSE. */
|
||||
return SendToGenerator(cx, JSGENOP_CLOSE, obj, gen, JSVAL_VOID, NULL);
|
||||
/* SendToGenerator always sets *rval to JSVAL_VOID for JSGENOP_CLOSE. */
|
||||
return SendToGenerator(cx, JSGENOP_CLOSE, obj, gen, JSVAL_VOID, &junk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common subroutine of generator_(next|send|throw|close) methods.
|
||||
*/
|
||||
static JSBool
|
||||
generator_op(JSContext *cx, JSGeneratorOp op,
|
||||
JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
generator_op(JSContext *cx, JSGeneratorOp op, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
JSGenerator *gen;
|
||||
jsval arg;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_GeneratorClass, argv))
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!JS_InstanceOf(cx, obj, &js_GeneratorClass, vp + 2))
|
||||
return JS_FALSE;
|
||||
|
||||
gen = (JSGenerator *) JS_GetPrivate(cx, obj);
|
||||
|
@ -957,9 +964,9 @@ generator_op(JSContext *cx, JSGeneratorOp op,
|
|||
break;
|
||||
|
||||
case JSGENOP_SEND:
|
||||
if (!JSVAL_IS_VOID(argv[0])) {
|
||||
if (!JSVAL_IS_VOID(vp[2])) {
|
||||
js_ReportValueError(cx, JSMSG_BAD_GENERATOR_SEND,
|
||||
JSDVG_SEARCH_STACK, argv[0], NULL);
|
||||
JSDVG_SEARCH_STACK, vp[2], NULL);
|
||||
return JS_FALSE;
|
||||
}
|
||||
break;
|
||||
|
@ -976,7 +983,7 @@ generator_op(JSContext *cx, JSGeneratorOp op,
|
|||
case JSGENOP_SEND:
|
||||
return js_ThrowStopIteration(cx, obj);
|
||||
case JSGENOP_THROW:
|
||||
JS_SetPendingException(cx, argv[0]);
|
||||
JS_SetPendingException(cx, vp[2]);
|
||||
return JS_FALSE;
|
||||
default:
|
||||
JS_ASSERT(op == JSGENOP_CLOSE);
|
||||
|
@ -985,48 +992,44 @@ generator_op(JSContext *cx, JSGeneratorOp op,
|
|||
}
|
||||
|
||||
arg = (op == JSGENOP_SEND || op == JSGENOP_THROW)
|
||||
? argv[0]
|
||||
? vp[2]
|
||||
: JSVAL_VOID;
|
||||
if (!SendToGenerator(cx, op, obj, gen, arg, rval))
|
||||
if (!SendToGenerator(cx, op, obj, gen, arg, vp))
|
||||
return JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
generator_send(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
generator_send(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return generator_op(cx, JSGENOP_SEND, obj, argc, argv, rval);
|
||||
return generator_op(cx, JSGENOP_SEND, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
generator_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
generator_next(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return generator_op(cx, JSGENOP_NEXT, obj, argc, argv, rval);
|
||||
return generator_op(cx, JSGENOP_NEXT, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
generator_throw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
generator_throw(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return generator_op(cx, JSGENOP_THROW, obj, argc, argv, rval);
|
||||
return generator_op(cx, JSGENOP_THROW, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
generator_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
generator_close(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return generator_op(cx, JSGENOP_CLOSE, obj, argc, argv, rval);
|
||||
return generator_op(cx, JSGENOP_CLOSE, vp);
|
||||
}
|
||||
|
||||
static JSFunctionSpec generator_methods[] = {
|
||||
{js_iterator_str, iterator_self, 0,JSPROP_READONLY|JSPROP_PERMANENT,0},
|
||||
{js_next_str, generator_next, 0,JSPROP_READONLY|JSPROP_PERMANENT,0},
|
||||
{js_send_str, generator_send, 1,JSPROP_READONLY|JSPROP_PERMANENT,0},
|
||||
{js_throw_str, generator_throw, 1,JSPROP_READONLY|JSPROP_PERMANENT,0},
|
||||
{js_close_str, generator_close, 0,JSPROP_READONLY|JSPROP_PERMANENT,0},
|
||||
{0,0,0,0,0}
|
||||
JS_FN(js_iterator_str, iterator_self, 0,0,JSPROP_ROPERM,0),
|
||||
JS_FN(js_next_str, generator_next, 0,0,JSPROP_ROPERM,0),
|
||||
JS_FN(js_send_str, generator_send, 1,1,JSPROP_ROPERM,0),
|
||||
JS_FN(js_throw_str, generator_throw, 1,1,JSPROP_ROPERM,0),
|
||||
JS_FN(js_close_str, generator_close, 0,0,JSPROP_ROPERM,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
#endif /* JS_HAS_GENERATORS */
|
||||
|
|
168
js/src/jsnum.c
168
js/src/jsnum.c
|
@ -66,35 +66,35 @@
|
|||
#include "jsstr.h"
|
||||
|
||||
static JSBool
|
||||
num_isNaN(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_isNaN(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
if (!js_ValueToNumber(cx, vp[2], &x))
|
||||
return JS_FALSE;
|
||||
*rval = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x));
|
||||
*vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
num_isFinite(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_isFinite(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsdouble x;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
if (!js_ValueToNumber(cx, vp[2], &x))
|
||||
return JS_FALSE;
|
||||
*rval = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_FINITE(x));
|
||||
*vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_FINITE(x));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
num_parseFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_parseFloat(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
jsdouble d;
|
||||
const jschar *bp, *ep;
|
||||
|
||||
str = js_ValueToString(cx, argv[0]);
|
||||
str = js_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
/* XXXbe js_strtod shouldn't require NUL termination */
|
||||
|
@ -104,15 +104,15 @@ num_parseFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rva
|
|||
if (!js_strtod(cx, bp, &ep, &d))
|
||||
return JS_FALSE;
|
||||
if (ep == bp) {
|
||||
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return js_NewNumberValue(cx, d, rval);
|
||||
return js_NewNumberValue(cx, d, vp);
|
||||
}
|
||||
|
||||
/* See ECMA 15.1.2.2. */
|
||||
static JSBool
|
||||
num_parseInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_parseInt(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsint radix;
|
||||
JSString *str;
|
||||
|
@ -120,17 +120,17 @@ num_parseInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
const jschar *bp, *ep;
|
||||
|
||||
if (argc > 1) {
|
||||
if (!js_ValueToECMAInt32(cx, argv[1], &radix))
|
||||
if (!js_ValueToECMAInt32(cx, vp[3], &radix))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
radix = 0;
|
||||
}
|
||||
if (radix != 0 && (radix < 2 || radix > 36)) {
|
||||
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
str = js_ValueToString(cx, argv[0]);
|
||||
str = js_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
/* XXXbe js_strtointeger shouldn't require NUL termination */
|
||||
|
@ -140,10 +140,10 @@ num_parseInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
if (!js_strtointeger(cx, bp, &ep, radix, &d))
|
||||
return JS_FALSE;
|
||||
if (ep == bp) {
|
||||
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return js_NewNumberValue(cx, d, rval);
|
||||
return js_NewNumberValue(cx, d, vp);
|
||||
}
|
||||
|
||||
const char js_Infinity_str[] = "Infinity";
|
||||
|
@ -154,11 +154,11 @@ const char js_parseFloat_str[] = "parseFloat";
|
|||
const char js_parseInt_str[] = "parseInt";
|
||||
|
||||
static JSFunctionSpec number_functions[] = {
|
||||
{js_isNaN_str, num_isNaN, 1,0,0},
|
||||
{js_isFinite_str, num_isFinite, 1,0,0},
|
||||
{js_parseFloat_str, num_parseFloat, 1,0,0},
|
||||
{js_parseInt_str, num_parseInt, 2,0,0},
|
||||
{0,0,0,0,0}
|
||||
JS_FN(js_isNaN_str, num_isNaN, 1,1,0,0),
|
||||
JS_FN(js_isFinite_str, num_isFinite, 1,1,0,0),
|
||||
JS_FN(js_parseFloat_str, num_parseFloat, 1,1,0,0),
|
||||
JS_FN(js_parseInt_str, num_parseInt, 1,2,0,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
JSClass js_NumberClass = {
|
||||
|
@ -193,7 +193,7 @@ Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
|
||||
#if JS_HAS_TOSOURCE
|
||||
static JSBool
|
||||
num_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval v;
|
||||
jsdouble d;
|
||||
|
@ -201,14 +201,9 @@ num_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
char buf[64];
|
||||
JSString *str;
|
||||
|
||||
if (JSVAL_IS_NUMBER((jsval)obj)) {
|
||||
v = (jsval)obj;
|
||||
} else {
|
||||
if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
JS_ASSERT(JSVAL_IS_NUMBER(v));
|
||||
}
|
||||
if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(JSVAL_IS_NUMBER(v));
|
||||
d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
|
||||
numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d);
|
||||
if (!numStr) {
|
||||
|
@ -219,7 +214,7 @@ num_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
@ -253,25 +248,20 @@ IntToString(jsint i, char *buf, size_t bufSize)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
num_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval v;
|
||||
jsdouble d;
|
||||
jsint base;
|
||||
JSString *str;
|
||||
|
||||
if (JSVAL_IS_NUMBER((jsval)obj)) {
|
||||
v = (jsval)obj;
|
||||
} else {
|
||||
if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
JS_ASSERT(JSVAL_IS_NUMBER(v));
|
||||
}
|
||||
if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(JSVAL_IS_NUMBER(v));
|
||||
d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
|
||||
base = 10;
|
||||
if (argc != 0) {
|
||||
if (!js_ValueToECMAInt32(cx, argv[0], &base))
|
||||
if (!js_ValueToECMAInt32(cx, vp[2], &base))
|
||||
return JS_FALSE;
|
||||
if (base < 2 || base > 36) {
|
||||
char numBuf[12];
|
||||
|
@ -294,13 +284,12 @@ num_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
}
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
num_toLocaleString(JSContext *cx, JSObject *obj, uintN argc,
|
||||
jsval *argv, jsval *rval)
|
||||
num_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
char thousandsLength, decimalLength;
|
||||
const char *numGrouping, *tmpGroup;
|
||||
|
@ -314,10 +303,10 @@ num_toLocaleString(JSContext *cx, JSObject *obj, uintN argc,
|
|||
* Create the string, move back to bytes to make string twiddling
|
||||
* a bit easier and so we can insert platform charset seperators.
|
||||
*/
|
||||
if (!num_toString(cx, obj, 0, argv, rval))
|
||||
if (!num_toString(cx, argc, vp))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(JSVAL_IS_STRING(*rval));
|
||||
numStr = JSVAL_TO_STRING(*rval);
|
||||
JS_ASSERT(JSVAL_IS_STRING(*vp));
|
||||
numStr = JSVAL_TO_STRING(*vp);
|
||||
num = js_GetStringBytes(cx, numStr);
|
||||
if (!num)
|
||||
return JS_FALSE;
|
||||
|
@ -383,7 +372,7 @@ num_toLocaleString(JSContext *cx, JSObject *obj, uintN argc,
|
|||
}
|
||||
|
||||
if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
|
||||
return cx->localeCallbacks->localeToUnicode(cx, buf, rval);
|
||||
return cx->localeCallbacks->localeToUnicode(cx, buf, vp);
|
||||
|
||||
str = JS_NewString(cx, buf, size);
|
||||
if (!str) {
|
||||
|
@ -391,21 +380,25 @@ num_toLocaleString(JSContext *cx, JSObject *obj, uintN argc,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
num_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_valueOf(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (JSVAL_IS_NUMBER((jsval)obj)) {
|
||||
*rval = (jsval)obj;
|
||||
jsval v;
|
||||
JSObject *obj;
|
||||
|
||||
v = vp[1];
|
||||
if (JSVAL_IS_NUMBER(v)) {
|
||||
*vp = v;
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv))
|
||||
obj = JSVAL_TO_OBJECT(v);
|
||||
if (!JS_InstanceOf(cx, obj, &js_NumberClass, vp + 2))
|
||||
return JS_FALSE;
|
||||
*rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
*vp = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -413,29 +406,28 @@ num_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
#define MAX_PRECISION 100
|
||||
|
||||
static JSBool
|
||||
num_to(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval, JSDToStrMode zeroArgMode,
|
||||
JSDToStrMode oneArgMode, jsint precisionMin, jsint precisionMax, jsint precisionOffset)
|
||||
num_to(JSContext *cx, JSDToStrMode zeroArgMode, JSDToStrMode oneArgMode,
|
||||
jsint precisionMin, jsint precisionMax, jsint precisionOffset,
|
||||
uintN argc, jsval *vp)
|
||||
{
|
||||
jsval v;
|
||||
jsdouble d, precision;
|
||||
JSString *str;
|
||||
char buf[DTOSTR_VARIABLE_BUFFER_SIZE(MAX_PRECISION+1)], *numStr; /* Use MAX_PRECISION+1 because precisionOffset can be 1 */
|
||||
|
||||
if (JSVAL_IS_NUMBER((jsval)obj)) {
|
||||
v = (jsval)obj;
|
||||
} else {
|
||||
if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
JS_ASSERT(JSVAL_IS_NUMBER(v));
|
||||
}
|
||||
/* Use MAX_PRECISION+1 because precisionOffset can be 1. */
|
||||
char buf[DTOSTR_VARIABLE_BUFFER_SIZE(MAX_PRECISION+1)];
|
||||
char *numStr;
|
||||
|
||||
if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(JSVAL_IS_NUMBER(v));
|
||||
d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
|
||||
|
||||
if (JSVAL_IS_VOID(argv[0])) {
|
||||
if (argc == 0) {
|
||||
precision = 0.0;
|
||||
oneArgMode = zeroArgMode;
|
||||
} else {
|
||||
if (!js_ValueToNumber(cx, argv[0], &precision))
|
||||
if (!js_ValueToNumber(cx, vp[2], &precision))
|
||||
return JS_FALSE;
|
||||
precision = js_DoubleToInteger(precision);
|
||||
if (precision < precisionMin || precision > precisionMax) {
|
||||
|
@ -456,42 +448,46 @@ num_to(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval, JSDTo
|
|||
str = JS_NewStringCopyZ(cx, numStr);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the following three implementations, we allow a larger range of precision
|
||||
* than ECMA requires; this is permitted by ECMA-262.
|
||||
*/
|
||||
static JSBool
|
||||
num_toFixed(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_toFixed(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
/* We allow a larger range of precision than ECMA requires; this is permitted by ECMA. */
|
||||
return num_to(cx, obj, argc, argv, rval, DTOSTR_FIXED, DTOSTR_FIXED, -20, MAX_PRECISION, 0);
|
||||
return num_to(cx, DTOSTR_FIXED, DTOSTR_FIXED, -20, MAX_PRECISION, 0,
|
||||
argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
num_toExponential(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_toExponential(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
/* We allow a larger range of precision than ECMA requires; this is permitted by ECMA. */
|
||||
return num_to(cx, obj, argc, argv, rval, DTOSTR_STANDARD_EXPONENTIAL, DTOSTR_EXPONENTIAL, 0, MAX_PRECISION, 1);
|
||||
return num_to(cx, DTOSTR_STANDARD_EXPONENTIAL, DTOSTR_EXPONENTIAL, 0,
|
||||
MAX_PRECISION, 1, argc, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
num_toPrecision(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
num_toPrecision(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
/* We allow a larger range of precision than ECMA requires; this is permitted by ECMA. */
|
||||
return num_to(cx, obj, argc, argv, rval, DTOSTR_STANDARD, DTOSTR_PRECISION, 1, MAX_PRECISION, 0);
|
||||
return num_to(cx, DTOSTR_STANDARD, DTOSTR_PRECISION, 1, MAX_PRECISION, 0,
|
||||
argc, vp);
|
||||
}
|
||||
|
||||
static JSFunctionSpec number_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, num_toSource, 0,JSFUN_THISP_NUMBER,0},
|
||||
JS_FN(js_toSource_str, num_toSource, 0,0,JSFUN_THISP_NUMBER,0),
|
||||
#endif
|
||||
{js_toString_str, num_toString, 0,JSFUN_THISP_NUMBER,0},
|
||||
{js_toLocaleString_str, num_toLocaleString, 0,JSFUN_THISP_NUMBER,0},
|
||||
{js_valueOf_str, num_valueOf, 0,JSFUN_THISP_NUMBER,0},
|
||||
{"toFixed", num_toFixed, 1,JSFUN_THISP_NUMBER,0},
|
||||
{"toExponential", num_toExponential, 1,JSFUN_THISP_NUMBER,0},
|
||||
{"toPrecision", num_toPrecision, 1,JSFUN_THISP_NUMBER,0},
|
||||
{0,0,0,0,0}
|
||||
JS_FN(js_toString_str, num_toString, 0,0,JSFUN_THISP_NUMBER,0),
|
||||
JS_FN(js_toLocaleString_str, num_toLocaleString, 0,0,JSFUN_THISP_NUMBER,0),
|
||||
JS_FN(js_valueOf_str, num_valueOf, 0,0,JSFUN_THISP_NUMBER,0),
|
||||
JS_FN("toFixed", num_toFixed, 1,1,JSFUN_THISP_NUMBER,0),
|
||||
JS_FN("toExponential", num_toExponential, 1,1,JSFUN_THISP_NUMBER,0),
|
||||
JS_FN("toPrecision", num_toPrecision, 1,1,JSFUN_THISP_NUMBER,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
/* NB: Keep this in synch with number_constants[]. */
|
||||
|
|
183
js/src/jsobj.c
183
js/src/jsobj.c
|
@ -703,11 +703,11 @@ js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map)
|
|||
#define OBJ_TOSTRING_EXTRA 4 /* for 4 local GC roots */
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
JSBool
|
||||
js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
static JSBool
|
||||
obj_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSBool ok, outermost;
|
||||
JSObject *obj;
|
||||
JSHashEntry *he;
|
||||
JSIdArray *ida;
|
||||
jschar *chars, *ochars, *vsharp;
|
||||
|
@ -735,6 +735,7 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
|
||||
/* If outermost, we need parentheses to be an expression, not a block. */
|
||||
outermost = (cx->sharpObjectMap.depth == 0);
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
he = js_EnterSharpObject(cx, obj, &ida, &chars);
|
||||
if (!he)
|
||||
return JS_FALSE;
|
||||
|
@ -833,15 +834,15 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
|
||||
/*
|
||||
* We have four local roots for cooked and raw value GC safety. Hoist the
|
||||
* "argv + 2" out of the loop using the val local, which refers to the raw
|
||||
* "vp + 4" out of the loop using the val local, which refers to the raw
|
||||
* (unconverted, "uncooked") values.
|
||||
*/
|
||||
val = argv + 2;
|
||||
val = vp + 4;
|
||||
|
||||
for (i = 0, length = ida->length; i < length; i++) {
|
||||
JSBool idIsLexicalIdentifier, needOldStyleGetterSetter;
|
||||
|
||||
/* Get strings for id and value and GC-root them via argv. */
|
||||
/* Get strings for id and value and GC-root them via vp. */
|
||||
id = ida->vector[i];
|
||||
|
||||
#if JS_HAS_GETTER_SETTER
|
||||
|
@ -861,7 +862,7 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
goto error;
|
||||
}
|
||||
*rval = STRING_TO_JSVAL(idstr); /* local root */
|
||||
*vp = STRING_TO_JSVAL(idstr); /* local root */
|
||||
idIsLexicalIdentifier = js_IsIdentifier(idstr);
|
||||
needOldStyleGetterSetter =
|
||||
!idIsLexicalIdentifier ||
|
||||
|
@ -936,7 +937,7 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
ok = JS_FALSE;
|
||||
goto error;
|
||||
}
|
||||
*rval = STRING_TO_JSVAL(idstr); /* local root */
|
||||
*vp = STRING_TO_JSVAL(idstr); /* local root */
|
||||
}
|
||||
idstrchars = JSSTRING_CHARS(idstr);
|
||||
idstrlength = JSSTRING_LENGTH(idstr);
|
||||
|
@ -948,7 +949,7 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
ok = JS_FALSE;
|
||||
goto error;
|
||||
}
|
||||
argv[j] = STRING_TO_JSVAL(valstr); /* local root */
|
||||
vp[2 + j] = STRING_TO_JSVAL(valstr); /* local root */
|
||||
vchars = JSSTRING_CHARS(valstr);
|
||||
vlength = JSSTRING_LENGTH(valstr);
|
||||
|
||||
|
@ -1137,7 +1138,7 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
free(chars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
|
||||
overflow:
|
||||
|
@ -1148,16 +1149,15 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
}
|
||||
#endif /* JS_HAS_TOSOURCE */
|
||||
|
||||
JSBool
|
||||
js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
static JSBool
|
||||
obj_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jschar *chars;
|
||||
size_t nchars;
|
||||
const char *clazz, *prefix;
|
||||
JSString *str;
|
||||
|
||||
clazz = OBJ_GET_CLASS(cx, obj)->name;
|
||||
clazz = OBJ_GET_CLASS(cx, JS_THIS_OBJECT(cx, vp))->name;
|
||||
nchars = 9 + strlen(clazz); /* 9 for "[object ]" */
|
||||
chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar));
|
||||
if (!chars)
|
||||
|
@ -1177,28 +1177,27 @@ js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
JS_free(cx, chars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
js_obj_toLocaleString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
obj_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
str = js_ValueToString(cx, argv[-1]);
|
||||
str = js_ValueToString(cx, vp[1]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
obj_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
obj_valueOf(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
*vp = vp[1];
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1455,33 +1454,37 @@ obj_watch_handler(JSContext *cx, JSObject *obj, jsval id, jsval old, jsval *nvp,
|
|||
}
|
||||
|
||||
static JSBool
|
||||
obj_watch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
obj_watch(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *callable;
|
||||
jsval userid, value;
|
||||
jsid propid;
|
||||
JSObject *obj;
|
||||
uintN attrs;
|
||||
|
||||
callable = js_ValueToCallableObject(cx, &argv[1], 0);
|
||||
callable = js_ValueToCallableObject(cx, &vp[3], 0);
|
||||
if (!callable)
|
||||
return JS_FALSE;
|
||||
|
||||
/* Compute the unique int/atom symbol id needed by js_LookupProperty. */
|
||||
userid = argv[0];
|
||||
userid = vp[2];
|
||||
if (!JS_ValueToId(cx, userid, &propid))
|
||||
return JS_FALSE;
|
||||
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!OBJ_CHECK_ACCESS(cx, obj, propid, JSACC_WATCH, &value, &attrs))
|
||||
return JS_FALSE;
|
||||
if (attrs & JSPROP_READONLY)
|
||||
return JS_TRUE;
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_SetWatchPoint(cx, obj, userid, obj_watch_handler, callable);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
obj_unwatch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
obj_unwatch(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return JS_ClearWatchPoint(cx, obj, argv[0], NULL, NULL);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_ClearWatchPoint(cx, JSVAL_TO_OBJECT(vp[1]), vp[2], NULL, NULL);
|
||||
}
|
||||
|
||||
#endif /* JS_HAS_OBJ_WATCHPOINT */
|
||||
|
@ -1493,30 +1496,31 @@ obj_unwatch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
|
||||
/* Proposed ECMA 15.2.4.5. */
|
||||
static JSBool
|
||||
obj_hasOwnProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
obj_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return js_HasOwnPropertyHelper(cx, obj, obj->map->ops->lookupProperty,
|
||||
argc, argv, rval);
|
||||
JSObject *obj;
|
||||
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
return js_HasOwnPropertyHelper(cx, obj->map->ops->lookupProperty, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_HasOwnPropertyHelper(JSContext *cx, JSObject *obj, JSLookupPropOp lookup,
|
||||
uintN argc, jsval *argv, jsval *rval)
|
||||
js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, jsval *vp)
|
||||
{
|
||||
jsid id;
|
||||
JSObject *obj2;
|
||||
JSObject *obj, *obj2;
|
||||
JSProperty *prop;
|
||||
JSScopeProperty *sprop;
|
||||
|
||||
if (!JS_ValueToId(cx, argv[0], &id))
|
||||
if (!JS_ValueToId(cx, vp[2], &id))
|
||||
return JS_FALSE;
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!lookup(cx, obj, id, &obj2, &prop))
|
||||
return JS_FALSE;
|
||||
if (!prop) {
|
||||
*rval = JSVAL_FALSE;
|
||||
*vp = JSVAL_FALSE;
|
||||
} else if (obj2 == obj) {
|
||||
*rval = JSVAL_TRUE;
|
||||
*vp = JSVAL_TRUE;
|
||||
} else {
|
||||
JSClass *clasp;
|
||||
JSExtendedClass *xclasp;
|
||||
|
@ -1527,7 +1531,7 @@ js_HasOwnPropertyHelper(JSContext *cx, JSObject *obj, JSLookupPropOp lookup,
|
|||
: NULL;
|
||||
if (xclasp && xclasp->outerObject &&
|
||||
xclasp->outerObject(cx, obj2) == obj) {
|
||||
*rval = JSVAL_TRUE;
|
||||
*vp = JSVAL_TRUE;
|
||||
} else if (OBJ_IS_NATIVE(obj2) && OBJ_GET_CLASS(cx, obj2) == clasp) {
|
||||
/*
|
||||
* The combination of JSPROP_SHARED and JSPROP_PERMANENT in a
|
||||
|
@ -1545,9 +1549,9 @@ js_HasOwnPropertyHelper(JSContext *cx, JSObject *obj, JSLookupPropOp lookup,
|
|||
* owned, or indirectly delegated.
|
||||
*/
|
||||
sprop = (JSScopeProperty *)prop;
|
||||
*rval = BOOLEAN_TO_JSVAL(SPROP_IS_SHARED_PERMANENT(sprop));
|
||||
*vp = BOOLEAN_TO_JSVAL(SPROP_IS_SHARED_PERMANENT(sprop));
|
||||
} else {
|
||||
*rval = JSVAL_FALSE;
|
||||
*vp = JSVAL_FALSE;
|
||||
}
|
||||
}
|
||||
if (prop)
|
||||
|
@ -1557,36 +1561,35 @@ js_HasOwnPropertyHelper(JSContext *cx, JSObject *obj, JSLookupPropOp lookup,
|
|||
|
||||
/* Proposed ECMA 15.2.4.6. */
|
||||
static JSBool
|
||||
obj_isPrototypeOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
obj_isPrototypeOf(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSBool b;
|
||||
|
||||
if (!js_IsDelegate(cx, obj, *argv, &b))
|
||||
if (!js_IsDelegate(cx, JSVAL_TO_OBJECT(vp[1]), vp[2], &b))
|
||||
return JS_FALSE;
|
||||
*rval = BOOLEAN_TO_JSVAL(b);
|
||||
*vp = BOOLEAN_TO_JSVAL(b);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Proposed ECMA 15.2.4.7. */
|
||||
static JSBool
|
||||
obj_propertyIsEnumerable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
obj_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsid id;
|
||||
JSObject *obj, *pobj;
|
||||
uintN attrs;
|
||||
JSObject *obj2;
|
||||
JSProperty *prop;
|
||||
JSBool ok;
|
||||
|
||||
if (!JS_ValueToId(cx, argv[0], &id))
|
||||
if (!JS_ValueToId(cx, vp[2], &id))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!prop) {
|
||||
*rval = JSVAL_FALSE;
|
||||
*vp = JSVAL_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1601,31 +1604,31 @@ obj_propertyIsEnumerable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
* technique used to satisfy ECMA requirements; users should not be able
|
||||
* to distinguish a shared permanent proto-property from a local one.
|
||||
*/
|
||||
if (obj2 != obj &&
|
||||
!(OBJ_IS_NATIVE(obj2) &&
|
||||
if (pobj != obj &&
|
||||
!(OBJ_IS_NATIVE(pobj) &&
|
||||
SPROP_IS_SHARED_PERMANENT((JSScopeProperty *)prop))) {
|
||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
*rval = JSVAL_FALSE;
|
||||
OBJ_DROP_PROPERTY(cx, pobj, prop);
|
||||
*vp = JSVAL_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
|
||||
OBJ_DROP_PROPERTY(cx, obj2, prop);
|
||||
ok = OBJ_GET_ATTRIBUTES(cx, pobj, id, prop, &attrs);
|
||||
OBJ_DROP_PROPERTY(cx, pobj, prop);
|
||||
if (ok)
|
||||
*rval = BOOLEAN_TO_JSVAL((attrs & JSPROP_ENUMERATE) != 0);
|
||||
*vp = BOOLEAN_TO_JSVAL((attrs & JSPROP_ENUMERATE) != 0);
|
||||
return ok;
|
||||
}
|
||||
|
||||
#if JS_HAS_GETTER_SETTER
|
||||
static JSBool
|
||||
obj_defineGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
obj_defineGetter(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval fval, junk;
|
||||
jsid id;
|
||||
JSObject *obj;
|
||||
uintN attrs;
|
||||
|
||||
fval = argv[1];
|
||||
fval = vp[3];
|
||||
if (JS_TypeOfValue(cx, fval) != JSTYPE_FUNCTION) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_GETTER_OR_SETTER,
|
||||
|
@ -1633,8 +1636,9 @@ obj_defineGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!JS_ValueToId(cx, argv[0], &id))
|
||||
if (!JS_ValueToId(cx, vp[2], &id))
|
||||
return JS_FALSE;
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!js_CheckRedeclaration(cx, obj, id, JSPROP_GETTER, NULL, NULL))
|
||||
return JS_FALSE;
|
||||
/*
|
||||
|
@ -1643,6 +1647,7 @@ obj_defineGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
*/
|
||||
if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs))
|
||||
return JS_FALSE;
|
||||
*vp = JSVAL_VOID;
|
||||
return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
|
||||
(JSPropertyOp) JSVAL_TO_OBJECT(fval), NULL,
|
||||
JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SHARED,
|
||||
|
@ -1650,14 +1655,14 @@ obj_defineGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
}
|
||||
|
||||
static JSBool
|
||||
obj_defineSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
obj_defineSetter(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval fval, junk;
|
||||
jsid id;
|
||||
JSObject *obj;
|
||||
uintN attrs;
|
||||
|
||||
fval = argv[1];
|
||||
fval = vp[3];
|
||||
if (JS_TypeOfValue(cx, fval) != JSTYPE_FUNCTION) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_GETTER_OR_SETTER,
|
||||
|
@ -1665,8 +1670,9 @@ obj_defineSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!JS_ValueToId(cx, argv[0], &id))
|
||||
if (!JS_ValueToId(cx, vp[2], &id))
|
||||
return JS_FALSE;
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!js_CheckRedeclaration(cx, obj, id, JSPROP_SETTER, NULL, NULL))
|
||||
return JS_FALSE;
|
||||
/*
|
||||
|
@ -1675,6 +1681,7 @@ obj_defineSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
*/
|
||||
if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs))
|
||||
return JS_FALSE;
|
||||
*vp = JSVAL_VOID;
|
||||
return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
|
||||
NULL, (JSPropertyOp) JSVAL_TO_OBJECT(fval),
|
||||
JSPROP_ENUMERATE | JSPROP_SETTER | JSPROP_SHARED,
|
||||
|
@ -1682,23 +1689,23 @@ obj_defineSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
}
|
||||
|
||||
static JSBool
|
||||
obj_lookupGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
obj_lookupGetter(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsid id;
|
||||
JSObject *pobj;
|
||||
JSProperty *prop;
|
||||
JSScopeProperty *sprop;
|
||||
|
||||
if (!JS_ValueToId(cx, argv[0], &id))
|
||||
if (!JS_ValueToId(cx, vp[2], &id))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, JSVAL_TO_OBJECT(vp[1]), id, &pobj, &prop))
|
||||
return JS_FALSE;
|
||||
*vp = JSVAL_VOID;
|
||||
if (prop) {
|
||||
if (OBJ_IS_NATIVE(pobj)) {
|
||||
sprop = (JSScopeProperty *) prop;
|
||||
if (sprop->attrs & JSPROP_GETTER)
|
||||
*rval = OBJECT_TO_JSVAL(sprop->getter);
|
||||
*vp = OBJECT_TO_JSVAL(sprop->getter);
|
||||
}
|
||||
OBJ_DROP_PROPERTY(cx, pobj, prop);
|
||||
}
|
||||
|
@ -1706,23 +1713,23 @@ obj_lookupGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
}
|
||||
|
||||
static JSBool
|
||||
obj_lookupSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
obj_lookupSetter(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsid id;
|
||||
JSObject *pobj;
|
||||
JSProperty *prop;
|
||||
JSScopeProperty *sprop;
|
||||
|
||||
if (!JS_ValueToId(cx, argv[0], &id))
|
||||
if (!JS_ValueToId(cx, vp[2], &id))
|
||||
return JS_FALSE;
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, JSVAL_TO_OBJECT(vp[1]), id, &pobj, &prop))
|
||||
return JS_FALSE;
|
||||
*vp = JSVAL_VOID;
|
||||
if (prop) {
|
||||
if (OBJ_IS_NATIVE(pobj)) {
|
||||
sprop = (JSScopeProperty *) prop;
|
||||
if (sprop->attrs & JSPROP_SETTER)
|
||||
*rval = OBJECT_TO_JSVAL(sprop->setter);
|
||||
*vp = OBJECT_TO_JSVAL(sprop->setter);
|
||||
}
|
||||
OBJ_DROP_PROPERTY(cx, pobj, prop);
|
||||
}
|
||||
|
@ -1746,25 +1753,25 @@ const char js_lookupSetter_str[] = "__lookupSetter__";
|
|||
|
||||
static JSFunctionSpec object_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, js_obj_toSource, 0, 0, OBJ_TOSTRING_EXTRA},
|
||||
JS_FN(js_toSource_str, obj_toSource, 0,0,0,OBJ_TOSTRING_EXTRA),
|
||||
#endif
|
||||
{js_toString_str, js_obj_toString, 0, 0, OBJ_TOSTRING_EXTRA},
|
||||
{js_toLocaleString_str, js_obj_toLocaleString, 0, 0, OBJ_TOSTRING_EXTRA},
|
||||
{js_valueOf_str, obj_valueOf, 0,0,0},
|
||||
JS_FN(js_toString_str, obj_toString, 0,0,0,0),
|
||||
JS_FN(js_toLocaleString_str, obj_toLocaleString, 0,0,0,0),
|
||||
JS_FN(js_valueOf_str, obj_valueOf, 0,0,0,0),
|
||||
#if JS_HAS_OBJ_WATCHPOINT
|
||||
{js_watch_str, obj_watch, 2,0,0},
|
||||
{js_unwatch_str, obj_unwatch, 1,0,0},
|
||||
JS_FN(js_watch_str, obj_watch, 2,2,0,0),
|
||||
JS_FN(js_unwatch_str, obj_unwatch, 1,1,0,0),
|
||||
#endif
|
||||
{js_hasOwnProperty_str, obj_hasOwnProperty, 1,0,0},
|
||||
{js_isPrototypeOf_str, obj_isPrototypeOf, 1,0,0},
|
||||
{js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0,0},
|
||||
JS_FN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,1,0,0),
|
||||
JS_FN(js_isPrototypeOf_str, obj_isPrototypeOf, 1,1,0,0),
|
||||
JS_FN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,1,0,0),
|
||||
#if JS_HAS_GETTER_SETTER
|
||||
{js_defineGetter_str, obj_defineGetter, 2,0,0},
|
||||
{js_defineSetter_str, obj_defineSetter, 2,0,0},
|
||||
{js_lookupGetter_str, obj_lookupGetter, 1,0,0},
|
||||
{js_lookupSetter_str, obj_lookupSetter, 1,0,0},
|
||||
JS_FN(js_defineGetter_str, obj_defineGetter, 2,2,0,0),
|
||||
JS_FN(js_defineSetter_str, obj_defineSetter, 2,2,0,0),
|
||||
JS_FN(js_lookupGetter_str, obj_lookupGetter, 1,1,0,0),
|
||||
JS_FN(js_lookupSetter_str, obj_lookupSetter, 1,1,0,0),
|
||||
#endif
|
||||
{0,0,0,0,0}
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static JSBool
|
||||
|
|
|
@ -154,19 +154,23 @@ struct JSObject {
|
|||
: (JS_ASSERT((slot) < (uint32)(obj)->dslots[-1]), \
|
||||
(obj)->dslots[(slot) - JS_INITIAL_NSLOTS] = (value)))
|
||||
|
||||
#define STOBJ_GET_PROTO(obj) \
|
||||
#define STOBJ_GET_PROTO(obj) \
|
||||
JSVAL_TO_OBJECT((obj)->fslots[JSSLOT_PROTO])
|
||||
#define STOBJ_SET_PROTO(obj,proto) \
|
||||
((obj)->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto))
|
||||
|
||||
#define STOBJ_GET_PARENT(obj) \
|
||||
#define STOBJ_GET_PARENT(obj) \
|
||||
JSVAL_TO_OBJECT((obj)->fslots[JSSLOT_PARENT])
|
||||
#define STOBJ_SET_PARENT(obj,parent) \
|
||||
((obj)->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent))
|
||||
|
||||
#define STOBJ_GET_CLASS(obj) \
|
||||
#define STOBJ_GET_CLASS(obj) \
|
||||
((JSClass *)JSVAL_TO_PRIVATE((obj)->fslots[JSSLOT_CLASS]))
|
||||
|
||||
#define STOBJ_GET_PRIVATE(obj) \
|
||||
(JS_ASSERT(JSVAL_IS_INT(STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE))), \
|
||||
JSVAL_TO_PRIVATE(STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE)))
|
||||
|
||||
#define OBJ_CHECK_SLOT(obj,slot) \
|
||||
JS_ASSERT(slot < (obj)->map->freeslot)
|
||||
|
||||
|
@ -195,6 +199,9 @@ struct JSObject {
|
|||
#define LOCKED_OBJ_GET_CLASS(obj) \
|
||||
(OBJ_CHECK_SLOT(obj, JSSLOT_CLASS), STOBJ_GET_CLASS(obj))
|
||||
|
||||
#define LOCKED_OBJ_GET_PRIVATE(obj) \
|
||||
(OBJ_CHECK_SLOT(obj, JSSLOT_PRIVATE), STOBJ_GET_PRIVATE(obj))
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
/* Thread-safe functions and wrapper macros for accessing slots in obj. */
|
||||
|
@ -260,10 +267,11 @@ struct JSObject {
|
|||
|
||||
/*
|
||||
* Class is invariant and comes from the fixed JSCLASS_SLOT. Thus no locking
|
||||
* is necessary to read it.
|
||||
* is necessary to read it. Same for the private slot.
|
||||
*/
|
||||
#define GC_AWARE_GET_CLASS(cx, obj) STOBJ_GET_CLASS(obj)
|
||||
#define OBJ_GET_CLASS(cx,obj) STOBJ_GET_CLASS(obj)
|
||||
#define OBJ_GET_PRIVATE(cx,obj) STOBJ_GET_PRIVATE(obj)
|
||||
|
||||
/* Test whether a map or object is native. */
|
||||
#define MAP_IS_NATIVE(map) \
|
||||
|
@ -360,16 +368,7 @@ extern void
|
|||
js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map);
|
||||
|
||||
extern JSBool
|
||||
js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_HasOwnPropertyHelper(JSContext *cx, JSObject *obj, JSLookupPropOp lookup,
|
||||
uintN argc, jsval *argv, jsval *rval);
|
||||
js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, jsval *vp);
|
||||
|
||||
extern JSObject*
|
||||
js_InitBlockClass(JSContext *cx, JSObject* obj);
|
||||
|
|
|
@ -2078,7 +2078,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
JS_GET_SCRIPT_OBJECT(jp->script, js_GetSrcNoteOffset(sn, 0),
|
||||
obj);
|
||||
do_function:
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
jp2 = JS_NEW_PRINTER(cx, "nested_function",
|
||||
jp->indent, jp->pretty);
|
||||
if (!jp2)
|
||||
|
@ -2114,6 +2114,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
if ((cs->prec != 0 &&
|
||||
cs->prec <= js_CodeSpec[NEXT_OP(pc)].prec) ||
|
||||
pc[JSOP_GROUP_LENGTH] == JSOP_NULL ||
|
||||
pc[JSOP_GROUP_LENGTH] == JSOP_GLOBALTHIS ||
|
||||
pc[JSOP_GROUP_LENGTH] == JSOP_DUP ||
|
||||
pc[JSOP_GROUP_LENGTH] == JSOP_IFEQ ||
|
||||
pc[JSOP_GROUP_LENGTH] == JSOP_IFNE) {
|
||||
|
@ -2736,7 +2737,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
case JSOP_RETURN:
|
||||
obj = jp->object;
|
||||
LOCAL_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_FunctionClass);
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
if (fun->flags & JSFUN_EXPR_CLOSURE) {
|
||||
rval = POP_STR();
|
||||
js_printf(jp, (*rval == '{') ? "(%s)%s" : ss_format,
|
||||
|
@ -3822,7 +3823,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
SprintStack ss2;
|
||||
|
||||
LOAD_FUNCTION(0);
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
LOCAL_ASSERT(FUN_INTERPRETED(fun));
|
||||
inner = fun->u.i.script;
|
||||
|
||||
|
@ -3855,11 +3856,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
jp->script = outer;
|
||||
|
||||
/*
|
||||
* Advance over this op and its null |this| push, and
|
||||
* Advance over this op and its global |this| push, and
|
||||
* arrange to advance over the call to this lambda.
|
||||
*/
|
||||
pc += len;
|
||||
LOCAL_ASSERT(*pc == JSOP_NULL);
|
||||
LOCAL_ASSERT(*pc == JSOP_GLOBALTHIS);
|
||||
pc += JSOP_NULL_LENGTH;
|
||||
LOCAL_ASSERT(*pc == JSOP_CALL);
|
||||
LOCAL_ASSERT(GET_ARGC(pc) == 0);
|
||||
|
@ -3938,14 +3939,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
* parenthesization without confusing getter/setter code
|
||||
* that checks for JSOP_ANONFUNOBJ and JSOP_NAMEDFUNOBJ.
|
||||
*/
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
if (!(fun->flags & JSFUN_EXPR_CLOSURE))
|
||||
indent |= JS_IN_GROUP_CONTEXT;
|
||||
if (!js_fun_toString(cx, obj, indent, 0, NULL, &val))
|
||||
str = JS_DecompileFunction(cx, fun, indent);
|
||||
if (!str)
|
||||
return NULL;
|
||||
}
|
||||
sprint_string_value:
|
||||
str = JSVAL_TO_STRING(val);
|
||||
sprint_string:
|
||||
todo = SprintString(&ss->sprinter, str);
|
||||
break;
|
||||
|
||||
|
@ -3957,9 +3958,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
case JSOP_REGEXP:
|
||||
GET_REGEXP_FROM_BYTECODE(jp->script, pc, 0, obj);
|
||||
do_regexp:
|
||||
if (!js_regexp_toString(cx, obj, 0, NULL, &val))
|
||||
if (!js_regexp_toString(cx, obj, &val))
|
||||
return NULL;
|
||||
goto sprint_string_value;
|
||||
str = JSVAL_TO_STRING(val);
|
||||
goto sprint_string;
|
||||
|
||||
case JSOP_TABLESWITCH:
|
||||
case JSOP_TABLESWITCHX:
|
||||
|
|
|
@ -262,7 +262,9 @@ OPDEF(JSOP_RETSUB, 115,"retsub", NULL, 1, 0, 0, 0, JOF_BYTE)
|
|||
|
||||
/* More exception handling ops. */
|
||||
OPDEF(JSOP_EXCEPTION, 116,"exception", NULL, 1, 0, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED117, 117,"", NULL, 0, 0, 0, 0, 0)
|
||||
|
||||
/* Push the global object as |this| for a non-reference-type callable. */
|
||||
OPDEF(JSOP_GLOBALTHIS,117,"globalthis", js_null_str, 1, 0, 1, 0, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* ECMA-compliant switch statement ops.
|
||||
|
@ -310,10 +312,13 @@ OPDEF(JSOP_NAMEDFUNOBJ, 129, "namedfunobj", NULL, 3, 0, 1, 19, JOF_OBJECT
|
|||
*/
|
||||
OPDEF(JSOP_SETLOCALPOP, 130, "setlocalpop", NULL, 3, 1, 0, 3, JOF_LOCAL|JOF_NAME|JOF_SET)
|
||||
|
||||
/* ECMA-mandated parenthesization opcode, which nulls the reference base register, obj; see jsinterp.c. */
|
||||
/* Parenthesization opcode to help the decompiler. */
|
||||
OPDEF(JSOP_GROUP, 131, "group", NULL, 1, 0, 0, 19, JOF_BYTE)
|
||||
|
||||
/* Host object extension: given 'o.item(i) = j', the left-hand side compiles JSOP_SETCALL, rather than JSOP_CALL. */
|
||||
/*
|
||||
* Host object extension: given 'o.item(i) = j', the left-hand side compiles
|
||||
* JSOP_SETCALL, rather than JSOP_CALL.
|
||||
*/
|
||||
OPDEF(JSOP_SETCALL, 132, "setcall", NULL, 3, -1, 2, 18, JOF_UINT16|JOF_SET|JOF_ASSIGNING)
|
||||
|
||||
/*
|
||||
|
|
|
@ -1236,7 +1236,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||
* can properly optimize accesses.
|
||||
*/
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, varobj) == &js_FunctionClass);
|
||||
JS_ASSERT(fp->fun == (JSFunction *) JS_GetPrivate(cx, varobj));
|
||||
JS_ASSERT(fp->fun == (JSFunction *) OBJ_GET_PRIVATE(cx, varobj));
|
||||
if (!js_LookupHiddenProperty(cx, varobj, ATOM_TO_JSID(funAtom),
|
||||
&pobj, &prop)) {
|
||||
return NULL;
|
||||
|
|
|
@ -132,6 +132,8 @@ typedef struct JSContext JSContext;
|
|||
typedef struct JSErrorReport JSErrorReport;
|
||||
typedef struct JSFunction JSFunction;
|
||||
typedef struct JSFunctionSpec JSFunctionSpec;
|
||||
typedef struct JSFastNativeSpec JSFastNativeSpec;
|
||||
typedef struct JSFastNativeBlock JSFastNativeBlock;
|
||||
typedef struct JSTracer JSTracer;
|
||||
typedef struct JSIdArray JSIdArray;
|
||||
typedef struct JSProperty JSProperty;
|
||||
|
@ -589,6 +591,10 @@ typedef JSBool
|
|||
(* JS_DLL_CALLBACK JSNative)(JSContext *cx, JSObject *obj, uintN argc,
|
||||
jsval *argv, jsval *rval);
|
||||
|
||||
/* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros. */
|
||||
typedef JSBool
|
||||
(* JS_DLL_CALLBACK JSFastNative)(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
/* Callbacks and their arguments. */
|
||||
|
||||
typedef enum JSContextOp {
|
||||
|
|
|
@ -3812,13 +3812,14 @@ regexp_finalize(JSContext *cx, JSObject *obj)
|
|||
|
||||
/* Forward static prototype. */
|
||||
static JSBool
|
||||
regexp_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
JSBool test, jsval *rval);
|
||||
|
||||
static JSBool
|
||||
regexp_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
return regexp_exec(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval);
|
||||
return regexp_exec_sub(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv,
|
||||
JS_FALSE, rval);
|
||||
}
|
||||
|
||||
#if JS_HAS_XDR
|
||||
|
@ -3894,8 +3895,7 @@ JSClass js_RegExpClass = {
|
|||
static const jschar empty_regexp_ucstr[] = {'(', '?', ':', ')', 0};
|
||||
|
||||
JSBool
|
||||
js_regexp_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
js_regexp_toString(JSContext *cx, JSObject *obj, jsval *vp)
|
||||
{
|
||||
JSRegExp *re;
|
||||
const jschar *source;
|
||||
|
@ -3904,13 +3904,13 @@ js_regexp_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
uintN flags;
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_RegExpClass, argv))
|
||||
if (!JS_InstanceOf(cx, obj, &js_RegExpClass, vp + 2))
|
||||
return JS_FALSE;
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
re = (JSRegExp *) JS_GetPrivate(cx, obj);
|
||||
if (!re) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
*rval = STRING_TO_JSVAL(cx->runtime->emptyString);
|
||||
*vp = STRING_TO_JSVAL(cx->runtime->emptyString);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -3951,13 +3951,19 @@ js_regexp_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
JS_free(cx, chars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
regexp_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
regexp_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return js_regexp_toString(cx, JS_THIS_OBJECT(cx, vp), vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
regexp_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSString *opt, *str;
|
||||
JSRegExp *oldre, *re;
|
||||
|
@ -4075,6 +4081,12 @@ created:
|
|||
return ok2;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
regexp_compile(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return regexp_compile_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
JSBool test, jsval *rval)
|
||||
|
@ -4152,30 +4164,31 @@ out:
|
|||
}
|
||||
|
||||
static JSBool
|
||||
regexp_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
regexp_exec(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return regexp_exec_sub(cx, obj, argc, argv, JS_FALSE, rval);
|
||||
return regexp_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, JS_FALSE,
|
||||
vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
regexp_test(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
regexp_test(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (!regexp_exec_sub(cx, obj, argc, argv, JS_TRUE, rval))
|
||||
if (!regexp_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, JS_TRUE, vp))
|
||||
return JS_FALSE;
|
||||
if (*rval != JSVAL_TRUE)
|
||||
*rval = JSVAL_FALSE;
|
||||
if (*vp != JSVAL_TRUE)
|
||||
*vp = JSVAL_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec regexp_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, js_regexp_toString, 0,0,0},
|
||||
JS_FN(js_toSource_str, regexp_toString, 0,0,0,0),
|
||||
#endif
|
||||
{js_toString_str, js_regexp_toString, 0,0,0},
|
||||
{"compile", regexp_compile, 1,0,0},
|
||||
{"exec", regexp_exec, 0,0,0},
|
||||
{"test", regexp_test, 0,0,0},
|
||||
{0,0,0,0,0}
|
||||
JS_FN(js_toString_str, regexp_toString, 0,0,0,0),
|
||||
JS_FN("compile", regexp_compile, 0,2,0,0),
|
||||
JS_FN("exec", regexp_exec, 0,1,0,0),
|
||||
JS_FN("test", regexp_test, 0,1,0,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static JSBool
|
||||
|
@ -4184,7 +4197,7 @@ RegExp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
|
||||
/*
|
||||
* If first arg is regexp and no flags are given, just return the arg.
|
||||
* (regexp_compile detects the regexp + flags case and throws a
|
||||
* (regexp_compile_sub detects the regexp + flags case and throws a
|
||||
* TypeError.) See 10.15.3.1.
|
||||
*/
|
||||
if ((argc < 2 || JSVAL_IS_VOID(argv[1])) &&
|
||||
|
@ -4200,12 +4213,12 @@ RegExp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* regexp_compile does not use rval to root its temporaries
|
||||
* so we can use it to root obj.
|
||||
* regexp_compile_sub does not use rval to root its temporaries so we
|
||||
* can use it to root obj.
|
||||
*/
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
return regexp_compile(cx, obj, argc, argv, rval);
|
||||
return regexp_compile_sub(cx, obj, argc, argv, rval);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
|
@ -4230,7 +4243,7 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
/* Give RegExp.prototype private data so it matches the empty string. */
|
||||
if (!regexp_compile(cx, proto, 0, NULL, &rval))
|
||||
if (!regexp_compile_sub(cx, proto, 0, NULL, &rval))
|
||||
goto bad;
|
||||
return proto;
|
||||
|
||||
|
|
|
@ -155,8 +155,7 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj);
|
|||
* Export js_regexp_toString to the decompiler.
|
||||
*/
|
||||
extern JSBool
|
||||
js_regexp_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
js_regexp_toString(JSContext *cx, JSObject *obj, jsval *vp);
|
||||
|
||||
/*
|
||||
* Create, serialize/deserialize, or clone a RegExp object.
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
|
||||
#if JS_HAS_SCRIPT_OBJECT
|
||||
|
||||
static const char js_script_exec[] = "Script.prototype.exec";
|
||||
static const char js_script_compile[] = "Script.prototype.compile";
|
||||
static const char js_script_exec_str[] = "Script.prototype.exec";
|
||||
static const char js_script_compile_str[] = "Script.prototype.compile";
|
||||
|
||||
/*
|
||||
* This routine requires that obj has been locked previously.
|
||||
|
@ -94,9 +94,9 @@ AdjustScriptExecDepth(JSContext *cx, JSObject *obj, jsint delta)
|
|||
|
||||
#if JS_HAS_TOSOURCE
|
||||
static JSBool
|
||||
script_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
script_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
uint32 indent;
|
||||
JSScript *script;
|
||||
size_t i, j, k, n;
|
||||
|
@ -104,11 +104,12 @@ script_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
jschar *s, *t;
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
|
||||
return JS_FALSE;
|
||||
|
||||
indent = 0;
|
||||
if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent))
|
||||
if (argc != 0 && !js_ValueToECMAUint32(cx, vp[2], &indent))
|
||||
return JS_FALSE;
|
||||
|
||||
script = (JSScript *) JS_GetPrivate(cx, obj);
|
||||
|
@ -151,28 +152,29 @@ script_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
JS_free(cx, t);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif /* JS_HAS_TOSOURCE */
|
||||
|
||||
static JSBool
|
||||
script_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
script_toString(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
uint32 indent;
|
||||
JSObject *obj;
|
||||
JSScript *script;
|
||||
JSString *str;
|
||||
|
||||
indent = 0;
|
||||
if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent))
|
||||
if (argc != 0 && !js_ValueToECMAUint32(cx, vp[2], &indent))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
|
||||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
|
||||
return JS_FALSE;
|
||||
script = (JSScript *) JS_GetPrivate(cx, obj);
|
||||
if (!script) {
|
||||
*rval = STRING_TO_JSVAL(cx->runtime->emptyString);
|
||||
*vp = STRING_TO_JSVAL(cx->runtime->emptyString);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -180,13 +182,13 @@ script_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
(uintN)indent);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
script_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
script_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSString *str;
|
||||
JSObject *scopeobj;
|
||||
|
@ -242,7 +244,7 @@ script_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
}
|
||||
|
||||
/* Ensure we compile this script with the right (inner) principals. */
|
||||
scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_compile);
|
||||
scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_compile_str);
|
||||
if (!scopeobj)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -295,7 +297,14 @@ out:
|
|||
}
|
||||
|
||||
static JSBool
|
||||
script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
script_compile(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return script_compile_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
script_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSObject *scopeobj, *parent;
|
||||
JSStackFrame *fp, *caller;
|
||||
|
@ -307,7 +316,7 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_FALSE;
|
||||
|
||||
scopeobj = NULL;
|
||||
if (argc) {
|
||||
if (argc != 0) {
|
||||
if (!js_ValueToObject(cx, argv[0], &scopeobj))
|
||||
return JS_FALSE;
|
||||
argv[0] = OBJECT_TO_JSVAL(scopeobj);
|
||||
|
@ -360,7 +369,7 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
}
|
||||
}
|
||||
|
||||
scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_exec);
|
||||
scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_exec_str);
|
||||
if (!scopeobj)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -388,6 +397,12 @@ out:
|
|||
return ok;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
script_exec(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
return script_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp);
|
||||
}
|
||||
|
||||
#endif /* JS_HAS_SCRIPT_OBJECT */
|
||||
|
||||
#if JS_HAS_XDR
|
||||
|
@ -618,9 +633,9 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
|
|||
*/
|
||||
|
||||
static JSBool
|
||||
script_freeze(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
script_freeze(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
JSXDRState *xdr;
|
||||
JSScript *script;
|
||||
JSBool ok, hasMagic;
|
||||
|
@ -628,7 +643,8 @@ script_freeze(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
void *buf;
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
|
||||
return JS_FALSE;
|
||||
script = (JSScript *) JS_GetPrivate(cx, obj);
|
||||
if (!script)
|
||||
|
@ -644,7 +660,7 @@ script_freeze(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
if (!ok)
|
||||
goto out;
|
||||
if (!hasMagic) {
|
||||
*rval = JSVAL_VOID;
|
||||
*vp = JSVAL_VOID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -673,7 +689,7 @@ script_freeze(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
goto out;
|
||||
}
|
||||
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
|
||||
out:
|
||||
JS_XDRDestroy(xdr);
|
||||
|
@ -681,9 +697,9 @@ out:
|
|||
}
|
||||
|
||||
static JSBool
|
||||
script_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
script_thaw(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
JSXDRState *xdr;
|
||||
JSString *str;
|
||||
void *buf;
|
||||
|
@ -693,15 +709,16 @@ script_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
JSBool ok, hasMagic;
|
||||
jsint execDepth;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
|
||||
obj = JSVAL_TO_OBJECT(vp[1]);
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
|
||||
return JS_FALSE;
|
||||
|
||||
if (argc == 0)
|
||||
return JS_TRUE;
|
||||
str = js_ValueToString(cx, argv[0]);
|
||||
str = js_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
argv[0] = STRING_TO_JSVAL(str);
|
||||
vp[2] = STRING_TO_JSVAL(str);
|
||||
|
||||
/* create new XDR */
|
||||
xdr = JS_XDRNewMem(cx, JSXDR_DECODE);
|
||||
|
@ -735,7 +752,7 @@ script_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
if (!ok)
|
||||
goto out;
|
||||
if (!hasMagic) {
|
||||
*rval = JSVAL_FALSE;
|
||||
*vp = JSVAL_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -768,14 +785,14 @@ script_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
out:
|
||||
/*
|
||||
* We reset the buffer to be NULL so that it doesn't free the chars
|
||||
* memory owned by str (argv[0]).
|
||||
* memory owned by str (vp[2]).
|
||||
*/
|
||||
JS_XDRMemSetData(xdr, NULL, 0);
|
||||
JS_XDRDestroy(xdr);
|
||||
#if IS_BIG_ENDIAN
|
||||
JS_free(cx, buf);
|
||||
#endif
|
||||
*rval = JSVAL_TRUE;
|
||||
*vp = JSVAL_TRUE;
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -788,16 +805,16 @@ static const char js_thaw_str[] = "thaw";
|
|||
|
||||
static JSFunctionSpec script_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, script_toSource, 0,0,0},
|
||||
JS_FN(js_toSource_str, script_toSource, 0,0,0,0),
|
||||
#endif
|
||||
{js_toString_str, script_toString, 0,0,0},
|
||||
{"compile", script_compile, 2,0,0},
|
||||
{"exec", script_exec, 1,0,0},
|
||||
JS_FN(js_toString_str, script_toString, 0,0,0,0),
|
||||
JS_FN("compile", script_compile, 0,2,0,0),
|
||||
JS_FN("exec", script_exec, 0,1,0,0),
|
||||
#if JS_HAS_XDR_FREEZE_THAW
|
||||
{"freeze", script_freeze, 0,0,0},
|
||||
{js_thaw_str, script_thaw, 1,0,0},
|
||||
JS_FN("freeze", script_freeze, 0,0,0,0),
|
||||
JS_FN(js_thaw_str, script_thaw, 0,1,0,0),
|
||||
#endif /* JS_HAS_XDR_FREEZE_THAW */
|
||||
{0,0,0,0,0}
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
#endif /* JS_HAS_SCRIPT_OBJECT */
|
||||
|
@ -816,7 +833,7 @@ static JSBool
|
|||
script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
#if JS_HAS_SCRIPT_OBJECT
|
||||
return script_exec(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval);
|
||||
return script_exec_sub(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval);
|
||||
#else
|
||||
return JS_FALSE;
|
||||
#endif
|
||||
|
@ -858,8 +875,8 @@ Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* script_compile does not use rval to root its temporaries
|
||||
* so we can use it to root obj.
|
||||
* script_compile_sub does not use rval to root its temporaries so we
|
||||
* can use it to root obj.
|
||||
*/
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
|
@ -867,27 +884,29 @@ Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
if (!JS_SetReservedSlot(cx, obj, 0, INT_TO_JSVAL(0)))
|
||||
return JS_FALSE;
|
||||
|
||||
return script_compile(cx, obj, argc, argv, rval);
|
||||
return script_compile_sub(cx, obj, argc, argv, rval);
|
||||
}
|
||||
|
||||
#if JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW
|
||||
|
||||
static JSBool
|
||||
script_static_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
script_static_thaw(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (!script_thaw(cx, obj, argc, argv, rval))
|
||||
vp[1] = OBJECT_TO_JSVAL(obj);
|
||||
if (!script_thaw(cx, vp))
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec script_static_methods[] = {
|
||||
{js_thaw_str, script_static_thaw, 1,0,0},
|
||||
{0,0,0,0,0}
|
||||
JS_FN(js_thaw_str, script_static_thaw, 1,1,0,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
#else /* !JS_HAS_SCRIPT_OBJECT || !JS_HAS_XDR_FREEZE_THAW */
|
||||
|
@ -1611,7 +1630,7 @@ js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
|
|||
pc += js_CodeSpec[*pc].length;
|
||||
if (*pc == JSOP_DEFFUN) {
|
||||
GET_FUNCTION_FROM_BYTECODE(script, pc, 0, obj);
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
fun = (JSFunction *) OBJ_GET_PRIVATE(cx, obj);
|
||||
JS_ASSERT(FUN_INTERPRETED(fun));
|
||||
return fun->u.i.script->lineno;
|
||||
}
|
||||
|
|
798
js/src/jsstr.c
798
js/src/jsstr.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -297,6 +297,22 @@ typedef enum JSCharType {
|
|||
extern JSBool
|
||||
js_InitRuntimeStringState(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Maximum character code for which we will create a pinned unit string on
|
||||
* demand -- see JSRuntime.unitStrings in jscntxt.h.
|
||||
*/
|
||||
#define UNIT_STRING_LIMIT 256
|
||||
|
||||
/*
|
||||
* Get the independent string containing only character code c (backstopped
|
||||
* with a NUL as usual for independent strings).
|
||||
*
|
||||
* This function must be called only for c < UNIT_STRING_LIMIT. It asserts to
|
||||
* insist on this requirement in DEBUG builds.
|
||||
*/
|
||||
extern JSString *
|
||||
js_GetUnitString(JSContext *cx, jschar c);
|
||||
|
||||
extern void
|
||||
js_FinishRuntimeStringState(JSContext *cx);
|
||||
|
||||
|
|
656
js/src/jsxml.c
656
js/src/jsxml.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче