jsscript.c

来自「java script test programing source code」· C语言 代码 · 共 1,718 行 · 第 1/4 页

C
1,718
字号
            index = i;        if (!JS_XDRUint32(xdr, &index))            goto bad;        /*         * Assert that, when decoding, the read index is valid and points to         * an unoccupied element of atoms array.         */        JS_ASSERT(index < natoms);        JS_ASSERT(xdr->mode == JSXDR_ENCODE || !atoms[index]);        if (!js_XDRAtom(xdr, &atoms[index]))            goto bad;    }    return JS_TRUE;  bad:    if (xdr->mode == JSXDR_DECODE) {        JS_free(cx, atoms);        map->vector = NULL;        map->length = 0;    }    return JS_FALSE;}JSBooljs_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic){    JSContext *cx;    JSScript *script, *newscript, *oldscript;    uint32 length, lineno, depth, magic, nsrcnotes, ntrynotes;    uint32 prologLength, version;    JSBool filenameWasSaved;    jssrcnote *notes, *sn;    cx = xdr->cx;    script = *scriptp;    nsrcnotes = ntrynotes = 0;    filenameWasSaved = JS_FALSE;    notes = NULL;    /*     * Encode prologLength and version after script->length (_2 or greater),     * but decode both new (>= _2) and old, prolog&version-free (_1) scripts.     * Version _3 supports principals serialization.  Version _4 reorders the     * nsrcnotes and ntrynotes fields to come before everything except magic,     * length, prologLength, and version, so that srcnote and trynote storage     * can be allocated as part of the JSScript (along with bytecode storage).     *     * So far, the magic number has not changed for every jsopcode.tbl change.     * We stipulate forward compatibility by requiring old bytecodes never to     * change or go away (modulo a few exceptions before the XDR interfaces     * evolved, and a few exceptions during active trunk development).  With     * the addition of JSOP_STOP to support JS_THREADED_INTERP, we make a new     * magic number (_5) so that we know to append JSOP_STOP to old scripts     * when deserializing.     */    if (xdr->mode == JSXDR_ENCODE)        magic = JSXDR_MAGIC_SCRIPT_CURRENT;    if (!JS_XDRUint32(xdr, &magic))        return JS_FALSE;    JS_ASSERT((uint32)JSXDR_MAGIC_SCRIPT_5 - (uint32)JSXDR_MAGIC_SCRIPT_1 == 4);    if (magic - (uint32)JSXDR_MAGIC_SCRIPT_1 > 4) {        if (!hasMagic) {            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                                 JSMSG_BAD_SCRIPT_MAGIC);            return JS_FALSE;        }        *hasMagic = JS_FALSE;        return JS_TRUE;    }    if (hasMagic)        *hasMagic = JS_TRUE;    if (xdr->mode == JSXDR_ENCODE) {        length = script->length;        prologLength = PTRDIFF(script->main, script->code, jsbytecode);        JS_ASSERT((int16)script->version != JSVERSION_UNKNOWN);        version = (uint32)script->version | (script->numGlobalVars << 16);        lineno = (uint32)script->lineno;        depth = (uint32)script->depth;        /* Count the srcnotes, keeping notes pointing at the first one. */        notes = SCRIPT_NOTES(script);        for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))            continue;        nsrcnotes = PTRDIFF(sn, notes, jssrcnote);        nsrcnotes++;            /* room for the terminator */        /* Count the trynotes. */        if (script->trynotes) {            while (script->trynotes[ntrynotes].catchStart)                ntrynotes++;            ntrynotes++;        /* room for the end marker */        }    }    if (!JS_XDRUint32(xdr, &length))        return JS_FALSE;    if (magic >= JSXDR_MAGIC_SCRIPT_2) {        if (!JS_XDRUint32(xdr, &prologLength))            return JS_FALSE;        if (!JS_XDRUint32(xdr, &version))            return JS_FALSE;        /* To fuse allocations, we need srcnote and trynote counts early. */        if (magic >= JSXDR_MAGIC_SCRIPT_4) {            if (!JS_XDRUint32(xdr, &nsrcnotes))                return JS_FALSE;            if (!JS_XDRUint32(xdr, &ntrynotes))                return JS_FALSE;        }    }    if (xdr->mode == JSXDR_DECODE) {        size_t alloclength = length;        if (magic < JSXDR_MAGIC_SCRIPT_5)            ++alloclength;      /* add a byte for JSOP_STOP */        script = js_NewScript(cx, alloclength, nsrcnotes, ntrynotes);        if (!script)            return JS_FALSE;        if (magic >= JSXDR_MAGIC_SCRIPT_2) {            script->main += prologLength;            script->version = (JSVersion) (version & 0xffff);            script->numGlobalVars = (uint16) (version >> 16);            /* If we know nsrcnotes, we allocated space for notes in script. */            if (magic >= JSXDR_MAGIC_SCRIPT_4)                notes = SCRIPT_NOTES(script);        }        *scriptp = script;    }    /*     * Control hereafter must goto error on failure, in order for the DECODE     * case to destroy script and conditionally free notes, which if non-null     * in the (DECODE and magic < _4) case must point at a temporary vector     * allocated just below.     */    oldscript = xdr->script;    xdr->script = script;    if (!JS_XDRBytes(xdr, (char *)script->code, length * sizeof(jsbytecode)) ||        !XDRAtomMap(xdr, &script->atomMap)) {        goto error;    }    if (magic < JSXDR_MAGIC_SCRIPT_5) {        if (xdr->mode == JSXDR_DECODE) {            /*             * Append JSOP_STOP to old scripts, to relieve the interpreter             * from having to bounds-check pc.  Also take care to increment             * length, as it is used below and must count all bytecode.             */            script->code[length++] = JSOP_STOP;        }        if (magic < JSXDR_MAGIC_SCRIPT_4) {            if (!JS_XDRUint32(xdr, &nsrcnotes))                goto error;            if (xdr->mode == JSXDR_DECODE) {                notes = (jssrcnote *)                        JS_malloc(cx, nsrcnotes * sizeof(jssrcnote));                if (!notes)                    goto error;            }        }    }    if (!JS_XDRBytes(xdr, (char *)notes, nsrcnotes * sizeof(jssrcnote)) ||        !JS_XDRCStringOrNull(xdr, (char **)&script->filename) ||        !JS_XDRUint32(xdr, &lineno) ||        !JS_XDRUint32(xdr, &depth) ||        (magic < JSXDR_MAGIC_SCRIPT_4 && !JS_XDRUint32(xdr, &ntrynotes))) {        goto error;    }    /* Script principals transcoding support comes with versions >= _3. */    if (magic >= JSXDR_MAGIC_SCRIPT_3) {        JSPrincipals *principals;        uint32 encodeable;        if (xdr->mode == JSXDR_ENCODE) {            principals = script->principals;            encodeable = (cx->runtime->principalsTranscoder != NULL);            if (!JS_XDRUint32(xdr, &encodeable))                goto error;            if (encodeable &&                !cx->runtime->principalsTranscoder(xdr, &principals)) {                goto error;            }        } else {            if (!JS_XDRUint32(xdr, &encodeable))                goto error;            if (encodeable) {                if (!cx->runtime->principalsTranscoder) {                    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                                         JSMSG_CANT_DECODE_PRINCIPALS);                    goto error;                }                if (!cx->runtime->principalsTranscoder(xdr, &principals))                    goto error;                script->principals = principals;            }        }    }    if (xdr->mode == JSXDR_DECODE) {        const char *filename = script->filename;        if (filename) {            filename = js_SaveScriptFilename(cx, filename);            if (!filename)                goto error;            JS_free(cx, (void *) script->filename);            script->filename = filename;            filenameWasSaved = JS_TRUE;        }        script->lineno = (uintN)lineno;        script->depth = (uintN)depth;        if (magic < JSXDR_MAGIC_SCRIPT_4) {            /*             * Argh, we have to reallocate script, copy notes into the extra             * space after the bytecodes, and free the temporary notes vector.             * First, add enough slop to nsrcnotes so we can align the address             * after the srcnotes of the first trynote.             */            uint32 osrcnotes = nsrcnotes;            if (ntrynotes)                nsrcnotes += JSTRYNOTE_ALIGNMASK;            newscript = (JSScript *) JS_realloc(cx, script,                                                sizeof(JSScript) +                                                length * sizeof(jsbytecode) +                                                nsrcnotes * sizeof(jssrcnote) +                                                ntrynotes * sizeof(JSTryNote));            if (!newscript)                goto error;            *scriptp = script = newscript;            script->code = (jsbytecode *)(script + 1);            script->main = script->code + prologLength;            memcpy(script->code + length, notes, osrcnotes * sizeof(jssrcnote));            JS_free(cx, (void *) notes);            notes = NULL;            if (ntrynotes) {                script->trynotes = (JSTryNote *)                                   ((jsword)(SCRIPT_NOTES(script) + nsrcnotes) &                                    ~(jsword)JSTRYNOTE_ALIGNMASK);                memset(script->trynotes, 0, ntrynotes * sizeof(JSTryNote));            }        }    }    while (ntrynotes) {        JSTryNote *tn = &script->trynotes[--ntrynotes];        uint32 start = (uint32) tn->start,               catchLength = (uint32) tn->length,               catchStart = (uint32) tn->catchStart;        if (!JS_XDRUint32(xdr, &start) ||            !JS_XDRUint32(xdr, &catchLength) ||            !JS_XDRUint32(xdr, &catchStart)) {            goto error;        }        tn->start = (ptrdiff_t) start;        tn->length = (ptrdiff_t) catchLength;        tn->catchStart = (ptrdiff_t) catchStart;    }    xdr->script = oldscript;    return JS_TRUE;  error:    if (xdr->mode == JSXDR_DECODE) {        if (script->filename && !filenameWasSaved) {            JS_free(cx, (void *) script->filename);            script->filename = NULL;        }        if (notes && magic < JSXDR_MAGIC_SCRIPT_4)            JS_free(cx, (void *) notes);        js_DestroyScript(cx, script);        *scriptp = NULL;    }    return JS_FALSE;}#if JS_HAS_XDR_FREEZE_THAW/* * These cannot be exposed to web content, and chrome does not need them, so * we take them out of the Mozilla client altogether.  Fortunately, there is * no way to serialize a native function (see fun_xdrObject in jsfun.c). */static JSBoolscript_freeze(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,              jsval *rval){    JSXDRState *xdr;    JSScript *script;    JSBool ok, hasMagic;    uint32 len;    void *buf;    JSString *str;    if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))        return JS_FALSE;    script = (JSScript *) JS_GetPrivate(cx, obj);    if (!script)        return JS_TRUE;    /* create new XDR */    xdr = JS_XDRNewMem(cx, JSXDR_ENCODE);    if (!xdr)        return JS_FALSE;    /* write  */    ok = js_XDRScript(xdr, &script, &hasMagic);    if (!ok)        goto out;    if (!hasMagic) {        *rval = JSVAL_VOID;        goto out;    }    buf = JS_XDRMemGetData(xdr, &len);    if (!buf) {        ok = JS_FALSE;        goto out;    }    JS_ASSERT((jsword)buf % sizeof(jschar) == 0);    len /= sizeof(jschar);    str = JS_NewUCStringCopyN(cx, (jschar *)buf, len);    if (!str) {        ok = JS_FALSE;        goto out;    }#if IS_BIG_ENDIAN  {    jschar *chars;    uint32 i;    /* Swap bytes in Unichars to keep frozen strings machine-independent. */    chars = JS_GetStringChars(str);    for (i = 0; i < len; i++)        chars[i] = JSXDR_SWAB16(chars[i]);  }#endif    *rval = STRING_TO_JSVAL(str);out:    JS_XDRDestroy(xdr);    return ok;}static JSBoolscript_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,            jsval *rval){    JSXDRState *xdr;    JSString *str;    void *buf;    uint32 len;    jsval v;    JSScript *script, *oldscript;    JSBool ok, hasMagic;    if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))        return JS_FALSE;    if (argc == 0)        return JS_TRUE;    str = js_ValueToString(cx, argv[0]);    if (!str)        return JS_FALSE;    argv[0] = STRING_TO_JSVAL(str);    /* create new XDR */    xdr = JS_XDRNewMem(cx, JSXDR_DECODE);    if (!xdr)        return JS_FALSE;    buf = JS_GetStringChars(str);    len = JS_GetStringLength(str);#if IS_BIG_ENDIAN  {    jschar *from, *to;    uint32 i;    /* Swap bytes in Unichars to keep frozen strings machine-independent. */    from = (jschar *)buf;    to = (jschar *) JS_malloc(cx, len * sizeof(jschar));    if (!to) {        JS_XDRDestroy(xdr);        return JS_FALSE;    }    for (i = 0; i < len; i++)        to[i] = JSXDR_SWAB16(from[i]);    buf = (char *)to;  }#endif    len *= sizeof(jschar);    JS_XDRMemSetData(xdr, buf, len);    /* XXXbe should magic mismatch be error, or false return value? */    ok = js_XDRScript(xdr, &script, &hasMagic);    if (!ok)        goto out;    if (!hasMagic) {        *rval = JSVAL_FALSE;        goto out;    }    JS_LOCK_OBJ(cx, obj);    execDepth = GetScriptExecDepth(cx, obj);    /*     * execDepth must be 0 to allow compilation here, otherwise the JSScript     * struct can be released while running.     */    if (execDepth > 0) {        JS_UNLOCK_OBJ(cx, obj);        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                             JSMSG_COMPILE_EXECED_SCRIPT);        goto out;    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?