jsscript.c
来自「一个基于alice开发的机器人」· C语言 代码 · 共 1,288 行 · 第 1/3 页
C
1,288 行
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) {
script = js_NewScript(cx, length, nsrcnotes, ntrynotes);
if (!script)
return JS_FALSE;
if (magic >= JSXDR_MAGIC_SCRIPT_2) {
script->main += prologLength;
script->version = (JSVersion) version;
/* 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 version < _4) case must point at a temporary vector
* allocated just below.
*/
if (!JS_XDRBytes(xdr, (char *)script->code, length * sizeof(jsbytecode)) ||
!XDRAtomMap(xdr, &script->atomMap)) {
goto error;
}
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);
}
}
}
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;
}
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 JSBool
script_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 JSBool
script_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
JSXDRState *xdr;
JSString *str;
void *buf;
uint32 len;
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;
/* 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;
}
/* Swap script for obj's old script, if any. */
oldscript = (JSScript *) JS_GetPrivate(cx, obj);
ok = JS_SetPrivate(cx, obj, script);
if (!ok) {
JS_free(cx, script);
goto out;
}
if (oldscript)
js_DestroyScript(cx, oldscript);
script->object = obj;
js_CallNewScriptHook(cx, script, NULL);
out:
/*
* We reset the buffer to be NULL so that it doesn't free the chars
* memory owned by str (argv[0]).
*/
JS_XDRMemSetData(xdr, NULL, 0);
JS_XDRDestroy(xdr);
#if IS_BIG_ENDIAN
JS_free(cx, buf);
#endif
*rval = JSVAL_TRUE;
return ok;
}
static const char js_thaw_str[] = "thaw";
#endif /* JS_HAS_XDR_FREEZE_THAW */
#endif /* JS_HAS_XDR */
static JSFunctionSpec script_methods[] = {
#if JS_HAS_TOSOURCE
{js_toSource_str, script_toSource, 0,0,0},
#endif
{js_toString_str, script_toString, 0,0,0},
{"compile", script_compile, 2,0,0},
{"exec", script_exec, 1,0,0},
#if JS_HAS_XDR_FREEZE_THAW
{"freeze", script_freeze, 0,0,0},
{js_thaw_str, script_thaw, 1,0,0},
#endif /* JS_HAS_XDR_FREEZE_THAW */
{0,0,0,0,0}
};
#endif /* JS_HAS_SCRIPT_OBJECT */
static void
script_finalize(JSContext *cx, JSObject *obj)
{
JSScript *script;
script = (JSScript *) JS_GetPrivate(cx, obj);
if (script)
js_DestroyScript(cx, script);
}
static JSBool
script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
#if JS_HAS_SCRIPT_OBJECT
return script_exec(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval);
#else
return JS_FALSE;
#endif
}
static uint32
script_mark(JSContext *cx, JSObject *obj, void *arg)
{
JSScript *script;
script = (JSScript *) JS_GetPrivate(cx, obj);
if (script)
js_MarkScript(cx, script, arg);
return 0;
}
JS_FRIEND_DATA(JSClass) js_ScriptClass = {
js_Script_str,
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize,
NULL, NULL, script_call, NULL,/*XXXbe xdr*/
NULL, NULL, script_mark, 0
};
#if JS_HAS_SCRIPT_OBJECT
static JSBool
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);
if (!obj)
return JS_FALSE;
}
return script_compile(cx, obj, argc, argv, rval);
}
#if JS_HAS_XDR_FREEZE_THAW
static JSBool
script_static_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
if (!obj)
return JS_FALSE;
if (!script_thaw(cx, obj, argc, argv, rval))
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
return JS_TRUE;
}
static JSFunctionSpec script_static_methods[] = {
{js_thaw_str, script_static_thaw, 1,0,0},
{0,0,0,0,0}
};
#else /* !JS_HAS_XDR_FREEZE_THAW */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?