bool js::XDRInterpretedFunction(XDRState<mode> *xdr, JSObject **objp, JSScript *parentScript) { /* NB: Keep this in sync with CloneInterpretedFunction. */ JSFunction *fun; JSAtom *atom; 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(); 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 (!fun->clearParent(cx)) return false; if (!fun->clearType(cx)) return false; atom = NULL; script = NULL; } if (!xdr->codeUint32(&firstword)) return false; if ((firstword & 1U) && !XDRAtom(xdr, &atom)) return false; if (!xdr->codeUint32(&flagsword)) return false; if (!XDRScript(xdr, &script, parentScript)) return false; if (mode == XDR_DECODE) { fun->nargs = flagsword >> 16; JS_ASSERT((flagsword & JSFUN_KINDMASK) >= JSFUN_INTERPRETED); fun->flags = uint16_t(flagsword); fun->atom.init(atom); fun->initScript(script); if (!script->typeSetFunction(cx, fun)) return false; JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs()); js_CallNewScriptHook(cx, fun->script(), fun); *objp = fun; }