зеркало из https://github.com/mozilla/gecko-dev.git
Bug 761723 - Add a runtime hook to retrieve source that wasn't saved. r=luke
--HG-- extra : rebase_source : de2e88f79e1e2a4a75ff5c5b296dbae052e4b076
This commit is contained in:
Родитель
7986d9113d
Коммит
0a424b0867
|
@ -801,6 +801,7 @@ JSRuntime::JSRuntime()
|
|||
negativeInfinityValue(UndefinedValue()),
|
||||
positiveInfinityValue(UndefinedValue()),
|
||||
emptyString(NULL),
|
||||
sourceHook(NULL),
|
||||
debugMode(false),
|
||||
spsProfiler(thisFromCtor()),
|
||||
profilingScripts(false),
|
||||
|
|
|
@ -716,6 +716,8 @@ struct JSRuntime : js::RuntimeFriendFields
|
|||
return !JS_CLIST_IS_EMPTY(&contextList);
|
||||
}
|
||||
|
||||
JS_SourceHook sourceHook;
|
||||
|
||||
/* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
|
||||
JSDebugHooks debugHooks;
|
||||
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
using namespace js;
|
||||
using namespace JS;
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook)
|
||||
{
|
||||
rt->sourceHook = hook;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
|
||||
{
|
||||
|
|
|
@ -175,6 +175,11 @@ JS_END_EXTERN_C
|
|||
|
||||
#ifdef __cplusplus
|
||||
|
||||
typedef bool (* JS_SourceHook)(JSContext *cx, JSScript *script, char **src, uint32_t *length);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook);
|
||||
|
||||
namespace js {
|
||||
|
||||
struct RuntimeFriendFields {
|
||||
|
|
|
@ -590,7 +590,10 @@ JSFunction::toString(JSContext *cx, bool bodyOnly, bool lambdaParen)
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
if (isInterpreted() && script()->source) {
|
||||
bool haveSource = isInterpreted();
|
||||
if (haveSource && !script()->source && !script()->loadSource(cx, &haveSource))
|
||||
return NULL;
|
||||
if (haveSource) {
|
||||
RootedString src(cx, script()->sourceData(cx));
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
@ -686,6 +689,13 @@ JSFunction::toString(JSContext *cx, bool bodyOnly, bool lambdaParen)
|
|||
if (!out.append(")"))
|
||||
return NULL;
|
||||
}
|
||||
} else if (isInterpreted()) {
|
||||
if ((!bodyOnly && !out.append("() {\n ")) ||
|
||||
!out.append("[sourceless code]") ||
|
||||
(!bodyOnly && !out.append("\n}")))
|
||||
return NULL;
|
||||
if (!lambdaParen && (flags & JSFUN_LAMBDA) && (!out.append(")")))
|
||||
return NULL;
|
||||
} else {
|
||||
JS_ASSERT(!(flags & JSFUN_EXPR_CLOSURE));
|
||||
if ((!bodyOnly && !out.append("() {\n ")) ||
|
||||
|
|
|
@ -1070,6 +1070,35 @@ SourceCompressorThread::waitOnCompression(SourceCompressionToken *userTok)
|
|||
}
|
||||
#endif /* JS_THREADSAFE */
|
||||
|
||||
bool
|
||||
JSScript::loadSource(JSContext *cx, bool *worked)
|
||||
{
|
||||
JS_ASSERT(!source);
|
||||
*worked = false;
|
||||
if (!cx->runtime->sourceHook)
|
||||
return true;
|
||||
char *src = NULL;
|
||||
uint32_t length;
|
||||
if (!cx->runtime->sourceHook(cx, this, &src, &length))
|
||||
return false;
|
||||
if (!src)
|
||||
return true;
|
||||
size_t newLength = length;
|
||||
jschar *usrc = InflateString(cx, src, &newLength);
|
||||
cx->free_(src);
|
||||
if (!usrc)
|
||||
return false;
|
||||
ScriptSource *ss = ScriptSource::createFromSource(cx, usrc, length, false, NULL, true);
|
||||
if (!ss) {
|
||||
cx->free_(usrc);
|
||||
return false;
|
||||
}
|
||||
source = ss;
|
||||
ss->attachToRuntime(cx->runtime);
|
||||
*worked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSFixedString *
|
||||
JSScript::sourceData(JSContext *cx)
|
||||
{
|
||||
|
@ -1147,7 +1176,8 @@ ScriptSource::substring(JSContext *cx, uint32_t start, uint32_t stop)
|
|||
|
||||
ScriptSource *
|
||||
ScriptSource::createFromSource(JSContext *cx, const jschar *src, uint32_t length,
|
||||
bool argumentsNotIncluded, SourceCompressionToken *tok)
|
||||
bool argumentsNotIncluded, SourceCompressionToken *tok,
|
||||
bool ownSource)
|
||||
{
|
||||
ScriptSource *ss = static_cast<ScriptSource *>(cx->malloc_(sizeof(*ss)));
|
||||
if (!ss)
|
||||
|
@ -1160,6 +1190,7 @@ ScriptSource::createFromSource(JSContext *cx, const jschar *src, uint32_t length
|
|||
}
|
||||
ss->next = NULL;
|
||||
ss->length_ = length;
|
||||
ss->compressedLength = 0;
|
||||
ss->marked = ss->onRuntime_ = false;
|
||||
ss->argumentsNotIncluded_ = argumentsNotIncluded;
|
||||
#ifdef DEBUG
|
||||
|
@ -1176,6 +1207,8 @@ ScriptSource::createFromSource(JSContext *cx, const jschar *src, uint32_t length
|
|||
ss->marked = true;
|
||||
#endif
|
||||
|
||||
JS_ASSERT_IF(ownSource, !tok);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
if (tok) {
|
||||
tok->ss = ss;
|
||||
|
@ -1183,21 +1216,23 @@ ScriptSource::createFromSource(JSContext *cx, const jschar *src, uint32_t length
|
|||
cx->runtime->sourceCompressorThread.compress(tok);
|
||||
} else
|
||||
#endif
|
||||
ss->considerCompressing(cx->runtime, src);
|
||||
ss->considerCompressing(cx->runtime, src, ownSource);
|
||||
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
void
|
||||
ScriptSource::considerCompressing(JSRuntime *rt, const jschar *src)
|
||||
ScriptSource::considerCompressing(JSRuntime *rt, const jschar *src, bool ownSource)
|
||||
{
|
||||
JS_ASSERT(!ready());
|
||||
const size_t memlen = length_ * sizeof(jschar);
|
||||
const size_t COMPRESS_THRESHOLD = 512;
|
||||
|
||||
size_t compressedLen;
|
||||
if (memlen >= COMPRESS_THRESHOLD &&
|
||||
if (ownSource) {
|
||||
data.source = const_cast<jschar *>(src);
|
||||
} else if (memlen >= COMPRESS_THRESHOLD &&
|
||||
TryCompressString(reinterpret_cast<const unsigned char *>(src), memlen,
|
||||
data.compressed, &compressedLen))
|
||||
{
|
||||
|
@ -1207,7 +1242,6 @@ ScriptSource::considerCompressing(JSRuntime *rt, const jschar *src)
|
|||
data.compressed = static_cast<unsigned char *>(mem);
|
||||
JS_ASSERT(data.compressed);
|
||||
} else {
|
||||
compressedLength = 0;
|
||||
PodCopy(data.source, src, length_);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -620,6 +620,8 @@ struct JSScript : public js::gc::Cell
|
|||
|
||||
JSFixedString *sourceData(JSContext *cx);
|
||||
|
||||
bool loadSource(JSContext *cx, bool *worked);
|
||||
|
||||
/* Return whether this script was compiled for 'eval' */
|
||||
bool isForEval() { return isCachedEval || isActiveEval; }
|
||||
|
||||
|
@ -978,7 +980,8 @@ struct ScriptSource
|
|||
const jschar *src,
|
||||
uint32_t length,
|
||||
bool argumentsNotIncluded = false,
|
||||
SourceCompressionToken *tok = NULL);
|
||||
SourceCompressionToken *tok = NULL,
|
||||
bool ownSource = false);
|
||||
void attachToRuntime(JSRuntime *rt);
|
||||
void mark() { JS_ASSERT(ready_); JS_ASSERT(onRuntime_); marked = true; }
|
||||
void destroy(JSRuntime *rt);
|
||||
|
@ -1000,7 +1003,7 @@ struct ScriptSource
|
|||
|
||||
private:
|
||||
bool compressed() { return !!compressedLength; }
|
||||
void considerCompressing(JSRuntime *rt, const jschar *src);
|
||||
void considerCompressing(JSRuntime *rt, const jschar *src, bool ownSource = false);
|
||||
};
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
|
Загрузка…
Ссылка в новой задаче