bool js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript, MutableHandleObject objp) { /* NB: Keep this in sync with CloneInterpretedFunction. */ Rooted<JSAtom*> atom(xdr->cx()); uint32_t firstword; /* flag telling whether fun->atom is non-null, plus for fun->u.i.skipmin, fun->u.i.wrapper, and 14 bits reserved for future use */ uint32_t flagsword; /* word for argument count and fun->flags */ JSContext *cx = xdr->cx(); RootedFunction fun(cx); JSScript *script; if (mode == XDR_ENCODE) { fun = objp->toFunction(); if (!fun->isInterpreted()) { JSAutoByteString funNameBytes; if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_SCRIPTED_FUNCTION, name); } return false; } firstword = !!fun->atom; flagsword = (fun->nargs << 16) | fun->flags; atom = fun->atom; script = fun->script(); } else { RootedObject parent(cx, NULL); fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, parent, NULL); if (!fun) return false; if (!JSObject::clearParent(cx, fun)) return false; if (!JSObject::clearType(cx, fun)) return false; atom = NULL; script = NULL; } if (!xdr->codeUint32(&firstword)) return false; if ((firstword & 1U) && !XDRAtom(xdr, atom.address())) return false; if (!xdr->codeUint32(&flagsword)) return false; if (!XDRScript(xdr, enclosingScope, enclosingScript, fun, &script)) return false; if (mode == XDR_DECODE) { fun->nargs = flagsword >> 16; fun->flags = uint16_t(flagsword); fun->atom.init(atom); fun->initScript(script); script->setFunction(fun); if (!fun->setTypeForScriptedFunction(cx)) return false; JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs()); js_CallNewScriptHook(cx, fun->script(), fun); objp.set(fun); }