mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 774471: Store source map URLs in the ScriptSource, not on each JSScript. r=jimb
This commit is contained in:
parent
28849e0b13
commit
38ba7ed72f
@ -190,6 +190,9 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *call
|
||||
parser.freeTree(pn);
|
||||
}
|
||||
|
||||
if (tokenStream.hasSourceMap())
|
||||
ss->setSourceMap(tokenStream.releaseSourceMap());
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
/*
|
||||
* Prevent XML data theft via <script src="http://victim.com/foo.xml">.
|
||||
@ -338,6 +341,9 @@ frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun, CompileOptions
|
||||
pn = fn->pn_body;
|
||||
}
|
||||
|
||||
if (parser.tokenStream.hasSourceMap())
|
||||
ss->setSourceMap(parser.tokenStream.releaseSourceMap());
|
||||
|
||||
if (!EmitFunctionScript(cx, &funbce, pn))
|
||||
return false;
|
||||
|
||||
|
@ -1246,17 +1246,16 @@ TokenStream::getAtSourceMappingURL()
|
||||
* we should stop and drop everything for, though. */
|
||||
return true;
|
||||
|
||||
int len = tokenbuf.length();
|
||||
size_t sourceMapLength = tokenbuf.length();
|
||||
|
||||
if (sourceMap)
|
||||
cx->free_(sourceMap);
|
||||
sourceMap = (jschar *) cx->malloc_(sizeof(jschar) * (len + 1));
|
||||
sourceMap = static_cast<jschar *>(cx->malloc_(sizeof(jschar) * (sourceMapLength + 1)));
|
||||
if (!sourceMap)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
sourceMap[i] = tokenbuf[i];
|
||||
sourceMap[len] = '\0';
|
||||
PodCopy(sourceMap, tokenbuf.begin(), sourceMapLength);
|
||||
sourceMap[sourceMapLength] = '\0';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -679,11 +679,16 @@ class TokenStream
|
||||
*/
|
||||
size_t endOffset(const Token &tok);
|
||||
|
||||
bool hasSourceMap() const {
|
||||
return sourceMap != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Give up responsibility for managing the sourceMap filename's memory.
|
||||
*/
|
||||
const jschar *releaseSourceMap() {
|
||||
const jschar* sm = sourceMap;
|
||||
jschar *releaseSourceMap() {
|
||||
JS_ASSERT(hasSourceMap());
|
||||
jschar *sm = sourceMap;
|
||||
sourceMap = NULL;
|
||||
return sm;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "tests.h"
|
||||
#include "jsscript.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
static JSScript *
|
||||
CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JS::HandleObject obj,
|
||||
@ -254,3 +255,40 @@ BEGIN_TEST(testXDR_source)
|
||||
return true;
|
||||
}
|
||||
END_TEST(testXDR_source)
|
||||
|
||||
BEGIN_TEST(testXDR_sourceMap)
|
||||
{
|
||||
const char *sourceMaps[] = {
|
||||
"http://example.com/source-map.json",
|
||||
"file:///var/source-map.json",
|
||||
NULL
|
||||
};
|
||||
for (const char **sm = sourceMaps; *sm; sm++) {
|
||||
JSScript *script = JS_CompileScript(cx, global, "", 0, __FILE__, __LINE__);
|
||||
CHECK(script);
|
||||
|
||||
size_t len = strlen(*sm);
|
||||
jschar *expected = js::InflateString(cx, *sm, &len);
|
||||
CHECK(expected);
|
||||
|
||||
// The script source takes responsibility of free'ing |expected|.
|
||||
script->scriptSource()->setSourceMap(expected);
|
||||
script = FreezeThaw(cx, script);
|
||||
CHECK(script);
|
||||
CHECK(script->scriptSource());
|
||||
CHECK(script->scriptSource()->hasSourceMap());
|
||||
|
||||
const jschar *actual = script->scriptSource()->sourceMap();
|
||||
CHECK(actual);
|
||||
|
||||
while (*expected) {
|
||||
CHECK(*actual);
|
||||
CHECK(*expected == *actual);
|
||||
expected++;
|
||||
actual++;
|
||||
}
|
||||
CHECK(!*actual);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
END_TEST(testXDR_sourceMap)
|
||||
|
@ -67,7 +67,6 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
debugModeBits(rt->debugMode ? DebugFromC : 0),
|
||||
watchpointMap(NULL),
|
||||
scriptCountsMap(NULL),
|
||||
sourceMapMap(NULL),
|
||||
debugScriptMap(NULL)
|
||||
{
|
||||
setGCMaxMallocBytes(rt->gcMaxMallocBytes);
|
||||
@ -77,7 +76,6 @@ JSCompartment::~JSCompartment()
|
||||
{
|
||||
Foreground::delete_(watchpointMap);
|
||||
Foreground::delete_(scriptCountsMap);
|
||||
Foreground::delete_(sourceMapMap);
|
||||
Foreground::delete_(debugScriptMap);
|
||||
}
|
||||
|
||||
|
@ -418,8 +418,6 @@ struct JSCompartment
|
||||
|
||||
js::ScriptCountsMap *scriptCountsMap;
|
||||
|
||||
js::SourceMapMap *sourceMapMap;
|
||||
|
||||
js::DebugScriptMap *debugScriptMap;
|
||||
};
|
||||
|
||||
|
@ -695,7 +695,9 @@ JS_GetScriptFilename(JSContext *cx, JSScript *script)
|
||||
JS_PUBLIC_API(const jschar *)
|
||||
JS_GetScriptSourceMap(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return script->hasSourceMap ? script->getSourceMap() : NULL;
|
||||
ScriptSource *source = script->scriptSource();
|
||||
JS_ASSERT(source);
|
||||
return source->hasSourceMap() ? source->sourceMap() : NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(unsigned)
|
||||
|
@ -908,61 +908,6 @@ JSScript::destroyScriptCounts(FreeOp *fop)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::setSourceMap(JSContext *cx, jschar *sourceMap)
|
||||
{
|
||||
JS_ASSERT(!hasSourceMap);
|
||||
|
||||
/* Create compartment's sourceMapMap if necessary. */
|
||||
SourceMapMap *map = compartment()->sourceMapMap;
|
||||
if (!map) {
|
||||
map = cx->new_<SourceMapMap>();
|
||||
if (!map || !map->init()) {
|
||||
cx->delete_(map);
|
||||
return false;
|
||||
}
|
||||
compartment()->sourceMapMap = map;
|
||||
}
|
||||
|
||||
if (!map->putNew(this, sourceMap))
|
||||
return false;
|
||||
|
||||
hasSourceMap = true; // safe to set this; we can't fail after this point
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
jschar *
|
||||
JSScript::getSourceMap() {
|
||||
JS_ASSERT(hasSourceMap);
|
||||
SourceMapMap *map = compartment()->sourceMapMap;
|
||||
JS_ASSERT(map);
|
||||
SourceMapMap::Ptr p = map->lookup(this);
|
||||
JS_ASSERT(p);
|
||||
return p->value;
|
||||
}
|
||||
|
||||
jschar *
|
||||
JSScript::releaseSourceMap()
|
||||
{
|
||||
JS_ASSERT(hasSourceMap);
|
||||
SourceMapMap *map = compartment()->sourceMapMap;
|
||||
JS_ASSERT(map);
|
||||
SourceMapMap::Ptr p = map->lookup(this);
|
||||
JS_ASSERT(p);
|
||||
jschar *sourceMap = p->value;
|
||||
map->remove(p);
|
||||
hasSourceMap = false;
|
||||
return sourceMap;
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::destroySourceMap(FreeOp *fop)
|
||||
{
|
||||
if (hasSourceMap)
|
||||
fop->free_(releaseSourceMap());
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
void
|
||||
SourceCompressorThread::compressorThread(void *arg)
|
||||
@ -1285,6 +1230,7 @@ ScriptSource::destroy(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(ready());
|
||||
rt->free_(data.compressed);
|
||||
rt->free_(sourceMap_);
|
||||
#ifdef DEBUG
|
||||
ready_ = false;
|
||||
#endif
|
||||
@ -1347,6 +1293,31 @@ ScriptSource::performXDR(XDRState<mode> *xdr)
|
||||
argumentsNotIncluded_ = argumentsNotIncluded;
|
||||
}
|
||||
|
||||
uint8_t haveSourceMap = hasSourceMap();
|
||||
if (!xdr->codeUint8(&haveSourceMap))
|
||||
return false;
|
||||
|
||||
if (haveSourceMap) {
|
||||
uint32_t sourceMapLen = (mode == XDR_DECODE) ? 0 : js_strlen(sourceMap_);
|
||||
if (!xdr->codeUint32(&sourceMapLen))
|
||||
return false;
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
size_t byteLen = (sourceMapLen + 1) * sizeof(jschar);
|
||||
sourceMap_ = static_cast<jschar *>(xdr->cx()->malloc_(byteLen));
|
||||
if (!sourceMap_)
|
||||
return false;
|
||||
}
|
||||
if (!xdr->codeChars(sourceMap_, sourceMapLen)) {
|
||||
if (mode == XDR_DECODE) {
|
||||
xdr->cx()->free_(sourceMap_);
|
||||
sourceMap_ = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
sourceMap_[sourceMapLen] = '\0';
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mode == XDR_DECODE)
|
||||
ready_ = true;
|
||||
@ -1355,6 +1326,21 @@ ScriptSource::performXDR(XDRState<mode> *xdr)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ScriptSource::setSourceMap(jschar *sm)
|
||||
{
|
||||
JS_ASSERT(!hasSourceMap());
|
||||
JS_ASSERT(sm);
|
||||
sourceMap_ = sm;
|
||||
}
|
||||
|
||||
const jschar *
|
||||
ScriptSource::sourceMap()
|
||||
{
|
||||
JS_ASSERT(hasSourceMap());
|
||||
return sourceMap_;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shared script filename management.
|
||||
*/
|
||||
@ -1749,14 +1735,6 @@ JSScript::fullyInitFromEmitter(JSContext *cx, Handle<JSScript*> script, Bytecode
|
||||
}
|
||||
script->nslots = script->nfixed + bce->maxStackDepth;
|
||||
|
||||
jschar *sourceMap = (jschar *) bce->parser->tokenStream.releaseSourceMap();
|
||||
if (sourceMap) {
|
||||
if (!script->setSourceMap(cx, sourceMap)) {
|
||||
cx->free_(sourceMap);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FinishTakingSrcNotes(cx, bce, script->notes()))
|
||||
return false;
|
||||
if (bce->ntrynotes != 0)
|
||||
@ -1915,7 +1893,6 @@ JSScript::finalize(FreeOp *fop)
|
||||
#endif
|
||||
|
||||
destroyScriptCounts(fop);
|
||||
destroySourceMap(fop);
|
||||
destroyDebugScript(fop);
|
||||
scriptSource_->decref(fop->runtime());
|
||||
|
||||
|
@ -302,11 +302,6 @@ typedef HashMap<JSScript *,
|
||||
DefaultHasher<JSScript *>,
|
||||
SystemAllocPolicy> ScriptCountsMap;
|
||||
|
||||
typedef HashMap<JSScript *,
|
||||
jschar *,
|
||||
DefaultHasher<JSScript *>,
|
||||
SystemAllocPolicy> SourceMapMap;
|
||||
|
||||
class DebugScript
|
||||
{
|
||||
friend struct ::JSScript;
|
||||
@ -542,8 +537,6 @@ struct JSScript : public js::gc::Cell
|
||||
bool isGeneratorExp:1; /* is a generator expression */
|
||||
bool hasScriptCounts:1;/* script has an entry in
|
||||
JSCompartment::scriptCountsMap */
|
||||
bool hasSourceMap:1; /* script has an entry in
|
||||
JSCompartment::sourceMapMap */
|
||||
bool hasDebugScript:1; /* script has an entry in
|
||||
JSCompartment::debugScriptMap */
|
||||
|
||||
@ -735,11 +728,6 @@ struct JSScript : public js::gc::Cell
|
||||
js::ScriptCounts releaseScriptCounts();
|
||||
void destroyScriptCounts(js::FreeOp *fop);
|
||||
|
||||
bool setSourceMap(JSContext *cx, jschar *sourceMap);
|
||||
jschar *getSourceMap();
|
||||
jschar *releaseSourceMap();
|
||||
void destroySourceMap(js::FreeOp *fop);
|
||||
|
||||
jsbytecode *main() {
|
||||
return code + mainOffset;
|
||||
}
|
||||
@ -989,6 +977,7 @@ struct ScriptSource
|
||||
uint32_t refs;
|
||||
uint32_t length_;
|
||||
uint32_t compressedLength_;
|
||||
jschar *sourceMap_;
|
||||
|
||||
// True if we can call JSRuntime::sourceHook to load the source on
|
||||
// demand. If sourceRetrievable_ and hasSourceData() are false, it is not
|
||||
@ -1004,6 +993,7 @@ struct ScriptSource
|
||||
: refs(0),
|
||||
length_(0),
|
||||
compressedLength_(0),
|
||||
sourceMap_(NULL),
|
||||
sourceRetrievable_(false),
|
||||
argumentsNotIncluded_(false)
|
||||
#ifdef DEBUG
|
||||
@ -1045,6 +1035,11 @@ struct ScriptSource
|
||||
template <XDRMode mode>
|
||||
bool performXDR(XDRState<mode> *xdr);
|
||||
|
||||
// Source maps
|
||||
void setSourceMap(jschar *sm);
|
||||
const jschar *sourceMap();
|
||||
bool hasSourceMap() const { return sourceMap_ != NULL; }
|
||||
|
||||
private:
|
||||
void destroy(JSRuntime *rt);
|
||||
bool compressed() { return compressedLength_ != 0; }
|
||||
|
@ -25,7 +25,7 @@ namespace js {
|
||||
* and saved versions. If deserialization fails, the data should be
|
||||
* invalidated if possible.
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 128);
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 129);
|
||||
|
||||
class XDRBuffer {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user