mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
bug 737624 - memory-only encoding/decoding of scripts and functions. r=:luke
The patch shrinks the API presented in jsxdrapi.h down to 4 functions to encode/decode scripts and interpreted functions to/from the memory. The newly introduced implementation header vm/Xdr.h replaces the former JSXDRState with the template class XDRState parametrized by the enum type with two constants, XDR_ENCODE and XDR_DECODE. This way a compiler can fully eliminate the former runtime checks for the decoding/encoding mode. As a drawback this required to explicitly instantiate the xdr implementation as I do not want to put all the xdr code to header files. The memory-only XDR allows to avoid coping filename and to-be-atomized chars to a temporary buffer as the code can just access the buffer directly. Another change is that new XDRScript takes as a parameter its parent script. This allowed to avoid keeping filename in XDRState and simplify the filename management. Another change is the removal of JS_HAS_HDR. As CloneScript uses XDR to copy a script, JS_HAS_XDR cannot be disabled. --HG-- rename : js/src/jsxdrapi.cpp => js/src/vm/Xdr.cpp
This commit is contained in:
parent
4358625535
commit
5a94b9c481
@ -44,7 +44,6 @@
|
|||||||
#include "nsXPIDLString.h"
|
#include "nsXPIDLString.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
#include "nsIJSRuntimeService.h"
|
#include "nsIJSRuntimeService.h"
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
#include "nsMemory.h"
|
#include "nsMemory.h"
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsAppDirectoryServiceDefs.h"
|
#include "nsAppDirectoryServiceDefs.h"
|
||||||
|
|
||||||
#include "jsxdrapi.h"
|
#include "jsapi.h"
|
||||||
|
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/scache/StartupCache.h"
|
#include "mozilla/scache/StartupCache.h"
|
||||||
|
@ -146,7 +146,6 @@ CPPSRCS = \
|
|||||||
jswatchpoint.cpp \
|
jswatchpoint.cpp \
|
||||||
jsweakmap.cpp \
|
jsweakmap.cpp \
|
||||||
jswrapper.cpp \
|
jswrapper.cpp \
|
||||||
jsxdrapi.cpp \
|
|
||||||
jsxml.cpp \
|
jsxml.cpp \
|
||||||
prmjtime.cpp \
|
prmjtime.cpp \
|
||||||
sharkctl.cpp \
|
sharkctl.cpp \
|
||||||
@ -177,6 +176,7 @@ CPPSRCS = \
|
|||||||
Statistics.cpp \
|
Statistics.cpp \
|
||||||
StringBuffer.cpp \
|
StringBuffer.cpp \
|
||||||
Unicode.cpp \
|
Unicode.cpp \
|
||||||
|
Xdr.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# Changes to internal header files, used externally, massively slow down
|
# Changes to internal header files, used externally, massively slow down
|
||||||
@ -210,7 +210,6 @@ INSTALLED_HEADERS = \
|
|||||||
jsutil.h \
|
jsutil.h \
|
||||||
jsversion.h \
|
jsversion.h \
|
||||||
jswrapper.h \
|
jswrapper.h \
|
||||||
jsxdrapi.h \
|
|
||||||
jsval.h \
|
jsval.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
@ -822,7 +822,7 @@ EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *body);
|
|||||||
* arity in JSSrcNoteSpec. This is why SRC_IF and SRC_INITPROP have the same
|
* arity in JSSrcNoteSpec. This is why SRC_IF and SRC_INITPROP have the same
|
||||||
* value below.
|
* value below.
|
||||||
*
|
*
|
||||||
* Don't forget to update JSXDR_BYTECODE_VERSION in jsxdrapi.h for all such
|
* Don't forget to update XDR_BYTECODE_VERSION in vm/Xdr.h for all such
|
||||||
* incompatible source note or other bytecode changes.
|
* incompatible source note or other bytecode changes.
|
||||||
*/
|
*/
|
||||||
enum SrcNoteType {
|
enum SrcNoteType {
|
||||||
|
@ -146,11 +146,11 @@ MSG_DEF(JSMSG_NO_INPUT, 59, 5, JSEXN_SYNTAXERR, "no input for /{0
|
|||||||
MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_ERR, "can't open {0}: {1}")
|
MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_ERR, "can't open {0}: {1}")
|
||||||
MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 61, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
|
MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 61, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
|
||||||
MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
|
MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
|
||||||
MSG_DEF(JSMSG_END_OF_DATA, 63, 0, JSEXN_INTERNALERR, "unexpected end of data")
|
MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE, 63, 0, JSEXN_INTERNALERR, "data are to big to encode")
|
||||||
MSG_DEF(JSMSG_SEEK_BEYOND_START, 64, 0, JSEXN_INTERNALERR, "illegal seek beyond start")
|
MSG_DEF(JSMSG_UNUSED64, 64, 0, JSEXN_NONE, "")
|
||||||
MSG_DEF(JSMSG_SEEK_BEYOND_END, 65, 0, JSEXN_INTERNALERR, "illegal seek beyond end")
|
MSG_DEF(JSMSG_UNUSED65, 65, 0, JSEXN_NONE, "")
|
||||||
MSG_DEF(JSMSG_END_SEEK, 66, 0, JSEXN_INTERNALERR, "illegal end-based seek")
|
MSG_DEF(JSMSG_UNUSED66, 66, 0, JSEXN_NONE, "")
|
||||||
MSG_DEF(JSMSG_WHITHER_WHENCE, 67, 1, JSEXN_INTERNALERR, "unknown seek whence: {0}")
|
MSG_DEF(JSMSG_UNUSED67, 67, 0, JSEXN_NONE, "")
|
||||||
MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
|
MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
|
||||||
MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
|
MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
|
||||||
MSG_DEF(JSMSG_MISSING_FORMAL, 70, 0, JSEXN_SYNTAXERR, "missing formal parameter")
|
MSG_DEF(JSMSG_MISSING_FORMAL, 70, 0, JSEXN_SYNTAXERR, "missing formal parameter")
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
|
|
||||||
/* Do the test a bunch of times, because sometimes we seem to randomly
|
/* Do the test a bunch of times, because sometimes we seem to randomly
|
||||||
miss the propcache */
|
miss the propcache */
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jsdbgapi.h"
|
#include "jsdbgapi.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
|
|
||||||
BEGIN_TEST(test_cloneScript)
|
BEGIN_TEST(test_cloneScript)
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
native(JSContext *cx, unsigned argc, jsval *vp)
|
native(JSContext *cx, unsigned argc, jsval *vp)
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "jspubtd.h"
|
#include "jspubtd.h"
|
||||||
#include "jstypes.h"
|
#include "jstypes.h"
|
||||||
#include "jsval.h"
|
#include "jsval.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
|
|
||||||
#include "js/HashTable.h"
|
#include "js/HashTable.h"
|
||||||
#include "js/MemoryMetrics.h"
|
#include "js/MemoryMetrics.h"
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
nativeGet(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
nativeGet(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "jsscript.h"
|
#include "jsscript.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
|
|
||||||
static JSScript *
|
static JSScript *
|
||||||
CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
|
CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
|
||||||
@ -28,44 +27,18 @@ CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
|
|||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
JSScript *
|
||||||
T *
|
FreezeThaw(JSContext *cx, JSScript *script)
|
||||||
FreezeThawImpl(JSContext *cx, T *thing, JSBool (*xdrAction)(JSXDRState *xdr, T **))
|
|
||||||
{
|
{
|
||||||
// freeze
|
// freeze
|
||||||
JSXDRState *w = JS_XDRNewMem(cx, JSXDR_ENCODE);
|
|
||||||
if (!w)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
void *memory = NULL;
|
|
||||||
uint32_t nbytes;
|
uint32_t nbytes;
|
||||||
if (xdrAction(w, &thing)) {
|
void *memory = JS_EncodeScript(cx, script, &nbytes);
|
||||||
void *p = JS_XDRMemGetData(w, &nbytes);
|
|
||||||
if (p) {
|
|
||||||
memory = JS_malloc(cx, nbytes);
|
|
||||||
if (memory)
|
|
||||||
memcpy(memory, p, nbytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JS_XDRDestroy(w);
|
|
||||||
if (!memory)
|
if (!memory)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// thaw
|
// thaw
|
||||||
JSXDRState *r = JS_XDRNewMem(cx, JSXDR_DECODE);
|
script = JS_DecodeScript(cx, memory, nbytes, script->principals, script->originPrincipals);
|
||||||
JS_XDRMemSetData(r, memory, nbytes);
|
js_free(memory);
|
||||||
|
|
||||||
JSScript *script = GetScript(cx, thing);
|
|
||||||
JS_XDRSetPrincipals(r, script->principals, script->originPrincipals);
|
|
||||||
if (!xdrAction(r, &thing))
|
|
||||||
thing = NULL;
|
|
||||||
JS_XDRDestroy(r); // this frees `memory
|
|
||||||
return thing;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSScript *
|
|
||||||
GetScript(JSContext *cx, JSScript *script)
|
|
||||||
{
|
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,16 +48,21 @@ GetScript(JSContext *cx, JSObject *funobj)
|
|||||||
return JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
|
return JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSScript *
|
JSObject *
|
||||||
FreezeThaw(JSContext *cx, JSScript *script)
|
|
||||||
{
|
|
||||||
return FreezeThawImpl(cx, script, JS_XDRScript);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSObject *
|
|
||||||
FreezeThaw(JSContext *cx, JSObject *funobj)
|
FreezeThaw(JSContext *cx, JSObject *funobj)
|
||||||
{
|
{
|
||||||
return FreezeThawImpl(cx, funobj, JS_XDRFunctionObject);
|
// freeze
|
||||||
|
uint32_t nbytes;
|
||||||
|
void *memory = JS_EncodeInterpretedFunction(cx, funobj, &nbytes);
|
||||||
|
if (!memory)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// thaw
|
||||||
|
JSScript *script = GetScript(cx, funobj);
|
||||||
|
funobj = JS_DecodeInterpretedFunction(cx, memory, nbytes,
|
||||||
|
script->principals, script->originPrincipals);
|
||||||
|
js_free(memory);
|
||||||
|
return funobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSPrincipals testPrincipals[] = {
|
static JSPrincipals testPrincipals[] = {
|
||||||
|
@ -82,6 +82,7 @@
|
|||||||
#include "jsweakmap.h"
|
#include "jsweakmap.h"
|
||||||
#include "jswrapper.h"
|
#include "jswrapper.h"
|
||||||
#include "jstypedarray.h"
|
#include "jstypedarray.h"
|
||||||
|
#include "jsxml.h"
|
||||||
|
|
||||||
#include "ds/LifoAlloc.h"
|
#include "ds/LifoAlloc.h"
|
||||||
#include "builtin/MapObject.h"
|
#include "builtin/MapObject.h"
|
||||||
@ -90,10 +91,10 @@
|
|||||||
#include "frontend/BytecodeEmitter.h"
|
#include "frontend/BytecodeEmitter.h"
|
||||||
#include "gc/Memory.h"
|
#include "gc/Memory.h"
|
||||||
#include "js/MemoryMetrics.h"
|
#include "js/MemoryMetrics.h"
|
||||||
#include "mozilla/Util.h"
|
|
||||||
#include "yarr/BumpPointerAllocator.h"
|
#include "yarr/BumpPointerAllocator.h"
|
||||||
#include "vm/MethodGuard.h"
|
#include "vm/MethodGuard.h"
|
||||||
#include "vm/StringBuffer.h"
|
#include "vm/StringBuffer.h"
|
||||||
|
#include "vm/Xdr.h"
|
||||||
|
|
||||||
#include "jsatominlines.h"
|
#include "jsatominlines.h"
|
||||||
#include "jsinferinlines.h"
|
#include "jsinferinlines.h"
|
||||||
@ -112,10 +113,6 @@
|
|||||||
#include "methodjit/Logging.h"
|
#include "methodjit/Logging.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
|
||||||
#include "jsxml.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::gc;
|
using namespace js::gc;
|
||||||
using namespace js::types;
|
using namespace js::types;
|
||||||
@ -6638,3 +6635,43 @@ AutoEnumStateRooter::~AutoEnumStateRooter()
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace JS
|
} // namespace JS
|
||||||
|
|
||||||
|
JS_PUBLIC_API(void *)
|
||||||
|
JS_EncodeScript(JSContext *cx, JSScript *script, uint32_t *lengthp)
|
||||||
|
{
|
||||||
|
XDREncoder encoder(cx);
|
||||||
|
if (!encoder.codeScript(&script))
|
||||||
|
return NULL;
|
||||||
|
return encoder.forgetData(lengthp);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(void *)
|
||||||
|
JS_EncodeInterpretedFunction(JSContext *cx, JSObject *funobj, uint32_t *lengthp)
|
||||||
|
{
|
||||||
|
XDREncoder encoder(cx);
|
||||||
|
if (!encoder.codeFunction(&funobj))
|
||||||
|
return NULL;
|
||||||
|
return encoder.forgetData(lengthp);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(JSScript *)
|
||||||
|
JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
|
||||||
|
JSPrincipals *principals, JSPrincipals *originPrincipals)
|
||||||
|
{
|
||||||
|
XDRDecoder decoder(cx, data, length, principals, originPrincipals);
|
||||||
|
JSScript *script;
|
||||||
|
if (!decoder.codeScript(&script))
|
||||||
|
return NULL;
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(JSObject *)
|
||||||
|
JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
|
||||||
|
JSPrincipals *principals, JSPrincipals *originPrincipals)
|
||||||
|
{
|
||||||
|
XDRDecoder decoder(cx, data, length, principals, originPrincipals);
|
||||||
|
JSObject *funobj;
|
||||||
|
if (!decoder.codeFunction(&funobj))
|
||||||
|
return NULL;
|
||||||
|
return funobj;
|
||||||
|
}
|
||||||
|
@ -5410,6 +5410,24 @@ extern JS_PUBLIC_API(JSBool)
|
|||||||
JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno);
|
JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encode/Decode interpreted scripts and functions to/from memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(void *)
|
||||||
|
JS_EncodeScript(JSContext *cx, JSScript *script, uint32_t *lengthp);
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(void *)
|
||||||
|
JS_EncodeInterpretedFunction(JSContext *cx, JSObject *funobj, uint32_t *lengthp);
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(JSScript *)
|
||||||
|
JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
|
||||||
|
JSPrincipals *principals, JSPrincipals *originPrincipals);
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(JSObject *)
|
||||||
|
JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
|
||||||
|
JSPrincipals *principals, JSPrincipals *originPrincipals);
|
||||||
|
|
||||||
JS_END_EXTERN_C
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
#endif /* jsapi_h___ */
|
#endif /* jsapi_h___ */
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
#include "vm/String-inl.h"
|
#include "vm/String-inl.h"
|
||||||
|
#include "vm/Xdr.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace js;
|
using namespace js;
|
||||||
@ -657,3 +658,65 @@ js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template<XDRMode mode>
|
||||||
|
bool
|
||||||
|
js::XDRAtom(XDRState<mode> *xdr, JSAtom **atomp)
|
||||||
|
{
|
||||||
|
if (mode == XDR_ENCODE) {
|
||||||
|
JSString *str = *atomp;
|
||||||
|
return xdr->codeString(&str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inline XDRState::codeString when decoding to avoid JSString allocation
|
||||||
|
* for already existing atoms. See bug 321985.
|
||||||
|
*/
|
||||||
|
uint32_t nchars;
|
||||||
|
if (!xdr->codeUint32(&nchars))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSContext *cx = xdr->cx();
|
||||||
|
JSAtom *atom;
|
||||||
|
#if IS_LITTLE_ENDIAN
|
||||||
|
/* Directly access the little endian chars in the XDR buffer. */
|
||||||
|
const jschar *chars = reinterpret_cast<const jschar *>(xdr->buf.read(nchars * sizeof(jschar)));
|
||||||
|
atom = js_AtomizeChars(cx, chars, nchars);
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* We must copy chars to a temporary buffer to convert between little and
|
||||||
|
* big endian data.
|
||||||
|
*/
|
||||||
|
jschar *chars;
|
||||||
|
jschar stackChars[256];
|
||||||
|
if (nchars <= ArrayLength(stackChars)) {
|
||||||
|
chars = stackChars;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This is very uncommon. Don't use the tempLifoAlloc arena for this as
|
||||||
|
* most allocations here will be bigger than tempLifoAlloc's default
|
||||||
|
* chunk size.
|
||||||
|
*/
|
||||||
|
chars = static_cast<jschar *>(cx->runtime->malloc_(nchars * sizeof(jschar)));
|
||||||
|
if (!chars)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_ALWAYS_TRUE(xdr->codeChars(chars, nchars));
|
||||||
|
atom = js_AtomizeChars(cx, chars, nchars);
|
||||||
|
if (chars != stackChars)
|
||||||
|
Foreground::free_(chars);
|
||||||
|
#endif /* !IS_LITTLE_ENDIAN */
|
||||||
|
|
||||||
|
if (!atom)
|
||||||
|
return false;
|
||||||
|
*atomp = atom;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template bool
|
||||||
|
js::XDRAtom(XDRState<XDR_ENCODE> *xdr, JSAtom **atomp);
|
||||||
|
|
||||||
|
template bool
|
||||||
|
js::XDRAtom(XDRState<XDR_DECODE> *xdr, JSAtom **atomp);
|
||||||
|
|
||||||
|
@ -478,4 +478,12 @@ js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
|||||||
extern void
|
extern void
|
||||||
js_InitAtomMap(JSContext *cx, js::AtomIndexMap *indices, JSAtom **atoms);
|
js_InitAtomMap(JSContext *cx, js::AtomIndexMap *indices, JSAtom **atoms);
|
||||||
|
|
||||||
|
namespace js {
|
||||||
|
|
||||||
|
template<XDRMode mode>
|
||||||
|
bool
|
||||||
|
XDRAtom(XDRState<mode> *xdr, JSAtom **atomp);
|
||||||
|
|
||||||
|
} /* namespace js */
|
||||||
|
|
||||||
#endif /* jsatom_h___ */
|
#endif /* jsatom_h___ */
|
||||||
|
@ -521,8 +521,8 @@ IsObjectInContextCompartment(const JSObject *obj, const JSContext *cx);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: these flag bits are encoded into the bytecode stream in the immediate
|
* NB: these flag bits are encoded into the bytecode stream in the immediate
|
||||||
* operand of JSOP_ITER, so don't change them without advancing jsxdrapi.h's
|
* operand of JSOP_ITER, so don't change them without advancing vm/Xdr.h's
|
||||||
* JSXDR_BYTECODE_VERSION.
|
* XDR_BYTECODE_VERSION.
|
||||||
*/
|
*/
|
||||||
#define JSITER_ENUMERATE 0x1 /* for-in compatible hidden default iterator */
|
#define JSITER_ENUMERATE 0x1 /* for-in compatible hidden default iterator */
|
||||||
#define JSITER_FOREACH 0x2 /* return [key, value] pair rather than key */
|
#define JSITER_FOREACH 0x2 /* return [key, value] pair rather than key */
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
#include "jsatom.h"
|
#include "jsatom.h"
|
||||||
#include "jsbool.h"
|
#include "jsbool.h"
|
||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
#include "jsversion.h"
|
#include "jsexn.h"
|
||||||
#include "jsfun.h"
|
#include "jsfun.h"
|
||||||
#include "jsgc.h"
|
#include "jsgc.h"
|
||||||
#include "jsgcmark.h"
|
#include "jsgcmark.h"
|
||||||
@ -66,7 +66,6 @@
|
|||||||
#include "jsscope.h"
|
#include "jsscope.h"
|
||||||
#include "jsscript.h"
|
#include "jsscript.h"
|
||||||
#include "jsstr.h"
|
#include "jsstr.h"
|
||||||
#include "jsexn.h"
|
|
||||||
|
|
||||||
#include "frontend/BytecodeCompiler.h"
|
#include "frontend/BytecodeCompiler.h"
|
||||||
#include "frontend/BytecodeEmitter.h"
|
#include "frontend/BytecodeEmitter.h"
|
||||||
@ -74,15 +73,12 @@
|
|||||||
#include "vm/Debugger.h"
|
#include "vm/Debugger.h"
|
||||||
#include "vm/MethodGuard.h"
|
#include "vm/MethodGuard.h"
|
||||||
#include "vm/ScopeObject.h"
|
#include "vm/ScopeObject.h"
|
||||||
|
#include "vm/Xdr.h"
|
||||||
|
|
||||||
#if JS_HAS_GENERATORS
|
#if JS_HAS_GENERATORS
|
||||||
# include "jsiter.h"
|
# include "jsiter.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if JS_HAS_XDR
|
|
||||||
# include "jsxdrapi.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef JS_METHODJIT
|
#ifdef JS_METHODJIT
|
||||||
#include "methodjit/MethodJIT.h"
|
#include "methodjit/MethodJIT.h"
|
||||||
#endif
|
#endif
|
||||||
@ -480,13 +476,10 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JS_HAS_XDR
|
template<XDRMode mode>
|
||||||
|
bool
|
||||||
/* XXX store parent and proto, if defined */
|
js::XDRInterpretedFunction(XDRState<mode> *xdr, JSObject **objp, JSScript *parentScript)
|
||||||
JSBool
|
|
||||||
js::XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
|
|
||||||
{
|
{
|
||||||
JSContext *cx;
|
|
||||||
JSFunction *fun;
|
JSFunction *fun;
|
||||||
JSAtom *atom;
|
JSAtom *atom;
|
||||||
uint32_t firstword; /* flag telling whether fun->atom is non-null,
|
uint32_t firstword; /* flag telling whether fun->atom is non-null,
|
||||||
@ -494,9 +487,9 @@ js::XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
|
|||||||
and 14 bits reserved for future use */
|
and 14 bits reserved for future use */
|
||||||
uint32_t flagsword; /* word for argument count and fun->flags */
|
uint32_t flagsword; /* word for argument count and fun->flags */
|
||||||
|
|
||||||
cx = xdr->cx;
|
JSContext *cx = xdr->cx();
|
||||||
JSScript *script;
|
JSScript *script;
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
fun = (*objp)->toFunction();
|
fun = (*objp)->toFunction();
|
||||||
if (!fun->isInterpreted()) {
|
if (!fun->isInterpreted()) {
|
||||||
JSAutoByteString funNameBytes;
|
JSAutoByteString funNameBytes;
|
||||||
@ -523,17 +516,17 @@ js::XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
|
|||||||
script = NULL;
|
script = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_XDRUint32(xdr, &firstword))
|
if (!xdr->codeUint32(&firstword))
|
||||||
return false;
|
return false;
|
||||||
if ((firstword & 1U) && !js_XDRAtom(xdr, &atom))
|
if ((firstword & 1U) && !XDRAtom(xdr, &atom))
|
||||||
return false;
|
return false;
|
||||||
if (!JS_XDRUint32(xdr, &flagsword))
|
if (!xdr->codeUint32(&flagsword))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!XDRScript(xdr, &script))
|
if (!XDRScript(xdr, &script, parentScript))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
fun->nargs = flagsword >> 16;
|
fun->nargs = flagsword >> 16;
|
||||||
JS_ASSERT((flagsword & JSFUN_KINDMASK) >= JSFUN_INTERPRETED);
|
JS_ASSERT((flagsword & JSFUN_KINDMASK) >= JSFUN_INTERPRETED);
|
||||||
fun->flags = uint16_t(flagsword);
|
fun->flags = uint16_t(flagsword);
|
||||||
@ -549,7 +542,11 @@ js::XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* JS_HAS_XDR */
|
template bool
|
||||||
|
js::XDRInterpretedFunction(XDRState<XDR_ENCODE> *xdr, JSObject **objp, JSScript *parentScript);
|
||||||
|
|
||||||
|
template bool
|
||||||
|
js::XDRInterpretedFunction(XDRState<XDR_DECODE> *xdr, JSObject **objp, JSScript *parentScript);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [[HasInstance]] internal method for Function objects: fetch the .prototype
|
* [[HasInstance]] internal method for Function objects: fetch the .prototype
|
||||||
|
@ -356,8 +356,9 @@ js_IsNamedLambda(JSFunction *fun) { return (fun->flags & JSFUN_LAMBDA) && fun->a
|
|||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
extern JSBool
|
template<XDRMode mode>
|
||||||
XDRFunctionObject(JSXDRState *xdr, JSObject **objp);
|
bool
|
||||||
|
XDRInterpretedFunction(XDRState<mode> *xdr, JSObject **objp, JSScript *parentScript);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@
|
|||||||
#define JSDOUBLE_HI32_EXPSHIFT 20
|
#define JSDOUBLE_HI32_EXPSHIFT 20
|
||||||
#define JSDOUBLE_EXPBIAS 1023
|
#define JSDOUBLE_EXPBIAS 1023
|
||||||
|
|
||||||
typedef union jsdpun {
|
union jsdpun {
|
||||||
struct {
|
struct {
|
||||||
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
|
#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
|
||||||
uint32_t lo, hi;
|
uint32_t lo, hi;
|
||||||
@ -84,7 +84,7 @@ typedef union jsdpun {
|
|||||||
} s;
|
} s;
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
double d;
|
double d;
|
||||||
} jsdpun;
|
};
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
JSDOUBLE_IS_NaN(double d)
|
JSDOUBLE_IS_NaN(double d)
|
||||||
|
@ -76,13 +76,15 @@
|
|||||||
#include "json.h"
|
#include "json.h"
|
||||||
#include "jswatchpoint.h"
|
#include "jswatchpoint.h"
|
||||||
#include "jswrapper.h"
|
#include "jswrapper.h"
|
||||||
|
#include "jsxml.h"
|
||||||
|
|
||||||
#include "builtin/MapObject.h"
|
#include "builtin/MapObject.h"
|
||||||
#include "frontend/BytecodeCompiler.h"
|
#include "frontend/BytecodeCompiler.h"
|
||||||
#include "frontend/BytecodeEmitter.h"
|
#include "frontend/BytecodeEmitter.h"
|
||||||
#include "frontend/Parser.h"
|
#include "frontend/Parser.h"
|
||||||
#include "vm/StringBuffer.h"
|
|
||||||
#include "js/MemoryMetrics.h"
|
#include "js/MemoryMetrics.h"
|
||||||
|
#include "vm/StringBuffer.h"
|
||||||
|
#include "vm/Xdr.h"
|
||||||
|
|
||||||
#include "jsarrayinlines.h"
|
#include "jsarrayinlines.h"
|
||||||
#include "jsatominlines.h"
|
#include "jsatominlines.h"
|
||||||
@ -93,14 +95,6 @@
|
|||||||
|
|
||||||
#include "vm/MethodGuard-inl.h"
|
#include "vm/MethodGuard-inl.h"
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
|
||||||
#include "jsxml.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if JS_HAS_XDR
|
|
||||||
#include "jsxdrapi.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "jsautooplen.h"
|
#include "jsautooplen.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
@ -316,6 +316,14 @@ typedef Handle<JSAtom*> HandleAtom;
|
|||||||
typedef Handle<jsid> HandleId;
|
typedef Handle<jsid> HandleId;
|
||||||
typedef Handle<Value> HandleValue;
|
typedef Handle<Value> HandleValue;
|
||||||
|
|
||||||
|
enum XDRMode {
|
||||||
|
XDR_ENCODE,
|
||||||
|
XDR_DECODE
|
||||||
|
};
|
||||||
|
|
||||||
|
template <XDRMode mode>
|
||||||
|
class XDRState;
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
namespace JSC {
|
namespace JSC {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
*
|
*
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
@ -226,7 +226,6 @@ typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
|
|||||||
typedef struct JSStructuredCloneReader JSStructuredCloneReader;
|
typedef struct JSStructuredCloneReader JSStructuredCloneReader;
|
||||||
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
|
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
|
||||||
typedef struct JSTracer JSTracer;
|
typedef struct JSTracer JSTracer;
|
||||||
typedef struct JSXDRState JSXDRState;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
class JSFlatString;
|
class JSFlatString;
|
||||||
@ -234,7 +233,7 @@ class JSString;
|
|||||||
#else
|
#else
|
||||||
typedef struct JSFlatString JSFlatString;
|
typedef struct JSFlatString JSFlatString;
|
||||||
typedef struct JSString JSString;
|
typedef struct JSString JSString;
|
||||||
#endif
|
#endif /* !__cplusplus */
|
||||||
|
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
typedef struct PRCallOnceType JSCallOnceType;
|
typedef struct PRCallOnceType JSCallOnceType;
|
||||||
|
@ -62,9 +62,6 @@
|
|||||||
#include "jsopcode.h"
|
#include "jsopcode.h"
|
||||||
#include "jsscope.h"
|
#include "jsscope.h"
|
||||||
#include "jsscript.h"
|
#include "jsscript.h"
|
||||||
#if JS_HAS_XDR
|
|
||||||
#include "jsxdrapi.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "frontend/BytecodeEmitter.h"
|
#include "frontend/BytecodeEmitter.h"
|
||||||
#include "frontend/Parser.h"
|
#include "frontend/Parser.h"
|
||||||
@ -72,6 +69,7 @@
|
|||||||
#include "methodjit/MethodJIT.h"
|
#include "methodjit/MethodJIT.h"
|
||||||
#include "methodjit/Retcon.h"
|
#include "methodjit/Retcon.h"
|
||||||
#include "vm/Debugger.h"
|
#include "vm/Debugger.h"
|
||||||
|
#include "vm/Xdr.h"
|
||||||
|
|
||||||
#include "jsinferinlines.h"
|
#include "jsinferinlines.h"
|
||||||
#include "jsinterpinlines.h"
|
#include "jsinterpinlines.h"
|
||||||
@ -296,10 +294,11 @@ Bindings::trace(JSTracer *trc)
|
|||||||
MarkShape(trc, &lastBinding, "shape");
|
MarkShape(trc, &lastBinding, "shape");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JS_HAS_XDR
|
} /* namespace js */
|
||||||
|
|
||||||
|
template<XDRMode mode>
|
||||||
static bool
|
static bool
|
||||||
XDRScriptConst(JSXDRState *xdr, HeapValue *vp)
|
XDRScriptConst(XDRState<mode> *xdr, HeapValue *vp)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* A script constant can be an arbitrary primitive value as they are used
|
* A script constant can be an arbitrary primitive value as they are used
|
||||||
@ -317,7 +316,7 @@ XDRScriptConst(JSXDRState *xdr, HeapValue *vp)
|
|||||||
};
|
};
|
||||||
|
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
if (vp->isInt32()) {
|
if (vp->isInt32()) {
|
||||||
tag = SCRIPT_INT;
|
tag = SCRIPT_INT;
|
||||||
} else if (vp->isDouble()) {
|
} else if (vp->isDouble()) {
|
||||||
@ -336,54 +335,54 @@ XDRScriptConst(JSXDRState *xdr, HeapValue *vp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_XDRUint32(xdr, &tag))
|
if (!xdr->codeUint32(&tag))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case SCRIPT_INT: {
|
case SCRIPT_INT: {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
if (mode == XDR_ENCODE)
|
||||||
i = uint32_t(vp->toInt32());
|
i = uint32_t(vp->toInt32());
|
||||||
if (!JS_XDRUint32(xdr, &i))
|
if (!xdr->codeUint32(&i))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
if (mode == XDR_DECODE)
|
||||||
vp->init(Int32Value(int32_t(i)));
|
vp->init(Int32Value(int32_t(i)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCRIPT_DOUBLE: {
|
case SCRIPT_DOUBLE: {
|
||||||
double d;
|
double d;
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
if (mode == XDR_ENCODE)
|
||||||
d = vp->toDouble();
|
d = vp->toDouble();
|
||||||
if (!JS_XDRDouble(xdr, &d))
|
if (!xdr->codeDouble(&d))
|
||||||
return false;
|
return false;
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
if (mode == XDR_DECODE)
|
||||||
vp->init(DoubleValue(d));
|
vp->init(DoubleValue(d));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCRIPT_STRING: {
|
case SCRIPT_STRING: {
|
||||||
JSString *str;
|
JSString *str;
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
if (mode == XDR_ENCODE)
|
||||||
str = vp->toString();
|
str = vp->toString();
|
||||||
if (!JS_XDRString(xdr, &str))
|
if (!xdr->codeString(&str))
|
||||||
return false;
|
return false;
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
if (mode == XDR_DECODE)
|
||||||
vp->init(StringValue(str));
|
vp->init(StringValue(str));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCRIPT_TRUE:
|
case SCRIPT_TRUE:
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
if (mode == XDR_DECODE)
|
||||||
vp->init(BooleanValue(true));
|
vp->init(BooleanValue(true));
|
||||||
break;
|
break;
|
||||||
case SCRIPT_FALSE:
|
case SCRIPT_FALSE:
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
if (mode == XDR_DECODE)
|
||||||
vp->init(BooleanValue(false));
|
vp->init(BooleanValue(false));
|
||||||
break;
|
break;
|
||||||
case SCRIPT_NULL:
|
case SCRIPT_NULL:
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
if (mode == XDR_DECODE)
|
||||||
vp->init(NullValue());
|
vp->init(NullValue());
|
||||||
break;
|
break;
|
||||||
case SCRIPT_VOID:
|
case SCRIPT_VOID:
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
if (mode == XDR_DECODE)
|
||||||
vp->init(UndefinedValue());
|
vp->init(UndefinedValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -393,8 +392,9 @@ XDRScriptConst(JSXDRState *xdr, HeapValue *vp)
|
|||||||
static const char *
|
static const char *
|
||||||
SaveScriptFilename(JSContext *cx, const char *filename);
|
SaveScriptFilename(JSContext *cx, const char *filename);
|
||||||
|
|
||||||
JSBool
|
template<XDRMode mode>
|
||||||
XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
bool
|
||||||
|
js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
|
||||||
{
|
{
|
||||||
enum ScriptBits {
|
enum ScriptBits {
|
||||||
NoScriptRval,
|
NoScriptRval,
|
||||||
@ -404,7 +404,7 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
MayNeedArgsObj,
|
MayNeedArgsObj,
|
||||||
NeedsArgsObj,
|
NeedsArgsObj,
|
||||||
OwnFilename,
|
OwnFilename,
|
||||||
SharedFilename
|
ParentFilename
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t length, lineno, nslots;
|
uint32_t length, lineno, nslots;
|
||||||
@ -414,7 +414,7 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
uint32_t nTypeSets = 0;
|
uint32_t nTypeSets = 0;
|
||||||
uint32_t scriptBits = 0;
|
uint32_t scriptBits = 0;
|
||||||
|
|
||||||
JSContext *cx = xdr->cx;
|
JSContext *cx = xdr->cx();
|
||||||
JSScript *script;
|
JSScript *script;
|
||||||
nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = 0;
|
nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = 0;
|
||||||
jssrcnote *notes = NULL;
|
jssrcnote *notes = NULL;
|
||||||
@ -426,9 +426,10 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
nargs = nvars = Bindings::BINDING_COUNT_LIMIT;
|
nargs = nvars = Bindings::BINDING_COUNT_LIMIT;
|
||||||
#endif
|
#endif
|
||||||
uint32_t argsVars;
|
uint32_t argsVars;
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
script = *scriptp;
|
script = *scriptp;
|
||||||
|
JS_ASSERT_IF(parentScript, parentScript->compartment() == script->compartment());
|
||||||
|
|
||||||
/* Should not XDR scripts optimized for a single global object. */
|
/* Should not XDR scripts optimized for a single global object. */
|
||||||
JS_ASSERT(!JSScript::isValidOffset(script->globalsOffset));
|
JS_ASSERT(!JSScript::isValidOffset(script->globalsOffset));
|
||||||
|
|
||||||
@ -436,9 +437,9 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
nvars = script->bindings.countVars();
|
nvars = script->bindings.countVars();
|
||||||
argsVars = (nargs << 16) | nvars;
|
argsVars = (nargs << 16) | nvars;
|
||||||
}
|
}
|
||||||
if (!JS_XDRUint32(xdr, &argsVars))
|
if (!xdr->codeUint32(&argsVars))
|
||||||
return false;
|
return false;
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
nargs = argsVars >> 16;
|
nargs = argsVars >> 16;
|
||||||
nvars = argsVars & 0xFFFF;
|
nvars = argsVars & 0xFFFF;
|
||||||
}
|
}
|
||||||
@ -466,7 +467,7 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector<JSAtom *> names(cx);
|
Vector<JSAtom *> names(cx);
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
if (!script->bindings.getLocalNameArray(cx, &names))
|
if (!script->bindings.getLocalNameArray(cx, &names))
|
||||||
return false;
|
return false;
|
||||||
PodZero(bitmap, bitmapLength);
|
PodZero(bitmap, bitmapLength);
|
||||||
@ -476,7 +477,7 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < bitmapLength; ++i) {
|
for (unsigned i = 0; i < bitmapLength; ++i) {
|
||||||
if (!JS_XDRUint32(xdr, &bitmap[i]))
|
if (!xdr->codeUint32(&bitmap[i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,7 +485,7 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
if (i < nargs &&
|
if (i < nargs &&
|
||||||
!(bitmap[i >> JS_BITS_PER_UINT32_LOG2] & JS_BIT(i & (JS_BITS_PER_UINT32 - 1))))
|
!(bitmap[i >> JS_BITS_PER_UINT32_LOG2] & JS_BIT(i & (JS_BITS_PER_UINT32 - 1))))
|
||||||
{
|
{
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
uint16_t dummy;
|
uint16_t dummy;
|
||||||
if (!bindings.addDestructuring(cx, &dummy))
|
if (!bindings.addDestructuring(cx, &dummy))
|
||||||
return false;
|
return false;
|
||||||
@ -495,11 +496,11 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSAtom *name;
|
JSAtom *name;
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
if (mode == XDR_ENCODE)
|
||||||
name = names[i];
|
name = names[i];
|
||||||
if (!js_XDRAtom(xdr, &name))
|
if (!XDRAtom(xdr, &name))
|
||||||
return false;
|
return false;
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
BindingKind kind = (i < nargs)
|
BindingKind kind = (i < nargs)
|
||||||
? ARGUMENT
|
? ARGUMENT
|
||||||
: (bitmap[i >> JS_BITS_PER_UINT32_LOG2] &
|
: (bitmap[i >> JS_BITS_PER_UINT32_LOG2] &
|
||||||
@ -512,18 +513,18 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
if (!bindings.ensureShape(cx))
|
if (!bindings.ensureShape(cx))
|
||||||
return false;
|
return false;
|
||||||
bindings.makeImmutable();
|
bindings.makeImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
if (mode == XDR_ENCODE)
|
||||||
length = script->length;
|
length = script->length;
|
||||||
if (!JS_XDRUint32(xdr, &length))
|
if (!xdr->codeUint32(&length))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
prologLength = script->mainOffset;
|
prologLength = script->mainOffset;
|
||||||
JS_ASSERT(script->getVersion() != JSVERSION_UNKNOWN);
|
JS_ASSERT(script->getVersion() != JSVERSION_UNKNOWN);
|
||||||
version = (uint32_t)script->getVersion() | (script->nfixed << 16);
|
version = (uint32_t)script->getVersion() | (script->nfixed << 16);
|
||||||
@ -569,44 +570,44 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
scriptBits |= (1 << NeedsArgsObj);
|
scriptBits |= (1 << NeedsArgsObj);
|
||||||
}
|
}
|
||||||
if (script->filename) {
|
if (script->filename) {
|
||||||
scriptBits |= (script->filename != xdr->sharedFilename)
|
scriptBits |= (parentScript && parentScript->filename == script->filename)
|
||||||
? (1 << OwnFilename)
|
? (1 << ParentFilename)
|
||||||
: (1 << SharedFilename);
|
: (1 << OwnFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ASSERT(!script->compileAndGo);
|
JS_ASSERT(!script->compileAndGo);
|
||||||
JS_ASSERT(!script->hasSingletons);
|
JS_ASSERT(!script->hasSingletons);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_XDRUint32(xdr, &prologLength))
|
if (!xdr->codeUint32(&prologLength))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!JS_XDRUint32(xdr, &version))
|
if (!xdr->codeUint32(&version))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To fuse allocations, we need srcnote, atom, objects, regexp, and trynote
|
* To fuse allocations, we need srcnote, atom, objects, regexp, and trynote
|
||||||
* counts early.
|
* counts early.
|
||||||
*/
|
*/
|
||||||
if (!JS_XDRUint32(xdr, &natoms))
|
if (!xdr->codeUint32(&natoms))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!JS_XDRUint32(xdr, &nsrcnotes))
|
if (!xdr->codeUint32(&nsrcnotes))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!JS_XDRUint32(xdr, &ntrynotes))
|
if (!xdr->codeUint32(&ntrynotes))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!JS_XDRUint32(xdr, &nobjects))
|
if (!xdr->codeUint32(&nobjects))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!JS_XDRUint32(xdr, &nregexps))
|
if (!xdr->codeUint32(&nregexps))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!JS_XDRUint32(xdr, &nconsts))
|
if (!xdr->codeUint32(&nconsts))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!JS_XDRUint32(xdr, &encodedClosedCount))
|
if (!xdr->codeUint32(&encodedClosedCount))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!JS_XDRUint32(xdr, &nTypeSets))
|
if (!xdr->codeUint32(&nTypeSets))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (!JS_XDRUint32(xdr, &scriptBits))
|
if (!xdr->codeUint32(&scriptBits))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
nClosedArgs = encodedClosedCount >> 16;
|
nClosedArgs = encodedClosedCount >> 16;
|
||||||
nClosedVars = encodedClosedCount & 0xFFFF;
|
nClosedVars = encodedClosedCount & 0xFFFF;
|
||||||
|
|
||||||
@ -637,7 +638,7 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
if (scriptBits & (1 << UsesEval))
|
if (scriptBits & (1 << UsesEval))
|
||||||
script->usesEval = true;
|
script->usesEval = true;
|
||||||
if (scriptBits & (1 << MayNeedArgsObj)) {
|
if (scriptBits & (1 << MayNeedArgsObj)) {
|
||||||
script->mayNeedArgsObj_ = true;
|
script->setMayNeedArgsObj();
|
||||||
if (scriptBits & (1 << NeedsArgsObj))
|
if (scriptBits & (1 << NeedsArgsObj))
|
||||||
script->setNeedsArgsObj(true);
|
script->setNeedsArgsObj(true);
|
||||||
} else {
|
} else {
|
||||||
@ -645,56 +646,41 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_XDRBytes(xdr, (char *)script->code, length * sizeof(jsbytecode)))
|
JS_STATIC_ASSERT(sizeof(jsbytecode) == 1);
|
||||||
return false;
|
JS_STATIC_ASSERT(sizeof(jssrcnote) == 1);
|
||||||
|
if (!xdr->codeBytes(script->code, length) ||
|
||||||
if (!JS_XDRBytes(xdr, (char *)notes, nsrcnotes * sizeof(jssrcnote)) ||
|
!xdr->codeBytes(notes, nsrcnotes) ||
|
||||||
!JS_XDRUint32(xdr, &lineno) ||
|
!xdr->codeUint32(&lineno) ||
|
||||||
!JS_XDRUint32(xdr, &nslots)) {
|
!xdr->codeUint32(&nslots)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scriptBits & (1 << OwnFilename)) {
|
if (scriptBits & (1 << OwnFilename)) {
|
||||||
char *filename;
|
const char *filename;
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
if (mode == XDR_ENCODE)
|
||||||
filename = const_cast<char *>(script->filename);
|
filename = script->filename;
|
||||||
if (!JS_XDRCString(xdr, &filename))
|
if (!xdr->codeCString(&filename))
|
||||||
return false;
|
return false;
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
script->filename = SaveScriptFilename(xdr->cx, filename);
|
script->filename = SaveScriptFilename(cx, filename);
|
||||||
Foreground::free_(filename);
|
|
||||||
if (!script->filename)
|
if (!script->filename)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!xdr->sharedFilename)
|
} else if (scriptBits & (1 << ParentFilename)) {
|
||||||
xdr->sharedFilename = script->filename;
|
JS_ASSERT(parentScript);
|
||||||
} else if (scriptBits & (1 << SharedFilename)) {
|
if (mode == XDR_DECODE)
|
||||||
JS_ASSERT(xdr->sharedFilename);
|
script->filename = parentScript->filename;
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
|
||||||
script->filename = xdr->sharedFilename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
script->lineno = lineno;
|
script->lineno = lineno;
|
||||||
script->nslots = uint16_t(nslots);
|
script->nslots = uint16_t(nslots);
|
||||||
script->staticLevel = uint16_t(nslots >> 16);
|
script->staticLevel = uint16_t(nslots >> 16);
|
||||||
|
xdr->initScriptPrincipals(script);
|
||||||
/* The origin principals must be normalized at this point. */
|
|
||||||
JS_ASSERT_IF(xdr->principals, xdr->originPrincipals);
|
|
||||||
JS_ASSERT(!script->principals);
|
|
||||||
JS_ASSERT(!script->originPrincipals);
|
|
||||||
if (xdr->principals) {
|
|
||||||
script->principals = xdr->principals;
|
|
||||||
JS_HoldPrincipals(xdr->principals);
|
|
||||||
}
|
|
||||||
if (xdr->originPrincipals) {
|
|
||||||
script->originPrincipals = xdr->originPrincipals;
|
|
||||||
JS_HoldPrincipals(xdr->originPrincipals);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i != natoms; ++i) {
|
for (i = 0; i != natoms; ++i) {
|
||||||
if (!js_XDRAtom(xdr, &script->atoms[i]))
|
if (!XDRAtom(xdr, &script->atoms[i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,16 +693,16 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
for (i = 0; i != nobjects; ++i) {
|
for (i = 0; i != nobjects; ++i) {
|
||||||
HeapPtr<JSObject> *objp = &script->objects()->vector[i];
|
HeapPtr<JSObject> *objp = &script->objects()->vector[i];
|
||||||
uint32_t isBlock;
|
uint32_t isBlock;
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
JSObject *obj = *objp;
|
JSObject *obj = *objp;
|
||||||
JS_ASSERT(obj->isFunction() || obj->isStaticBlock());
|
JS_ASSERT(obj->isFunction() || obj->isStaticBlock());
|
||||||
isBlock = obj->isBlock() ? 1 : 0;
|
isBlock = obj->isBlock() ? 1 : 0;
|
||||||
}
|
}
|
||||||
if (!JS_XDRUint32(xdr, &isBlock))
|
if (!xdr->codeUint32(&isBlock))
|
||||||
return false;
|
return false;
|
||||||
if (isBlock == 0) {
|
if (isBlock == 0) {
|
||||||
JSObject *tmp = *objp;
|
JSObject *tmp = *objp;
|
||||||
if (!XDRFunctionObject(xdr, &tmp))
|
if (!XDRInterpretedFunction(xdr, &tmp, parentScript))
|
||||||
return false;
|
return false;
|
||||||
*objp = tmp;
|
*objp = tmp;
|
||||||
} else {
|
} else {
|
||||||
@ -732,11 +718,11 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (i = 0; i != nClosedArgs; ++i) {
|
for (i = 0; i != nClosedArgs; ++i) {
|
||||||
if (!JS_XDRUint32(xdr, &script->closedSlots[i]))
|
if (!xdr->codeUint32(&script->closedSlots[i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (i = 0; i != nClosedVars; ++i) {
|
for (i = 0; i != nClosedVars; ++i) {
|
||||||
if (!JS_XDRUint32(xdr, &script->closedSlots[nClosedArgs + i]))
|
if (!xdr->codeUint32(&script->closedSlots[nClosedArgs + i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,16 +741,16 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
tn = tnfirst + ntrynotes;
|
tn = tnfirst + ntrynotes;
|
||||||
do {
|
do {
|
||||||
--tn;
|
--tn;
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
kindAndDepth = (uint32_t(tn->kind) << 16)
|
kindAndDepth = (uint32_t(tn->kind) << 16)
|
||||||
| uint32_t(tn->stackDepth);
|
| uint32_t(tn->stackDepth);
|
||||||
}
|
}
|
||||||
if (!JS_XDRUint32(xdr, &kindAndDepth) ||
|
if (!xdr->codeUint32(&kindAndDepth) ||
|
||||||
!JS_XDRUint32(xdr, &tn->start) ||
|
!xdr->codeUint32(&tn->start) ||
|
||||||
!JS_XDRUint32(xdr, &tn->length)) {
|
!xdr->codeUint32(&tn->length)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
tn->kind = uint8_t(kindAndDepth >> 16);
|
tn->kind = uint8_t(kindAndDepth >> 16);
|
||||||
tn->stackDepth = uint16_t(kindAndDepth);
|
tn->stackDepth = uint16_t(kindAndDepth);
|
||||||
}
|
}
|
||||||
@ -779,7 +765,7 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
if (cx->hasRunOption(JSOPTION_PCCOUNT))
|
if (cx->hasRunOption(JSOPTION_PCCOUNT))
|
||||||
(void) script->initCounts(cx);
|
(void) script->initCounts(cx);
|
||||||
*scriptp = script;
|
*scriptp = script;
|
||||||
@ -788,9 +774,11 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* JS_HAS_XDR */
|
template bool
|
||||||
|
js::XDRScript(XDRState<XDR_ENCODE> *xdr, JSScript **scriptp, JSScript *parentScript);
|
||||||
|
|
||||||
} /* namespace js */
|
template bool
|
||||||
|
js::XDRScript(XDRState<XDR_DECODE> *xdr, JSScript **scriptp, JSScript *parentScript);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSScript::initCounts(JSContext *cx)
|
JSScript::initCounts(JSContext *cx)
|
||||||
@ -844,8 +832,6 @@ JSScript::destroyCounts(JSContext *cx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace js {
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shared script filename management.
|
* Shared script filename management.
|
||||||
*/
|
*/
|
||||||
@ -924,8 +910,6 @@ FreeScriptFilenames(JSCompartment *comp)
|
|||||||
table.clear();
|
table.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace js */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JSScript data structures memory alignment:
|
* JSScript data structures memory alignment:
|
||||||
*
|
*
|
||||||
@ -1240,7 +1224,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
|||||||
if (bce->inFunction()) {
|
if (bce->inFunction()) {
|
||||||
bool needsArgsObj = bce->mayOverwriteArguments() || bce->needsEagerArguments();
|
bool needsArgsObj = bce->mayOverwriteArguments() || bce->needsEagerArguments();
|
||||||
if (needsArgsObj || bce->usesArguments()) {
|
if (needsArgsObj || bce->usesArguments()) {
|
||||||
script->mayNeedArgsObj_ = true;
|
script->setMayNeedArgsObj();
|
||||||
if (needsArgsObj)
|
if (needsArgsObj)
|
||||||
script->setNeedsArgsObj(true);
|
script->setNeedsArgsObj(true);
|
||||||
}
|
}
|
||||||
@ -1626,74 +1610,32 @@ CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, unsigned *line
|
|||||||
*origin = script->originPrincipals;
|
*origin = script->originPrincipals;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AutoJSXDRState {
|
} /* namespace js */
|
||||||
public:
|
|
||||||
AutoJSXDRState(JSXDRState *x
|
|
||||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
|
||||||
: xdr(x)
|
|
||||||
{
|
|
||||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
|
||||||
}
|
|
||||||
~AutoJSXDRState()
|
|
||||||
{
|
|
||||||
JS_XDRDestroy(xdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator JSXDRState*() const
|
|
||||||
{
|
|
||||||
return xdr;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSXDRState* operator->() const
|
|
||||||
{
|
|
||||||
return xdr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
JSXDRState *const xdr;
|
|
||||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
|
||||||
};
|
|
||||||
|
|
||||||
JSScript *
|
JSScript *
|
||||||
CloneScript(JSContext *cx, JSScript *script)
|
js::CloneScript(JSContext *cx, JSScript *script)
|
||||||
{
|
{
|
||||||
JS_ASSERT(cx->compartment != script->compartment());
|
JS_ASSERT(cx->compartment != script->compartment());
|
||||||
|
|
||||||
/* Serialize script. */
|
/* Serialize script. */
|
||||||
AutoJSXDRState w(JS_XDRNewMem(cx, JSXDR_ENCODE));
|
XDREncoder encoder(cx);
|
||||||
if (!w)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!XDRScript(w, &script))
|
if (!XDRScript(&encoder, &script, NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
uint32_t nbytes;
|
uint32_t nbytes;
|
||||||
void *p = JS_XDRMemGetData(w, &nbytes);
|
const void *p = encoder.getData(&nbytes);
|
||||||
if (!p)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* De-serialize script. */
|
/* De-serialize script. */
|
||||||
AutoJSXDRState r(JS_XDRNewMem(cx, JSXDR_DECODE));
|
XDRDecoder decoder(cx, p, nbytes, cx->compartment->principals, script->originPrincipals);
|
||||||
if (!r)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/*
|
JSScript *newScript;
|
||||||
* Hand p off from w to r. Don't want them to share the data mem, lest
|
if (!XDRScript(&decoder, &newScript, NULL))
|
||||||
* they both try to free it in JS_XDRDestroy.
|
|
||||||
*/
|
|
||||||
JS_XDRMemSetData(r, p, nbytes);
|
|
||||||
JS_XDRMemSetData(w, NULL, 0);
|
|
||||||
|
|
||||||
JS_XDRSetPrincipals(r, cx->compartment->principals, script->originPrincipals);
|
|
||||||
JSScript *newScript = NULL;
|
|
||||||
if (!XDRScript(r, &newScript))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return newScript;
|
return newScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace js */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
JSScript::copyClosedSlotsTo(JSScript *other)
|
JSScript::copyClosedSlotsTo(JSScript *other)
|
||||||
{
|
{
|
||||||
|
@ -323,14 +323,6 @@ class DebugScript
|
|||||||
BreakpointSite *breakpoints[1];
|
BreakpointSite *breakpoints[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* NB: after a successful JSXDR_DECODE, js_XDRScript callers must do any
|
|
||||||
* required subsequent set-up of owning function or script object and then call
|
|
||||||
* js_CallNewScriptHook.
|
|
||||||
*/
|
|
||||||
extern JSBool
|
|
||||||
XDRScript(JSXDRState *xdr, JSScript **scriptp);
|
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
static const uint32_t JS_SCRIPT_COOKIE = 0xc00cee;
|
static const uint32_t JS_SCRIPT_COOKIE = 0xc00cee;
|
||||||
@ -356,8 +348,6 @@ struct JSScript : public js::gc::Cell
|
|||||||
|
|
||||||
static JSScript *NewScriptFromEmitter(JSContext *cx, js::BytecodeEmitter *bce);
|
static JSScript *NewScriptFromEmitter(JSContext *cx, js::BytecodeEmitter *bce);
|
||||||
|
|
||||||
friend JSBool js::XDRScript(JSXDRState *, JSScript **);
|
|
||||||
|
|
||||||
#ifdef JS_CRASH_DIAGNOSTICS
|
#ifdef JS_CRASH_DIAGNOSTICS
|
||||||
/*
|
/*
|
||||||
* Make sure that the cookie size does not affect the GC alignment
|
* Make sure that the cookie size does not affect the GC alignment
|
||||||
@ -445,6 +435,10 @@ struct JSScript : public js::gc::Cell
|
|||||||
void setNeedsArgsObj(bool needsArgsObj);
|
void setNeedsArgsObj(bool needsArgsObj);
|
||||||
bool applySpeculationFailed(JSContext *cx);
|
bool applySpeculationFailed(JSContext *cx);
|
||||||
|
|
||||||
|
void setMayNeedArgsObj() {
|
||||||
|
mayNeedArgsObj_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t natoms; /* length of atoms array */
|
uint32_t natoms; /* length of atoms array */
|
||||||
uint16_t nslots; /* vars plus maximum stack depth */
|
uint16_t nslots; /* vars plus maximum stack depth */
|
||||||
uint16_t staticLevel;/* static level for display maintenance */
|
uint16_t staticLevel;/* static level for display maintenance */
|
||||||
@ -890,6 +884,15 @@ CurrentScriptFileLineOrigin(JSContext *cx, unsigned *linenop, LineOption = NOT_C
|
|||||||
extern JSScript *
|
extern JSScript *
|
||||||
CloneScript(JSContext *cx, JSScript *script);
|
CloneScript(JSContext *cx, JSScript *script);
|
||||||
|
|
||||||
}
|
/*
|
||||||
|
* NB: after a successful XDR_DECODE, XDRScript callers must do any required
|
||||||
|
* subsequent set-up of owning function or script object and then call
|
||||||
|
* js_CallNewScriptHook.
|
||||||
|
*/
|
||||||
|
template<XDRMode mode>
|
||||||
|
bool
|
||||||
|
XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript);
|
||||||
|
|
||||||
|
} /* namespace js */
|
||||||
|
|
||||||
#endif /* jsscript_h___ */
|
#endif /* jsscript_h___ */
|
||||||
|
@ -85,7 +85,6 @@
|
|||||||
#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */
|
#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */
|
||||||
#endif
|
#endif
|
||||||
#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */
|
#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */
|
||||||
#define JS_HAS_XDR 0 /* has XDR API and internal support */
|
|
||||||
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
|
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
|
||||||
#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
|
#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
|
||||||
#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */
|
#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */
|
||||||
@ -108,7 +107,6 @@
|
|||||||
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
||||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||||
#define JS_HAS_XDR 1 /* has XDR API and internal support */
|
|
||||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||||
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
||||||
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
||||||
@ -127,7 +125,6 @@
|
|||||||
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
||||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||||
#define JS_HAS_XDR 1 /* has XDR API and internal support */
|
|
||||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||||
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
||||||
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
||||||
@ -146,7 +143,6 @@
|
|||||||
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
||||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||||
#define JS_HAS_XDR 1 /* has XDR API and internal support */
|
|
||||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||||
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
||||||
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
||||||
@ -165,7 +161,6 @@
|
|||||||
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
||||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||||
#define JS_HAS_XDR 1 /* has XDR API and internal support */
|
|
||||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||||
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
||||||
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
||||||
|
@ -1,589 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
||||||
*
|
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is Mozilla Communicator client code, released
|
|
||||||
* March 31, 1998.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* Netscape Communications Corporation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
||||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#include "mozilla/Util.h"
|
|
||||||
|
|
||||||
#include "jsversion.h"
|
|
||||||
|
|
||||||
#if JS_HAS_XDR
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "jstypes.h"
|
|
||||||
#include "jsutil.h"
|
|
||||||
#include "jsdhash.h"
|
|
||||||
#include "jsprf.h"
|
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jscntxt.h"
|
|
||||||
#include "jsnum.h"
|
|
||||||
#include "jsscript.h" /* js_XDRScript */
|
|
||||||
#include "jsstr.h"
|
|
||||||
#include "jsxdrapi.h"
|
|
||||||
#include "vm/Debugger.h"
|
|
||||||
|
|
||||||
#include "jsobjinlines.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace js;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define DBG(x) x
|
|
||||||
#else
|
|
||||||
#define DBG(x) ((void)0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct JSXDRMemState {
|
|
||||||
JSXDRState state;
|
|
||||||
char *base;
|
|
||||||
uint32_t count;
|
|
||||||
uint32_t limit;
|
|
||||||
} JSXDRMemState;
|
|
||||||
|
|
||||||
#define MEM_BLOCK 8192
|
|
||||||
#define MEM_PRIV(xdr) ((JSXDRMemState *)(xdr))
|
|
||||||
|
|
||||||
#define MEM_BASE(xdr) (MEM_PRIV(xdr)->base)
|
|
||||||
#define MEM_COUNT(xdr) (MEM_PRIV(xdr)->count)
|
|
||||||
#define MEM_LIMIT(xdr) (MEM_PRIV(xdr)->limit)
|
|
||||||
|
|
||||||
#define MEM_LEFT(xdr, bytes) \
|
|
||||||
JS_BEGIN_MACRO \
|
|
||||||
if ((xdr)->mode == JSXDR_DECODE && \
|
|
||||||
MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
|
|
||||||
JS_ReportErrorNumber((xdr)->cx, js_GetErrorMessage, NULL, \
|
|
||||||
JSMSG_END_OF_DATA); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
JS_END_MACRO
|
|
||||||
|
|
||||||
#define MEM_NEED(xdr, bytes) \
|
|
||||||
JS_BEGIN_MACRO \
|
|
||||||
if ((xdr)->mode == JSXDR_ENCODE) { \
|
|
||||||
if (MEM_LIMIT(xdr) && \
|
|
||||||
MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
|
|
||||||
uint32_t limit_ = JS_ROUNDUP(MEM_COUNT(xdr) + bytes, MEM_BLOCK);\
|
|
||||||
void *data_ = (xdr)->cx->realloc_(MEM_BASE(xdr), limit_); \
|
|
||||||
if (!data_) \
|
|
||||||
return 0; \
|
|
||||||
MEM_BASE(xdr) = (char *) data_; \
|
|
||||||
MEM_LIMIT(xdr) = limit_; \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
MEM_LEFT(xdr, bytes); \
|
|
||||||
} \
|
|
||||||
JS_END_MACRO
|
|
||||||
|
|
||||||
#define MEM_DATA(xdr) ((void *)(MEM_BASE(xdr) + MEM_COUNT(xdr)))
|
|
||||||
#define MEM_INCR(xdr,bytes) (MEM_COUNT(xdr) += (bytes))
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
mem_get32(JSXDRState *xdr, uint32_t *lp)
|
|
||||||
{
|
|
||||||
MEM_LEFT(xdr, 4);
|
|
||||||
*lp = *(uint32_t *)MEM_DATA(xdr);
|
|
||||||
MEM_INCR(xdr, 4);
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
mem_set32(JSXDRState *xdr, uint32_t *lp)
|
|
||||||
{
|
|
||||||
MEM_NEED(xdr, 4);
|
|
||||||
*(uint32_t *)MEM_DATA(xdr) = *lp;
|
|
||||||
MEM_INCR(xdr, 4);
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
mem_getbytes(JSXDRState *xdr, char *bytes, uint32_t len)
|
|
||||||
{
|
|
||||||
MEM_LEFT(xdr, len);
|
|
||||||
js_memcpy(bytes, MEM_DATA(xdr), len);
|
|
||||||
MEM_INCR(xdr, len);
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
mem_setbytes(JSXDRState *xdr, char *bytes, uint32_t len)
|
|
||||||
{
|
|
||||||
MEM_NEED(xdr, len);
|
|
||||||
js_memcpy(MEM_DATA(xdr), bytes, len);
|
|
||||||
MEM_INCR(xdr, len);
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
mem_raw(JSXDRState *xdr, uint32_t len)
|
|
||||||
{
|
|
||||||
void *data;
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
|
||||||
MEM_NEED(xdr, len);
|
|
||||||
} else if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
MEM_LEFT(xdr, len);
|
|
||||||
}
|
|
||||||
data = MEM_DATA(xdr);
|
|
||||||
MEM_INCR(xdr, len);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
mem_seek(JSXDRState *xdr, int32_t offset, JSXDRWhence whence)
|
|
||||||
{
|
|
||||||
switch (whence) {
|
|
||||||
case JSXDR_SEEK_CUR:
|
|
||||||
if ((int32_t)MEM_COUNT(xdr) + offset < 0) {
|
|
||||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
|
||||||
JSMSG_SEEK_BEYOND_START);
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
if (offset > 0)
|
|
||||||
MEM_NEED(xdr, offset);
|
|
||||||
MEM_COUNT(xdr) += offset;
|
|
||||||
return JS_TRUE;
|
|
||||||
case JSXDR_SEEK_SET:
|
|
||||||
if (offset < 0) {
|
|
||||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
|
||||||
JSMSG_SEEK_BEYOND_START);
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
|
||||||
if ((uint32_t)offset > MEM_COUNT(xdr))
|
|
||||||
MEM_NEED(xdr, offset - MEM_COUNT(xdr));
|
|
||||||
MEM_COUNT(xdr) = offset;
|
|
||||||
} else {
|
|
||||||
if ((uint32_t)offset > MEM_LIMIT(xdr)) {
|
|
||||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
|
||||||
JSMSG_SEEK_BEYOND_END);
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
MEM_COUNT(xdr) = offset;
|
|
||||||
}
|
|
||||||
return JS_TRUE;
|
|
||||||
case JSXDR_SEEK_END:
|
|
||||||
if (offset >= 0 ||
|
|
||||||
xdr->mode == JSXDR_ENCODE ||
|
|
||||||
(int32_t)MEM_LIMIT(xdr) + offset < 0) {
|
|
||||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
|
||||||
JSMSG_END_SEEK);
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset;
|
|
||||||
return JS_TRUE;
|
|
||||||
default: {
|
|
||||||
char numBuf[12];
|
|
||||||
JS_snprintf(numBuf, sizeof numBuf, "%d", whence);
|
|
||||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
|
||||||
JSMSG_WHITHER_WHENCE, numBuf);
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t
|
|
||||||
mem_tell(JSXDRState *xdr)
|
|
||||||
{
|
|
||||||
return MEM_COUNT(xdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mem_finalize(JSXDRState *xdr)
|
|
||||||
{
|
|
||||||
xdr->cx->free_(MEM_BASE(xdr));
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSXDROps xdrmem_ops = {
|
|
||||||
mem_get32, mem_set32, mem_getbytes, mem_setbytes,
|
|
||||||
mem_raw, mem_seek, mem_tell, mem_finalize
|
|
||||||
};
|
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
|
||||||
JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx)
|
|
||||||
{
|
|
||||||
xdr->mode = mode;
|
|
||||||
xdr->cx = cx;
|
|
||||||
xdr->sharedFilename = NULL;
|
|
||||||
xdr->principals = NULL;
|
|
||||||
xdr->originPrincipals = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSXDRState *)
|
|
||||||
JS_XDRNewMem(JSContext *cx, JSXDRMode mode)
|
|
||||||
{
|
|
||||||
JSXDRState *xdr = (JSXDRState *) cx->malloc_(sizeof(JSXDRMemState));
|
|
||||||
if (!xdr)
|
|
||||||
return NULL;
|
|
||||||
JS_XDRInitBase(xdr, mode, cx);
|
|
||||||
if (mode == JSXDR_ENCODE) {
|
|
||||||
if (!(MEM_BASE(xdr) = (char *) cx->malloc_(MEM_BLOCK))) {
|
|
||||||
cx->free_(xdr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* XXXbe ok, so better not deref MEM_BASE(xdr) if not ENCODE */
|
|
||||||
MEM_BASE(xdr) = NULL;
|
|
||||||
}
|
|
||||||
xdr->ops = &xdrmem_ops;
|
|
||||||
MEM_COUNT(xdr) = 0;
|
|
||||||
MEM_LIMIT(xdr) = MEM_BLOCK;
|
|
||||||
return xdr;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(void *)
|
|
||||||
JS_XDRMemGetData(JSXDRState *xdr, uint32_t *lp)
|
|
||||||
{
|
|
||||||
if (xdr->ops != &xdrmem_ops)
|
|
||||||
return NULL;
|
|
||||||
*lp = MEM_COUNT(xdr);
|
|
||||||
return MEM_BASE(xdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
|
||||||
JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32_t len)
|
|
||||||
{
|
|
||||||
if (xdr->ops != &xdrmem_ops)
|
|
||||||
return;
|
|
||||||
MEM_LIMIT(xdr) = len;
|
|
||||||
MEM_BASE(xdr) = (char *) data;
|
|
||||||
MEM_COUNT(xdr) = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(uint32_t)
|
|
||||||
JS_XDRMemDataLeft(JSXDRState *xdr)
|
|
||||||
{
|
|
||||||
if (xdr->ops != &xdrmem_ops)
|
|
||||||
return 0;
|
|
||||||
return MEM_LIMIT(xdr) - MEM_COUNT(xdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
|
||||||
JS_XDRMemResetData(JSXDRState *xdr)
|
|
||||||
{
|
|
||||||
if (xdr->ops != &xdrmem_ops)
|
|
||||||
return;
|
|
||||||
MEM_COUNT(xdr) = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
|
||||||
JS_XDRDestroy(JSXDRState *xdr)
|
|
||||||
{
|
|
||||||
JSContext *cx = xdr->cx;
|
|
||||||
xdr->ops->finalize(xdr);
|
|
||||||
cx->free_(xdr);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
|
||||||
JS_XDRSetPrincipals(JSXDRState *xdr, JSPrincipals *principals, JSPrincipals *originPrincipals)
|
|
||||||
{
|
|
||||||
JS_ASSERT(xdr->mode == JSXDR_DECODE);
|
|
||||||
xdr->principals = principals;
|
|
||||||
xdr->originPrincipals = JSScript::normalizeOriginPrincipals(principals, originPrincipals);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRUint8(JSXDRState *xdr, uint8_t *b)
|
|
||||||
{
|
|
||||||
uint32_t l = *b;
|
|
||||||
if (!JS_XDRUint32(xdr, &l))
|
|
||||||
return JS_FALSE;
|
|
||||||
*b = (uint8_t) l;
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRUint16(JSXDRState *xdr, uint16_t *s)
|
|
||||||
{
|
|
||||||
uint32_t l = *s;
|
|
||||||
if (!JS_XDRUint32(xdr, &l))
|
|
||||||
return JS_FALSE;
|
|
||||||
*s = (uint16_t) l;
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRUint32(JSXDRState *xdr, uint32_t *lp)
|
|
||||||
{
|
|
||||||
JSBool ok = JS_TRUE;
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
|
||||||
uint32_t xl = JSXDR_SWAB32(*lp);
|
|
||||||
ok = xdr->ops->set32(xdr, &xl);
|
|
||||||
} else if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
ok = xdr->ops->get32(xdr, lp);
|
|
||||||
*lp = JSXDR_SWAB32(*lp);
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32_t len)
|
|
||||||
{
|
|
||||||
uint32_t padlen;
|
|
||||||
static char padbuf[JSXDR_ALIGN-1];
|
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
|
||||||
if (!xdr->ops->setbytes(xdr, bytes, len))
|
|
||||||
return JS_FALSE;
|
|
||||||
} else {
|
|
||||||
if (!xdr->ops->getbytes(xdr, bytes, len))
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
len = xdr->ops->tell(xdr);
|
|
||||||
if (len % JSXDR_ALIGN) {
|
|
||||||
padlen = JSXDR_ALIGN - (len % JSXDR_ALIGN);
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
|
||||||
if (!xdr->ops->setbytes(xdr, padbuf, padlen))
|
|
||||||
return JS_FALSE;
|
|
||||||
} else {
|
|
||||||
if (!xdr->ops->seek(xdr, padlen, JSXDR_SEEK_CUR))
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert between a C string and the XDR representation:
|
|
||||||
* leading 32-bit count, then counted vector of chars,
|
|
||||||
* then possibly \0 padding to multiple of 4.
|
|
||||||
*/
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRCString(JSXDRState *xdr, char **sp)
|
|
||||||
{
|
|
||||||
uint32_t len;
|
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
|
||||||
len = strlen(*sp);
|
|
||||||
JS_XDRUint32(xdr, &len);
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
if (!(*sp = (char *) xdr->cx->malloc_(len + 1)))
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
if (!JS_XDRBytes(xdr, *sp, len)) {
|
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
|
||||||
xdr->cx->free_(*sp);
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
(*sp)[len] = '\0';
|
|
||||||
}
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSBool
|
|
||||||
XDRChars(JSXDRState *xdr, jschar *chars, uint32_t nchars)
|
|
||||||
{
|
|
||||||
uint32_t i, padlen, nbytes;
|
|
||||||
jschar *raw;
|
|
||||||
|
|
||||||
nbytes = nchars * sizeof(jschar);
|
|
||||||
padlen = nbytes % JSXDR_ALIGN;
|
|
||||||
if (padlen) {
|
|
||||||
padlen = JSXDR_ALIGN - padlen;
|
|
||||||
nbytes += padlen;
|
|
||||||
}
|
|
||||||
if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes)))
|
|
||||||
return JS_FALSE;
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
|
||||||
for (i = 0; i != nchars; i++)
|
|
||||||
raw[i] = JSXDR_SWAB16(chars[i]);
|
|
||||||
if (padlen)
|
|
||||||
memset((char *)raw + nbytes - padlen, 0, padlen);
|
|
||||||
} else if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
for (i = 0; i != nchars; i++)
|
|
||||||
chars[i] = JSXDR_SWAB16(raw[i]);
|
|
||||||
}
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert between a JS (Unicode) string and the XDR representation.
|
|
||||||
*/
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRString(JSXDRState *xdr, JSString **strp)
|
|
||||||
{
|
|
||||||
uint32_t nchars;
|
|
||||||
jschar *chars;
|
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
|
||||||
nchars = (*strp)->length();
|
|
||||||
if (!JS_XDRUint32(xdr, &nchars))
|
|
||||||
return JS_FALSE;
|
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
|
||||||
chars = (jschar *) xdr->cx->malloc_((nchars + 1) * sizeof(jschar));
|
|
||||||
else
|
|
||||||
chars = const_cast<jschar *>((*strp)->getChars(xdr->cx));
|
|
||||||
if (!chars)
|
|
||||||
return JS_FALSE;
|
|
||||||
|
|
||||||
if (!XDRChars(xdr, chars, nchars))
|
|
||||||
goto bad;
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
chars[nchars] = 0;
|
|
||||||
*strp = JS_NewUCString(xdr->cx, chars, nchars);
|
|
||||||
if (!*strp)
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
return JS_TRUE;
|
|
||||||
|
|
||||||
bad:
|
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
|
||||||
xdr->cx->free_(chars);
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp)
|
|
||||||
{
|
|
||||||
uint32_t null = (*strp == NULL);
|
|
||||||
if (!JS_XDRUint32(xdr, &null))
|
|
||||||
return JS_FALSE;
|
|
||||||
if (null) {
|
|
||||||
*strp = NULL;
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
return JS_XDRString(xdr, strp);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRDouble(JSXDRState *xdr, double *dp)
|
|
||||||
{
|
|
||||||
jsdpun u;
|
|
||||||
|
|
||||||
u.d = (xdr->mode == JSXDR_ENCODE) ? *dp : 0.0;
|
|
||||||
if (!JS_XDRUint32(xdr, &u.s.lo) || !JS_XDRUint32(xdr, &u.s.hi))
|
|
||||||
return false;
|
|
||||||
if (xdr->mode == JSXDR_DECODE)
|
|
||||||
*dp = u.d;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern JSBool
|
|
||||||
js_XDRAtom(JSXDRState *xdr, JSAtom **atomp)
|
|
||||||
{
|
|
||||||
JSString *str;
|
|
||||||
uint32_t nchars;
|
|
||||||
JSAtom *atom;
|
|
||||||
JSContext *cx;
|
|
||||||
jschar *chars;
|
|
||||||
jschar stackChars[256];
|
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
|
||||||
str = *atomp;
|
|
||||||
return JS_XDRString(xdr, &str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Inline JS_XDRString when decoding to avoid JSString allocation
|
|
||||||
* for already existing atoms. See bug 321985.
|
|
||||||
*/
|
|
||||||
if (!JS_XDRUint32(xdr, &nchars))
|
|
||||||
return JS_FALSE;
|
|
||||||
atom = NULL;
|
|
||||||
cx = xdr->cx;
|
|
||||||
if (nchars <= ArrayLength(stackChars)) {
|
|
||||||
chars = stackChars;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* This is very uncommon. Don't use the tempLifoAlloc arena for this as
|
|
||||||
* most allocations here will be bigger than tempLifoAlloc's default
|
|
||||||
* chunk size.
|
|
||||||
*/
|
|
||||||
chars = (jschar *) cx->malloc_(nchars * sizeof(jschar));
|
|
||||||
if (!chars)
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XDRChars(xdr, chars, nchars))
|
|
||||||
atom = js_AtomizeChars(cx, chars, nchars);
|
|
||||||
if (chars != stackChars)
|
|
||||||
cx->free_(chars);
|
|
||||||
|
|
||||||
if (!atom)
|
|
||||||
return JS_FALSE;
|
|
||||||
*atomp = atom;
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
|
|
||||||
{
|
|
||||||
return XDRFunctionObject(xdr, objp);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|
||||||
{
|
|
||||||
JSScript *script;
|
|
||||||
uint32_t magic;
|
|
||||||
uint32_t bytecodeVer;
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
script = NULL;
|
|
||||||
*scriptp = NULL;
|
|
||||||
} else {
|
|
||||||
script = *scriptp;
|
|
||||||
magic = JSXDR_MAGIC_SCRIPT_CURRENT;
|
|
||||||
bytecodeVer = JSXDR_BYTECODE_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!JS_XDRUint32(xdr, &magic))
|
|
||||||
return false;
|
|
||||||
if (!JS_XDRUint32(xdr, &bytecodeVer))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (magic != JSXDR_MAGIC_SCRIPT_CURRENT ||
|
|
||||||
bytecodeVer != JSXDR_BYTECODE_VERSION) {
|
|
||||||
/* We do not provide binary compatibility with older scripts. */
|
|
||||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, JSMSG_BAD_SCRIPT_MAGIC);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!XDRScript(xdr, &script))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
JS_ASSERT(!script->compileAndGo);
|
|
||||||
script->globalObject = GetCurrentGlobal(xdr->cx);
|
|
||||||
js_CallNewScriptHook(xdr->cx, script, NULL);
|
|
||||||
Debugger::onNewScript(xdr->cx, script, NULL);
|
|
||||||
*scriptp = script;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* JS_HAS_XDR */
|
|
@ -1,224 +0,0 @@
|
|||||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
||||||
* vim: set ts=8 sw=4 et tw=78:
|
|
||||||
*
|
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is Mozilla Communicator client code, released
|
|
||||||
* March 31, 1998.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* Netscape Communications Corporation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
||||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#ifndef jsxdrapi_h___
|
|
||||||
#define jsxdrapi_h___
|
|
||||||
|
|
||||||
/*
|
|
||||||
* JS external data representation interface API.
|
|
||||||
*
|
|
||||||
* The XDR system is comprised of three major parts:
|
|
||||||
*
|
|
||||||
* - the state serialization/deserialization APIs, which allow consumers
|
|
||||||
* of the API to serialize JS runtime state (script bytecodes, atom maps,
|
|
||||||
* object graphs, etc.) for later restoration. These portions
|
|
||||||
* are implemented in various appropriate files, such as jsscript.c
|
|
||||||
* for the script portions and jsobj.c for object state.
|
|
||||||
* - the callback APIs through which the runtime requests an opaque
|
|
||||||
* representation of a native object, and through which the runtime
|
|
||||||
* constructs a live native object from an opaque representation. These
|
|
||||||
* portions are the responsibility of the native object implementor.
|
|
||||||
* - utility functions for en/decoding of primitive types, such as
|
|
||||||
* JSStrings. This portion is implemented in jsxdrapi.c.
|
|
||||||
*
|
|
||||||
* Spiritually guided by Sun's XDR, where appropriate.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "jspubtd.h"
|
|
||||||
#include "jsprvtd.h"
|
|
||||||
|
|
||||||
JS_BEGIN_EXTERN_C
|
|
||||||
|
|
||||||
/* We use little-endian byteorder for all encoded data */
|
|
||||||
|
|
||||||
#if defined IS_LITTLE_ENDIAN
|
|
||||||
#define JSXDR_SWAB32(x) x
|
|
||||||
#define JSXDR_SWAB16(x) x
|
|
||||||
#elif defined IS_BIG_ENDIAN
|
|
||||||
#define JSXDR_SWAB32(x) (((uint32_t)(x) >> 24) | \
|
|
||||||
(((uint32_t)(x) >> 8) & 0xff00) | \
|
|
||||||
(((uint32_t)(x) << 8) & 0xff0000) | \
|
|
||||||
((uint32_t)(x) << 24))
|
|
||||||
#define JSXDR_SWAB16(x) (((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8))
|
|
||||||
#else
|
|
||||||
#error "unknown byte order"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define JSXDR_ALIGN 4
|
|
||||||
|
|
||||||
typedef enum JSXDRMode {
|
|
||||||
JSXDR_ENCODE,
|
|
||||||
JSXDR_DECODE
|
|
||||||
} JSXDRMode;
|
|
||||||
|
|
||||||
typedef enum JSXDRWhence {
|
|
||||||
JSXDR_SEEK_SET,
|
|
||||||
JSXDR_SEEK_CUR,
|
|
||||||
JSXDR_SEEK_END
|
|
||||||
} JSXDRWhence;
|
|
||||||
|
|
||||||
typedef struct JSXDROps {
|
|
||||||
JSBool (*get32)(JSXDRState *, uint32_t *);
|
|
||||||
JSBool (*set32)(JSXDRState *, uint32_t *);
|
|
||||||
JSBool (*getbytes)(JSXDRState *, char *, uint32_t);
|
|
||||||
JSBool (*setbytes)(JSXDRState *, char *, uint32_t);
|
|
||||||
void * (*raw)(JSXDRState *, uint32_t);
|
|
||||||
JSBool (*seek)(JSXDRState *, int32_t, JSXDRWhence);
|
|
||||||
uint32_t (*tell)(JSXDRState *);
|
|
||||||
void (*finalize)(JSXDRState *);
|
|
||||||
} JSXDROps;
|
|
||||||
|
|
||||||
struct JSXDRState {
|
|
||||||
JSXDRMode mode;
|
|
||||||
JSXDROps *ops;
|
|
||||||
JSContext *cx;
|
|
||||||
const char *sharedFilename;
|
|
||||||
JSPrincipals *principals;
|
|
||||||
JSPrincipals *originPrincipals;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSXDRState *)
|
|
||||||
JS_XDRNewMem(JSContext *cx, JSXDRMode mode);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void *)
|
|
||||||
JS_XDRMemGetData(JSXDRState *xdr, uint32_t *lp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32_t len);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(uint32_t)
|
|
||||||
JS_XDRMemDataLeft(JSXDRState *xdr);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_XDRMemResetData(JSXDRState *xdr);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_XDRDestroy(JSXDRState *xdr);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set principals that should be assigned to decoded scripts and functions.
|
|
||||||
* The principals is not held via JS_HoldPrincipals/JS_DropPrincipals unless
|
|
||||||
* they are stored in a decoded script. Thus the caller must either ensure
|
|
||||||
* that the principals outlive the XDR instance or are explicitly set to NULL
|
|
||||||
* before they release by the caller.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_XDRSetPrincipals(JSXDRState *xdr, JSPrincipals *principals, JSPrincipals *originPrincipals);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRUint8(JSXDRState *xdr, uint8_t *b);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRUint16(JSXDRState *xdr, uint16_t *s);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRUint32(JSXDRState *xdr, uint32_t *lp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32_t len);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRCString(JSXDRState *xdr, char **sp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRString(JSXDRState *xdr, JSString **strp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRDouble(JSXDRState *xdr, double *dp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRFunctionObject(JSXDRState *xdr, JSObject **objp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Magic numbers.
|
|
||||||
*/
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_1 0xdead0001
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_2 0xdead0002
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_3 0xdead0003
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_4 0xdead0004
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_5 0xdead0005
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_6 0xdead0006
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_7 0xdead0007
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_8 0xdead0008
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_9 0xdead0009
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_10 0xdead000a
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_11 0xdead000b
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_12 0xdead000c
|
|
||||||
#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_12
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bytecode version number. Increment the subtrahend whenever JS bytecode
|
|
||||||
* changes incompatibly.
|
|
||||||
*
|
|
||||||
* This version number is XDR'd near the front of xdr bytecode and
|
|
||||||
* aborts deserialization if there is a mismatch between the current
|
|
||||||
* and saved versions. If deserialization fails, the data should be
|
|
||||||
* invalidated if possible.
|
|
||||||
*/
|
|
||||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 111)
|
|
||||||
|
|
||||||
JS_END_EXTERN_C
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Library-private functions.
|
|
||||||
*/
|
|
||||||
extern JSBool
|
|
||||||
js_XDRAtom(JSXDRState *xdr, JSAtom **atomp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set principals that should be assigned to decoded scripts and functions.
|
|
||||||
* The principals is not held via JS_HoldPrincipals/JS_DropPrincipals unless
|
|
||||||
* they are stored in a decoded script. Thus the caller must either ensure
|
|
||||||
* that principal outlive the XDR instance or are explicitly set to NULL
|
|
||||||
* before they release by the caller.
|
|
||||||
*/
|
|
||||||
extern void
|
|
||||||
js_XDRSetPrincipals(JSXDRState *xdr, JSPrincipals *principals, JSPrincipals *originPrincipals);
|
|
||||||
|
|
||||||
#endif /* ! jsxdrapi_h___ */
|
|
@ -45,6 +45,7 @@
|
|||||||
#include "vm/GlobalObject.h"
|
#include "vm/GlobalObject.h"
|
||||||
#include "vm/MethodGuard.h"
|
#include "vm/MethodGuard.h"
|
||||||
#include "vm/Stack.h"
|
#include "vm/Stack.h"
|
||||||
|
#include "vm/Xdr.h"
|
||||||
|
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "vm/MatchPairs.h"
|
#include "vm/MatchPairs.h"
|
||||||
#include "vm/RegExpStatics.h"
|
#include "vm/RegExpStatics.h"
|
||||||
#include "vm/StringBuffer.h"
|
#include "vm/StringBuffer.h"
|
||||||
|
#include "vm/Xdr.h"
|
||||||
|
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
@ -746,36 +747,38 @@ js::ParseRegExpFlags(JSContext *cx, JSString *flagStr, RegExpFlag *flagsOut)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JS_HAS_XDR
|
template<XDRMode mode>
|
||||||
# include "jsxdrapi.h"
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
js::XDRScriptRegExpObject(JSXDRState *xdr, HeapPtrObject *objp)
|
js::XDRScriptRegExpObject(XDRState<mode> *xdr, HeapPtrObject *objp)
|
||||||
{
|
{
|
||||||
JSAtom *source = 0;
|
JSAtom *source = 0;
|
||||||
uint32_t flagsword = 0;
|
uint32_t flagsword = 0;
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
JS_ASSERT(objp);
|
JS_ASSERT(objp);
|
||||||
RegExpObject &reobj = (*objp)->asRegExp();
|
RegExpObject &reobj = (*objp)->asRegExp();
|
||||||
source = reobj.getSource();
|
source = reobj.getSource();
|
||||||
flagsword = reobj.getFlags();
|
flagsword = reobj.getFlags();
|
||||||
}
|
}
|
||||||
if (!js_XDRAtom(xdr, &source) || !JS_XDRUint32(xdr, &flagsword))
|
if (!XDRAtom(xdr, &source) || !xdr->codeUint32(&flagsword))
|
||||||
return false;
|
return false;
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
RegExpFlag flags = RegExpFlag(flagsword);
|
RegExpFlag flags = RegExpFlag(flagsword);
|
||||||
RegExpObject *reobj = RegExpObject::createNoStatics(xdr->cx, source, flags, NULL);
|
RegExpObject *reobj = RegExpObject::createNoStatics(xdr->cx(), source, flags, NULL);
|
||||||
if (!reobj)
|
if (!reobj)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!reobj->clearParent(xdr->cx))
|
if (!reobj->clearParent(xdr->cx()))
|
||||||
return false;
|
return false;
|
||||||
if (!reobj->clearType(xdr->cx))
|
if (!reobj->clearType(xdr->cx()))
|
||||||
return false;
|
return false;
|
||||||
objp->init(reobj);
|
objp->init(reobj);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif /* !JS_HAS_XDR */
|
|
||||||
|
|
||||||
|
template bool
|
||||||
|
js::XDRScriptRegExpObject(XDRState<XDR_ENCODE> *xdr, HeapPtrObject *objp);
|
||||||
|
|
||||||
|
template bool
|
||||||
|
js::XDRScriptRegExpObject(XDRState<XDR_DECODE> *xdr, HeapPtrObject *objp);
|
||||||
|
@ -469,8 +469,9 @@ ParseRegExpFlags(JSContext *cx, JSString *flagStr, RegExpFlag *flagsOut);
|
|||||||
inline bool
|
inline bool
|
||||||
RegExpToShared(JSContext *cx, JSObject &obj, RegExpGuard *g);
|
RegExpToShared(JSContext *cx, JSObject &obj, RegExpGuard *g);
|
||||||
|
|
||||||
|
template<XDRMode mode>
|
||||||
bool
|
bool
|
||||||
XDRScriptRegExpObject(JSXDRState *xdr, HeapPtrObject *objp);
|
XDRScriptRegExpObject(XDRState<mode> *xdr, HeapPtrObject *objp);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
@ -42,12 +42,10 @@
|
|||||||
#include "jscompartment.h"
|
#include "jscompartment.h"
|
||||||
#include "jsiter.h"
|
#include "jsiter.h"
|
||||||
#include "jsscope.h"
|
#include "jsscope.h"
|
||||||
#if JS_HAS_XDR
|
|
||||||
#include "jsxdrapi.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "GlobalObject.h"
|
#include "GlobalObject.h"
|
||||||
#include "ScopeObject.h"
|
#include "ScopeObject.h"
|
||||||
|
#include "Xdr.h"
|
||||||
|
|
||||||
#include "jsatominlines.h"
|
#include "jsatominlines.h"
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
@ -936,8 +934,6 @@ Class js::BlockClass = {
|
|||||||
JS_ConvertStub
|
JS_ConvertStub
|
||||||
};
|
};
|
||||||
|
|
||||||
#if JS_HAS_XDR
|
|
||||||
|
|
||||||
#define NO_PARENT_INDEX UINT32_MAX
|
#define NO_PARENT_INDEX UINT32_MAX
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
@ -957,16 +953,17 @@ FindObjectIndex(JSObjectArray *array, JSObject *obj)
|
|||||||
return NO_PARENT_INDEX;
|
return NO_PARENT_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<XDRMode mode>
|
||||||
bool
|
bool
|
||||||
js::XDRStaticBlockObject(JSXDRState *xdr, JSScript *script, StaticBlockObject **objp)
|
js::XDRStaticBlockObject(XDRState<mode> *xdr, JSScript *script, StaticBlockObject **objp)
|
||||||
{
|
{
|
||||||
JSContext *cx = xdr->cx;
|
JSContext *cx = xdr->cx();
|
||||||
|
|
||||||
StaticBlockObject *obj = NULL;
|
StaticBlockObject *obj = NULL;
|
||||||
uint32_t parentId = 0;
|
uint32_t parentId = 0;
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
uint32_t depthAndCount = 0;
|
uint32_t depthAndCount = 0;
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
obj = *objp;
|
obj = *objp;
|
||||||
parentId = JSScript::isValidOffset(script->objectsOffset)
|
parentId = JSScript::isValidOffset(script->objectsOffset)
|
||||||
? FindObjectIndex(script->objects(), obj->enclosingBlock())
|
? FindObjectIndex(script->objects(), obj->enclosingBlock())
|
||||||
@ -979,10 +976,10 @@ js::XDRStaticBlockObject(JSXDRState *xdr, JSScript *script, StaticBlockObject **
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* First, XDR the parent atomid. */
|
/* First, XDR the parent atomid. */
|
||||||
if (!JS_XDRUint32(xdr, &parentId))
|
if (!xdr->codeUint32(&parentId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
obj = StaticBlockObject::create(cx);
|
obj = StaticBlockObject::create(cx);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return false;
|
return false;
|
||||||
@ -1000,10 +997,10 @@ js::XDRStaticBlockObject(JSXDRState *xdr, JSScript *script, StaticBlockObject **
|
|||||||
|
|
||||||
AutoObjectRooter tvr(cx, obj);
|
AutoObjectRooter tvr(cx, obj);
|
||||||
|
|
||||||
if (!JS_XDRUint32(xdr, &depthAndCount))
|
if (!xdr->codeUint32(&depthAndCount))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
uint32_t depth = uint16_t(depthAndCount >> 16);
|
uint32_t depth = uint16_t(depthAndCount >> 16);
|
||||||
count = uint16_t(depthAndCount);
|
count = uint16_t(depthAndCount);
|
||||||
obj->setStackDepth(depth);
|
obj->setStackDepth(depth);
|
||||||
@ -1014,7 +1011,7 @@ js::XDRStaticBlockObject(JSXDRState *xdr, JSScript *script, StaticBlockObject **
|
|||||||
*/
|
*/
|
||||||
for (unsigned i = 0; i < count; i++) {
|
for (unsigned i = 0; i < count; i++) {
|
||||||
JSAtom *atom;
|
JSAtom *atom;
|
||||||
if (!js_XDRAtom(xdr, &atom))
|
if (!XDRAtom(xdr, &atom))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* The empty string indicates an int id. */
|
/* The empty string indicates an int id. */
|
||||||
@ -1054,11 +1051,15 @@ js::XDRStaticBlockObject(JSXDRState *xdr, JSScript *script, StaticBlockObject **
|
|||||||
? JSID_TO_ATOM(propid)
|
? JSID_TO_ATOM(propid)
|
||||||
: cx->runtime->emptyString;
|
: cx->runtime->emptyString;
|
||||||
|
|
||||||
if (!js_XDRAtom(xdr, &atom))
|
if (!XDRAtom(xdr, &atom))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* JS_HAS_XDR */
|
template bool
|
||||||
|
js::XDRStaticBlockObject(XDRState<XDR_ENCODE> *xdr, JSScript *script, StaticBlockObject **objp);
|
||||||
|
|
||||||
|
template bool
|
||||||
|
js::XDRStaticBlockObject(XDRState<XDR_DECODE> *xdr, JSScript *script, StaticBlockObject **objp);
|
||||||
|
@ -276,8 +276,9 @@ class ClonedBlockObject : public BlockObject
|
|||||||
bool containsVar(PropertyName *name, Value *vp, JSContext *cx);
|
bool containsVar(PropertyName *name, Value *vp, JSContext *cx);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool
|
template<XDRMode mode>
|
||||||
XDRStaticBlockObject(JSXDRState *xdr, JSScript *script, StaticBlockObject **objp);
|
bool
|
||||||
|
XDRStaticBlockObject(XDRState<mode> *xdr, JSScript *script, StaticBlockObject **objp);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
239
js/src/vm/Xdr.cpp
Normal file
239
js/src/vm/Xdr.cpp
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code, released
|
||||||
|
* March 31, 1998.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "mozilla/Util.h"
|
||||||
|
|
||||||
|
#include "jsversion.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "jstypes.h"
|
||||||
|
#include "jsutil.h"
|
||||||
|
#include "jsdhash.h"
|
||||||
|
#include "jsprf.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jscntxt.h"
|
||||||
|
#include "jsnum.h"
|
||||||
|
#include "jsscript.h"
|
||||||
|
#include "jsstr.h"
|
||||||
|
|
||||||
|
#include "Xdr.h"
|
||||||
|
#include "Debugger.h"
|
||||||
|
|
||||||
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace js;
|
||||||
|
|
||||||
|
namespace js {
|
||||||
|
|
||||||
|
void
|
||||||
|
XDRBuffer::freeBuffer()
|
||||||
|
{
|
||||||
|
Foreground::free_(base);
|
||||||
|
#ifdef DEBUG
|
||||||
|
memset(this, 0xe2, sizeof *this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
XDRBuffer::grow(size_t n)
|
||||||
|
{
|
||||||
|
JS_ASSERT(n > size_t(limit - cursor));
|
||||||
|
|
||||||
|
const size_t MEM_BLOCK = 8192;
|
||||||
|
size_t offset = cursor - base;
|
||||||
|
size_t newCapacity = JS_ROUNDUP(offset + n, MEM_BLOCK);
|
||||||
|
if (isUint32Overflow(newCapacity)) {
|
||||||
|
JS_ReportErrorNumber(cx(), js_GetErrorMessage, NULL, JSMSG_TOO_BIG_TO_ENCODE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *data = OffTheBooks::realloc_(base, newCapacity);
|
||||||
|
if (!data) {
|
||||||
|
js_ReportOutOfMemory(cx());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
base = static_cast<uint8_t *>(data);
|
||||||
|
cursor = base + offset;
|
||||||
|
limit = base + newCapacity;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<XDRMode mode>
|
||||||
|
bool
|
||||||
|
XDRState<mode>::codeChars(jschar *chars, size_t nchars)
|
||||||
|
{
|
||||||
|
size_t nbytes = nchars * sizeof(jschar);
|
||||||
|
if (mode == XDR_ENCODE) {
|
||||||
|
uint8_t *ptr = buf.write(nbytes);
|
||||||
|
if (!ptr)
|
||||||
|
return false;
|
||||||
|
#ifdef IS_LITTLE_ENDIAN
|
||||||
|
memcpy(ptr, chars, nbytes);
|
||||||
|
#else
|
||||||
|
for (size_t i = 0; i != nchars; i++) {
|
||||||
|
uint16_t tmp = NormalizeByteOrder16(chars[i]);
|
||||||
|
memcpy(ptr, &tmp, sizeof tmp);
|
||||||
|
ptr += sizeof tmp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
const uint8_t *ptr = buf.read(nbytes);
|
||||||
|
#ifdef IS_LITTLE_ENDIAN
|
||||||
|
memcpy(chars, ptr, nbytes);
|
||||||
|
#else
|
||||||
|
for (size_t i = 0; i != nchars; i++) {
|
||||||
|
uint16_t tmp;
|
||||||
|
memcpy(&tmp, ptr, sizeof tmp);
|
||||||
|
chars[i] = NormalizeByteOrder16(tmp);
|
||||||
|
ptr += sizeof tmp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert between a JS (Unicode) string and the XDR representation.
|
||||||
|
*/
|
||||||
|
template<XDRMode mode>
|
||||||
|
bool
|
||||||
|
XDRState<mode>::codeString(JSString **strp)
|
||||||
|
{
|
||||||
|
uint32_t nchars;
|
||||||
|
jschar *chars;
|
||||||
|
|
||||||
|
if (mode == XDR_ENCODE)
|
||||||
|
nchars = (*strp)->length();
|
||||||
|
if (!codeUint32(&nchars))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mode == XDR_DECODE)
|
||||||
|
chars = (jschar *) cx()->malloc_((nchars + 1) * sizeof(jschar));
|
||||||
|
else
|
||||||
|
chars = const_cast<jschar *>((*strp)->getChars(cx()));
|
||||||
|
if (!chars)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!codeChars(chars, nchars))
|
||||||
|
goto bad;
|
||||||
|
if (mode == XDR_DECODE) {
|
||||||
|
chars[nchars] = 0;
|
||||||
|
*strp = JS_NewUCString(cx(), chars, nchars);
|
||||||
|
if (!*strp)
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
if (mode == XDR_DECODE)
|
||||||
|
Foreground::free_(chars);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<XDRMode mode>
|
||||||
|
static bool
|
||||||
|
VersionCheck(XDRState<mode> *xdr)
|
||||||
|
{
|
||||||
|
uint32_t bytecodeVer;
|
||||||
|
if (mode == XDR_ENCODE)
|
||||||
|
bytecodeVer = XDR_BYTECODE_VERSION;
|
||||||
|
|
||||||
|
if (!xdr->codeUint32(&bytecodeVer))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mode == XDR_DECODE && bytecodeVer != XDR_BYTECODE_VERSION) {
|
||||||
|
/* We do not provide binary compatibility with older scripts. */
|
||||||
|
JS_ReportErrorNumber(xdr->cx(), js_GetErrorMessage, NULL, JSMSG_BAD_SCRIPT_MAGIC);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<XDRMode mode>
|
||||||
|
bool
|
||||||
|
XDRState<mode>::codeFunction(JSObject **objp)
|
||||||
|
{
|
||||||
|
if (mode == XDR_DECODE)
|
||||||
|
*objp = NULL;
|
||||||
|
|
||||||
|
return VersionCheck(this) && XDRInterpretedFunction(this, objp, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<XDRMode mode>
|
||||||
|
bool
|
||||||
|
XDRState<mode>::codeScript(JSScript **scriptp)
|
||||||
|
{
|
||||||
|
JSScript *script;
|
||||||
|
if (mode == XDR_DECODE) {
|
||||||
|
script = NULL;
|
||||||
|
*scriptp = NULL;
|
||||||
|
} else {
|
||||||
|
script = *scriptp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!VersionCheck(this) || !XDRScript(this, &script, NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mode == XDR_DECODE) {
|
||||||
|
JS_ASSERT(!script->compileAndGo);
|
||||||
|
script->globalObject = GetCurrentGlobal(cx());
|
||||||
|
js_CallNewScriptHook(cx(), script, NULL);
|
||||||
|
Debugger::onNewScript(cx(), script, NULL);
|
||||||
|
*scriptp = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
XDRDecoder::XDRDecoder(JSContext *cx, const void *data, uint32_t length,
|
||||||
|
JSPrincipals *principals, JSPrincipals *originPrincipals)
|
||||||
|
: XDRState<XDR_DECODE>(cx)
|
||||||
|
{
|
||||||
|
buf.setData(data, length);
|
||||||
|
this->principals = principals;
|
||||||
|
this->originPrincipals = JSScript::normalizeOriginPrincipals(principals, originPrincipals);
|
||||||
|
}
|
||||||
|
|
||||||
|
template class XDRState<XDR_ENCODE>;
|
||||||
|
template class XDRState<XDR_DECODE>;
|
||||||
|
|
||||||
|
} /* namespace js */
|
||||||
|
|
322
js/src/vm/Xdr.h
Normal file
322
js/src/vm/Xdr.h
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=8 sw=4 et tw=78:
|
||||||
|
*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is SpiderMonkey string object code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* the Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef Xdr_h___
|
||||||
|
#define Xdr_h___
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jsprvtd.h"
|
||||||
|
#include "jsnum.h"
|
||||||
|
|
||||||
|
namespace js {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bytecode version number. Increment the subtrahend whenever JS bytecode
|
||||||
|
* changes incompatibly.
|
||||||
|
*
|
||||||
|
* This version number is XDR'd near the front of xdr bytecode and
|
||||||
|
* aborts deserialization if there is a mismatch between the current
|
||||||
|
* and saved versions. If deserialization fails, the data should be
|
||||||
|
* invalidated if possible.
|
||||||
|
*/
|
||||||
|
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 112);
|
||||||
|
|
||||||
|
class XDRBuffer {
|
||||||
|
public:
|
||||||
|
XDRBuffer(JSContext *cx)
|
||||||
|
: context(cx), base(NULL), cursor(NULL), limit(NULL) { }
|
||||||
|
|
||||||
|
JSContext *cx() const {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *getData(uint32_t *lengthp) const {
|
||||||
|
JS_ASSERT(size_t(cursor - base) <= size_t(UINT32_MAX));
|
||||||
|
*lengthp = uint32_t(cursor - base);
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setData(const void *data, uint32_t length) {
|
||||||
|
base = static_cast<uint8_t *>(const_cast<void *>(data));
|
||||||
|
cursor = base;
|
||||||
|
limit = base + length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *read(size_t n) {
|
||||||
|
JS_ASSERT(n <= size_t(limit - cursor));
|
||||||
|
uint8_t *ptr = cursor;
|
||||||
|
cursor += n;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *readCString() {
|
||||||
|
char *ptr = reinterpret_cast<char *>(cursor);
|
||||||
|
cursor = reinterpret_cast<uint8_t *>(strchr(ptr, '\0')) + 1;
|
||||||
|
JS_ASSERT(base < cursor);
|
||||||
|
JS_ASSERT(cursor <= limit);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *write(size_t n) {
|
||||||
|
if (n > size_t(limit - cursor)) {
|
||||||
|
if (!grow(n))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
uint8_t *ptr = cursor;
|
||||||
|
cursor += n;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isUint32Overflow(size_t n) {
|
||||||
|
return size_t(-1) > size_t(UINT32_MAX) && n > size_t(UINT32_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeBuffer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool grow(size_t n);
|
||||||
|
|
||||||
|
JSContext *const context;
|
||||||
|
uint8_t *base;
|
||||||
|
uint8_t *cursor;
|
||||||
|
uint8_t *limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* We use little-endian byteorder for all encoded data */
|
||||||
|
|
||||||
|
#if defined IS_LITTLE_ENDIAN
|
||||||
|
|
||||||
|
inline uint32_t
|
||||||
|
NormalizeByteOrder32(uint32_t x)
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t
|
||||||
|
NormalizeByteOrder16(uint16_t x)
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined IS_BIG_ENDIAN
|
||||||
|
|
||||||
|
inline uint32_t
|
||||||
|
NormalizeByteOrder32(uint32_t x)
|
||||||
|
{
|
||||||
|
return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t
|
||||||
|
NormalizeByteOrder16(uint16_t x)
|
||||||
|
{
|
||||||
|
return (x >> 8) | (x << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "unknown byte order"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <XDRMode mode>
|
||||||
|
class XDRState {
|
||||||
|
public:
|
||||||
|
XDRBuffer buf;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
JSPrincipals *principals;
|
||||||
|
JSPrincipals *originPrincipals;
|
||||||
|
|
||||||
|
XDRState(JSContext *cx)
|
||||||
|
: buf(cx), principals(NULL), originPrincipals(NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
JSContext *cx() const {
|
||||||
|
return buf.cx();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool codeUint8(uint8_t *n) {
|
||||||
|
if (mode == XDR_ENCODE) {
|
||||||
|
uint8_t *ptr = buf.write(sizeof *n);
|
||||||
|
if (!ptr)
|
||||||
|
return false;
|
||||||
|
*ptr = *n;
|
||||||
|
} else {
|
||||||
|
*n = *buf.read(sizeof *n);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool codeUint16(uint16_t *n) {
|
||||||
|
uint16_t tmp;
|
||||||
|
if (mode == XDR_ENCODE) {
|
||||||
|
uint8_t *ptr = buf.write(sizeof tmp);
|
||||||
|
if (!ptr)
|
||||||
|
return false;
|
||||||
|
tmp = NormalizeByteOrder16(*n);
|
||||||
|
memcpy(ptr, &tmp, sizeof tmp);
|
||||||
|
} else {
|
||||||
|
memcpy(&tmp, buf.read(sizeof tmp), sizeof tmp);
|
||||||
|
*n = NormalizeByteOrder16(tmp);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool codeUint32(uint32_t *n) {
|
||||||
|
uint32_t tmp;
|
||||||
|
if (mode == XDR_ENCODE) {
|
||||||
|
uint8_t *ptr = buf.write(sizeof tmp);
|
||||||
|
if (!ptr)
|
||||||
|
return false;
|
||||||
|
tmp = NormalizeByteOrder32(*n);
|
||||||
|
memcpy(ptr, &tmp, sizeof tmp);
|
||||||
|
} else {
|
||||||
|
memcpy(&tmp, buf.read(sizeof tmp), sizeof tmp);
|
||||||
|
*n = NormalizeByteOrder32(tmp);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool codeDouble(double *dp) {
|
||||||
|
jsdpun tmp;
|
||||||
|
if (mode == XDR_ENCODE) {
|
||||||
|
uint8_t *ptr = buf.write(sizeof tmp);
|
||||||
|
if (!ptr)
|
||||||
|
return false;
|
||||||
|
tmp.d = *dp;
|
||||||
|
tmp.s.lo = NormalizeByteOrder32(tmp.s.lo);
|
||||||
|
tmp.s.hi = NormalizeByteOrder32(tmp.s.hi);
|
||||||
|
memcpy(ptr, &tmp.s.lo, sizeof tmp.s.lo);
|
||||||
|
memcpy(ptr + sizeof tmp.s.lo, &tmp.s.hi, sizeof tmp.s.hi);
|
||||||
|
} else {
|
||||||
|
const uint8_t *ptr = buf.read(sizeof tmp);
|
||||||
|
memcpy(&tmp.s.lo, ptr, sizeof tmp.s.lo);
|
||||||
|
memcpy(&tmp.s.hi, ptr + sizeof tmp.s.lo, sizeof tmp.s.hi);
|
||||||
|
tmp.s.lo = NormalizeByteOrder32(tmp.s.lo);
|
||||||
|
tmp.s.hi = NormalizeByteOrder32(tmp.s.hi);
|
||||||
|
*dp = tmp.d;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool codeBytes(void *bytes, size_t len) {
|
||||||
|
if (mode == XDR_ENCODE) {
|
||||||
|
uint8_t *ptr = buf.write(len);
|
||||||
|
if (!ptr)
|
||||||
|
return false;
|
||||||
|
memcpy(ptr, bytes, len);
|
||||||
|
} else {
|
||||||
|
memcpy(bytes, buf.read(len), len);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* During encoding the string is written into the buffer together with its
|
||||||
|
* terminating '\0'. During decoding the method returns a pointer into the
|
||||||
|
* decoding buffer and the caller must copy the string if it will outlive
|
||||||
|
* the decoding buffer.
|
||||||
|
*/
|
||||||
|
bool codeCString(const char **sp) {
|
||||||
|
if (mode == XDR_ENCODE) {
|
||||||
|
size_t n = strlen(*sp) + 1;
|
||||||
|
uint8_t *ptr = buf.write(n);
|
||||||
|
if (!ptr)
|
||||||
|
return false;
|
||||||
|
memcpy(ptr, *sp, n);
|
||||||
|
} else {
|
||||||
|
*sp = buf.readCString();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool codeChars(jschar *chars, size_t nchars);
|
||||||
|
bool codeString(JSString **strp);
|
||||||
|
|
||||||
|
bool codeFunction(JSObject **objp);
|
||||||
|
bool codeScript(JSScript **scriptp);
|
||||||
|
|
||||||
|
void initScriptPrincipals(JSScript *script) {
|
||||||
|
JS_ASSERT(mode == XDR_DECODE);
|
||||||
|
|
||||||
|
/* The origin principals must be normalized at this point. */
|
||||||
|
JS_ASSERT_IF(principals, originPrincipals);
|
||||||
|
JS_ASSERT(!script->principals);
|
||||||
|
JS_ASSERT(!script->originPrincipals);
|
||||||
|
if (principals) {
|
||||||
|
script->principals = principals;
|
||||||
|
JS_HoldPrincipals(principals);
|
||||||
|
}
|
||||||
|
if (originPrincipals) {
|
||||||
|
script->originPrincipals = originPrincipals;
|
||||||
|
JS_HoldPrincipals(originPrincipals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class XDREncoder : public XDRState<XDR_ENCODE> {
|
||||||
|
public:
|
||||||
|
XDREncoder(JSContext *cx)
|
||||||
|
: XDRState<XDR_ENCODE>(cx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~XDREncoder() {
|
||||||
|
buf.freeBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *getData(uint32_t *lengthp) const {
|
||||||
|
return buf.getData(lengthp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *forgetData(uint32_t *lengthp) {
|
||||||
|
void *data = buf.getData(lengthp);
|
||||||
|
buf.setData(NULL, 0);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class XDRDecoder : public XDRState<XDR_DECODE> {
|
||||||
|
public:
|
||||||
|
XDRDecoder(JSContext *cx, const void *data, uint32_t length,
|
||||||
|
JSPrincipals *principals, JSPrincipals *originPrincipals);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace js */
|
||||||
|
|
||||||
|
#endif /* Xdr_h___ */
|
@ -78,7 +78,6 @@
|
|||||||
#include "nsIJARURI.h"
|
#include "nsIJARURI.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsDOMFile.h"
|
#include "nsDOMFile.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
#include "jsprf.h"
|
#include "jsprf.h"
|
||||||
#include "nsJSPrincipals.h"
|
#include "nsJSPrincipals.h"
|
||||||
// For reporting errors with the console service
|
// For reporting errors with the console service
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jsdbgapi.h"
|
#include "jsdbgapi.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
|
|
||||||
#include "nsJSPrincipals.h"
|
#include "nsJSPrincipals.h"
|
||||||
|
|
||||||
@ -54,31 +53,20 @@ using namespace mozilla::scache;
|
|||||||
// principals to the system principals.
|
// principals to the system principals.
|
||||||
nsresult
|
nsresult
|
||||||
ReadCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx,
|
ReadCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx,
|
||||||
nsIPrincipal *systemPrincipal, JSScript **script)
|
nsIPrincipal *systemPrincipal, JSScript **scriptp)
|
||||||
{
|
{
|
||||||
nsAutoArrayPtr<char> buf;
|
nsAutoArrayPtr<char> buf;
|
||||||
PRUint32 len;
|
PRUint32 len;
|
||||||
nsresult rv = cache->GetBuffer(PromiseFlatCString(uri).get(),
|
nsresult rv = cache->GetBuffer(PromiseFlatCString(uri).get(),
|
||||||
getter_Transfers(buf), &len);
|
getter_Transfers(buf), &len);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv))
|
||||||
return rv; // don't warn since NOT_AVAILABLE is an ok error
|
return rv; // don't warn since NOT_AVAILABLE is an ok error
|
||||||
}
|
|
||||||
|
|
||||||
JSXDRState *xdr = ::JS_XDRNewMem(cx, JSXDR_DECODE);
|
JSScript *script = JS_DecodeScript(cx, buf, len, nsJSPrincipals::get(systemPrincipal), nsnull);
|
||||||
if (!xdr) {
|
if (!script)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
*scriptp = script;
|
||||||
|
return NS_OK;
|
||||||
::JS_XDRMemSetData(xdr, buf, len);
|
|
||||||
::JS_XDRSetPrincipals(xdr, nsJSPrincipals::get(systemPrincipal), nsnull);
|
|
||||||
|
|
||||||
JSBool ok = ::JS_XDRScript(xdr, script);
|
|
||||||
|
|
||||||
// Prevent XDR from automatically freeing the buffer.
|
|
||||||
::JS_XDRMemSetData(xdr, NULL, 0);
|
|
||||||
::JS_XDRDestroy(xdr);
|
|
||||||
|
|
||||||
return ok ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@ -88,21 +76,13 @@ WriteCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx,
|
|||||||
MOZ_ASSERT(JS_GetScriptPrincipals(script) == nsJSPrincipals::get(systemPrincipal));
|
MOZ_ASSERT(JS_GetScriptPrincipals(script) == nsJSPrincipals::get(systemPrincipal));
|
||||||
MOZ_ASSERT(JS_GetScriptOriginPrincipals(script) == nsJSPrincipals::get(systemPrincipal));
|
MOZ_ASSERT(JS_GetScriptOriginPrincipals(script) == nsJSPrincipals::get(systemPrincipal));
|
||||||
|
|
||||||
JSXDRState *xdr = ::JS_XDRNewMem(cx, JSXDR_ENCODE);
|
uint32_t size;
|
||||||
if (!xdr) {
|
void *data = JS_EncodeScript(cx, script, &size);
|
||||||
|
if (!data)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv;
|
MOZ_ASSERT(size);
|
||||||
if (!::JS_XDRScript(xdr, &script)) {
|
nsresult rv = cache->PutBuffer(PromiseFlatCString(uri).get(), static_cast<char *>(data), size);
|
||||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
js_free(data);
|
||||||
} else {
|
|
||||||
uint32_t size;
|
|
||||||
char* data = static_cast<char *>(::JS_XDRMemGetData(xdr, &size));
|
|
||||||
MOZ_ASSERT(size);
|
|
||||||
rv = cache->PutBuffer(PromiseFlatCString(uri).get(), data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
::JS_XDRDestroy(xdr);
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
#include "jsatom.h"
|
#include "jsatom.h"
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
#include "jsgc.h"
|
#include "jsgc.h"
|
||||||
#include "jsxdrapi.h"
|
|
||||||
#include "dom_quickstubs.h"
|
#include "dom_quickstubs.h"
|
||||||
#include "nsNullPrincipal.h"
|
#include "nsNullPrincipal.h"
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
@ -2839,34 +2838,23 @@ WriteScriptOrFunction(nsIObjectOutputStream *stream, JSContext *cx,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSXDRState *xdr = JS_XDRNewMem(cx, JSXDR_ENCODE);
|
uint32_t size;
|
||||||
if (!xdr)
|
void* data;
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
JSBool ok;
|
|
||||||
{
|
{
|
||||||
JSAutoRequest ar(cx);
|
JSAutoRequest ar(cx);
|
||||||
if (functionObj)
|
if (functionObj)
|
||||||
ok = JS_XDRFunctionObject(xdr, &functionObj);
|
data = JS_EncodeInterpretedFunction(cx, functionObj, &size);
|
||||||
else
|
else
|
||||||
ok = JS_XDRScript(xdr, &script);
|
data = JS_EncodeScript(cx, script, &size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (!data)
|
||||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
} else {
|
MOZ_ASSERT(size);
|
||||||
// Get the encoded JSXDRState data and write it. The JSXDRState owns
|
rv = stream->Write32(size);
|
||||||
// this buffer memory and will free it beneath JS_XDRDestroy.
|
if (NS_SUCCEEDED(rv))
|
||||||
uint32_t size;
|
rv = stream->WriteBytes(static_cast<char *>(data), size);
|
||||||
const char* data = reinterpret_cast<const char*>(::JS_XDRMemGetData(xdr, &size));
|
js_free(data);
|
||||||
NS_ASSERTION(data, "no decoded JSXDRState data!");
|
|
||||||
|
|
||||||
rv = stream->Write32(size);
|
|
||||||
if (NS_SUCCEEDED(rv))
|
|
||||||
rv = stream->WriteBytes(data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_XDRDestroy(xdr);
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -2911,31 +2899,26 @@ ReadScriptOrFunction(nsIObjectInputStream *stream, JSContext *cx,
|
|||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
JSXDRState *xdr = JS_XDRNewMem(cx, JSXDR_DECODE);
|
|
||||||
if (!xdr) {
|
|
||||||
nsMemory::Free(data);
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_XDRMemSetData(xdr, data, size);
|
|
||||||
JS_XDRSetPrincipals(xdr, principal, originPrincipal);
|
|
||||||
|
|
||||||
JSBool ok;
|
|
||||||
{
|
{
|
||||||
JSAutoRequest ar(cx);
|
JSAutoRequest ar(cx);
|
||||||
if (scriptp)
|
if (scriptp) {
|
||||||
ok = JS_XDRScript(xdr, scriptp);
|
JSScript *script = JS_DecodeScript(cx, data, size, principal, originPrincipal);
|
||||||
else
|
if (!script)
|
||||||
ok = JS_XDRFunctionObject(xdr, functionObjp);
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
else
|
||||||
|
*scriptp = script;
|
||||||
|
} else {
|
||||||
|
JSObject *funobj = JS_DecodeInterpretedFunction(cx, data, size,
|
||||||
|
principal, originPrincipal);
|
||||||
|
if (!funobj)
|
||||||
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
else
|
||||||
|
*functionObjp = funobj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We cannot rely on XDR automatically freeing the data memory as we must
|
|
||||||
// use nsMemory::Free to release it.
|
|
||||||
JS_XDRMemSetData(xdr, NULL, 0);
|
|
||||||
JS_XDRDestroy(xdr);
|
|
||||||
nsMemory::Free(data);
|
nsMemory::Free(data);
|
||||||
|
return rv;
|
||||||
return ok ? NS_OK : NS_ERROR_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
Loading…
Reference in New Issue
Block a user