зеркало из https://github.com/mozilla/pjs.git
bug=423874 r=brendan a1.9b5=dsicore
Allocating native functions together with JSObject
This commit is contained in:
Родитель
fa81372ac7
Коммит
5ab7e29428
|
@ -1636,8 +1636,7 @@ nsScriptSecurityManager::CheckFunctionAccess(JSContext *aCx, void *aFunObj,
|
|||
{
|
||||
#ifdef DEBUG
|
||||
{
|
||||
JSFunction *fun =
|
||||
(JSFunction *)caps_GetJSPrivate((JSObject *)aFunObj);
|
||||
JSFunction *fun = GET_FUNCTION_PRIVATE(aCx, (JSObject *)aFunObj);
|
||||
JSScript *script = JS_GetFunctionScript(aCx, fun);
|
||||
|
||||
NS_ASSERTION(!script, "Null principal for non-native function!");
|
||||
|
@ -2152,7 +2151,7 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
|
|||
nsresult *rv)
|
||||
{
|
||||
NS_PRECONDITION(rv, "Null out param");
|
||||
JSFunction *fun = (JSFunction *) caps_GetJSPrivate(obj);
|
||||
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
JSScript *script = JS_GetFunctionScript(cx, fun);
|
||||
|
||||
*rv = NS_OK;
|
||||
|
@ -2221,7 +2220,7 @@ nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
|
|||
#ifdef DEBUG
|
||||
if (NS_SUCCEEDED(*rv) && !result)
|
||||
{
|
||||
JSFunction *fun = (JSFunction *)caps_GetJSPrivate(obj);
|
||||
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
JSScript *script = JS_GetFunctionScript(cx, fun);
|
||||
|
||||
NS_ASSERTION(!script, "Null principal for non-native function!");
|
||||
|
|
|
@ -1033,7 +1033,9 @@ jsdScript::CreatePPLineMap()
|
|||
PRBool scriptOwner = PR_FALSE;
|
||||
|
||||
if (fun) {
|
||||
if (fun->nargs > 12)
|
||||
PRUint32 nargs = JS_GetFunctionArity(fun);
|
||||
|
||||
if (nargs > 12)
|
||||
return nsnull;
|
||||
JSString *jsstr = JS_DecompileFunctionBody (cx, fun, 4);
|
||||
if (!jsstr)
|
||||
|
@ -1042,7 +1044,7 @@ jsdScript::CreatePPLineMap()
|
|||
const char *argnames[] = {"arg1", "arg2", "arg3", "arg4",
|
||||
"arg5", "arg6", "arg7", "arg8",
|
||||
"arg9", "arg10", "arg11", "arg12" };
|
||||
fun = JS_CompileUCFunction (cx, obj, "ppfun", fun->nargs, argnames,
|
||||
fun = JS_CompileUCFunction (cx, obj, "ppfun", nargs, argnames,
|
||||
JS_GetStringChars(jsstr),
|
||||
JS_GetStringLength(jsstr),
|
||||
"x-jsd:ppbuffer?type=function", 3);
|
||||
|
|
55
js/src/js.c
55
js/src/js.c
|
@ -933,15 +933,15 @@ CountHeap(JSContext *cx, uintN argc, jsval *vp)
|
|||
const char *name;
|
||||
int32 kind;
|
||||
} traceKindNames[] = {
|
||||
{ "all", -1 },
|
||||
{ "object", JSTRACE_OBJECT },
|
||||
{ "double", JSTRACE_DOUBLE },
|
||||
{ "string", JSTRACE_STRING },
|
||||
{ "function", JSTRACE_FUNCTION },
|
||||
{ "all", -1 },
|
||||
{ "object", JSTRACE_OBJECT },
|
||||
{ "double", JSTRACE_DOUBLE },
|
||||
{ "string", JSTRACE_STRING },
|
||||
{ "function", JSTRACE_SCRIPTED_FUNCTION },
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
{ "namespace", JSTRACE_NAMESPACE },
|
||||
{ "qname", JSTRACE_QNAME },
|
||||
{ "xml", JSTRACE_XML },
|
||||
{ "namespace", JSTRACE_NAMESPACE },
|
||||
{ "qname", JSTRACE_QNAME },
|
||||
{ "xml", JSTRACE_XML },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1029,7 +1029,7 @@ ValueToScript(JSContext *cx, jsval v)
|
|||
fun = JS_ValueToFunction(cx, v);
|
||||
if (!fun)
|
||||
return NULL;
|
||||
script = FUN_SCRIPT(fun);
|
||||
script = JS_GetFunctionScript(cx, fun);
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
@ -1371,26 +1371,31 @@ Disassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return JS_FALSE;
|
||||
|
||||
if (VALUE_IS_FUNCTION(cx, argv[i])) {
|
||||
JSFunction *fun = JS_ValueToFunction(cx, argv[i]);
|
||||
if (fun && (fun->flags & JSFUN_FLAGS_MASK)) {
|
||||
uint16 flags = fun->flags;
|
||||
fputs("flags:", stdout);
|
||||
JSFunction *fun;
|
||||
uint16 flags;
|
||||
|
||||
fun = JS_ValueToFunction(cx, argv[i]);
|
||||
if (fun) {
|
||||
flags = JS_GetFunctionFlags(fun);
|
||||
if (flags & JSFUN_FLAGS_MASK) {
|
||||
fputs("flags:", stdout);
|
||||
|
||||
#define SHOW_FLAG(flag) if (flags & JSFUN_##flag) fputs(" " #flag, stdout);
|
||||
|
||||
SHOW_FLAG(LAMBDA);
|
||||
SHOW_FLAG(SETTER);
|
||||
SHOW_FLAG(GETTER);
|
||||
SHOW_FLAG(BOUND_METHOD);
|
||||
SHOW_FLAG(HEAVYWEIGHT);
|
||||
SHOW_FLAG(THISP_STRING);
|
||||
SHOW_FLAG(THISP_NUMBER);
|
||||
SHOW_FLAG(THISP_BOOLEAN);
|
||||
SHOW_FLAG(EXPR_CLOSURE);
|
||||
SHOW_FLAG(INTERPRETED);
|
||||
SHOW_FLAG(LAMBDA);
|
||||
SHOW_FLAG(SETTER);
|
||||
SHOW_FLAG(GETTER);
|
||||
SHOW_FLAG(BOUND_METHOD);
|
||||
SHOW_FLAG(HEAVYWEIGHT);
|
||||
SHOW_FLAG(THISP_STRING);
|
||||
SHOW_FLAG(THISP_NUMBER);
|
||||
SHOW_FLAG(THISP_BOOLEAN);
|
||||
SHOW_FLAG(EXPR_CLOSURE);
|
||||
SHOW_FLAG(SCRIPTED);
|
||||
|
||||
#undef SHOW_FLAG
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2947,7 +2952,7 @@ Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
type = JS_TypeOfValue(cx, argv[i]);
|
||||
if (type == JSTYPE_FUNCTION) {
|
||||
fun = JS_ValueToFunction(cx, argv[i]);
|
||||
str = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
|
||||
str = JS_GetFunctionId(fun);
|
||||
} else if (type == JSTYPE_STRING) {
|
||||
str = JSVAL_TO_STRING(argv[i]);
|
||||
} else {
|
||||
|
|
118
js/src/jsapi.c
118
js/src/jsapi.c
|
@ -369,7 +369,7 @@ JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
|
|||
break;
|
||||
case 'f':
|
||||
fun = va_arg(ap, JSFunction *);
|
||||
*sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
|
||||
*sp = fun ? OBJECT_TO_JSVAL(FUN_OBJECT(fun)) : JSVAL_NULL;
|
||||
break;
|
||||
case 'v':
|
||||
*sp = va_arg(ap, jsval);
|
||||
|
@ -2014,7 +2014,7 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
|
|||
name = "double";
|
||||
break;
|
||||
|
||||
case JSTRACE_FUNCTION:
|
||||
case JSTRACE_SCRIPTED_FUNCTION:
|
||||
name = "function";
|
||||
break;
|
||||
|
||||
|
@ -2074,9 +2074,9 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
|
|||
JS_snprintf(buf, bufsize, "%g", *(jsdouble *)thing);
|
||||
break;
|
||||
|
||||
case JSTRACE_FUNCTION:
|
||||
case JSTRACE_SCRIPTED_FUNCTION:
|
||||
{
|
||||
JSFunction *fun = (JSFunction *)thing;
|
||||
JSScriptedFunction *fun = (JSScriptedFunction *)thing;
|
||||
|
||||
if (fun->atom && ATOM_IS_STRING(fun->atom))
|
||||
js_PutEscapedString(buf, bufsize, ATOM_TO_STRING(fun->atom), 0);
|
||||
|
@ -2668,7 +2668,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
|||
JSTempValueRooter tvr;
|
||||
jsval cval, rval;
|
||||
JSBool named;
|
||||
JSFunction *fun;
|
||||
JSNativeFunction *fun;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
|
||||
|
@ -2698,7 +2698,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
|||
}
|
||||
|
||||
/* Create a prototype object for this class. */
|
||||
proto = js_NewObject(cx, clasp, parent_proto, obj);
|
||||
proto = js_NewObject(cx, clasp, parent_proto, obj, 0);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
|
@ -2741,7 +2741,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
|||
* we know to create an object of this class when we call the
|
||||
* constructor.
|
||||
*/
|
||||
fun->u.n.clasp = clasp;
|
||||
fun->clasp = clasp;
|
||||
|
||||
/*
|
||||
* Optionally construct the prototype object, before the class has
|
||||
|
@ -2749,7 +2749,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
|||
* different object, as is done for operator new -- and as at least
|
||||
* XML support requires.
|
||||
*/
|
||||
ctor = fun->object;
|
||||
ctor = &fun->object;
|
||||
if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
|
||||
cval = OBJECT_TO_JSVAL(ctor);
|
||||
if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval))
|
||||
|
@ -2966,7 +2966,7 @@ JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
|
|||
CHECK_REQUEST(cx);
|
||||
if (!clasp)
|
||||
clasp = &js_ObjectClass; /* default class is Object */
|
||||
return js_NewObject(cx, clasp, proto, parent);
|
||||
return js_NewObject(cx, clasp, proto, parent, 0);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
|
@ -2976,7 +2976,7 @@ JS_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
CHECK_REQUEST(cx);
|
||||
if (!clasp)
|
||||
clasp = &js_ObjectClass; /* default class is Object */
|
||||
return js_NewObjectWithGivenProto(cx, clasp, proto, parent);
|
||||
return js_NewObjectWithGivenProto(cx, clasp, proto, parent, 0);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -3120,7 +3120,7 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
|
|||
CHECK_REQUEST(cx);
|
||||
if (!clasp)
|
||||
clasp = &js_ObjectClass; /* default class is Object */
|
||||
nobj = js_NewObject(cx, clasp, proto, obj);
|
||||
nobj = js_NewObject(cx, clasp, proto, obj, 0);
|
||||
if (!nobj)
|
||||
return NULL;
|
||||
if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
|
||||
|
@ -3999,7 +3999,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
|
|||
JSIdArray *ida;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj);
|
||||
iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj, 0);
|
||||
if (!iterobj)
|
||||
return NULL;
|
||||
|
||||
|
@ -4197,6 +4197,7 @@ JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
|
|||
JSObject *parent, const char *name)
|
||||
{
|
||||
JSAtom *atom;
|
||||
JSNativeFunction *fun;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
|
@ -4207,7 +4208,8 @@ JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
|
|||
if (!atom)
|
||||
return NULL;
|
||||
}
|
||||
return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
|
||||
fun = js_NewNativeFunction(cx, native, nargs, flags, parent, atom);
|
||||
return fun ? NATIVE_TO_FUN(fun) : NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
|
@ -4224,49 +4226,43 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
|||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFunctionObject(JSFunction *fun)
|
||||
{
|
||||
return fun->object;
|
||||
return FUN_OBJECT(fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(const char *)
|
||||
JS_GetFunctionName(JSFunction *fun)
|
||||
{
|
||||
return fun->atom
|
||||
? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
|
||||
: js_anonymous_str;
|
||||
JSAtom *atom;
|
||||
|
||||
atom = FUN_ATOM(fun);
|
||||
return atom ? JS_GetStringBytes(ATOM_TO_STRING(atom)) : js_anonymous_str;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
JS_GetFunctionId(JSFunction *fun)
|
||||
{
|
||||
return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
|
||||
JSAtom *atom;
|
||||
|
||||
atom = FUN_ATOM(fun);
|
||||
return atom ? ATOM_TO_STRING(atom) : NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uintN)
|
||||
JS_GetFunctionFlags(JSFunction *fun)
|
||||
{
|
||||
#ifdef MOZILLA_1_8_BRANCH
|
||||
uintN flags = fun->flags;
|
||||
|
||||
return JSFUN_DISJOINT_FLAGS(flags) |
|
||||
(JSFUN_GETTER_TEST(flags) ? JSFUN_GETTER : 0) |
|
||||
(JSFUN_SETTER_TEST(flags) ? JSFUN_SETTER : 0) |
|
||||
(JSFUN_BOUND_METHOD_TEST(flags) ? JSFUN_BOUND_METHOD : 0) |
|
||||
(JSFUN_HEAVYWEIGHT_TEST(flags) ? JSFUN_HEAVYWEIGHT : 0);
|
||||
#else
|
||||
return fun->flags;
|
||||
#endif
|
||||
return FUN_FLAGS(fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uint16)
|
||||
JS_GetFunctionArity(JSFunction *fun)
|
||||
{
|
||||
return fun->nargs;
|
||||
return FUN_NARGS(fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
|
||||
return HAS_FUNCTION_CLASS(obj);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
|
@ -4386,6 +4382,7 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
|
|||
uintN flags;
|
||||
JSObject *ctor;
|
||||
JSFunction *fun;
|
||||
JSNativeFunction *native;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
ctor = NULL;
|
||||
|
@ -4412,14 +4409,16 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
|
|||
fs->nargs + 1, flags);
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
fun->u.n.extra = (uint16)fs->extra;
|
||||
fun->u.n.minargs = (uint16)(fs->extra >> 16);
|
||||
native = FUN_TO_NATIVE(fun);
|
||||
native->extra = (uint16)fs->extra;
|
||||
native->minargs = (uint16)(fs->extra >> 16);
|
||||
|
||||
/*
|
||||
* As jsapi.h notes, fs must point to storage that lives as long
|
||||
* as fun->object lives.
|
||||
*/
|
||||
if (!JS_SetReservedSlot(cx, fun->object, 0, PRIVATE_TO_JSVAL(fs)))
|
||||
if (!JS_SetReservedSlot(cx, &native->object, 0,
|
||||
PRIVATE_TO_JSVAL(fs)))
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -4428,8 +4427,9 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
|
|||
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);
|
||||
native = FUN_TO_NATIVE(fun);
|
||||
native->extra = (uint16)fs->extra;
|
||||
native->minargs = (uint16)(fs->extra >> 16);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -4439,12 +4439,14 @@ JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
|
|||
uintN nargs, uintN attrs)
|
||||
{
|
||||
JSAtom *atom;
|
||||
JSNativeFunction *fun;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
atom = js_Atomize(cx, name, strlen(name), 0);
|
||||
if (!atom)
|
||||
return NULL;
|
||||
return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
|
||||
fun = js_DefineFunction(cx, obj, atom, call, nargs, attrs);
|
||||
return fun ? NATIVE_TO_FUN(fun) : NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
|
@ -4453,11 +4455,13 @@ JS_DefineUCFunction(JSContext *cx, JSObject *obj,
|
|||
uintN nargs, uintN attrs)
|
||||
{
|
||||
JSAtom *atom;
|
||||
JSNativeFunction *fun;
|
||||
|
||||
atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
|
||||
if (!atom)
|
||||
return NULL;
|
||||
return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
|
||||
fun = js_DefineFunction(cx, obj, atom, call, nargs, attrs);
|
||||
return fun ? NATIVE_TO_FUN(fun) : NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
|
@ -4635,10 +4639,10 @@ JS_NewScriptObject(JSContext *cx, JSScript *script)
|
|||
JSObject *obj;
|
||||
|
||||
if (!script)
|
||||
return js_NewObject(cx, &js_ScriptClass, NULL, NULL);
|
||||
return js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
|
||||
|
||||
JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
|
||||
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
|
||||
if (obj) {
|
||||
JS_SetPrivate(cx, obj, script);
|
||||
script->object = obj;
|
||||
|
@ -4723,7 +4727,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
|
|||
const jschar *chars, size_t length,
|
||||
const char *filename, uintN lineno)
|
||||
{
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
JSTempValueRooter tvr;
|
||||
JSAtom *funAtom, *argAtom;
|
||||
uintN i;
|
||||
|
@ -4738,7 +4742,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
|
|||
goto out2;
|
||||
}
|
||||
}
|
||||
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
|
||||
fun = js_NewScriptedFunction(cx, NULL, 0, obj, funAtom);
|
||||
if (!fun)
|
||||
goto out2;
|
||||
|
||||
|
@ -4782,12 +4786,12 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
|
|||
#endif
|
||||
|
||||
out:
|
||||
cx->weakRoots.newborn[JSTRACE_FUNCTION] = fun;
|
||||
cx->weakRoots.newborn[JSTRACE_SCRIPTED_FUNCTION] = fun;
|
||||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
|
||||
out2:
|
||||
LAST_FRAME_CHECKS(cx, fun);
|
||||
return fun;
|
||||
return fun ? SCRIPTED_TO_FUN(fun) : NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
|
@ -4798,7 +4802,7 @@ JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
|
|||
JSString *str;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
jp = JS_NEW_PRINTER(cx, name, NULL,
|
||||
jp = JS_NEW_PRINTER(cx, name,
|
||||
indent & ~JS_DONT_PRETTY_PRINT,
|
||||
!(indent & JS_DONT_PRETTY_PRINT));
|
||||
if (!jp)
|
||||
|
@ -4818,15 +4822,18 @@ JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
|
|||
JSString *str;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
jp = JS_NEW_PRINTER(cx, "JS_DecompileFunction", fun,
|
||||
jp = JS_NEW_PRINTER(cx, "JS_DecompileFunction",
|
||||
indent & ~JS_DONT_PRETTY_PRINT,
|
||||
!(indent & JS_DONT_PRETTY_PRINT));
|
||||
if (!jp)
|
||||
return NULL;
|
||||
if (js_DecompileFunction(jp))
|
||||
if (FUN_IS_SCRIPTED(fun)
|
||||
? js_DecompileFunction(jp, FUN_TO_SCRIPTED(fun))
|
||||
: js_DecompileNativeFunction(jp, FUN_TO_NATIVE(fun))) {
|
||||
str = js_GetPrinterOutput(jp);
|
||||
else
|
||||
} else {
|
||||
str = NULL;
|
||||
}
|
||||
js_DestroyPrinter(jp);
|
||||
return str;
|
||||
}
|
||||
|
@ -4838,15 +4845,19 @@ JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
|
|||
JSString *str;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
jp = JS_NEW_PRINTER(cx, "JS_DecompileFunctionBody", fun,
|
||||
|
||||
jp = JS_NEW_PRINTER(cx, "JS_DecompileFunctionBody",
|
||||
indent & ~JS_DONT_PRETTY_PRINT,
|
||||
!(indent & JS_DONT_PRETTY_PRINT));
|
||||
if (!jp)
|
||||
return NULL;
|
||||
if (js_DecompileFunctionBody(jp))
|
||||
if (FUN_IS_SCRIPTED(fun)
|
||||
? js_DecompileFunctionBody(jp, FUN_TO_SCRIPTED(fun))
|
||||
: js_DecompileNativeFunctionBody(jp, FUN_TO_NATIVE(fun))) {
|
||||
str = js_GetPrinterOutput(jp);
|
||||
else
|
||||
} else {
|
||||
str = NULL;
|
||||
}
|
||||
js_DestroyPrinter(jp);
|
||||
return str;
|
||||
}
|
||||
|
@ -4972,10 +4983,11 @@ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
|
|||
jsval *argv, jsval *rval)
|
||||
{
|
||||
JSBool ok;
|
||||
jsval funval;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv,
|
||||
rval);
|
||||
funval = OBJECT_TO_JSVAL(FUN_OBJECT(fun));
|
||||
ok = js_InternalCall(cx, obj, funval, argc, argv, rval);
|
||||
LAST_FRAME_CHECKS(cx, ok);
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -2879,7 +2879,7 @@ Array(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
|
||||
/* If called without new, replace obj with a new Array object. */
|
||||
if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
|
||||
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
|
@ -2929,7 +2929,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector)
|
|||
JSTempValueRooter tvr;
|
||||
JSObject *obj;
|
||||
|
||||
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
|
@ -2946,7 +2946,7 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector)
|
|||
JSObject *
|
||||
js_NewSlowArrayObject(JSContext *cx)
|
||||
{
|
||||
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL);
|
||||
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL, 0);
|
||||
if (obj)
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
|
||||
return obj;
|
||||
|
|
|
@ -2150,7 +2150,7 @@ js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
|
|||
JSObject *obj;
|
||||
jsdouble *date;
|
||||
|
||||
obj = js_NewObject(cx, &js_DateClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_DateClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -564,7 +564,9 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
clasp = OBJ_GET_CLASS(cx, closure);
|
||||
if (clasp == &js_FunctionClass) {
|
||||
fun = GET_FUNCTION_PRIVATE(cx, closure);
|
||||
script = FUN_SCRIPT(fun);
|
||||
script = FUN_IS_SCRIPTED(fun)
|
||||
? FUN_TO_SCRIPTED(fun)->script
|
||||
: NULL;
|
||||
} else if (clasp == &js_ScriptClass) {
|
||||
fun = NULL;
|
||||
script = (JSScript *) JS_GetPrivate(cx, closure);
|
||||
|
@ -576,10 +578,15 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
nslots = 2;
|
||||
injectFrame = JS_TRUE;
|
||||
if (fun) {
|
||||
nslots += FUN_MINARGS(fun);
|
||||
if (!FUN_INTERPRETED(fun)) {
|
||||
nslots += fun->u.n.extra;
|
||||
injectFrame = !(fun->flags & JSFUN_FAST_NATIVE);
|
||||
if (FUN_IS_SCRIPTED(fun)) {
|
||||
nslots += FUN_TO_SCRIPTED(fun)->nargs;
|
||||
} else {
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
nfun = FUN_TO_NATIVE(fun);
|
||||
nslots += NATIVE_FUN_MINARGS(nfun);
|
||||
nslots += nfun->extra;
|
||||
injectFrame = !(nfun->flags & JSFUN_FAST_NATIVE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -657,7 +664,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 = GET_FUNCTION_PRIVATE(cx, funobj);
|
||||
userid = ATOM_KEY(wrapper->atom);
|
||||
userid = ATOM_KEY(FUN_ATOM(wrapper));
|
||||
*rval = argv[0];
|
||||
return js_watch_set(cx, obj, userid, rval);
|
||||
}
|
||||
|
@ -666,7 +673,7 @@ JSPropertyOp
|
|||
js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
|
||||
{
|
||||
JSAtom *atom;
|
||||
JSFunction *wrapper;
|
||||
JSNativeFunction *wrapper;
|
||||
|
||||
if (!(attrs & JSPROP_SETTER))
|
||||
return &js_watch_set; /* & to silence schoolmarmish MSVC */
|
||||
|
@ -680,12 +687,12 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
|
|||
} else {
|
||||
atom = NULL;
|
||||
}
|
||||
wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0,
|
||||
OBJ_GET_PARENT(cx, (JSObject *)setter),
|
||||
atom);
|
||||
wrapper = js_NewNativeFunction(cx, js_watch_set_wrapper, 1, 0,
|
||||
OBJ_GET_PARENT(cx, (JSObject *)setter),
|
||||
atom);
|
||||
if (!wrapper)
|
||||
return NULL;
|
||||
return (JSPropertyOp) wrapper->object;
|
||||
return (JSPropertyOp) &wrapper->object;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -918,19 +925,33 @@ JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
|
|||
JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return FUN_SCRIPT(fun);
|
||||
return FUN_IS_SCRIPTED(fun) ? FUN_TO_SCRIPTED(fun)->script : NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSNative)
|
||||
JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return FUN_NATIVE(fun);
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
if (FUN_IS_SCRIPTED(fun))
|
||||
return NULL;
|
||||
|
||||
nfun = FUN_TO_NATIVE(fun);
|
||||
return (nfun->flags & JSFUN_FAST_NATIVE) ? NULL : nfun->native;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFastNative)
|
||||
JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return FUN_FAST_NATIVE(fun);
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
if (FUN_IS_SCRIPTED(fun))
|
||||
return NULL;
|
||||
|
||||
nfun = FUN_TO_NATIVE(fun);
|
||||
return (nfun->flags & JSFUN_FAST_NATIVE)
|
||||
? (JSFastNative) nfun->native
|
||||
: NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSPrincipals *)
|
||||
|
@ -983,7 +1004,7 @@ JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
|
|||
JSRuntime *rt = cx->runtime;
|
||||
|
||||
if (rt->findObjectPrincipals) {
|
||||
if (fp->fun->object != fp->callee)
|
||||
if (FUN_OBJECT(fp->fun) != fp->callee)
|
||||
return rt->findObjectPrincipals(cx, fp->callee);
|
||||
/* FALL THROUGH */
|
||||
}
|
||||
|
@ -1552,13 +1573,25 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
|
|||
{
|
||||
size_t nbytes;
|
||||
|
||||
nbytes = sizeof *fun;
|
||||
if (fun->object)
|
||||
nbytes += JS_GetObjectTotalSize(cx, fun->object);
|
||||
if (FUN_INTERPRETED(fun))
|
||||
nbytes += JS_GetScriptTotalSize(cx, fun->u.i.script);
|
||||
if (fun->atom)
|
||||
nbytes += GetAtomTotalSize(cx, fun->atom);
|
||||
if (FUN_IS_SCRIPTED(fun)) {
|
||||
JSScriptedFunction *sfun;
|
||||
|
||||
sfun = FUN_TO_SCRIPTED(fun);
|
||||
nbytes = sizeof *sfun;
|
||||
nbytes += JS_GetScriptTotalSize(cx, sfun->script);
|
||||
if (sfun->object)
|
||||
nbytes += JS_GetObjectTotalSize(cx, sfun->object);
|
||||
if (sfun->atom)
|
||||
nbytes += GetAtomTotalSize(cx, sfun->atom);
|
||||
} else {
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
nfun = FUN_TO_NATIVE(fun);
|
||||
nbytes = sizeof(JSNativeFunction) - sizeof(JSObject);
|
||||
nbytes += JS_GetObjectTotalSize(cx, &nfun->object);
|
||||
if (nfun->atom)
|
||||
nbytes += GetAtomTotalSize(cx, nfun->atom);
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
|
@ -1667,7 +1700,7 @@ JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = js_NewObject(cx, clasp, proto, parent);
|
||||
obj = js_NewObject(cx, clasp, proto, parent, 0);
|
||||
if (obj && system)
|
||||
STOBJ_SET_SYSTEM(obj);
|
||||
return obj;
|
||||
|
|
|
@ -54,9 +54,13 @@ static char dempty[] = "<null>";
|
|||
char *
|
||||
jsdtrace_funcclass_name(JSFunction *fun)
|
||||
{
|
||||
return (!FUN_INTERPRETED(fun) && fun->u.n.clasp)
|
||||
? (char *)fun->u.n.clasp->name
|
||||
: dempty;
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
if (FUN_IS_SCRIPTED(fun))
|
||||
return dempty;
|
||||
|
||||
nfun = FUN_TO_NATIVE(fun);
|
||||
return nfun->clasp ? (char *) nfun->clasp->name : dempty;
|
||||
}
|
||||
|
||||
char *
|
||||
|
|
|
@ -2037,7 +2037,7 @@ CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
JSBool *answer)
|
||||
{
|
||||
JSBool ok;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
JSParseNode *pn2;
|
||||
|
||||
ok = JS_TRUE;
|
||||
|
@ -2053,7 +2053,7 @@ CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
* name in that scope object. See comments at case JSOP_NAMEDFUNOBJ:
|
||||
* in jsinterp.c.
|
||||
*/
|
||||
fun = GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object);
|
||||
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object));
|
||||
if (fun->atom)
|
||||
*answer = JS_TRUE;
|
||||
break;
|
||||
|
@ -3924,7 +3924,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
switch (pn->pn_type) {
|
||||
case TOK_FUNCTION:
|
||||
{
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
void *cg2mark;
|
||||
JSCodeGenerator *cg2;
|
||||
uintN slot;
|
||||
|
@ -3937,8 +3937,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
}
|
||||
#endif
|
||||
|
||||
fun = GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object);
|
||||
if (fun->u.i.script) {
|
||||
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object));
|
||||
if (fun->script) {
|
||||
/*
|
||||
* This second pass is needed to emit JSOP_NOP with a source note
|
||||
* for the already-emitted function. See comments in the TOK_LC
|
||||
|
|
|
@ -175,7 +175,7 @@ struct JSTreeContext { /* tree context for semantic checks */
|
|||
XXX combine with blockChain? */
|
||||
JSAtomList decls; /* function, const, and var declarations */
|
||||
JSParseContext *parseContext;
|
||||
JSFunction *fun; /* function to store argument and variable
|
||||
JSScriptedFunction *fun; /* function to store argument and variable
|
||||
names when flags & TCF_IN_FUNCTION */
|
||||
};
|
||||
|
||||
|
|
|
@ -321,8 +321,11 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
|
|||
elem->funName = NULL;
|
||||
elem->argc = 0;
|
||||
} else {
|
||||
elem->funName = fp->fun->atom
|
||||
? ATOM_TO_STRING(fp->fun->atom)
|
||||
JSAtom *atom;
|
||||
|
||||
atom = FUN_ATOM(fp->fun);
|
||||
elem->funName = atom
|
||||
? ATOM_TO_STRING(atom)
|
||||
: cx->runtime->emptyString;
|
||||
elem->argc = fp->argc;
|
||||
memcpy(values, fp->argv, fp->argc * sizeof(jsval));
|
||||
|
@ -750,7 +753,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
.classPrototypeAtom),
|
||||
rval))
|
||||
return JS_FALSE;
|
||||
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL);
|
||||
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
|
@ -1043,7 +1046,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
|||
/* Initialize the prototypes first. */
|
||||
for (i = 0; exceptions[i].name != 0; i++) {
|
||||
JSAtom *atom;
|
||||
JSFunction *fun;
|
||||
JSNativeFunction *fun;
|
||||
JSObject *funobj;
|
||||
JSString *nameString;
|
||||
int protoIndex = exceptions[i].protoIndex;
|
||||
|
@ -1053,7 +1056,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
|||
(protoIndex != JSEXN_NONE)
|
||||
? protos[protoIndex]
|
||||
: obj_proto,
|
||||
obj);
|
||||
obj, 0);
|
||||
if (!protos[i])
|
||||
break;
|
||||
|
||||
|
@ -1067,10 +1070,10 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
|||
break;
|
||||
|
||||
/* Make this constructor make objects of class Exception. */
|
||||
fun->u.n.clasp = &js_ErrorClass;
|
||||
fun->clasp = &js_ErrorClass;
|
||||
|
||||
/* Extract the constructor object. */
|
||||
funobj = fun->object;
|
||||
funobj = &fun->object;
|
||||
|
||||
/* Make the prototype and constructor links. */
|
||||
if (!js_SetClassPrototype(cx, funobj, protos[i],
|
||||
|
@ -1223,7 +1226,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
|
|||
goto out;
|
||||
tv[0] = OBJECT_TO_JSVAL(errProto);
|
||||
|
||||
errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL);
|
||||
errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL, 0);
|
||||
if (!errObject) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
|
|
381
js/src/jsfun.c
381
js/src/jsfun.c
|
@ -242,7 +242,8 @@ js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
|
|||
* We must be in a function activation; the function must be lightweight
|
||||
* or else fp must have a variable object.
|
||||
*/
|
||||
JS_ASSERT(fp->fun && (!(fp->fun->flags & JSFUN_HEAVYWEIGHT) || fp->varobj));
|
||||
JS_ASSERT(fp->fun);
|
||||
JS_ASSERT_IF(FUN_FLAGS(fp->fun) & JSFUN_HEAVYWEIGHT, fp->varobj);
|
||||
|
||||
/* Skip eval and debugger frames. */
|
||||
while (fp->flags & JSFRAME_SPECIAL)
|
||||
|
@ -254,7 +255,7 @@ js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
|
|||
return argsobj;
|
||||
|
||||
/* Link the new object to fp so it can get actual argument values. */
|
||||
argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL);
|
||||
argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL, 0);
|
||||
if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) {
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
|
@ -418,7 +419,7 @@ args_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
break;
|
||||
|
||||
default:
|
||||
if (FUN_INTERPRETED(fp->fun) &&
|
||||
if (FUN_IS_SCRIPTED(fp->fun) &&
|
||||
(uintN)slot < fp->argc &&
|
||||
!ArgWasDeleted(cx, fp, slot)) {
|
||||
fp->argv[slot] = *vp;
|
||||
|
@ -602,7 +603,7 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent)
|
|||
}
|
||||
|
||||
/* Create the call object and link it to its stack frame. */
|
||||
callobj = js_NewObject(cx, &js_CallClass, NULL, parent);
|
||||
callobj = js_NewObject(cx, &js_CallClass, NULL, parent, 0);
|
||||
if (!callobj || !JS_SetPrivate(cx, callobj, fp)) {
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
|
@ -669,7 +670,7 @@ call_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
|
||||
if (!fp)
|
||||
return JS_TRUE;
|
||||
JS_ASSERT(fp->fun);
|
||||
JS_ASSERT(fp->fun && FUN_IS_SCRIPTED(fp->fun));
|
||||
|
||||
slot = JSVAL_TO_INT(id);
|
||||
switch (slot) {
|
||||
|
@ -683,7 +684,7 @@ call_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
break;
|
||||
|
||||
default:
|
||||
if ((uintN)slot < JS_MAX(fp->argc, fp->fun->nargs))
|
||||
if ((uintN)slot < JS_MAX(fp->argc, FUN_TO_SCRIPTED(fp->fun)->nargs))
|
||||
*vp = fp->argv[slot];
|
||||
break;
|
||||
}
|
||||
|
@ -701,7 +702,7 @@ call_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
|
||||
if (!fp)
|
||||
return JS_TRUE;
|
||||
JS_ASSERT(fp->fun);
|
||||
JS_ASSERT(fp->fun && FUN_IS_SCRIPTED(fp->fun));
|
||||
|
||||
slot = JSVAL_TO_INT(id);
|
||||
switch (slot) {
|
||||
|
@ -710,7 +711,7 @@ call_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
break;
|
||||
|
||||
default:
|
||||
if ((uintN)slot < JS_MAX(fp->argc, fp->fun->nargs))
|
||||
if ((uintN)slot < JS_MAX(fp->argc, FUN_TO_SCRIPTED(fp->fun)->nargs))
|
||||
fp->argv[slot] = *vp;
|
||||
break;
|
||||
}
|
||||
|
@ -749,7 +750,7 @@ static JSBool
|
|||
call_enumerate(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSStackFrame *fp;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
uintN n, i, slot;
|
||||
void *mark;
|
||||
jsuword *names;
|
||||
|
@ -769,7 +770,7 @@ call_enumerate(JSContext *cx, JSObject *obj)
|
|||
* and functions in fp->vars for declared variables and nested-at-top-level
|
||||
* local functions.
|
||||
*/
|
||||
fun = fp->fun;
|
||||
fun = FUN_TO_SCRIPTED(fp->fun);
|
||||
n = JS_GET_LOCAL_NAME_COUNT(fun);
|
||||
if (n == 0)
|
||||
return JS_TRUE;
|
||||
|
@ -821,6 +822,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
|
|||
{
|
||||
JSStackFrame *fp;
|
||||
jsid id;
|
||||
JSScriptedFunction *fun;
|
||||
JSLocalKind localKind;
|
||||
JSPropertyOp getter, setter;
|
||||
uintN slot, attrs;
|
||||
|
@ -829,7 +831,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
|
|||
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
|
||||
if (!fp)
|
||||
return JS_TRUE;
|
||||
JS_ASSERT(fp->fun);
|
||||
JS_ASSERT(fp->fun && FUN_IS_SCRIPTED(fp->fun));
|
||||
JS_ASSERT(GET_FUNCTION_PRIVATE(cx, fp->callee) == fp->fun);
|
||||
|
||||
if (!JSVAL_IS_STRING(idval))
|
||||
|
@ -838,16 +840,17 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
|
|||
if (!js_ValueToStringId(cx, idval, &id))
|
||||
return JS_FALSE;
|
||||
|
||||
localKind = js_LookupLocal(cx, fp->fun, JSID_TO_ATOM(id), &slot);
|
||||
fun = FUN_TO_SCRIPTED(fp->fun);
|
||||
localKind = js_LookupLocal(cx, fun, JSID_TO_ATOM(id), &slot);
|
||||
if (localKind != JSLOCAL_NONE) {
|
||||
if (localKind == JSLOCAL_ARG) {
|
||||
JS_ASSERT(slot < fp->fun->nargs);
|
||||
JS_ASSERT(slot < fun->nargs);
|
||||
vp = fp->argv;
|
||||
getter = setter = NULL;
|
||||
attrs = JSPROP_PERMANENT;
|
||||
} else {
|
||||
JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
|
||||
JS_ASSERT(fp->fun->u.i.nvars == fp->nvars);
|
||||
JS_ASSERT(FUN_TO_SCRIPTED(fp->fun)->nvars == fp->nvars);
|
||||
JS_ASSERT(slot < fp->nvars);
|
||||
vp = fp->vars;
|
||||
getter = js_GetCallVariable;
|
||||
|
@ -1012,14 +1015,16 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
case ARGS_LENGTH:
|
||||
case FUN_ARITY:
|
||||
*vp = INT_TO_JSVAL((jsint)fun->nargs);
|
||||
*vp = INT_TO_JSVAL((jsint) FUN_NARGS(fun));
|
||||
break;
|
||||
|
||||
case FUN_NAME:
|
||||
*vp = fun->atom
|
||||
? ATOM_KEY(fun->atom)
|
||||
: STRING_TO_JSVAL(cx->runtime->emptyString);
|
||||
case FUN_NAME: {
|
||||
JSAtom *atom;
|
||||
|
||||
atom = FUN_ATOM(fun);
|
||||
*vp = atom ? ATOM_KEY(atom) : STRING_TO_JSVAL(cx->runtime->emptyString);
|
||||
break;
|
||||
}
|
||||
|
||||
case FUN_CALLER:
|
||||
if (fp && fp->down && fp->down->fun)
|
||||
|
@ -1035,7 +1040,7 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
default:
|
||||
/* XXX fun[0] and fun.arguments[0] are equivalent. */
|
||||
if (fp && fp->fun && (uintN)slot < fp->fun->nargs)
|
||||
if (fp && fp->fun && (uintN)slot < FUN_NARGS(fp->fun))
|
||||
*vp = fp->argv[slot];
|
||||
break;
|
||||
}
|
||||
|
@ -1070,7 +1075,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
return JS_TRUE;
|
||||
|
||||
fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
JS_ASSERT(fun->object);
|
||||
JS_ASSERT(FUN_OBJECT(fun));
|
||||
|
||||
/*
|
||||
* No need to reflect fun.prototype in 'fun.prototype = ... '.
|
||||
|
@ -1099,7 +1104,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
* Beware of the wacky case of a user function named Object -- trying
|
||||
* to find a prototype for that will recur back here _ad perniciem_.
|
||||
*/
|
||||
if (fun->atom == CLASS_ATOM(cx, Object))
|
||||
if (FUN_ATOM(fun) == CLASS_ATOM(cx, Object))
|
||||
return JS_TRUE;
|
||||
|
||||
/*
|
||||
|
@ -1107,7 +1112,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
* object itself.
|
||||
*/
|
||||
proto = js_NewObject(cx, &js_ObjectClass, NULL,
|
||||
OBJ_GET_PARENT(cx, obj));
|
||||
OBJ_GET_PARENT(cx, obj), 0);
|
||||
if (!proto)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -1166,7 +1171,7 @@ static JSBool
|
|||
fun_xdrObject(JSXDRState *xdr, JSObject **objp)
|
||||
{
|
||||
JSContext *cx;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
uint32 nullAtom; /* flag to indicate if fun->atom is NULL */
|
||||
uintN nargs, nvars, n;
|
||||
uint32 localsword; /* word to xdr argument and variable counts */
|
||||
|
@ -1176,20 +1181,23 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
|
|||
|
||||
cx = xdr->cx;
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
fun = GET_FUNCTION_PRIVATE(cx, *objp);
|
||||
if (!FUN_INTERPRETED(fun)) {
|
||||
JSFunction *f;
|
||||
|
||||
f = GET_FUNCTION_PRIVATE(cx, *objp);
|
||||
if (!FUN_IS_SCRIPTED(f)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_NOT_SCRIPTED_FUNCTION,
|
||||
JS_GetFunctionName(fun));
|
||||
JS_GetFunctionName(f));
|
||||
return JS_FALSE;
|
||||
}
|
||||
fun = FUN_TO_SCRIPTED(f);
|
||||
nullAtom = !fun->atom;
|
||||
nargs = fun->nargs;
|
||||
nvars = fun->u.i.nvars;
|
||||
nvars = fun->nvars;
|
||||
localsword = (nargs << 16) | nvars;
|
||||
flagsword = fun->flags;
|
||||
} else {
|
||||
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
|
||||
fun = js_NewScriptedFunction(cx, NULL, 0, NULL, NULL);
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
STOBJ_SET_PARENT(fun->object, NULL);
|
||||
|
@ -1215,7 +1223,7 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
|
|||
if (xdr->mode == JSXDR_DECODE) {
|
||||
nargs = localsword >> 16;
|
||||
nvars = localsword & JS_BITMASK(16);
|
||||
JS_ASSERT(flagsword | JSFUN_INTERPRETED);
|
||||
JS_ASSERT(flagsword | JSFUN_SCRIPTED);
|
||||
fun->flags = (uint16) flagsword;
|
||||
}
|
||||
|
||||
|
@ -1316,15 +1324,15 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
|
|||
js_FreezeLocalNames(cx, fun);
|
||||
}
|
||||
|
||||
if (!js_XDRScript(xdr, &fun->u.i.script, NULL))
|
||||
if (!js_XDRScript(xdr, &fun->script, NULL))
|
||||
goto bad;
|
||||
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
*objp = fun->object;
|
||||
#ifdef CHECK_SCRIPT_OWNER
|
||||
fun->u.i.script->owner = NULL;
|
||||
fun->script->owner = NULL;
|
||||
#endif
|
||||
js_CallNewScriptHook(cx, fun->u.i.script, fun);
|
||||
js_CallNewScriptHook(cx, fun->script, fun);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -1376,17 +1384,30 @@ static void
|
|||
fun_trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
JSFunction *fun;
|
||||
JSNativeFunction *native;
|
||||
|
||||
/* A newborn function object may have a not yet initialized private slot. */
|
||||
fun = (JSFunction *) JS_GetPrivate(trc->context, obj);
|
||||
if (fun)
|
||||
JS_CALL_TRACER(trc, fun, JSTRACE_FUNCTION, "private");
|
||||
if (!fun)
|
||||
return;
|
||||
|
||||
if (FUN_IS_SCRIPTED(fun)) {
|
||||
JS_CALL_TRACER(trc, FUN_TO_SCRIPTED(fun),
|
||||
JSTRACE_SCRIPTED_FUNCTION, "private");
|
||||
return;
|
||||
}
|
||||
|
||||
native = (JSNativeFunction *) obj;
|
||||
JS_ASSERT(FUN_TO_NATIVE(fun) == native);
|
||||
if (native->atom)
|
||||
JS_CALL_STRING_TRACER(trc, ATOM_TO_STRING(native->atom), "atom");
|
||||
}
|
||||
|
||||
static uint32
|
||||
fun_reserveSlots(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSFunction *fun;
|
||||
JSScript *script;
|
||||
|
||||
/*
|
||||
* We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during
|
||||
|
@ -1394,9 +1415,12 @@ fun_reserveSlots(JSContext *cx, JSObject *obj)
|
|||
* private slot of the function object is set.
|
||||
*/
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
return (fun && FUN_INTERPRETED(fun) &&
|
||||
fun->u.i.script && fun->u.i.script->regexpsOffset != 0)
|
||||
? JS_SCRIPT_REGEXPS(fun->u.i.script)->length
|
||||
if (!fun || !FUN_IS_SCRIPTED(fun))
|
||||
return 0;
|
||||
|
||||
script = FUN_TO_SCRIPTED(fun)->script;
|
||||
return (script && script->regexpsOffset != 0)
|
||||
? JS_SCRIPT_REGEXPS(script)->length
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
@ -1699,7 +1723,7 @@ static JSBool
|
|||
Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSStackFrame *fp, *caller;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
JSObject *parent;
|
||||
uintN i, n, lineno;
|
||||
JSAtom *atom;
|
||||
|
@ -1715,7 +1739,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
|
||||
fp = cx->fp;
|
||||
if (!(fp->flags & JSFRAME_CONSTRUCTING)) {
|
||||
obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
|
@ -1725,8 +1749,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
* The constructor is called before the private slot is initialized so we
|
||||
* must use JS_GetPrivate, not GET_FUNCTION_PRIVATE here.
|
||||
*/
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
if (fun)
|
||||
if (JS_GetPrivate(cx, obj))
|
||||
return JS_TRUE;
|
||||
|
||||
/*
|
||||
|
@ -1741,8 +1764,8 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
*/
|
||||
parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]));
|
||||
|
||||
fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
|
||||
parent, cx->runtime->atomState.anonymousAtom);
|
||||
fun = js_NewScriptedFunction(cx, obj, JSFUN_LAMBDA, parent,
|
||||
cx->runtime->atomState.anonymousAtom);
|
||||
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
|
@ -1754,7 +1777,9 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
* are built for Function.prototype.call or .apply activations that invoke
|
||||
* Function indirectly from a script.
|
||||
*/
|
||||
JS_ASSERT(!fp->script && fp->fun && fp->fun->u.n.native == Function);
|
||||
JS_ASSERT(fp->fun &&
|
||||
!FUN_IS_SCRIPTED(fp->fun) &&
|
||||
FUN_TO_NATIVE(fp->fun)->native == Function);
|
||||
caller = JS_GetScriptedCaller(cx, fp);
|
||||
if (caller) {
|
||||
principals = JS_EvalFramePrincipals(cx, fp, caller);
|
||||
|
@ -1932,7 +1957,7 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj)
|
|||
{
|
||||
JSObject *proto;
|
||||
JSAtom *atom;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
|
||||
proto = JS_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,
|
||||
function_props, function_methods, NULL, NULL);
|
||||
|
@ -1942,15 +1967,15 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj)
|
|||
0);
|
||||
if (!atom)
|
||||
goto bad;
|
||||
fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);
|
||||
fun = js_NewScriptedFunction(cx, proto, 0, obj, NULL);
|
||||
if (!fun)
|
||||
goto bad;
|
||||
fun->u.i.script = js_NewScript(cx, 1, 0, 0, 0, 0, 0);
|
||||
if (!fun->u.i.script)
|
||||
fun->script = js_NewScript(cx, 1, 0, 0, 0, 0, 0);
|
||||
if (!fun->script)
|
||||
goto bad;
|
||||
fun->u.i.script->code[0] = JSOP_STOP;
|
||||
fun->script->code[0] = JSOP_STOP;
|
||||
#ifdef CHECK_SCRIPT_OWNER
|
||||
fun->u.i.script->owner = NULL;
|
||||
fun->script->owner = NULL;
|
||||
#endif
|
||||
return proto;
|
||||
|
||||
|
@ -1977,18 +2002,20 @@ js_InitCallClass(JSContext *cx, JSObject *obj)
|
|||
return proto;
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
||||
uintN flags, JSObject *parent, JSAtom *atom)
|
||||
JSScriptedFunction *
|
||||
js_NewScriptedFunction(JSContext *cx, JSObject *funobj, uintN flags,
|
||||
JSObject *parent, JSAtom *atom)
|
||||
{
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *sfun;
|
||||
JSTempValueRooter tvr;
|
||||
|
||||
JS_ASSERT((flags & ~JSFUN_LAMBDA) == 0);
|
||||
|
||||
/* If funobj is null, allocate an object for it. */
|
||||
if (funobj) {
|
||||
OBJ_SET_PARENT(cx, funobj, parent);
|
||||
} else {
|
||||
funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
|
||||
funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);
|
||||
if (!funobj)
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2000,115 +2027,134 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
|||
* Allocate fun after allocating funobj so allocations in js_NewObject
|
||||
* and hooks called from it do not wipe out fun from newborn[GCX_FUNCTION].
|
||||
*/
|
||||
fun = (JSFunction *) js_NewGCThing(cx, GCX_FUNCTION, sizeof(JSFunction));
|
||||
if (!fun)
|
||||
sfun = (JSScriptedFunction *)
|
||||
js_NewGCThing(cx, GCX_FUNCTION, sizeof(JSScriptedFunction));
|
||||
if (!sfun)
|
||||
goto out;
|
||||
|
||||
/* Initialize all function members. */
|
||||
fun->object = NULL;
|
||||
fun->nargs = nargs;
|
||||
fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED);
|
||||
if (flags & JSFUN_INTERPRETED) {
|
||||
JS_ASSERT(!native);
|
||||
JS_ASSERT(nargs == 0);
|
||||
fun->u.i.nvars = 0;
|
||||
fun->u.i.spare = 0;
|
||||
fun->u.i.script = NULL;
|
||||
sfun->object = NULL;
|
||||
sfun->flags = (flags & JSFUN_FLAGS_MASK) | JSFUN_SCRIPTED;
|
||||
sfun->nargs = 0;
|
||||
sfun->nvars = 0;
|
||||
sfun->spare = 0;
|
||||
sfun->script = NULL;
|
||||
#ifdef DEBUG
|
||||
fun->u.i.names.taggedAtom = 0;
|
||||
sfun->names.taggedAtom = 0;
|
||||
#endif
|
||||
} else {
|
||||
fun->u.n.native = native;
|
||||
fun->u.n.extra = 0;
|
||||
fun->u.n.minargs = 0;
|
||||
fun->u.n.clasp = NULL;
|
||||
}
|
||||
fun->atom = atom;
|
||||
sfun->atom = atom;
|
||||
|
||||
/* Link fun to funobj and vice versa. */
|
||||
if (!js_LinkFunctionObject(cx, fun, funobj)) {
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
fun = NULL;
|
||||
}
|
||||
sfun->object = funobj;
|
||||
JS_SetPrivate(cx, funobj, SCRIPTED_TO_FUN(sfun));
|
||||
|
||||
out:
|
||||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
return fun;
|
||||
return sfun;
|
||||
}
|
||||
|
||||
JSNativeFunction *
|
||||
js_NewNativeFunction(JSContext *cx, JSNative native, uintN nargs,
|
||||
uintN flags, JSObject *parent, JSAtom *atom)
|
||||
{
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
JS_ASSERT(!(flags & (JSFUN_LAMBDA | JSFUN_SCRIPTED)));
|
||||
nfun = (JSNativeFunction *) js_NewObject(cx, &js_FunctionClass, NULL,
|
||||
parent,
|
||||
sizeof(JSNativeFunction) -
|
||||
sizeof(JSObject));
|
||||
if (!nfun)
|
||||
return NULL;
|
||||
|
||||
/* Initialize all function members. */
|
||||
nfun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_SCRIPTED);
|
||||
nfun->nargs = nargs;
|
||||
nfun->native = native;
|
||||
nfun->extra = 0;
|
||||
nfun->minargs = 0;
|
||||
nfun->clasp = NULL;
|
||||
nfun->atom = atom;
|
||||
JS_SetPrivate(cx, &nfun->object, NATIVE_TO_FUN(nfun));
|
||||
|
||||
return nfun;
|
||||
}
|
||||
|
||||
static void
|
||||
TraceLocalNames(JSTracer *trc, JSFunction *fun);
|
||||
TraceLocalNames(JSTracer *trc, JSScriptedFunction *fun);
|
||||
|
||||
void
|
||||
js_TraceFunction(JSTracer *trc, JSFunction *fun)
|
||||
js_TraceFunction(JSTracer *trc, JSScriptedFunction *fun)
|
||||
{
|
||||
if (fun->object)
|
||||
JS_CALL_OBJECT_TRACER(trc, fun->object, "object");
|
||||
if (fun->atom)
|
||||
JS_CALL_STRING_TRACER(trc, ATOM_TO_STRING(fun->atom), "atom");
|
||||
if (FUN_INTERPRETED(fun)) {
|
||||
if (fun->u.i.script)
|
||||
js_TraceScript(trc, fun->u.i.script);
|
||||
TraceLocalNames(trc, fun);
|
||||
}
|
||||
if (fun->script)
|
||||
js_TraceScript(trc, fun->script);
|
||||
TraceLocalNames(trc, fun);
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyLocalNames(JSContext *cx, JSFunction *fun);
|
||||
DestroyLocalNames(JSContext *cx, JSScriptedFunction *fun);
|
||||
|
||||
void
|
||||
js_FinalizeFunction(JSContext *cx, JSFunction *fun)
|
||||
js_FinalizeFunction(JSContext *cx, JSScriptedFunction *fun)
|
||||
{
|
||||
/*
|
||||
* Null-check of i.script is required since the parser sets interpreted
|
||||
* very early.
|
||||
* Null-check of i.script is required since the parser creates
|
||||
* JSScriptedFunction very early.
|
||||
*/
|
||||
if (FUN_INTERPRETED(fun)) {
|
||||
if (fun->u.i.script)
|
||||
js_DestroyScript(cx, fun->u.i.script);
|
||||
DestroyLocalNames(cx, fun);
|
||||
}
|
||||
if (fun->script)
|
||||
js_DestroyScript(cx, fun->script);
|
||||
DestroyLocalNames(cx, fun);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
||||
{
|
||||
JSObject *newfunobj;
|
||||
JSFunction *fun;
|
||||
JSObject *newfunobj;
|
||||
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass);
|
||||
newfunobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
|
||||
if (!newfunobj)
|
||||
return NULL;
|
||||
fun = GET_FUNCTION_PRIVATE(cx, funobj);
|
||||
if (!js_LinkFunctionObject(cx, fun, newfunobj)) {
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
if (FUN_IS_SCRIPTED(fun)) {
|
||||
JSScriptedFunction *sfun;
|
||||
|
||||
sfun = FUN_TO_SCRIPTED(fun);
|
||||
JS_ASSERT(sfun->object);
|
||||
newfunobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);
|
||||
if (!newfunobj)
|
||||
return NULL;
|
||||
JS_SetPrivate(cx, newfunobj, SCRIPTED_TO_FUN(sfun));
|
||||
} else {
|
||||
JS_ASSERT((JSNativeFunction *) funobj == FUN_TO_NATIVE(fun));
|
||||
newfunobj = js_NewObject(cx, &js_FunctionClass, NULL, parent,
|
||||
sizeof(JSNativeFunction) - sizeof(JSObject));
|
||||
if (!newfunobj)
|
||||
return NULL;
|
||||
memcpy((uint8 *) newfunobj + sizeof(JSObject),
|
||||
(uint8 *) funobj + sizeof(JSObject),
|
||||
sizeof(JSNativeFunction) - sizeof(JSObject));
|
||||
JS_SetPrivate(cx, newfunobj,
|
||||
NATIVE_TO_FUN((JSNativeFunction *) newfunobj));
|
||||
}
|
||||
return newfunobj;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *funobj)
|
||||
{
|
||||
if (!fun->object)
|
||||
fun->object = funobj;
|
||||
return JS_SetPrivate(cx, funobj, fun);
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
JSNativeFunction *
|
||||
js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
|
||||
uintN nargs, uintN attrs)
|
||||
{
|
||||
JSFunction *fun;
|
||||
JSNativeFunction *fun;
|
||||
JSPropertyOp gsop;
|
||||
|
||||
fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);
|
||||
fun = js_NewNativeFunction(cx, native, nargs, attrs, obj, atom);
|
||||
if (!fun)
|
||||
return NULL;
|
||||
gsop = (attrs & JSFUN_STUB_GSOPS) ? JS_PropertyStub : NULL;
|
||||
if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
|
||||
OBJECT_TO_JSVAL(fun->object),
|
||||
OBJECT_TO_JSVAL(&fun->object),
|
||||
gsop, gsop,
|
||||
attrs & ~JSFUN_FLAGS_MASK, NULL)) {
|
||||
return NULL;
|
||||
|
@ -2148,6 +2194,7 @@ js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
|
|||
{
|
||||
JSFunction *fun;
|
||||
JSObject *funobj;
|
||||
JSAtom *atom;
|
||||
JSStackFrame *caller;
|
||||
JSPrincipals *principals;
|
||||
|
||||
|
@ -2157,7 +2204,19 @@ js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
|
|||
fun = js_ValueToFunction(cx, vp, flags);
|
||||
if (!fun)
|
||||
return NULL;
|
||||
funobj = fun->object;
|
||||
if (FUN_IS_SCRIPTED(fun)) {
|
||||
JSScriptedFunction *sfun;
|
||||
|
||||
sfun = FUN_TO_SCRIPTED(fun);
|
||||
funobj = sfun->object;
|
||||
atom = sfun->atom;
|
||||
} else {
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
nfun = FUN_TO_NATIVE(fun);
|
||||
funobj = &nfun->object;
|
||||
atom = nfun->atom;
|
||||
}
|
||||
*vp = OBJECT_TO_JSVAL(funobj);
|
||||
|
||||
caller = JS_GetScriptedCaller(cx, cx->fp);
|
||||
|
@ -2169,8 +2228,8 @@ js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
|
|||
}
|
||||
|
||||
if (!js_CheckPrincipalsAccess(cx, funobj, principals,
|
||||
fun->atom
|
||||
? fun->atom
|
||||
atom
|
||||
? atom
|
||||
: cx->runtime->atomState.anonymousAtom)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2321,7 +2380,8 @@ HashLocalName(JSContext *cx, JSLocalNameMap *map, JSAtom *name,
|
|||
}
|
||||
|
||||
JSBool
|
||||
js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
|
||||
js_AddLocal(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
|
||||
JSLocalKind kind)
|
||||
{
|
||||
jsuword taggedAtom;
|
||||
uint16 *indexp;
|
||||
|
@ -2329,14 +2389,13 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
|
|||
jsuword *array;
|
||||
JSLocalNameMap *map;
|
||||
|
||||
JS_ASSERT(FUN_INTERPRETED(fun));
|
||||
JS_ASSERT(!fun->u.i.script);
|
||||
JS_ASSERT(!fun->script);
|
||||
JS_ASSERT(((jsuword) atom & 1) == 0);
|
||||
taggedAtom = (jsuword) atom;
|
||||
if (kind == JSLOCAL_ARG) {
|
||||
indexp = &fun->nargs;
|
||||
} else {
|
||||
indexp = &fun->u.i.nvars;
|
||||
indexp = &fun->nvars;
|
||||
if (kind == JSLOCAL_CONST)
|
||||
taggedAtom |= 1;
|
||||
else
|
||||
|
@ -2344,17 +2403,17 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
|
|||
}
|
||||
n = JS_GET_LOCAL_NAME_COUNT(fun);
|
||||
if (n == 0) {
|
||||
JS_ASSERT(fun->u.i.names.taggedAtom == 0);
|
||||
fun->u.i.names.taggedAtom = taggedAtom;
|
||||
JS_ASSERT(fun->names.taggedAtom == 0);
|
||||
fun->names.taggedAtom = taggedAtom;
|
||||
} else if (n < MAX_ARRAY_LOCALS) {
|
||||
if (n > 1) {
|
||||
array = fun->u.i.names.array;
|
||||
array = fun->names.array;
|
||||
} else {
|
||||
array = (jsuword *) JS_malloc(cx, MAX_ARRAY_LOCALS * sizeof *array);
|
||||
if (!array)
|
||||
return JS_FALSE;
|
||||
array[0] = fun->u.i.names.taggedAtom;
|
||||
fun->u.i.names.array = array;
|
||||
array[0] = fun->names.taggedAtom;
|
||||
fun->names.array = array;
|
||||
}
|
||||
if (kind == JSLOCAL_ARG) {
|
||||
/*
|
||||
|
@ -2362,19 +2421,19 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
|
|||
* so for the following arguments nvars != 0.
|
||||
*/
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
if (fun->u.i.nvars != 0) {
|
||||
if (fun->nvars != 0) {
|
||||
memmove(array + fun->nargs + 1, array + fun->nargs,
|
||||
fun->u.i.nvars * sizeof *array);
|
||||
fun->nvars * sizeof *array);
|
||||
}
|
||||
#else
|
||||
JS_ASSERT(fun->u.i.nvars == 0);
|
||||
JS_ASSERT(fun->nvars == 0);
|
||||
#endif
|
||||
array[fun->nargs] = taggedAtom;
|
||||
} else {
|
||||
array[n] = taggedAtom;
|
||||
}
|
||||
} else if (n == MAX_ARRAY_LOCALS) {
|
||||
array = fun->u.i.names.array;
|
||||
array = fun->names.array;
|
||||
map = (JSLocalNameMap *) JS_malloc(cx, sizeof *map);
|
||||
if (!map)
|
||||
return JS_FALSE;
|
||||
|
@ -2408,7 +2467,7 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
|
|||
* At this point the entry is added and we cannot fail. It is time
|
||||
* to replace fun->u.i.names with the built map.
|
||||
*/
|
||||
fun->u.i.names.map = map;
|
||||
fun->names.map = map;
|
||||
JS_free(cx, array);
|
||||
} else {
|
||||
if (*indexp == JS_BITMASK(16)) {
|
||||
|
@ -2418,7 +2477,7 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
|
|||
: JSMSG_TOO_MANY_FUN_VARS);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!HashLocalName(cx, fun->u.i.names.map, atom, kind, *indexp))
|
||||
if (!HashLocalName(cx, fun->names.map, atom, kind, *indexp))
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -2428,18 +2487,18 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
|
|||
}
|
||||
|
||||
JSLocalKind
|
||||
js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp)
|
||||
js_LookupLocal(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
|
||||
uintN *indexp)
|
||||
{
|
||||
uintN n, i;
|
||||
jsuword *array;
|
||||
JSLocalNameHashEntry *entry;
|
||||
|
||||
JS_ASSERT(FUN_INTERPRETED(fun));
|
||||
n = JS_GET_LOCAL_NAME_COUNT(fun);
|
||||
if (n == 0)
|
||||
return JSLOCAL_NONE;
|
||||
if (n <= MAX_ARRAY_LOCALS) {
|
||||
array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
|
||||
array = (n == 1) ? &fun->names.taggedAtom : fun->names.array;
|
||||
|
||||
/* Search from the tail to pick up the last duplicated name. */
|
||||
i = n;
|
||||
|
@ -2460,7 +2519,7 @@ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp)
|
|||
} while (i != 0);
|
||||
} else {
|
||||
entry = (JSLocalNameHashEntry *)
|
||||
JS_DHashTableOperate(&fun->u.i.names.map->names, atom,
|
||||
JS_DHashTableOperate(&fun->names.map->names, atom,
|
||||
JS_DHASH_LOOKUP);
|
||||
if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr)) {
|
||||
JS_ASSERT(entry->localKind != JSLOCAL_NONE);
|
||||
|
@ -2473,11 +2532,11 @@ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp)
|
|||
}
|
||||
|
||||
typedef struct JSLocalNameEnumeratorArgs {
|
||||
JSFunction *fun;
|
||||
jsuword *names;
|
||||
JSScriptedFunction *fun;
|
||||
jsuword *names;
|
||||
#ifdef DEBUG
|
||||
uintN nCopiedArgs;
|
||||
uintN nCopiedVars;
|
||||
uintN nCopiedArgs;
|
||||
uintN nCopiedVars;
|
||||
#endif
|
||||
} JSLocalNameEnumeratorArgs;
|
||||
|
||||
|
@ -2501,8 +2560,8 @@ get_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
|||
} else {
|
||||
JS_ASSERT(entry->localKind == JSLOCAL_VAR ||
|
||||
entry->localKind == JSLOCAL_CONST);
|
||||
JS_ASSERT(entry->index < args->fun->u.i.nvars);
|
||||
JS_ASSERT(args->nCopiedVars++ < args->fun->u.i.nvars);
|
||||
JS_ASSERT(entry->index < args->fun->nvars);
|
||||
JS_ASSERT(args->nCopiedVars++ < args->fun->nvars);
|
||||
i = args->fun->nargs + entry->index;
|
||||
constFlag = (entry->localKind == JSLOCAL_CONST);
|
||||
}
|
||||
|
@ -2511,7 +2570,7 @@ get_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
|||
}
|
||||
|
||||
jsuword *
|
||||
js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
|
||||
js_GetLocalNameArray(JSContext *cx, JSScriptedFunction *fun, JSArenaPool *pool)
|
||||
{
|
||||
uintN n;
|
||||
jsuword *names;
|
||||
|
@ -2519,12 +2578,11 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
|
|||
JSLocalNameEnumeratorArgs args;
|
||||
JSNameIndexPair *dup;
|
||||
|
||||
JS_ASSERT(FUN_INTERPRETED(fun));
|
||||
n = JS_GET_LOCAL_NAME_COUNT(fun);
|
||||
JS_ASSERT(n != 0);
|
||||
|
||||
if (n <= MAX_ARRAY_LOCALS)
|
||||
return (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
|
||||
return (n == 1) ? &fun->names.taggedAtom : fun->names.array;
|
||||
|
||||
/*
|
||||
* No need to check for overflow of the allocation size as we are making a
|
||||
|
@ -2540,7 +2598,7 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
|
|||
/* Some parameter names can be NULL due to destructuring patterns. */
|
||||
memset(names, 0, fun->nargs * sizeof *names);
|
||||
#endif
|
||||
map = fun->u.i.names.map;
|
||||
map = fun->names.map;
|
||||
args.fun = fun;
|
||||
args.names = names;
|
||||
#ifdef DEBUG
|
||||
|
@ -2556,7 +2614,7 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
|
|||
#if !JS_HAS_DESTRUCTURING
|
||||
JS_ASSERT(args.nCopiedArgs == fun->nargs);
|
||||
#endif
|
||||
JS_ASSERT(args.nCopiedVars == fun->u.i.nvars);
|
||||
JS_ASSERT(args.nCopiedVars == fun->nvars);
|
||||
|
||||
return names;
|
||||
}
|
||||
|
@ -2579,18 +2637,17 @@ trace_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
|||
}
|
||||
|
||||
static void
|
||||
TraceLocalNames(JSTracer *trc, JSFunction *fun)
|
||||
TraceLocalNames(JSTracer *trc, JSScriptedFunction *fun)
|
||||
{
|
||||
uintN n, i;
|
||||
JSAtom *atom;
|
||||
jsuword *array;
|
||||
|
||||
JS_ASSERT(FUN_INTERPRETED(fun));
|
||||
n = JS_GET_LOCAL_NAME_COUNT(fun);
|
||||
if (n == 0)
|
||||
return;
|
||||
if (n <= MAX_ARRAY_LOCALS) {
|
||||
array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
|
||||
array = (n == 1) ? &fun->names.taggedAtom : fun->names.array;
|
||||
i = n;
|
||||
do {
|
||||
--i;
|
||||
|
@ -2603,7 +2660,7 @@ TraceLocalNames(JSTracer *trc, JSFunction *fun)
|
|||
}
|
||||
} while (i != 0);
|
||||
} else {
|
||||
JS_DHashTableEnumerate(&fun->u.i.names.map->names,
|
||||
JS_DHashTableEnumerate(&fun->names.map->names,
|
||||
trace_local_names_enumerator, trc);
|
||||
|
||||
/*
|
||||
|
@ -2614,33 +2671,31 @@ TraceLocalNames(JSTracer *trc, JSFunction *fun)
|
|||
}
|
||||
|
||||
void
|
||||
DestroyLocalNames(JSContext *cx, JSFunction *fun)
|
||||
DestroyLocalNames(JSContext *cx, JSScriptedFunction *fun)
|
||||
{
|
||||
uintN n;
|
||||
|
||||
n = fun->nargs + fun->u.i.nvars;
|
||||
n = fun->nargs + fun->nvars;
|
||||
if (n <= 1)
|
||||
return;
|
||||
if (n <= MAX_ARRAY_LOCALS)
|
||||
JS_free(cx, fun->u.i.names.array);
|
||||
JS_free(cx, fun->names.array);
|
||||
else
|
||||
FreeLocalNameHash(cx, fun->u.i.names.map);
|
||||
FreeLocalNameHash(cx, fun->names.map);
|
||||
}
|
||||
|
||||
void
|
||||
js_FreezeLocalNames(JSContext *cx, JSFunction *fun)
|
||||
js_FreezeLocalNames(JSContext *cx, JSScriptedFunction *fun)
|
||||
{
|
||||
uintN n;
|
||||
jsuword *array;
|
||||
|
||||
JS_ASSERT(FUN_INTERPRETED(fun));
|
||||
JS_ASSERT(!fun->u.i.script);
|
||||
n = fun->nargs + fun->u.i.nvars;
|
||||
JS_ASSERT(!fun->script);
|
||||
n = fun->nargs + fun->nvars;
|
||||
if (2 <= n && n < MAX_ARRAY_LOCALS) {
|
||||
/* Shrink over-allocated array ignoring realloc failures. */
|
||||
array = (jsuword *) JS_realloc(cx, fun->u.i.names.array,
|
||||
n * sizeof *array);
|
||||
array = (jsuword *) JS_realloc(cx, fun->names.array, n * sizeof *array);
|
||||
if (array)
|
||||
fun->u.i.names.array = array;
|
||||
fun->names.array = array;
|
||||
}
|
||||
}
|
||||
|
|
126
js/src/jsfun.h
126
js/src/jsfun.h
|
@ -44,6 +44,7 @@
|
|||
*/
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
|
@ -62,44 +63,73 @@ typedef union JSLocalNames {
|
|||
JSLocalNameMap *map;
|
||||
} JSLocalNames;
|
||||
|
||||
struct JSFunction {
|
||||
JSObject *object; /* back-pointer to GC'ed object header */
|
||||
struct JSNativeFunction {
|
||||
JSObject object;
|
||||
uint16 flags; /* bound method and other flags, see jsapi.h */
|
||||
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 minargs;/* minimum number of specified arguments, used
|
||||
uint16 extra; /* number of arg slots for local GC roots */
|
||||
uint16 minargs; /* minimum number of specified arguments, used
|
||||
only when calling fast native */
|
||||
JSNative native; /* native method pointer or null */
|
||||
JSClass *clasp; /* if non-null, constructor for this class */
|
||||
} n;
|
||||
struct {
|
||||
uint16 nvars; /* number of local variables */
|
||||
uint16 spare; /* reserved for future use */
|
||||
JSScript *script;/* interpreted bytecode descriptor or null */
|
||||
JSLocalNames names; /* argument and variable names */
|
||||
} i;
|
||||
} u;
|
||||
JSNative native; /* native method pointer or null */
|
||||
JSClass *clasp; /* if non-null, constructor for this class */
|
||||
JSAtom *atom; /* name for diagnostics and decompiling */
|
||||
};
|
||||
|
||||
struct JSScriptedFunction {
|
||||
JSObject *object; /* back-pointer to GC'ed object header */
|
||||
uint16 flags; /* bound method and other flags, see jsapi.h */
|
||||
uint16 nargs; /* number of arguments */
|
||||
uint16 nvars; /* number of local variables */
|
||||
uint16 spare; /* reserved for future use */
|
||||
JSScript *script; /* interpreted bytecode descriptor or null */
|
||||
JSLocalNames names; /* argument and variable names */
|
||||
JSAtom *atom; /* name for diagnostics and decompiling */
|
||||
};
|
||||
|
||||
#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_SCRIPTED 0x8000 /* use FUN_TO_SCRIPTED if set,
|
||||
FUN_TO_NATIVE if unset */
|
||||
|
||||
#define JSFUN_SCRIPT_OR_FAST_NATIVE (JSFUN_INTERPRETED | JSFUN_FAST_NATIVE)
|
||||
|
||||
#define FUN_INTERPRETED(fun) ((fun)->flags & JSFUN_INTERPRETED)
|
||||
#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)
|
||||
/*
|
||||
* JSFunction * points into the flags field of either JSNativeFunction
|
||||
* or JSScriptedFunction.
|
||||
*/
|
||||
#define FUN_FLAGS(fun) (*(uint16 *) (fun))
|
||||
|
||||
#define FUN_IS_SCRIPTED(fun) (FUN_FLAGS(fun) & JSFUN_SCRIPTED)
|
||||
|
||||
#define FUN_TO_SCRIPTED(fun) \
|
||||
(JS_ASSERT(FUN_IS_SCRIPTED(fun)), \
|
||||
(JSScriptedFunction *)((uint8 *)fun - offsetof(JSScriptedFunction, flags)))
|
||||
|
||||
#define FUN_TO_NATIVE(fun) \
|
||||
(JS_ASSERT(!FUN_IS_SCRIPTED(fun)), \
|
||||
(JSNativeFunction *)((uint8 *)fun - offsetof(JSNativeFunction, flags)))
|
||||
|
||||
#define NATIVE_TO_FUN(nfun) \
|
||||
(JS_ASSERT(((nfun)->flags & JSFUN_SCRIPTED) == 0), \
|
||||
(JSFunction *) (void *) &(nfun)->flags)
|
||||
|
||||
#define SCRIPTED_TO_FUN(sfun) \
|
||||
(JS_ASSERT((sfun)->flags & JSFUN_SCRIPTED), \
|
||||
(JSFunction *) (void *) &(sfun)->flags)
|
||||
|
||||
#define FUN_NARGS(fun) (FUN_IS_SCRIPTED(fun) \
|
||||
? FUN_TO_SCRIPTED(fun)->nargs \
|
||||
: FUN_TO_NATIVE(fun)->nargs)
|
||||
|
||||
#define FUN_OBJECT(fun) (FUN_IS_SCRIPTED(fun) \
|
||||
? FUN_TO_SCRIPTED(fun)->object \
|
||||
: &FUN_TO_NATIVE(fun)->object)
|
||||
|
||||
#define FUN_ATOM(fun) (FUN_IS_SCRIPTED(fun) \
|
||||
? FUN_TO_SCRIPTED(fun)->atom \
|
||||
: FUN_TO_NATIVE(fun)->atom)
|
||||
|
||||
#define NATIVE_FUN_MINARGS(nfun) \
|
||||
(((nfun)->flags & JSFUN_FAST_NATIVE) ? (nfun)->minargs : (nfun)->nargs)
|
||||
|
||||
extern JSClass js_ArgumentsClass;
|
||||
extern JS_FRIEND_DATA(JSClass) js_CallClass;
|
||||
|
@ -107,19 +137,20 @@ extern JS_FRIEND_DATA(JSClass) js_CallClass;
|
|||
/* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */
|
||||
extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
|
||||
|
||||
#define HAS_FUNCTION_CLASS(obj) (STOBJ_GET_CLASS(obj) == &js_FunctionClass)
|
||||
|
||||
/*
|
||||
* NB: jsapi.h and jsobj.h must be included before any call to this macro.
|
||||
*/
|
||||
#define VALUE_IS_FUNCTION(cx, v) \
|
||||
(!JSVAL_IS_PRIMITIVE(v) && \
|
||||
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass)
|
||||
(!JSVAL_IS_PRIMITIVE(v) && HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)))
|
||||
|
||||
/*
|
||||
* Macro to access the private slot of the function object after the slot is
|
||||
* initialized.
|
||||
*/
|
||||
#define GET_FUNCTION_PRIVATE(cx, funobj) \
|
||||
(JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass), \
|
||||
(JS_ASSERT(HAS_FUNCTION_CLASS(funobj)), \
|
||||
(JSFunction *) OBJ_GET_PRIVATE(cx, funobj))
|
||||
|
||||
extern JSObject *
|
||||
|
@ -135,19 +166,24 @@ extern JSFunction *
|
|||
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
|
||||
uintN flags, JSObject *parent, JSAtom *atom);
|
||||
|
||||
extern void
|
||||
js_TraceFunction(JSTracer *trc, JSFunction *fun);
|
||||
extern JSNativeFunction *
|
||||
js_NewNativeFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
|
||||
JSObject *parent, JSAtom *atom);
|
||||
|
||||
extern JSScriptedFunction *
|
||||
js_NewScriptedFunction(JSContext *cx, JSObject *funobj, uintN flags,
|
||||
JSObject *parent, JSAtom *atom);
|
||||
|
||||
extern void
|
||||
js_FinalizeFunction(JSContext *cx, JSFunction *fun);
|
||||
js_TraceFunction(JSTracer *trc, JSScriptedFunction *fun);
|
||||
|
||||
extern void
|
||||
js_FinalizeFunction(JSContext *cx, JSScriptedFunction *fun);
|
||||
|
||||
extern JSObject *
|
||||
js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
|
||||
|
||||
extern JSBool
|
||||
js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *object);
|
||||
|
||||
extern JSFunction *
|
||||
extern JSNativeFunction *
|
||||
js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
|
||||
uintN nargs, uintN flags);
|
||||
|
||||
|
@ -206,10 +242,11 @@ typedef enum JSLocalKind {
|
|||
JSLOCAL_CONST
|
||||
} JSLocalKind;
|
||||
|
||||
#define JS_GET_LOCAL_NAME_COUNT(fun) ((fun)->nargs + (fun)->u.i.nvars)
|
||||
#define JS_GET_LOCAL_NAME_COUNT(fun) ((fun)->nargs + (fun)->nvars)
|
||||
|
||||
extern JSBool
|
||||
js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind);
|
||||
js_AddLocal(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
|
||||
JSLocalKind kind);
|
||||
|
||||
/*
|
||||
* Look up an argument or variable name returning its kind when found or
|
||||
|
@ -218,7 +255,8 @@ js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind);
|
|||
* variable.
|
||||
*/
|
||||
extern JSLocalKind
|
||||
js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
|
||||
js_LookupLocal(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
|
||||
uintN *indexp);
|
||||
|
||||
/*
|
||||
* Functions to work with local names as an array of words.
|
||||
|
@ -235,7 +273,7 @@ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
|
|||
* corresponds to the const declaration.
|
||||
*/
|
||||
extern jsuword *
|
||||
js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool);
|
||||
js_GetLocalNameArray(JSContext *cx, JSScriptedFunction *fun, JSArenaPool *pool);
|
||||
|
||||
#define JS_LOCAL_NAME_TO_ATOM(nameWord) \
|
||||
((JSAtom *) ((nameWord) & ~(jsuword) 1))
|
||||
|
@ -244,7 +282,7 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool);
|
|||
((((nameWord) & (jsuword) 1)) != 0)
|
||||
|
||||
extern void
|
||||
js_FreezeLocalNames(JSContext *cx, JSFunction *fun);
|
||||
js_FreezeLocalNames(JSContext *cx, JSScriptedFunction *fun);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
|
|
|
@ -2250,8 +2250,8 @@ JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind)
|
|||
JS_CALL_STRING_TRACER(trc, JSSTRDEP_BASE(str), "base");
|
||||
break;
|
||||
|
||||
case JSTRACE_FUNCTION:
|
||||
js_TraceFunction(trc, (JSFunction *)thing);
|
||||
case JSTRACE_SCRIPTED_FUNCTION:
|
||||
js_TraceFunction(trc, (JSScriptedFunction *) thing);
|
||||
break;
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
|
@ -2660,7 +2660,7 @@ gc_lock_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
|
|||
void
|
||||
js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
|
||||
{
|
||||
uintN nslots, minargs, skip;
|
||||
uintN nslots, skip;
|
||||
|
||||
if (fp->callobj)
|
||||
JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call");
|
||||
|
@ -2682,8 +2682,8 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
|
|||
}
|
||||
|
||||
/* Allow for primitive this parameter due to JSFUN_THISP_* flags. */
|
||||
JS_ASSERT(JSVAL_IS_OBJECT((jsval)fp->thisp) ||
|
||||
(fp->fun && JSFUN_THISP_FLAGS(fp->fun->flags)));
|
||||
JS_ASSERT_IF(!JSVAL_IS_OBJECT((jsval)fp->thisp),
|
||||
fp->fun && JSFUN_THISP_FLAGS(FUN_FLAGS(fp->fun)));
|
||||
JS_CALL_VALUE_TRACER(trc, (jsval)fp->thisp, "this");
|
||||
|
||||
if (fp->callee)
|
||||
|
@ -2693,14 +2693,22 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
|
|||
nslots = fp->argc;
|
||||
skip = 0;
|
||||
if (fp->fun) {
|
||||
minargs = FUN_MINARGS(fp->fun);
|
||||
if (minargs > nslots)
|
||||
nslots = minargs;
|
||||
if (!FUN_INTERPRETED(fp->fun)) {
|
||||
JS_ASSERT(!(fp->fun->flags & JSFUN_FAST_NATIVE));
|
||||
nslots += fp->fun->u.n.extra;
|
||||
if (FUN_IS_SCRIPTED(fp->fun)) {
|
||||
JSScriptedFunction *sfun;
|
||||
|
||||
sfun = FUN_TO_SCRIPTED(fp->fun);
|
||||
if (nslots < sfun->nargs)
|
||||
nslots = sfun->nargs;
|
||||
} else {
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
JS_ASSERT(!(FUN_FLAGS(fp->fun) & JSFUN_FAST_NATIVE));
|
||||
nfun = FUN_TO_NATIVE(fp->fun);
|
||||
if (nslots < nfun->nargs)
|
||||
nslots = nfun->nargs;
|
||||
nslots += nfun->extra;
|
||||
}
|
||||
if (fp->fun->flags & JSFRAME_ROOTED_ARGV)
|
||||
if (fp->flags & JSFRAME_ROOTED_ARGV)
|
||||
skip = 2 + fp->argc;
|
||||
}
|
||||
TRACE_JSVALS(trc, 2 + nslots - skip, fp->argv - 2 + skip, "operand");
|
||||
|
@ -3328,7 +3336,8 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
|
|||
/* Do nothing. */
|
||||
break;
|
||||
case GCX_FUNCTION:
|
||||
js_FinalizeFunction(cx, (JSFunction *) thing);
|
||||
js_FinalizeFunction(cx,
|
||||
(JSScriptedFunction *) thing);
|
||||
break;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
case GCX_NAMESPACE:
|
||||
|
|
|
@ -52,15 +52,15 @@ JS_BEGIN_EXTERN_C
|
|||
|
||||
JS_STATIC_ASSERT(JSTRACE_STRING == 2);
|
||||
|
||||
#define JSTRACE_FUNCTION 3
|
||||
#define JSTRACE_NAMESPACE 4
|
||||
#define JSTRACE_QNAME 5
|
||||
#define JSTRACE_XML 6
|
||||
#define JSTRACE_SCRIPTED_FUNCTION 3
|
||||
#define JSTRACE_NAMESPACE 4
|
||||
#define JSTRACE_QNAME 5
|
||||
#define JSTRACE_XML 6
|
||||
|
||||
/*
|
||||
* One past the maximum trace kind.
|
||||
*/
|
||||
#define JSTRACE_LIMIT 7
|
||||
#define JSTRACE_LIMIT 7
|
||||
|
||||
/*
|
||||
* We use the trace kinds as the types for all GC things except external
|
||||
|
@ -69,7 +69,8 @@ JS_STATIC_ASSERT(JSTRACE_STRING == 2);
|
|||
#define GCX_OBJECT JSTRACE_OBJECT /* JSObject */
|
||||
#define GCX_DOUBLE JSTRACE_DOUBLE /* jsdouble */
|
||||
#define GCX_STRING JSTRACE_STRING /* JSString */
|
||||
#define GCX_FUNCTION JSTRACE_FUNCTION /* JSFunction */
|
||||
#define GCX_FUNCTION JSTRACE_SCRIPTED_FUNCTION
|
||||
/* JSScriptedFunction */
|
||||
#define GCX_NAMESPACE JSTRACE_NAMESPACE /* JSXMLNamespace */
|
||||
#define GCX_QNAME JSTRACE_QNAME /* JSXMLQName */
|
||||
#define GCX_XML JSTRACE_XML /* JSXML */
|
||||
|
@ -235,14 +236,15 @@ js_IsAboutToBeFinalized(JSContext *cx, void *thing);
|
|||
#if JS_HAS_XML_SUPPORT
|
||||
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_XML)
|
||||
#else
|
||||
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_FUNCTION)
|
||||
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= \
|
||||
JSTRACE_SCRIPTED_FUNCTION)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_FUNCTION is the last non-xml
|
||||
* trace kind when JS_HAS_XML_SUPPORT is false.
|
||||
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_SCRIPTED_FUNCTION is the last
|
||||
* non-xml trace kind when JS_HAS_XML_SUPPORT is false.
|
||||
*/
|
||||
JS_STATIC_ASSERT(JSTRACE_FUNCTION + 1 == JSTRACE_NAMESPACE);
|
||||
JS_STATIC_ASSERT(JSTRACE_SCRIPTED_FUNCTION + 1 == JSTRACE_NAMESPACE);
|
||||
|
||||
/*
|
||||
* Trace jsval when JSVAL_IS_OBJECT(v) can be an arbitrary GC thing casted as
|
||||
|
|
|
@ -645,7 +645,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
|
|||
* insist that there is a call object for a heavyweight function call.
|
||||
*/
|
||||
JS_ASSERT(!fp->fun ||
|
||||
!(fp->fun->flags & JSFUN_HEAVYWEIGHT) ||
|
||||
!(FUN_FLAGS(fp->fun) & JSFUN_HEAVYWEIGHT) ||
|
||||
fp->callobj);
|
||||
JS_ASSERT(fp->scopeChain);
|
||||
return fp->scopeChain;
|
||||
|
@ -931,7 +931,7 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp)
|
|||
vp[0] = ID_TO_VALUE(id);
|
||||
}
|
||||
#endif
|
||||
obj = js_NewObject(cx, &js_NoSuchMethodClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_NoSuchMethodClass, NULL, NULL, 0);
|
||||
if (!obj) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
|
@ -1088,20 +1088,27 @@ js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags)
|
|||
have_fun:
|
||||
/* Get private data and set derived locals from it. */
|
||||
fun = GET_FUNCTION_PRIVATE(cx, funobj);
|
||||
nslots = FUN_MINARGS(fun);
|
||||
nslots = (nslots > argc) ? nslots - argc : 0;
|
||||
if (FUN_INTERPRETED(fun)) {
|
||||
if (FUN_IS_SCRIPTED(fun)) {
|
||||
JSScriptedFunction *sfun;
|
||||
|
||||
sfun = FUN_TO_SCRIPTED(fun);
|
||||
native = NULL;
|
||||
script = fun->u.i.script;
|
||||
nvars = fun->u.i.nvars;
|
||||
script = sfun->script;
|
||||
nvars = sfun->nvars;
|
||||
nslots = (sfun->nargs > argc) ? sfun->nargs - argc : 0;
|
||||
} else {
|
||||
native = fun->u.n.native;
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
nfun = FUN_TO_NATIVE(fun);
|
||||
native = nfun->native;
|
||||
script = NULL;
|
||||
nvars = 0;
|
||||
nslots += fun->u.n.extra;
|
||||
nslots = NATIVE_FUN_MINARGS(nfun);
|
||||
nslots = (nslots > argc) ? nslots - argc : 0;
|
||||
nslots += nfun->extra;
|
||||
}
|
||||
|
||||
if (JSFUN_BOUND_METHOD_TEST(fun->flags)) {
|
||||
if (JSFUN_BOUND_METHOD_TEST(FUN_FLAGS(fun))) {
|
||||
/* Handle bound method special case. */
|
||||
vp[1] = OBJECT_TO_JSVAL(parent);
|
||||
} else if (!JSVAL_IS_OBJECT(vp[1])) {
|
||||
|
@ -1124,7 +1131,7 @@ have_fun:
|
|||
* JS_THIS or JS_THIS_OBJECT, and scripted functions will go through
|
||||
* the appropriate this-computing bytecode, e.g., JSOP_THIS.
|
||||
*/
|
||||
if (native && (!fun || !(fun->flags & JSFUN_FAST_NATIVE))) {
|
||||
if (native && (!fun || !(FUN_FLAGS(fun) & JSFUN_FAST_NATIVE))) {
|
||||
if (!js_ComputeThis(cx, JS_FALSE, vp + 2)) {
|
||||
ok = JS_FALSE;
|
||||
goto out2;
|
||||
|
@ -1164,7 +1171,7 @@ have_fun:
|
|||
} while (--i != 0);
|
||||
}
|
||||
|
||||
if (native && fun && (fun->flags & JSFUN_FAST_NATIVE)) {
|
||||
if (native && fun && (FUN_FLAGS(fun) & JSFUN_FAST_NATIVE)) {
|
||||
JSTempValueRooter tvr;
|
||||
#ifdef DEBUG_NOT_THROWING
|
||||
JSBool alreadyThrowing = cx->throwing;
|
||||
|
@ -1286,7 +1293,7 @@ have_fun:
|
|||
} else if (script) {
|
||||
/* Use parent scope so js_GetCallObject can find the right "Call". */
|
||||
frame.scopeChain = parent;
|
||||
if (JSFUN_HEAVYWEIGHT_TEST(fun->flags)) {
|
||||
if (JSFUN_HEAVYWEIGHT_TEST(FUN_FLAGS(fun))) {
|
||||
/* Scope with a call object parented by the callee's parent. */
|
||||
if (!js_GetCallObject(cx, &frame, parent)) {
|
||||
ok = JS_FALSE;
|
||||
|
@ -1401,7 +1408,7 @@ js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
|
|||
JS_ASSERT(mode == JSACC_READ || mode == JSACC_WRITE);
|
||||
if (cx->runtime->checkObjectAccess &&
|
||||
VALUE_IS_FUNCTION(cx, fval) &&
|
||||
FUN_INTERPRETED(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fval))) &&
|
||||
FUN_IS_SCRIPTED(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fval))) &&
|
||||
!cx->runtime->checkObjectAccess(cx, obj, ID_TO_VALUE(id), mode,
|
||||
&fval)) {
|
||||
return JS_FALSE;
|
||||
|
@ -1835,11 +1842,16 @@ js_InvokeConstructor(JSContext *cx, jsval *vp, uintN argc)
|
|||
|
||||
if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) {
|
||||
fun2 = GET_FUNCTION_PRIVATE(cx, obj2);
|
||||
if (!FUN_INTERPRETED(fun2) && fun2->u.n.clasp)
|
||||
clasp = fun2->u.n.clasp;
|
||||
if (!FUN_IS_SCRIPTED(fun2)) {
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
nfun = FUN_TO_NATIVE(fun2);
|
||||
if (nfun->clasp)
|
||||
clasp = nfun->clasp;
|
||||
}
|
||||
}
|
||||
}
|
||||
obj = js_NewObject(cx, clasp, proto, parent);
|
||||
obj = js_NewObject(cx, clasp, proto, parent, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -2452,6 +2464,7 @@ js_Interpret(JSContext *cx)
|
|||
jsdouble d, d2;
|
||||
JSClass *clasp;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *sfun;
|
||||
JSType type;
|
||||
#if !JS_THREADED_INTERP && defined DEBUG
|
||||
FILE *tracefp = NULL;
|
||||
|
@ -3114,13 +3127,13 @@ interrupt:
|
|||
switch (op) {
|
||||
case JSOP_FORARG:
|
||||
slot = GET_ARGNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->nargs);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
|
||||
fp->argv[slot] = rval;
|
||||
break;
|
||||
|
||||
case JSOP_FORVAR:
|
||||
slot = GET_VARNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->u.i.nvars);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
|
||||
fp->vars[slot] = rval;
|
||||
break;
|
||||
|
||||
|
@ -3951,7 +3964,7 @@ interrupt:
|
|||
|
||||
do_arg_incop:
|
||||
slot = GET_ARGNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->nargs);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
|
||||
METER_SLOT_OP(op, slot);
|
||||
vp = fp->argv + slot;
|
||||
goto do_int_fast_incop;
|
||||
|
@ -3987,7 +4000,7 @@ interrupt:
|
|||
*/
|
||||
do_var_incop:
|
||||
slot = GET_VARNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->u.i.nvars);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
|
||||
METER_SLOT_OP(op, slot);
|
||||
vp = fp->vars + slot;
|
||||
|
||||
|
@ -4087,7 +4100,7 @@ interrupt:
|
|||
BEGIN_CASE(JSOP_GETARGPROP)
|
||||
i = ARGNO_LEN;
|
||||
slot = GET_ARGNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->nargs);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
|
||||
PUSH_OPND(fp->argv[slot]);
|
||||
len = JSOP_GETARGPROP_LENGTH;
|
||||
goto do_getprop_body;
|
||||
|
@ -4095,7 +4108,7 @@ interrupt:
|
|||
BEGIN_CASE(JSOP_GETVARPROP)
|
||||
i = VARNO_LEN;
|
||||
slot = GET_VARNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->u.i.nvars);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
|
||||
PUSH_OPND(fp->vars[slot]);
|
||||
len = JSOP_GETVARPROP_LENGTH;
|
||||
goto do_getprop_body;
|
||||
|
@ -4601,10 +4614,11 @@ interrupt:
|
|||
vp = regs.sp - (argc + 2);
|
||||
lval = *vp;
|
||||
if (VALUE_IS_FUNCTION(cx, lval)) {
|
||||
JSNativeFunction *nfun;
|
||||
|
||||
obj = JSVAL_TO_OBJECT(lval);
|
||||
fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
|
||||
if (FUN_INTERPRETED(fun)) {
|
||||
if (FUN_IS_SCRIPTED(fun)) {
|
||||
uintN nframeslots, nvars, missing;
|
||||
JSArena *a;
|
||||
jsuword nbytes;
|
||||
|
@ -4616,8 +4630,9 @@ interrupt:
|
|||
/* 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;
|
||||
sfun = FUN_TO_SCRIPTED(fun);
|
||||
nvars = sfun->nvars;
|
||||
script = sfun->script;
|
||||
atoms = script->atomMap.vector;
|
||||
nbytes = (nframeslots + nvars + script->depth) *
|
||||
sizeof(jsval);
|
||||
|
@ -4625,10 +4640,10 @@ interrupt:
|
|||
/* Allocate missing expected args adjacent to actuals. */
|
||||
a = cx->stackPool.current;
|
||||
newmark = (void *) a->avail;
|
||||
if (fun->nargs <= argc) {
|
||||
if (sfun->nargs <= argc) {
|
||||
missing = 0;
|
||||
} else {
|
||||
newsp = vp + 2 + fun->nargs;
|
||||
newsp = vp + 2 + sfun->nargs;
|
||||
JS_ASSERT(newsp > regs.sp);
|
||||
if ((jsuword) newsp <= a->limit) {
|
||||
if ((jsuword) newsp > a->avail)
|
||||
|
@ -4638,8 +4653,8 @@ interrupt:
|
|||
} while (newsp != regs.sp);
|
||||
missing = 0;
|
||||
} else {
|
||||
missing = fun->nargs - argc;
|
||||
nbytes += (2 + fun->nargs) * sizeof(jsval);
|
||||
missing = sfun->nargs - argc;
|
||||
nbytes += (2 + sfun->nargs) * sizeof(jsval);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4700,7 +4715,7 @@ interrupt:
|
|||
newifp->mark = newmark;
|
||||
|
||||
/* Compute the 'this' parameter now that argv is set. */
|
||||
JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));
|
||||
JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(sfun->flags));
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(vp[1]));
|
||||
newifp->frame.thisp = (JSObject *)vp[1];
|
||||
|
||||
|
@ -4722,7 +4737,7 @@ interrupt:
|
|||
}
|
||||
|
||||
/* Scope with a call object parented by callee's parent. */
|
||||
if (JSFUN_HEAVYWEIGHT_TEST(fun->flags) &&
|
||||
if (JSFUN_HEAVYWEIGHT_TEST(sfun->flags) &&
|
||||
!js_GetCallObject(cx, &newifp->frame, parent)) {
|
||||
goto bad_inline_call;
|
||||
}
|
||||
|
@ -4780,16 +4795,17 @@ interrupt:
|
|||
}
|
||||
#endif
|
||||
|
||||
if (fun->flags & JSFUN_FAST_NATIVE) {
|
||||
JS_ASSERT(fun->u.n.extra == 0);
|
||||
if (argc < fun->u.n.minargs) {
|
||||
uintN nargs;
|
||||
nfun = FUN_TO_NATIVE(fun);
|
||||
if (nfun->flags & JSFUN_FAST_NATIVE) {
|
||||
uintN nargs;
|
||||
|
||||
JS_ASSERT(nfun->extra == 0);
|
||||
if (argc < nfun->minargs) {
|
||||
/*
|
||||
* If we can't fit missing args and local roots in
|
||||
* this frame's operand stack, take the slow path.
|
||||
*/
|
||||
nargs = fun->u.n.minargs - argc;
|
||||
nargs = nfun->minargs - argc;
|
||||
if (regs.sp + nargs > fp->spbase + script->depth)
|
||||
goto do_invoke;
|
||||
do {
|
||||
|
@ -4800,7 +4816,7 @@ interrupt:
|
|||
JS_ASSERT(JSVAL_IS_OBJECT(vp[1]) ||
|
||||
PRIMITIVE_THIS_TEST(fun, vp[1]));
|
||||
|
||||
ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp);
|
||||
ok = ((JSFastNative) nfun->native)(cx, argc, vp);
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (VALUE_IS_FUNCTION(cx, lval)) {
|
||||
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
|
||||
|
@ -5394,7 +5410,7 @@ interrupt:
|
|||
BEGIN_CASE(JSOP_GETARG)
|
||||
BEGIN_CASE(JSOP_CALLARG)
|
||||
slot = GET_ARGNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->nargs);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
|
||||
METER_SLOT_OP(op, slot);
|
||||
PUSH_OPND(fp->argv[slot]);
|
||||
if (op == JSOP_CALLARG)
|
||||
|
@ -5403,7 +5419,7 @@ interrupt:
|
|||
|
||||
BEGIN_CASE(JSOP_SETARG)
|
||||
slot = GET_ARGNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->nargs);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nargs);
|
||||
METER_SLOT_OP(op, slot);
|
||||
vp = &fp->argv[slot];
|
||||
GC_POKE(cx, *vp);
|
||||
|
@ -5413,7 +5429,7 @@ interrupt:
|
|||
BEGIN_CASE(JSOP_GETVAR)
|
||||
BEGIN_CASE(JSOP_CALLVAR)
|
||||
slot = GET_VARNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->u.i.nvars);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
|
||||
METER_SLOT_OP(op, slot);
|
||||
PUSH_OPND(fp->vars[slot]);
|
||||
if (op == JSOP_CALLVAR)
|
||||
|
@ -5422,7 +5438,7 @@ interrupt:
|
|||
|
||||
BEGIN_CASE(JSOP_SETVAR)
|
||||
slot = GET_VARNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->u.i.nvars);
|
||||
JS_ASSERT(slot < FUN_TO_SCRIPTED(fp->fun)->nvars);
|
||||
METER_SLOT_OP(op, slot);
|
||||
vp = &fp->vars[slot];
|
||||
GC_POKE(cx, *vp);
|
||||
|
@ -5601,8 +5617,8 @@ interrupt:
|
|||
* and setters do not need a slot, their value is stored elsewhere
|
||||
* in the property itself, not in obj slots.
|
||||
*/
|
||||
fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
flags = JSFUN_GSFLAG2ATTR(fun->flags);
|
||||
sfun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
|
||||
flags = JSFUN_GSFLAG2ATTR(sfun->flags);
|
||||
if (flags) {
|
||||
attrs |= flags | JSPROP_SHARED;
|
||||
rval = JSVAL_VOID;
|
||||
|
@ -5622,7 +5638,7 @@ interrupt:
|
|||
* here at runtime as well as at compile-time, to handle eval
|
||||
* as well as multiple HTML script tags.
|
||||
*/
|
||||
id = ATOM_TO_JSID(fun->atom);
|
||||
id = ATOM_TO_JSID(sfun->atom);
|
||||
ok = js_CheckRedeclaration(cx, parent, id, attrs, NULL, NULL);
|
||||
if (ok) {
|
||||
if (attrs == JSPROP_ENUMERATE) {
|
||||
|
@ -5705,7 +5721,7 @@ interrupt:
|
|||
obj2 = js_GetScopeChain(cx, fp);
|
||||
if (!obj2)
|
||||
goto error;
|
||||
parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2);
|
||||
parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2, 0);
|
||||
if (!parent)
|
||||
goto error;
|
||||
|
||||
|
@ -5738,16 +5754,17 @@ interrupt:
|
|||
|
||||
/*
|
||||
* 4. Create a property in the object Result(1). The property's
|
||||
* name is [fun->atom, the identifier parsed by the compiler],
|
||||
* name is [sfun->atom, the identifier parsed by the compiler],
|
||||
* value is Result(3), and attributes are { DontDelete, ReadOnly }.
|
||||
*/
|
||||
fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
attrs = JSFUN_GSFLAG2ATTR(fun->flags);
|
||||
sfun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
|
||||
attrs = JSFUN_GSFLAG2ATTR(sfun->flags);
|
||||
if (attrs) {
|
||||
attrs |= JSPROP_SHARED;
|
||||
rval = JSVAL_VOID;
|
||||
}
|
||||
ok = OBJ_DEFINE_PROPERTY(cx, parent, ATOM_TO_JSID(fun->atom), rval,
|
||||
ok = OBJ_DEFINE_PROPERTY(cx, parent, ATOM_TO_JSID(sfun->atom),
|
||||
rval,
|
||||
(attrs & JSPROP_GETTER)
|
||||
? JS_EXTENSION (JSPropertyOp) obj
|
||||
: JS_PropertyStub,
|
||||
|
@ -5908,7 +5925,7 @@ interrupt:
|
|||
JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
|
||||
obj = (i == JSProto_Array)
|
||||
? js_NewArrayObject(cx, 0, NULL)
|
||||
: js_NewObject(cx, &js_ObjectClass, NULL, NULL);
|
||||
: js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
goto error;
|
||||
PUSH_OPND(OBJECT_TO_JSVAL(obj));
|
||||
|
|
|
@ -397,7 +397,7 @@ extern const uint16 js_PrimitiveTestFlags[];
|
|||
|
||||
#define PRIMITIVE_THIS_TEST(fun,thisv) \
|
||||
(JS_ASSERT(thisv != JSVAL_VOID), \
|
||||
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \
|
||||
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS(FUN_FLAGS(fun)), \
|
||||
js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1]))
|
||||
|
||||
/*
|
||||
|
|
|
@ -400,7 +400,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
|
|||
* we use the parent slot to keep track of the iterable, we must
|
||||
* fix it up after.
|
||||
*/
|
||||
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL);
|
||||
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL, 0);
|
||||
if (!iterobj)
|
||||
goto bad;
|
||||
|
||||
|
@ -725,13 +725,13 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp)
|
|||
jsval *newsp;
|
||||
|
||||
/* After the following return, failing control flow must goto bad. */
|
||||
obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
/* Load and compute stack slot counts. */
|
||||
argc = fp->argc;
|
||||
nargs = JS_MAX(argc, fp->fun->nargs);
|
||||
nargs = JS_MAX(argc, FUN_TO_SCRIPTED(fp->fun)->nargs);
|
||||
nvars = fp->nvars;
|
||||
nslots = 2 + nargs + nvars + fp->script->depth;
|
||||
|
||||
|
|
|
@ -863,8 +863,9 @@ obj_toSource(JSContext *cx, uintN argc, jsval *vp)
|
|||
* they might appear here. This code can be confused by people
|
||||
* defining Function.prototype.toString, so let's be cautious.
|
||||
*/
|
||||
if (JSFUN_GETTER_TEST(fun->flags) ||
|
||||
JSFUN_SETTER_TEST(fun->flags)) { /* skip "getter/setter" */
|
||||
if (JSFUN_GETTER_TEST(FUN_FLAGS(fun)) ||
|
||||
JSFUN_SETTER_TEST(FUN_FLAGS(fun))) {
|
||||
/* skip "getter/setter" */
|
||||
const jschar *tmp = js_strchr_limit(vchars, ' ', end);
|
||||
if (tmp)
|
||||
vchars = tmp + 1;
|
||||
|
@ -1754,7 +1755,7 @@ Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
JS_ASSERT(!argc || JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0]));
|
||||
if (cx->fp->flags & JSFRAME_CONSTRUCTING)
|
||||
return JS_TRUE;
|
||||
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -1895,7 +1896,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
|
|||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = js_NewObject(cx, &js_WithClass, proto, parent);
|
||||
obj = js_NewObject(cx, &js_WithClass, proto, parent, 0);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(cx->fp));
|
||||
|
@ -1914,7 +1915,7 @@ js_NewBlockObject(JSContext *cx)
|
|||
* scopes. Make sure obj has its own scope too, since clearing proto does
|
||||
* not affect OBJ_SCOPE(obj).
|
||||
*/
|
||||
obj = js_NewObject(cx, &js_BlockClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_BlockClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
|
@ -1932,7 +1933,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, JSObject *parent,
|
|||
{
|
||||
JSObject *clone;
|
||||
|
||||
clone = js_NewObject(cx, &js_BlockClass, proto, parent);
|
||||
clone = js_NewObject(cx, &js_BlockClass, proto, parent, 0);
|
||||
if (!clone)
|
||||
return NULL;
|
||||
STOBJ_SET_SLOT(clone, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(fp));
|
||||
|
@ -2418,7 +2419,8 @@ js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp)
|
|||
}
|
||||
|
||||
JSObject *
|
||||
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
|
||||
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
|
||||
uintN extraBytes)
|
||||
{
|
||||
jsid id;
|
||||
|
||||
|
@ -2435,12 +2437,12 @@ js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
|
|||
}
|
||||
}
|
||||
|
||||
return js_NewObjectWithGivenProto(cx, clasp, proto, parent);
|
||||
return js_NewObjectWithGivenProto(cx, clasp, proto, parent, extraBytes);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JSObject *parent)
|
||||
JSObject *parent, uintN extraBytes)
|
||||
{
|
||||
JSObject *obj;
|
||||
JSObjectOps *ops;
|
||||
|
@ -2464,7 +2466,8 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
* GC-thing allocations under js_GetClassPrototype or clasp->getObjectOps,
|
||||
* to avoid displacing the newborn root for obj.
|
||||
*/
|
||||
obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
|
||||
obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT,
|
||||
sizeof(JSObject) + extraBytes);
|
||||
if (!obj)
|
||||
goto earlybad;
|
||||
|
||||
|
@ -2766,7 +2769,7 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
|||
proto = JSVAL_TO_OBJECT(rval);
|
||||
}
|
||||
|
||||
obj = js_NewObject(cx, clasp, proto, parent);
|
||||
obj = js_NewObject(cx, clasp, proto, parent, 0);
|
||||
if (!obj)
|
||||
goto out;
|
||||
|
||||
|
@ -4651,7 +4654,7 @@ js_PrimitiveToObject(JSContext *cx, jsval *vp)
|
|||
JS_ASSERT(!JSVAL_IS_OBJECT(*vp));
|
||||
JS_ASSERT(*vp != JSVAL_VOID);
|
||||
clasp = PrimitiveClasses[JSVAL_TAG(*vp) - 1];
|
||||
obj = js_NewObject(cx, clasp, NULL, NULL);
|
||||
obj = js_NewObject(cx, clasp, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, *vp);
|
||||
|
|
|
@ -432,14 +432,15 @@ extern JSBool
|
|||
js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp);
|
||||
|
||||
extern JSObject *
|
||||
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
|
||||
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
|
||||
uintN extraBytes);
|
||||
|
||||
/*
|
||||
* See jsapi.h, JS_NewObjectWithGivenProto.
|
||||
*/
|
||||
extern JSObject *
|
||||
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JSObject *parent);
|
||||
JSObject *parent, uintN extraBytes);
|
||||
|
||||
/*
|
||||
* Fast access to immutable standard objects (constructors and prototypes).
|
||||
|
|
|
@ -617,7 +617,7 @@ struct JSPrinter {
|
|||
JSScript *script; /* script being printed */
|
||||
jsbytecode *dvgfence; /* DecompileExpression fencepost */
|
||||
jsbytecode **pcstack; /* DecompileExpression modelled stack */
|
||||
JSFunction *fun; /* interpreted function */
|
||||
JSScriptedFunction *fun; /* interpreted function */
|
||||
jsuword *localNames; /* argument and variable names */
|
||||
};
|
||||
|
||||
|
@ -630,8 +630,7 @@ struct JSPrinter {
|
|||
#define JS_IN_GROUP_CONTEXT 0x10000
|
||||
|
||||
JSPrinter *
|
||||
JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
|
||||
uintN indent, JSBool pretty)
|
||||
JS_NEW_PRINTER(JSContext *cx, const char *name, uintN indent, JSBool pretty)
|
||||
{
|
||||
JSPrinter *jp;
|
||||
|
||||
|
@ -646,15 +645,8 @@ JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
|
|||
jp->script = NULL;
|
||||
jp->dvgfence = NULL;
|
||||
jp->pcstack = NULL;
|
||||
jp->fun = fun;
|
||||
jp->localNames = NULL;
|
||||
if (fun && FUN_INTERPRETED(fun) && JS_GET_LOCAL_NAME_COUNT(fun)) {
|
||||
jp->localNames = js_GetLocalNameArray(cx, fun, &jp->pool);
|
||||
if (!jp->localNames) {
|
||||
js_DestroyPrinter(jp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
jp->fun = NULL;
|
||||
return jp;
|
||||
}
|
||||
|
||||
|
@ -665,6 +657,21 @@ js_DestroyPrinter(JSPrinter *jp)
|
|||
JS_free(jp->sprinter.context, jp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
InitFunctionPrinter(JSPrinter *jp, JSScriptedFunction *fun)
|
||||
{
|
||||
JS_ASSERT(!jp->fun);
|
||||
JS_ASSERT(!jp->localNames);
|
||||
if (JS_GET_LOCAL_NAME_COUNT(fun) != 0) {
|
||||
jp->localNames = js_GetLocalNameArray(jp->sprinter.context, fun,
|
||||
&jp->pool);
|
||||
if (!jp->localNames)
|
||||
return JS_FALSE;
|
||||
}
|
||||
jp->fun = fun;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSString *
|
||||
js_GetPrinterOutput(JSPrinter *jp)
|
||||
{
|
||||
|
@ -789,7 +796,7 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|||
* decompiled string on success.
|
||||
*/
|
||||
static char *
|
||||
DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
|
||||
DecompileExpression(JSContext *cx, JSScript *script, JSScriptedFunction *fun,
|
||||
jsbytecode *pc);
|
||||
|
||||
/*
|
||||
|
@ -1129,17 +1136,15 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
|
|||
static JSAtom *
|
||||
GetSlotAtom(JSPrinter *jp, JSBool argument, uintN slot)
|
||||
{
|
||||
JSFunction *fun;
|
||||
JSAtom *name;
|
||||
|
||||
fun = jp->fun;
|
||||
LOCAL_ASSERT_RV(jp->fun, NULL);
|
||||
LOCAL_ASSERT_RV(jp->localNames, NULL);
|
||||
if (argument) {
|
||||
LOCAL_ASSERT_RV(slot < fun->nargs, NULL);
|
||||
LOCAL_ASSERT_RV(slot < jp->fun->nargs, NULL);
|
||||
} else {
|
||||
LOCAL_ASSERT_RV(slot < fun->u.i.nvars, NULL);
|
||||
slot += fun->nargs;
|
||||
LOCAL_ASSERT_RV(slot < jp->fun->nvars, NULL);
|
||||
slot += jp->fun->nargs;
|
||||
}
|
||||
name = JS_LOCAL_NAME_TO_ATOM(jp->localNames[slot]);
|
||||
#if !JS_HAS_DESTRUCTURING
|
||||
|
@ -1631,7 +1636,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
char **argv;
|
||||
JSAtom *atom;
|
||||
JSObject *obj;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
JSString *str;
|
||||
JSBool ok;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
|
@ -2020,12 +2025,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
obj);
|
||||
do_function:
|
||||
js_puts(jp, "\n");
|
||||
fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
jp2 = JS_NEW_PRINTER(cx, "nested_function", fun,
|
||||
jp2 = JS_NEW_PRINTER(cx, "nested_function",
|
||||
jp->indent, jp->pretty);
|
||||
if (!jp2)
|
||||
return NULL;
|
||||
ok = js_DecompileFunction(jp2);
|
||||
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
|
||||
ok = js_DecompileFunction(jp2, fun);
|
||||
if (ok && jp2->sprinter.base)
|
||||
js_puts(jp, jp2->sprinter.base);
|
||||
js_DestroyPrinter(jp2);
|
||||
|
@ -3767,9 +3772,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
SprintStack ss2;
|
||||
|
||||
LOAD_FUNCTION(0);
|
||||
fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
LOCAL_ASSERT(FUN_INTERPRETED(fun));
|
||||
inner = fun->u.i.script;
|
||||
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
|
||||
inner = fun->script;
|
||||
|
||||
/*
|
||||
* All allocation when decompiling is LIFO, using malloc
|
||||
|
@ -3884,10 +3888,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
* parenthesization without confusing getter/setter code
|
||||
* that checks for JSOP_ANONFUNOBJ and JSOP_NAMEDFUNOBJ.
|
||||
*/
|
||||
fun = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
|
||||
if (!(fun->flags & JSFUN_EXPR_CLOSURE))
|
||||
indent |= JS_IN_GROUP_CONTEXT;
|
||||
str = JS_DecompileFunction(cx, fun, indent);
|
||||
str = JS_DecompileFunction(cx, SCRIPTED_TO_FUN(fun),
|
||||
indent);
|
||||
if (!str)
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4615,55 +4620,83 @@ out:
|
|||
return ok;
|
||||
}
|
||||
|
||||
static const char native_code_str[] = "\t[native code]\n";
|
||||
|
||||
JSBool
|
||||
js_DecompileNativeFunction(JSPrinter *jp, JSNativeFunction *fun)
|
||||
{
|
||||
if (jp->pretty)
|
||||
js_printf(jp, "\t");
|
||||
if (JSFUN_GETTER_TEST(fun->flags))
|
||||
js_printf(jp, "%s ", js_getter_str);
|
||||
else if (JSFUN_SETTER_TEST(fun->flags))
|
||||
js_printf(jp, "%s ", js_setter_str);
|
||||
|
||||
js_printf(jp, "%s ", js_function_str);
|
||||
if (fun->atom && !QuoteString(&jp->sprinter, ATOM_TO_STRING(fun->atom), 0))
|
||||
return JS_FALSE;
|
||||
js_printf(jp, "() {\n");
|
||||
jp->indent += 4;
|
||||
js_printf(jp, native_code_str);
|
||||
jp->indent -= 4;
|
||||
js_printf(jp, "\t}");
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_DecompileNativeFunctionBody(JSPrinter *jp, JSNativeFunction *fun)
|
||||
{
|
||||
js_printf(jp, native_code_str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_DecompileScript(JSPrinter *jp, JSScript *script)
|
||||
{
|
||||
return DecompileCode(jp, script, script->code, (uintN)script->length, 0);
|
||||
}
|
||||
|
||||
static const char native_code_str[] = "\t[native code]\n";
|
||||
|
||||
JSBool
|
||||
js_DecompileFunctionBody(JSPrinter *jp)
|
||||
js_DecompileFunctionBody(JSPrinter *jp, JSScriptedFunction *fun)
|
||||
{
|
||||
JSScript *script;
|
||||
|
||||
JS_ASSERT(jp->fun);
|
||||
JS_ASSERT(!jp->script);
|
||||
if (!FUN_INTERPRETED(jp->fun)) {
|
||||
js_printf(jp, native_code_str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
script = jp->fun->u.i.script;
|
||||
JS_ASSERT(!jp->fun);
|
||||
if (!InitFunctionPrinter(jp, fun))
|
||||
return JS_FALSE;
|
||||
script = fun->script;
|
||||
return DecompileCode(jp, script, script->code, (uintN)script->length, 0);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_DecompileFunction(JSPrinter *jp)
|
||||
js_DecompileFunction(JSPrinter *jp, JSScriptedFunction *fun)
|
||||
{
|
||||
JSFunction *fun;
|
||||
uintN i;
|
||||
JSAtom *param;
|
||||
jsbytecode *pc, *endpc;
|
||||
ptrdiff_t len;
|
||||
JSBool ok;
|
||||
#ifdef JS_HAS_DESTRUCTURING
|
||||
SprintStack ss;
|
||||
void *mark;
|
||||
#endif
|
||||
|
||||
fun = jp->fun;
|
||||
JS_ASSERT(fun);
|
||||
JS_ASSERT(!jp->script);
|
||||
if (!InitFunctionPrinter(jp, fun))
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* If pretty, conform to ECMA-262 Edition 3, 15.3.4.2, by decompiling a
|
||||
* FunctionDeclaration. Otherwise, check the JSFUN_LAMBDA flag and force
|
||||
* an expression by parenthesizing.
|
||||
*/
|
||||
if (jp->pretty) {
|
||||
if (jp->pretty)
|
||||
js_printf(jp, "\t");
|
||||
} else {
|
||||
if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
|
||||
js_puts(jp, "(");
|
||||
}
|
||||
else if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
|
||||
js_puts(jp, "(");
|
||||
|
||||
if (JSFUN_GETTER_TEST(fun->flags))
|
||||
js_printf(jp, "%s ", js_getter_str);
|
||||
else if (JSFUN_SETTER_TEST(fun->flags))
|
||||
|
@ -4674,102 +4707,89 @@ js_DecompileFunction(JSPrinter *jp)
|
|||
return JS_FALSE;
|
||||
js_puts(jp, "(");
|
||||
|
||||
if (!FUN_INTERPRETED(fun)) {
|
||||
js_printf(jp, ") {\n");
|
||||
jp->indent += 4;
|
||||
js_printf(jp, native_code_str);
|
||||
jp->indent -= 4;
|
||||
js_printf(jp, "\t}");
|
||||
} else {
|
||||
#ifdef JS_HAS_DESTRUCTURING
|
||||
SprintStack ss;
|
||||
void *mark;
|
||||
#endif
|
||||
|
||||
/* Print the parameters. */
|
||||
pc = fun->u.i.script->main;
|
||||
endpc = pc + fun->u.i.script->length;
|
||||
ok = JS_TRUE;
|
||||
/* Print the parameters. */
|
||||
pc = fun->script->main;
|
||||
endpc = pc + fun->script->length;
|
||||
ok = JS_TRUE;
|
||||
|
||||
#ifdef JS_HAS_DESTRUCTURING
|
||||
/* Skip JSOP_GENERATOR in case of destructuring parameters. */
|
||||
if (*pc == JSOP_GENERATOR)
|
||||
pc += JSOP_GENERATOR_LENGTH;
|
||||
/* Skip JSOP_GENERATOR in case of destructuring parameters. */
|
||||
if (*pc == JSOP_GENERATOR)
|
||||
pc += JSOP_GENERATOR_LENGTH;
|
||||
|
||||
ss.printer = NULL;
|
||||
jp->script = fun->u.i.script;
|
||||
mark = JS_ARENA_MARK(&jp->sprinter.context->tempPool);
|
||||
ss.printer = NULL;
|
||||
jp->script = fun->script;
|
||||
mark = JS_ARENA_MARK(&jp->sprinter.context->tempPool);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < fun->nargs; i++) {
|
||||
if (i > 0)
|
||||
js_puts(jp, ", ");
|
||||
for (i = 0; i < fun->nargs; i++) {
|
||||
if (i > 0)
|
||||
js_puts(jp, ", ");
|
||||
|
||||
param = GetSlotAtom(jp, JS_TRUE, i);
|
||||
param = GetSlotAtom(jp, JS_TRUE, i);
|
||||
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, JS_FALSE)
|
||||
|
||||
if (!param) {
|
||||
ptrdiff_t todo;
|
||||
const char *lval;
|
||||
if (!param) {
|
||||
ptrdiff_t todo;
|
||||
const char *lval;
|
||||
|
||||
LOCAL_ASSERT(*pc == JSOP_GETARG);
|
||||
pc += JSOP_GETARG_LENGTH;
|
||||
LOCAL_ASSERT(*pc == JSOP_DUP);
|
||||
if (!ss.printer) {
|
||||
ok = InitSprintStack(jp->sprinter.context, &ss, jp,
|
||||
fun->u.i.script->depth);
|
||||
if (!ok)
|
||||
break;
|
||||
}
|
||||
pc = DecompileDestructuring(&ss, pc, endpc);
|
||||
if (!pc) {
|
||||
ok = JS_FALSE;
|
||||
LOCAL_ASSERT(*pc == JSOP_GETARG);
|
||||
pc += JSOP_GETARG_LENGTH;
|
||||
LOCAL_ASSERT(*pc == JSOP_DUP);
|
||||
if (!ss.printer) {
|
||||
ok = InitSprintStack(jp->sprinter.context, &ss, jp,
|
||||
fun->script->depth);
|
||||
if (!ok)
|
||||
break;
|
||||
}
|
||||
LOCAL_ASSERT(*pc == JSOP_POP);
|
||||
pc += JSOP_POP_LENGTH;
|
||||
lval = PopStr(&ss, JSOP_NOP);
|
||||
todo = SprintCString(&jp->sprinter, lval);
|
||||
if (todo < 0) {
|
||||
ok = JS_FALSE;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
pc = DecompileDestructuring(&ss, pc, endpc);
|
||||
if (!pc) {
|
||||
ok = JS_FALSE;
|
||||
break;
|
||||
}
|
||||
LOCAL_ASSERT(*pc == JSOP_POP);
|
||||
pc += JSOP_POP_LENGTH;
|
||||
lval = PopStr(&ss, JSOP_NOP);
|
||||
todo = SprintCString(&jp->sprinter, lval);
|
||||
if (todo < 0) {
|
||||
ok = JS_FALSE;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
#undef LOCAL_ASSERT
|
||||
#endif
|
||||
|
||||
if (!QuoteString(&jp->sprinter, ATOM_TO_STRING(param), 0)) {
|
||||
ok = JS_FALSE;
|
||||
break;
|
||||
}
|
||||
if (!QuoteString(&jp->sprinter, ATOM_TO_STRING(param), 0)) {
|
||||
ok = JS_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JS_HAS_DESTRUCTURING
|
||||
jp->script = NULL;
|
||||
JS_ARENA_RELEASE(&jp->sprinter.context->tempPool, mark);
|
||||
jp->script = NULL;
|
||||
JS_ARENA_RELEASE(&jp->sprinter.context->tempPool, mark);
|
||||
#endif
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
if (fun->flags & JSFUN_EXPR_CLOSURE) {
|
||||
js_printf(jp, ") ");
|
||||
} else {
|
||||
js_printf(jp, ") {\n");
|
||||
jp->indent += 4;
|
||||
}
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
if (fun->flags & JSFUN_EXPR_CLOSURE) {
|
||||
js_printf(jp, ") ");
|
||||
} else {
|
||||
js_printf(jp, ") {\n");
|
||||
jp->indent += 4;
|
||||
}
|
||||
|
||||
len = fun->u.i.script->code + fun->u.i.script->length - pc;
|
||||
ok = DecompileCode(jp, fun->u.i.script, pc, (uintN)len, 0);
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
len = fun->script->code + fun->script->length - pc;
|
||||
ok = DecompileCode(jp, fun->script, pc, (uintN)len, 0);
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!(fun->flags & JSFUN_EXPR_CLOSURE)) {
|
||||
jp->indent -= 4;
|
||||
js_printf(jp, "\t}");
|
||||
}
|
||||
if (!(fun->flags & JSFUN_EXPR_CLOSURE)) {
|
||||
jp->indent -= 4;
|
||||
js_printf(jp, "\t}");
|
||||
}
|
||||
|
||||
if (!jp->pretty && !jp->grouped && (fun->flags & JSFUN_LAMBDA))
|
||||
|
@ -4861,7 +4881,9 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
|
|||
goto do_fallback;
|
||||
}
|
||||
|
||||
name = DecompileExpression(cx, script, fp->fun, pc);
|
||||
name = DecompileExpression(cx, script,
|
||||
fp->fun ? FUN_TO_SCRIPTED(fp->fun) : NULL,
|
||||
pc);
|
||||
if (name != FAILED_EXPRESSION_DECOMPILER)
|
||||
return name;
|
||||
|
||||
|
@ -4876,7 +4898,7 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
|
|||
}
|
||||
|
||||
static char *
|
||||
DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
|
||||
DecompileExpression(JSContext *cx, JSScript *script, JSScriptedFunction *fun,
|
||||
jsbytecode *pc)
|
||||
{
|
||||
JSOp op;
|
||||
|
@ -4957,13 +4979,16 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
|
|||
}
|
||||
|
||||
name = NULL;
|
||||
jp = JS_NEW_PRINTER(cx, "js_DecompileValueGenerator", fun, 0, JS_FALSE);
|
||||
jp = JS_NEW_PRINTER(cx, "js_DecompileValueGenerator", 0, JS_FALSE);
|
||||
if (jp) {
|
||||
jp->dvgfence = end;
|
||||
jp->pcstack = pcstack;
|
||||
if (DecompileCode(jp, script, begin, (uintN) len, (uintN) pcdepth)) {
|
||||
name = (jp->sprinter.base) ? jp->sprinter.base : (char *) "";
|
||||
name = JS_strdup(cx, name);
|
||||
if (!fun || InitFunctionPrinter(jp, fun)) {
|
||||
jp->dvgfence = end;
|
||||
jp->pcstack = pcstack;
|
||||
if (DecompileCode(jp, script, begin, (uintN) len,
|
||||
(uintN) pcdepth)) {
|
||||
name = (jp->sprinter.base) ? jp->sprinter.base : (char *) "";
|
||||
name = JS_strdup(cx, name);
|
||||
}
|
||||
}
|
||||
js_DestroyPrinter(jp);
|
||||
}
|
||||
|
|
|
@ -282,16 +282,15 @@ js_QuoteString(JSContext *cx, JSString *str, jschar quote);
|
|||
*/
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
# define JS_NEW_PRINTER(cx, name, fun, indent, pretty) \
|
||||
js_NewPrinter(cx, name, fun, indent, pretty)
|
||||
# define JS_NEW_PRINTER(cx, name, indent, pretty) \
|
||||
js_NewPrinter(cx, name, indent, pretty)
|
||||
#else
|
||||
# define JS_NEW_PRINTER(cx, name, fun, indent, pretty) \
|
||||
js_NewPrinter(cx, fun, indent, pretty)
|
||||
# define JS_NEW_PRINTER(cx, name, indent, pretty) \
|
||||
js_NewPrinter(cx, indent, pretty)
|
||||
#endif
|
||||
|
||||
extern JSPrinter *
|
||||
JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
|
||||
uintN indent, JSBool pretty);
|
||||
JS_NEW_PRINTER(JSContext *cx, const char *name, uintN indent, JSBool pretty);
|
||||
|
||||
extern void
|
||||
js_DestroyPrinter(JSPrinter *jp);
|
||||
|
@ -361,14 +360,20 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
|
|||
/*
|
||||
* Decompilers, for script, function, and expression pretty-printing.
|
||||
*/
|
||||
extern JSBool
|
||||
js_DecompileNativeFunctionBody(JSPrinter *jp, JSNativeFunction *fun);
|
||||
|
||||
JSBool
|
||||
js_DecompileNativeFunction(JSPrinter *jp, JSNativeFunction *fun);
|
||||
|
||||
extern JSBool
|
||||
js_DecompileScript(JSPrinter *jp, JSScript *script);
|
||||
|
||||
extern JSBool
|
||||
js_DecompileFunctionBody(JSPrinter *jp);
|
||||
js_DecompileFunctionBody(JSPrinter *jp, JSScriptedFunction *fun);
|
||||
|
||||
extern JSBool
|
||||
js_DecompileFunction(JSPrinter *jp);
|
||||
js_DecompileFunction(JSPrinter *jp, JSScriptedFunction *fun);
|
||||
|
||||
/*
|
||||
* Find the source expression that resulted in v, and return a newly allocated
|
||||
|
|
|
@ -891,7 +891,8 @@ FunctionBody(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
|
|||
* handler attribute in an HTML <INPUT> tag.
|
||||
*/
|
||||
JSBool
|
||||
js_CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals,
|
||||
js_CompileFunctionBody(JSContext *cx, JSScriptedFunction *fun,
|
||||
JSPrincipals *principals,
|
||||
const jschar *chars, size_t length,
|
||||
const char *filename, uintN lineno)
|
||||
{
|
||||
|
@ -997,7 +998,7 @@ BindArg(JSContext *cx, JSAtom *atom, JSTreeContext *tc)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
BindLocalVariable(JSContext *cx, JSFunction *fun, JSAtom *atom,
|
||||
BindLocalVariable(JSContext *cx, JSScriptedFunction *fun, JSAtom *atom,
|
||||
JSLocalKind localKind)
|
||||
{
|
||||
JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
|
||||
|
@ -1055,17 +1056,16 @@ BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom,
|
|||
}
|
||||
#endif /* JS_HAS_DESTRUCTURING */
|
||||
|
||||
static JSFunction *
|
||||
static JSScriptedFunction *
|
||||
NewCompilerFunction(JSContext *cx, JSTreeContext *tc, JSAtom *atom,
|
||||
uintN lambda)
|
||||
{
|
||||
JSObject *parent;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
|
||||
JS_ASSERT((lambda & ~JSFUN_LAMBDA) == 0);
|
||||
parent = (tc->flags & TCF_IN_FUNCTION) ? tc->fun->object : cx->fp->varobj;
|
||||
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED | lambda,
|
||||
parent, atom);
|
||||
fun = js_NewScriptedFunction(cx, NULL, lambda, parent, atom);
|
||||
if (fun && !(tc->flags & TCF_COMPILE_N_GO)) {
|
||||
STOBJ_SET_PARENT(fun->object, NULL);
|
||||
STOBJ_SET_PROTO(fun->object, NULL);
|
||||
|
@ -1083,7 +1083,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||
JSAtom *funAtom;
|
||||
JSParsedObjectBox *funpob;
|
||||
JSAtomListElement *ale;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
JSTreeContext funtc;
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
JSParseNode *item, *list = NULL;
|
||||
|
@ -4253,7 +4253,7 @@ GeneratorExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
|
|||
uintN oldflags, JSParseNode *pn, JSParseNode *kid)
|
||||
{
|
||||
JSParseNode *body, *lambda;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
|
||||
/* Initialize pn, connecting it to kid. */
|
||||
JS_ASSERT(pn->pn_arity == PN_UNARY);
|
||||
|
|
|
@ -464,7 +464,8 @@ js_CompileScript(JSContext *cx, JSObject *obj, JSPrincipals *principals,
|
|||
FILE *file, const char *filename, uintN lineno);
|
||||
|
||||
extern JSBool
|
||||
js_CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals,
|
||||
js_CompileFunctionBody(JSContext *cx, JSScriptedFunction *fun,
|
||||
JSPrincipals *principals,
|
||||
const jschar *chars, size_t length,
|
||||
const char *filename, uintN lineno);
|
||||
|
||||
|
|
|
@ -92,10 +92,12 @@ typedef struct JSArgumentFormatMap JSArgumentFormatMap;
|
|||
typedef struct JSCodeGenerator JSCodeGenerator;
|
||||
typedef struct JSGCThing JSGCThing;
|
||||
typedef struct JSGenerator JSGenerator;
|
||||
typedef struct JSNativeFunction JSNativeFunction;
|
||||
typedef struct JSParseContext JSParseContext;
|
||||
typedef struct JSParsedObjectBox JSParsedObjectBox;
|
||||
typedef struct JSParseNode JSParseNode;
|
||||
typedef struct JSPropCacheEntry JSPropCacheEntry;
|
||||
typedef struct JSScriptedFunction JSScriptedFunction;
|
||||
typedef struct JSSharpObjectMap JSSharpObjectMap;
|
||||
typedef struct JSTempValueRooter JSTempValueRooter;
|
||||
typedef struct JSThread JSThread;
|
||||
|
@ -237,7 +239,7 @@ typedef union JSTempValueUnion {
|
|||
jsval value;
|
||||
JSObject *object;
|
||||
JSString *string;
|
||||
JSFunction *function;
|
||||
JSScriptedFunction *function;
|
||||
JSXML *xml;
|
||||
JSXMLQName *qname;
|
||||
JSTempValueTrace trace;
|
||||
|
|
|
@ -3868,7 +3868,7 @@ regexp_xdrObject(JSXDRState *xdr, JSObject **objp)
|
|||
return JS_FALSE;
|
||||
}
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL);
|
||||
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
STOBJ_SET_PARENT(obj, NULL);
|
||||
|
@ -4236,7 +4236,7 @@ RegExp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
}
|
||||
|
||||
/* Otherwise, replace obj with a new RegExp object. */
|
||||
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -4296,7 +4296,7 @@ js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
|
|||
if (!re)
|
||||
return NULL;
|
||||
JS_PUSH_TEMP_ROOT_STRING(cx, str, &tvr);
|
||||
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, re)) {
|
||||
js_DestroyRegExp(cx, re);
|
||||
obj = NULL;
|
||||
|
@ -4314,7 +4314,7 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
|
|||
JSRegExp *re;
|
||||
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
|
||||
clone = js_NewObject(cx, &js_RegExpClass, NULL, parent);
|
||||
clone = js_NewObject(cx, &js_RegExpClass, NULL, parent, 0);
|
||||
if (!clone)
|
||||
return NULL;
|
||||
re = (JSRegExp *) JS_GetPrivate(cx, obj);
|
||||
|
|
|
@ -880,7 +880,7 @@ Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
{
|
||||
/* If not constructing, replace obj with a new Script object. */
|
||||
if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
|
||||
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -904,7 +904,7 @@ script_static_thaw(JSContext *cx, uintN argc, jsval *vp)
|
|||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
vp[1] = OBJECT_TO_JSVAL(obj);
|
||||
|
@ -1407,7 +1407,7 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
|
|||
uint32 mainLength, prologLength, nsrcnotes;
|
||||
JSScript *script;
|
||||
const char *filename;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
|
||||
/* The counts of indexed things must be checked during code generation. */
|
||||
JS_ASSERT(cg->atomList.count <= INDEX_LIMIT);
|
||||
|
@ -1452,16 +1452,13 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
|
|||
if (cg->regexpList.length != 0)
|
||||
FinishParsedObjects(&cg->regexpList, JS_SCRIPT_REGEXPS(script));
|
||||
|
||||
/*
|
||||
* We initialize fun->u.script to be the script constructed above
|
||||
* so that the debugger has a valid FUN_SCRIPT(fun).
|
||||
*/
|
||||
/* Initialize fun->script early for the debugger. */
|
||||
fun = NULL;
|
||||
if (cg->treeContext.flags & TCF_IN_FUNCTION) {
|
||||
fun = cg->treeContext.fun;
|
||||
JS_ASSERT(FUN_INTERPRETED(fun) && !FUN_SCRIPT(fun));
|
||||
JS_ASSERT(!fun->script);
|
||||
js_FreezeLocalNames(cx, fun);
|
||||
fun->u.i.script = script;
|
||||
fun->script = script;
|
||||
#ifdef CHECK_SCRIPT_OWNER
|
||||
script->owner = NULL;
|
||||
#endif
|
||||
|
@ -1485,21 +1482,22 @@ bad:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun)
|
||||
void
|
||||
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSScriptedFunction *fun)
|
||||
{
|
||||
JSNewScriptHook hook;
|
||||
|
||||
hook = cx->debugHooks->newScriptHook;
|
||||
if (hook) {
|
||||
JS_KEEP_ATOMS(cx->runtime);
|
||||
hook(cx, script->filename, script->lineno, script, fun,
|
||||
hook(cx, script->filename, script->lineno, script,
|
||||
fun ? SCRIPTED_TO_FUN(fun) : NULL,
|
||||
cx->debugHooks->newScriptHookData);
|
||||
JS_UNKEEP_ATOMS(cx->runtime);
|
||||
}
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
void
|
||||
js_CallDestroyScriptHook(JSContext *cx, JSScript *script)
|
||||
{
|
||||
JSDestroyScriptHook hook;
|
||||
|
@ -1679,7 +1677,7 @@ uintN
|
|||
js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
JSObject *obj;
|
||||
JSFunction *fun;
|
||||
JSScriptedFunction *fun;
|
||||
uintN lineno;
|
||||
ptrdiff_t offset, target;
|
||||
jssrcnote *sn;
|
||||
|
@ -1697,9 +1695,8 @@ 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 = GET_FUNCTION_PRIVATE(cx, obj);
|
||||
JS_ASSERT(FUN_INTERPRETED(fun));
|
||||
return fun->u.i.script->lineno;
|
||||
fun = FUN_TO_SCRIPTED(GET_FUNCTION_PRIVATE(cx, obj));
|
||||
return fun->script->lineno;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -227,10 +227,10 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg);
|
|||
* of js_XDRScript, the hook should be invoked only after successful decode
|
||||
* of any owning function (the fun parameter) or script object (null fun).
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun);
|
||||
extern void
|
||||
js_CallNewScriptHook(JSContext *cx, JSScript *script, JSScriptedFunction *fun);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
extern void
|
||||
js_CallDestroyScriptHook(JSContext *cx, JSScript *script);
|
||||
|
||||
extern void
|
||||
|
|
|
@ -331,7 +331,7 @@ js_GetXMLNamespaceObject(JSContext *cx, JSXMLNamespace *ns)
|
|||
JS_ASSERT(JS_GetPrivate(cx, obj) == ns);
|
||||
return obj;
|
||||
}
|
||||
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, ns)) {
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
|
@ -607,7 +607,7 @@ js_GetXMLQNameObject(JSContext *cx, JSXMLQName *qn)
|
|||
JS_ASSERT(JS_GetPrivate(cx, obj) == qn);
|
||||
return obj;
|
||||
}
|
||||
obj = js_NewObject(cx, &js_QNameClass.base, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_QNameClass.base, NULL, NULL, 0);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
|
@ -632,7 +632,7 @@ js_GetAttributeNameObject(JSContext *cx, JSXMLQName *qn)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL, 0);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
|
@ -748,7 +748,7 @@ Namespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
}
|
||||
|
||||
/* Create and return a new QName object exactly as if constructed. */
|
||||
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
|
@ -830,6 +830,7 @@ QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
{
|
||||
jsval nameval, nsval;
|
||||
JSBool isQName, isNamespace;
|
||||
JSFunction *fun;
|
||||
JSXMLQName *qn;
|
||||
JSString *uri, *prefix, *name;
|
||||
JSObject *nsobj;
|
||||
|
@ -854,9 +855,8 @@ QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
* Use the constructor's clasp so we can be shared by AttributeName
|
||||
* (see below after this function).
|
||||
*/
|
||||
obj = js_NewObject(cx,
|
||||
JS_ValueToFunction(cx, argv[-2])->u.n.clasp,
|
||||
NULL, NULL);
|
||||
fun = JS_ValueToFunction(cx, argv[-2]);
|
||||
obj = js_NewObject(cx, FUN_TO_NATIVE(fun)->clasp, NULL, NULL, 0);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
|
@ -7584,7 +7584,7 @@ NewXMLObject(JSContext *cx, JSXML *xml)
|
|||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL);
|
||||
obj = js_NewObject(cx, &js_XMLClass, NULL, NULL, 0);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, xml)) {
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
|
@ -7713,7 +7713,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj)
|
|||
fun = JS_DefineFunction(cx, obj, js_XMLList_str, XMLList, 1, 0);
|
||||
if (!fun)
|
||||
return NULL;
|
||||
if (!js_SetClassPrototype(cx, fun->object, proto,
|
||||
if (!js_SetClassPrototype(cx, &FUN_TO_NATIVE(fun)->object, proto,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -7877,7 +7877,7 @@ js_SetDefaultXMLNamespace(JSContext *cx, jsval v)
|
|||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(fp->fun && !JSFUN_HEAVYWEIGHT_TEST(fp->fun->flags));
|
||||
JS_ASSERT(fp->fun && !JSFUN_HEAVYWEIGHT_TEST(FUN_FLAGS(fp->fun)));
|
||||
}
|
||||
fp->xmlNamespace = JSVAL_TO_OBJECT(v);
|
||||
return JS_TRUE;
|
||||
|
@ -7997,7 +7997,8 @@ js_GetAnyName(JSContext *cx, jsval *vp)
|
|||
break;
|
||||
}
|
||||
|
||||
obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL, NULL);
|
||||
obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL,
|
||||
NULL, 0);
|
||||
if (!obj || !JS_SetPrivate(cx, obj, qn)) {
|
||||
cx->weakRoots.newborn[GCX_OBJECT] = NULL;
|
||||
ok = JS_FALSE;
|
||||
|
@ -8311,7 +8312,7 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized)
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
filterobj = js_NewObject(cx, &js_XMLFilterClass, NULL, NULL);
|
||||
filterobj = js_NewObject(cx, &js_XMLFilterClass, NULL, NULL, 0);
|
||||
if (!filterobj)
|
||||
return JS_FALSE;
|
||||
|
||||
|
|
|
@ -53,10 +53,10 @@
|
|||
#include "jsj_private.h"
|
||||
#include "jsjava.h"
|
||||
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsfun.h"
|
||||
#include "jscntxt.h" /* For js_ReportErrorAgain().*/
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsscript.h"
|
||||
|
||||
#include "netscape_javascript_JSObject.h" /* javah-generated headers */
|
||||
|
|
|
@ -533,12 +533,12 @@ nsXPConnect::Collect()
|
|||
return gCollected;
|
||||
}
|
||||
|
||||
// JSTRACE_FUNCTION can hold on to a lot of objects, adding it to the cycle
|
||||
// collector reduces the number of edges to those objects.
|
||||
// JSTRACE_SCRIPTED_FUNCTION can hold on to a lot of objects, adding it to the
|
||||
// cycle collector reduces the number of edges to those objects.
|
||||
// JSTRACE_XML can recursively hold on to more JSTRACE_XML objects, adding it to
|
||||
// the cycle collector avoids stack overflow.
|
||||
#define ADD_TO_CC(_kind) \
|
||||
((_kind) == JSTRACE_OBJECT || (_kind) == JSTRACE_FUNCTION || \
|
||||
((_kind) == JSTRACE_OBJECT || (_kind) == JSTRACE_SCRIPTED_FUNCTION || \
|
||||
(_kind) == JSTRACE_XML)
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
|
|
Загрузка…
Ссылка в новой задаче